Skip to content

Commit 6f8bf8b

Browse files
updates localized field hooks
1 parent 46f5749 commit 6f8bf8b

File tree

4 files changed

+164
-8
lines changed

4 files changed

+164
-8
lines changed

packages/ui-extensions-react/src/surfaces/checkout.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,4 +361,7 @@ export {useDeliverySelectionGroups} from './checkout/hooks/delivery-selection-gr
361361
export {useCheckoutToken} from './checkout/hooks/checkout-token';
362362
export {useCustomerPrivacy} from './checkout/hooks/customer-privacy';
363363
export {useInstructions} from './checkout/hooks/instructions';
364-
export {useLocalizedFields} from './checkout/hooks/localized-fields';
364+
export {
365+
useLocalizedFields,
366+
useLocalizedField,
367+
} from './checkout/hooks/localized-fields';

packages/ui-extensions-react/src/surfaces/checkout/hooks/localized-fields.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {useSubscription} from './subscription';
1515
*/
1616
export function useLocalizedFields<
1717
Target extends RenderExtensionTarget = RenderExtensionTarget,
18-
>(keys: LocalizedFieldKey[]): LocalizedField[] | undefined {
18+
>(keys?: LocalizedFieldKey[]): LocalizedField[] {
1919
const {localizedFields} = useApi<Target>();
2020

2121
if (!localizedFields) {
@@ -24,7 +24,26 @@ export function useLocalizedFields<
2424
);
2525
}
2626

27-
return useSubscription(localizedFields)?.filter(({key}) =>
28-
keys.includes(key),
29-
);
27+
const localizedFieldsData = useSubscription(localizedFields);
28+
29+
if (!keys) {
30+
return localizedFieldsData;
31+
}
32+
33+
if (!keys.length) {
34+
return [];
35+
}
36+
37+
return localizedFieldsData.filter(({key}) => keys.includes(key));
38+
}
39+
40+
/**
41+
* Returns the current localized field or undefined for the specified
42+
* localized field key and re-renders your component if the value changes.
43+
*/
44+
export function useLocalizedField<
45+
Target extends RenderExtensionTarget = RenderExtensionTarget,
46+
>(key: LocalizedFieldKey): LocalizedField | undefined {
47+
const fields = useLocalizedFields<Target>([key]);
48+
return fields[0];
3049
}

packages/ui-extensions-react/src/surfaces/checkout/hooks/tests/localized-fields.test.ts

Lines changed: 136 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type {LocalizedField} from '@shopify/ui-extensions/checkout';
22

3-
import {useLocalizedFields} from '../localized-fields';
3+
import {useLocalizedFields, useLocalizedField} from '../localized-fields';
44

55
import {mount, createMockStatefulRemoteSubscribable} from './mount';
66

@@ -19,7 +19,53 @@ describe('useLocalizedFields', () => {
1919
);
2020
});
2121

22-
it('returns empty if no localized fields match the passed keys', () => {
22+
it('returns all localized fields if no keys are passed', () => {
23+
const localizedFields: LocalizedField[] = [
24+
{
25+
key: 'TAX_CREDENTIAL_BR',
26+
title: 'CPF/CNPJ',
27+
value: 'test-value',
28+
},
29+
{
30+
key: 'SHIPPING_CREDENTIAL_BR',
31+
title: 'CPF/CNPJ',
32+
value: 'test-value',
33+
},
34+
];
35+
36+
const extensionApi = {
37+
localizedFields: createMockStatefulRemoteSubscribable(localizedFields),
38+
};
39+
40+
const {value} = mount.hook(() => useLocalizedFields(), {extensionApi});
41+
42+
expect(value).toStrictEqual(localizedFields);
43+
});
44+
45+
it('returns an empty array if the passed keys array is empty', () => {
46+
const localizedFields: LocalizedField[] = [
47+
{
48+
key: 'TAX_CREDENTIAL_BR',
49+
title: 'CPF/CNPJ',
50+
value: 'test-value',
51+
},
52+
{
53+
key: 'SHIPPING_CREDENTIAL_BR',
54+
title: 'CPF/CNPJ',
55+
value: 'test-value',
56+
},
57+
];
58+
59+
const extensionApi = {
60+
localizedFields: createMockStatefulRemoteSubscribable(localizedFields),
61+
};
62+
63+
const {value} = mount.hook(() => useLocalizedFields([]), {extensionApi});
64+
65+
expect(value).toStrictEqual([]);
66+
});
67+
68+
it('returns an empty array if no localized fields match the passed keys', () => {
2369
const localizedFields: LocalizedField[] = [
2470
{
2571
key: 'TAX_CREDENTIAL_BR',
@@ -75,4 +121,92 @@ describe('useLocalizedFields', () => {
75121

76122
expect(value).toMatchObject([localizedFields[0], localizedFields[2]]);
77123
});
124+
125+
it('returns an array of localized fields for any matching fields', () => {
126+
const localizedFields: LocalizedField[] = [
127+
{
128+
key: 'TAX_CREDENTIAL_MX',
129+
title: 'Tax credential MX',
130+
value: 'test-value',
131+
},
132+
{
133+
key: 'SHIPPING_CREDENTIAL_MX',
134+
title: 'Shipping credential MX',
135+
value: 'test-value',
136+
},
137+
{
138+
key: 'TAX_CREDENTIAL_USE_MX',
139+
title: 'Tax credential use MX',
140+
value: 'test-value',
141+
},
142+
];
143+
144+
const extensionApi = {
145+
localizedFields: createMockStatefulRemoteSubscribable(localizedFields),
146+
};
147+
148+
const {value} = mount.hook(
149+
() =>
150+
useLocalizedFields([
151+
'TAX_CREDENTIAL_MX',
152+
'TAX_CREDENTIAL_BR',
153+
'TAX_CREDENTIAL_USE_MX',
154+
]),
155+
{extensionApi},
156+
);
157+
158+
expect(value).toMatchObject([localizedFields[0], localizedFields[2]]);
159+
});
160+
});
161+
162+
describe('useLocalizedField', () => {
163+
it('returns the localized field that matches the passed key', async () => {
164+
const localizedFields: LocalizedField[] = [
165+
{
166+
key: 'TAX_CREDENTIAL_MX',
167+
title: 'Tax credential MX',
168+
value: 'test-value-1',
169+
},
170+
{
171+
key: 'SHIPPING_CREDENTIAL_MX',
172+
title: 'Shipping credential MX',
173+
value: 'test-value-2',
174+
},
175+
{
176+
key: 'TAX_CREDENTIAL_USE_MX',
177+
title: 'Tax credential use MX',
178+
value: 'test-value-3',
179+
},
180+
];
181+
182+
const extensionApi = {
183+
localizedFields: createMockStatefulRemoteSubscribable(localizedFields),
184+
};
185+
186+
const {value} = mount.hook(
187+
() => useLocalizedField('TAX_CREDENTIAL_USE_MX'),
188+
{
189+
extensionApi,
190+
},
191+
);
192+
193+
expect(value).toStrictEqual(localizedFields[2]);
194+
});
195+
196+
it('returns undefined if no localized field matches the passed key', async () => {
197+
const localizedFields: LocalizedField[] = [];
198+
199+
const extensionApi = {
200+
localizedFields: createMockStatefulRemoteSubscribable(localizedFields),
201+
};
202+
203+
const {value} = mount.hook(
204+
() => useLocalizedField('TAX_CREDENTIAL_USE_MX'),
205+
{
206+
extensionApi,
207+
},
208+
);
209+
210+
expect(value).toBeUndefined();
211+
});
78212
});

packages/ui-extensions/src/surfaces/checkout/api/standard/standard.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,7 @@ export interface StandardApi<Target extends ExtensionTarget = ExtensionTarget> {
746746
* The API for reading additional fields that are required in checkout under certain circumstances.
747747
* For example, some countries require additional fields for customs information or tax identification numbers.
748748
*/
749-
localizedFields?: StatefulRemoteSubscribable<LocalizedField[] | undefined>;
749+
localizedFields?: StatefulRemoteSubscribable<LocalizedField[]>;
750750
}
751751

752752
export interface Ui {

0 commit comments

Comments
 (0)