Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions packages/lib/src/components/internal/Address/Address.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ export default function Address(props: AddressProps) {
formatters: addressFormatters
});

// In partial address mode, country is not in the form schema but we need it for regionalized labels.
// Store the merchant's country config once at mount, then use it if form data doesn't have country.
const initialCountryRef = useRef<string | undefined>((props.data as AddressData)?.country);
const effectiveCountry = data.country || initialCountryRef.current;
const dataWithCountry = useMemo(() => ({ ...data, country: effectiveCountry }), [data, effectiveCountry]);


const setSearchData = useCallback(
(selectedAddress: AddressData) => {
const propsKeysToProcess = ADDRESS_SCHEMA;
Expand Down Expand Up @@ -145,6 +152,11 @@ export default function Address(props: AddressProps) {
return acc;
}, {});

// In partial address mode, ensure country is included in output for regionalized labels/validation.
if (!(processedData as AddressData).country && initialCountryRef.current) {
(processedData as AddressData).country = initialCountryRef.current;
}

props.onChange({ data: processedData, valid, errors, isValid });
}, [data, valid, errors, isValid]);

Expand All @@ -159,15 +171,15 @@ export default function Address(props: AddressProps) {
key={fieldName}
allowedCountries={props.allowedCountries}
classNameModifiers={[...classNameModifiers, fieldName]}
data={data}
data={dataWithCountry}
errors={errors}
valid={valid}
fieldName={fieldName}
onInput={handleChangeFor(fieldName, 'input')}
onBlur={handleChangeFor(fieldName, 'blur')}
onDropdownChange={handleChangeFor(fieldName, 'blur')}
specifications={specifications}
maxLength={getMaxLengthByFieldAndCountry(countrySpecificFormatters, fieldName, data.country, true)}
maxLength={getMaxLengthByFieldAndCountry(countrySpecificFormatters, fieldName, effectiveCountry, true)}
trimOnBlur={true}
disabled={!enabledFields.includes(fieldName)}
onFieldFocusAnalytics={props.onFieldFocusAnalytics}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Specifications from './Specifications';
import { PARTIAL_ADDRESS_SCHEMA } from './constants';

describe('Specifications', () => {
const addressSpecificationsMock = {
Expand Down Expand Up @@ -65,3 +66,25 @@ describe('Specifications', () => {
expect(specifications.getAddressSchemaForCountryFlat('PT')).toStrictEqual(['country', 'city', 'postalCode']);
});
});

describe('Partial Address Schema Specifications', () => {
const partialSpecifications = new Specifications(PARTIAL_ADDRESS_SCHEMA);

test('should use zipCode label for US postal code in partial mode', () => {
expect(partialSpecifications.getKeyForField('postalCode', 'US')).toBe('zipCode');
});

test.each(['GB', 'CA', 'AU', 'BR', 'FR', 'DE', 'NL'])(
'should use default postalCode label for %s in partial mode',
countryCode => {
expect(partialSpecifications.getKeyForField('postalCode', countryCode)).toBe('postalCode');
}
);

test.each(['US', 'GB', 'FR'])(
'partial schema for %s should only contain postalCode field',
countryCode => {
expect(partialSpecifications.getAddressSchemaForCountryFlat(countryCode)).toStrictEqual(['postalCode']);
}
);
});
13 changes: 6 additions & 7 deletions packages/lib/src/components/internal/Address/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,12 @@ export const ADDRESS_SPECIFICATIONS: AddressSpecifications = {
}
};

export const PARTIAL_ADDRESS_SCHEMA: AddressSpecifications = {
default: {
labels: {
[POSTAL_CODE]: 'zipCode'
},
export const PARTIAL_ADDRESS_SCHEMA: AddressSpecifications = Object.keys(ADDRESS_SPECIFICATIONS).reduce((acc, countryCode) => {
acc[countryCode] = {
labels: ADDRESS_SPECIFICATIONS[countryCode].labels,
schema: [POSTAL_CODE]
}
};
};
return acc;
}, {} as AddressSpecifications);

export const COUNTRIES_WITH_CUSTOM_SPECIFICATION = Object.keys(ADDRESS_SPECIFICATIONS);