Skip to content

Commit

Permalink
[checkout] Update to ceb0a94a415d4e34f97c6ed41f7fd9dabf06deeb
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielParpal committed Jun 12, 2024
1 parent f2d1ce4 commit 3c3505c
Show file tree
Hide file tree
Showing 33 changed files with 889 additions and 184 deletions.
6 changes: 6 additions & 0 deletions .changeset/long-news-prove.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@shopify/ui-extensions': minor
'@shopify/ui-extensions-react': minor
---

Support split shipping in Shipping option list and item targets.
2 changes: 2 additions & 0 deletions packages/ui-extensions-react/src/surfaces/checkout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,5 +344,7 @@ export {useApplyRedeemableChange} from './checkout/hooks/redeemable';
export {useDeliveryGroups} from './checkout/hooks/delivery-groups';
export {useDeliveryGroup} from './checkout/hooks/delivery-group';
export {useDeliveryGroupTarget} from './checkout/hooks/delivery-group-target';
export {useDeliveryGroupListTarget} from './checkout/hooks/delivery-group-list-target';
export {useDeliverySelectionGroups} from './checkout/hooks/delivery-selection-groups';
export {useCheckoutToken} from './checkout/hooks/checkout-token';
export {useCustomerPrivacy} from './checkout/hooks/customer-privacy';
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type {DeliveryGroupList} from '@shopify/ui-extensions/checkout';

import {useApi} from './api';
import {useSubscription} from './subscription';

/**
* Returns the delivery group list the extension is attached to. This hook can only be used by extensions in the following
* extension targets:
* - purchase.checkout.shipping-option-list.render-before
* - purchase.checkout.shipping-option-list.render-after
*/
export function useDeliveryGroupListTarget(): DeliveryGroupList | undefined {
const api = useApi<
| 'purchase.checkout.shipping-option-list.render-before'
| 'purchase.checkout.shipping-option-list.render-after'
>();

return useSubscription(api.target);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,17 @@ import {useSubscription} from './subscription';
* extension targets:
* - purchase.checkout.shipping-option-list.render-before
* - purchase.checkout.shipping-option-list.render-after
*
* > Caution: Deprecated as of version `2024-07`, use `useDeliveryGroupListTarget()` instead.
*
* @deprecated Deprecated as of version `2024-07`, use `useDeliveryGroupListTarget()` instead.
*/
export function useDeliveryGroupTarget(): DeliveryGroup | undefined {
const api = useApi<
| 'purchase.checkout.shipping-option-list.render-before'
| 'purchase.checkout.shipping-option-list.render-after'
>();

return useSubscription(api.target);
const target = useSubscription(api.target);
return target?.deliveryGroups[0];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type {DeliverySelectionGroup} from '@shopify/ui-extensions/checkout';

import {useApi} from './api';
import {useSubscription} from './subscription';

/**
* Returns the list of delivery selection groups available to the buyers. This hook can only be used by extensions in the following
* extension targets:
* - purchase.checkout.shipping-option-list.render-before
* - purchase.checkout.shipping-option-list.render-after
*/
export function useDeliverySelectionGroups():
| DeliverySelectionGroup[]
| undefined {
const api = useApi<
| 'purchase.checkout.shipping-option-list.render-before'
| 'purchase.checkout.shipping-option-list.render-after'
>();

return useSubscription(api.deliverySelectionGroups);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import type {ShippingOption} from '@shopify/ui-extensions/checkout';
import type {
ShippingOption,
ShippingOptionItemRenderMode,
} from '@shopify/ui-extensions/checkout';
import {useMemo} from 'react';

import {ExtensionHasNoTargetError} from '../errors';
Expand All @@ -15,6 +18,7 @@ import {useSubscription} from './subscription';
export function useShippingOptionTarget(): {
shippingOptionTarget: ShippingOption;
isTargetSelected: boolean;
renderMode: ShippingOptionItemRenderMode;
} {
const api = useApi<
| 'purchase.checkout.shipping-option-item.render-after'
Expand All @@ -29,13 +33,15 @@ export function useShippingOptionTarget(): {

const shippingOptionTarget = useSubscription(api.target);
const isTargetSelected = useSubscription(api.isTargetSelected);
const renderMode = api.renderMode;

const shippingOption = useMemo(() => {
return {
shippingOptionTarget,
isTargetSelected,
renderMode,
};
}, [shippingOptionTarget, isTargetSelected]);
}, [shippingOptionTarget, isTargetSelected, renderMode]);

return shippingOption;
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function useSubscription<Value>(
// Check for this and schedule an update if work has occurred.
checkForUpdates(subscription.current);

return () => {
return (): void => {
didUnsubscribe = true;
unsubscribe();
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import type {
DeliveryGroup,
ExtensionTarget,
ShippingOption,
} from '@shopify/ui-extensions/checkout';

import {useDeliveryGroupListTarget} from '../delivery-group-list-target';

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

describe('useDeliveryGroupListTarget', () => {
it('returns the DeliveryGroupList target if it exists', async () => {
const deliveryGroup: DeliveryGroup = {
selectedDeliveryOption: {
handle: 'shipping_method_1',
},
groupType: 'oneTimePurchase',
isDeliveryRequired: true,
targetedCartLines: [
{
id: 'gid://shopify/CartLine/stable_id',
},
],
deliveryOptions: [
{
handle: 'shipping_method_1',
title: 'Shipping method 1',
description: undefined,
type: 'shipping',
carrier: {
name: 'test carrier',
},
cost: {
amount: 10,
currencyCode: 'USD',
},
costAfterDiscounts: {
amount: 10,
currencyCode: 'USD',
},
deliveryEstimate: {
timeInTransit: {
lower: 10000,
upper: 10000,
},
},
} as ShippingOption,
],
};

const deliveryGroup2: DeliveryGroup = {
...deliveryGroup,
targetedCartLines: [
{
id: 'gid://shopify/CartLine/stable_id_2',
},
],
};

const target: ExtensionTarget =
'purchase.checkout.shipping-option-list.render-before';

const {value} = mount.hook(() => useDeliveryGroupListTarget(), {
extensionApi: {
extension: {target},
target: createMockStatefulRemoteSubscribable({
groupType: 'oneTimePurchase',
deliveryGroups: [deliveryGroup, deliveryGroup2],
}) as any,
},
});

expect(value).toStrictEqual({
groupType: 'oneTimePurchase',
deliveryGroups: [deliveryGroup, deliveryGroup2],
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
ShippingOption,
} from '@shopify/ui-extensions/checkout';

// eslint-disable-next-line import/no-deprecated
import {useDeliveryGroupTarget} from '../delivery-group-target';

import {mount, createMockStatefulRemoteSubscribable} from './mount';
Expand Down Expand Up @@ -48,15 +49,29 @@ describe('useDeliveryGroupTarget', () => {
],
};

const deliveryGroup2: DeliveryGroup = {
...deliveryGroup,
targetedCartLines: [
{
id: 'gid://shopify/CartLine/stable_id_2',
},
],
};

const target: ExtensionTarget =
'purchase.checkout.shipping-option-list.render-before';

// eslint-disable-next-line import/no-deprecated
const {value} = mount.hook(() => useDeliveryGroupTarget(), {
extensionApi: {
extension: {target},
target: createMockStatefulRemoteSubscribable(deliveryGroup),
target: createMockStatefulRemoteSubscribable({
groupType: 'oneTimePurchase',
deliveryGroups: [deliveryGroup, deliveryGroup2],
}) as any,
},
});

expect(value).toBe(deliveryGroup);
expect(value).toStrictEqual(deliveryGroup);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import type {ExtensionTarget} from '@shopify/ui-extensions/checkout';
import {faker} from '@faker-js/faker';

import {useDeliverySelectionGroups} from '../delivery-selection-groups';

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

describe('useDeliverySelectionGroups', () => {
it('returns deliverySelectionGroups if it exists', async () => {
const deliverySelectionGroup = {
handle: faker.string.uuid(),
selected: false,
title: 'Lowest price',
associatedDeliveryOptions: [
{handle: faker.string.uuid()},
{handle: faker.string.uuid()},
],
cost: {
amount: 10,
currencyCode: 'USD',
},
costAfterDiscounts: {
amount: 10,
currencyCode: 'USD',
},
};

const target: ExtensionTarget =
'purchase.checkout.shipping-option-list.render-before';

const {value} = mount.hook(() => useDeliverySelectionGroups(), {
extensionApi: {
extension: {target},
deliverySelectionGroups: createMockStatefulRemoteSubscribable([
deliverySelectionGroup,
]) as any,
},
});

expect(value).toStrictEqual([deliverySelectionGroup]);
});

it('returns undefined if delivery selection groups are missing', async () => {
const target: ExtensionTarget =
'purchase.checkout.shipping-option-list.render-before';

const {value} = mount.hook(() => useDeliverySelectionGroups(), {
extensionApi: {
extension: {target},
deliverySelectionGroups:
createMockStatefulRemoteSubscribable(undefined),
},
});

expect(value).toBeUndefined();
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {
ExtensionTarget,
ShippingOption,
ShippingOptionItemRenderMode,
} from '@shopify/ui-extensions/checkout';

import {useShippingOptionTarget} from '../shipping-option-target';
Expand Down Expand Up @@ -31,6 +32,10 @@ describe('useShippingOptionTarget', () => {
},
} as ShippingOption;

const renderMode: ShippingOptionItemRenderMode = {
overlay: false,
};

it('throws if extension target has no api.target', async () => {
const runner = async () => {
const target: ExtensionTarget = 'purchase.checkout.block.render';
Expand All @@ -39,6 +44,7 @@ describe('useShippingOptionTarget', () => {
extension: {target},
target: undefined,
isTargetSelected: createMockStatefulRemoteSubscribable(true),
renderMode,
},
});
};
Expand All @@ -54,6 +60,7 @@ describe('useShippingOptionTarget', () => {
extension: {target},
target: createMockStatefulRemoteSubscribable(shippingOption),
isTargetSelected: undefined,
renderMode,
},
});
};
Expand All @@ -69,12 +76,14 @@ describe('useShippingOptionTarget', () => {
extension: {target},
target: createMockStatefulRemoteSubscribable(shippingOption),
isTargetSelected: createMockStatefulRemoteSubscribable(true),
renderMode,
},
});

expect(value).toStrictEqual({
shippingOptionTarget: shippingOption,
isTargetSelected: true,
renderMode,
});
});
});
5 changes: 3 additions & 2 deletions packages/ui-extensions-react/src/surfaces/checkout/render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {ExtensionApiContext} from './context';
* hook.
*
* @param target The extension target you are registering for. You can see a full list
* of the available targets in our [developer documentation](https://shopify.dev/docs/api/checkout-ui-extensions/extension-targets-overview#placements).
* of the available targets in our [developer documentation](https://shopify.dev/docs/api/checkout-ui-extensions/extension-targets-overview#supported-locations).
*
* @param render The function that will be called when Checkout begins rendering
* your extension. This function is called with the API checkout provided to your
Expand Down Expand Up @@ -70,7 +70,7 @@ export function reactExtension<Target extends RenderExtensionTarget>(
* hook.
*
* @param target The extension target you are registering for. You can see a full list
* of the available targets in our [developer documentation](https://shopify.dev/docs/api/checkout-ui-extensions/extension-targets-overview#placements).
* of the available targets in our [developer documentation](https://shopify.dev/docs/api/checkout-ui-extensions/extension-targets-overview#supported-locations).
*
* @param render The function that will be called when Checkout begins rendering
* your extension. This function is called with the API checkout provided to your
Expand All @@ -83,6 +83,7 @@ export function reactExtension<Target extends RenderExtensionTarget>(
*/
export function render<Target extends RenderExtensionTarget>(
target: Target,

render: (api: ApiForRenderExtension<Target>) => ReactElement<any>,
): ExtensionTargets[Target] {
return reactExtension(target, render);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,21 @@ const data: ReferenceEntityTemplateSchema = {
{
title: 'useDeliveryGroupTarget',
description:
'Returns the delivery group for the `purchase.checkout.shipping-option-list.render-before` and `purchase.checkout.shipping-option-list.render-after` attached extensions.',
'Returns the delivery group for the `purchase.checkout.shipping-option-list.render-before` and `purchase.checkout.shipping-option-list.render-after` attached extensions. This is deprecated, use `useDeliveryGroupListTarget()` instead.',
type: 'UseDeliveryGroupTargetGeneratedType',
},
{
title: 'useDeliveryGroupListTarget',
description:
'Returns the delivery group list for the `purchase.checkout.shipping-option-list.render-before` and `purchase.checkout.shipping-option-list.render-after` attached extensions.',
type: 'UseDeliveryGroupListTargetGeneratedType',
},
{
title: 'useDeliverySelectionGroups',
description:
'Returns the delivery selection groups for the `purchase.checkout.shipping-option-list.render-before` and `purchase.checkout.shipping-option-list.render-after` attached extensions.',
type: 'UseDeliverySelectionGroupsGeneratedType',
},
{
title: 'PickupPointListApi',
description:
Expand Down
Loading

0 comments on commit 3c3505c

Please sign in to comment.