Skip to content

Commit 18fc77e

Browse files
glo82145del22123
andauthored
PWA-3664 : Config option selection fix (#4607)
* PWA-3664 : Config option selection fix * PWA-3664 : Config option selection fix * PWA-3664 : Config option selection fix * PWA-3664 : Config option selection fix * PWA-3664 : Config option selection fix * PWA-3664 : Config option selection fix --------- Co-authored-by: Bharathidasan Elangovan <del22123@adobe.com>
1 parent 454eb03 commit 18fc77e

11 files changed

Lines changed: 637 additions & 253 deletions

packages/peregrine/lib/talons/ProductFullDetail/__tests__/useProductFullDetail.spec.js

Lines changed: 210 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,123 @@ describe('shouldShowSimpleProductOutOfStockButton', () => {
667667
});
668668
});
669669

670+
const configurableSparseVariantMissingChildStockStatusProps = {
671+
...defaultProps,
672+
product: {
673+
...defaultProps.product,
674+
__typename: 'ConfigurableProduct',
675+
stock_status: 'IN_STOCK',
676+
media_gallery_entries: [],
677+
price_range: {
678+
maximum_price: {
679+
final_price: {
680+
value: 10,
681+
currency: 'USD'
682+
},
683+
discount: {
684+
amount_off: 0
685+
}
686+
}
687+
},
688+
configurable_options: [
689+
{
690+
attribute_code: 'color',
691+
attribute_id: '179',
692+
id: 1,
693+
label: 'Color',
694+
values: [
695+
{
696+
__typename: 'ConfigurableProductOptionsValues',
697+
uid: 'c1',
698+
default_label: 'A',
699+
label: 'A',
700+
store_label: 'A',
701+
use_default_value: true,
702+
value_index: 10,
703+
swatch_data: null,
704+
media_gallery_entries: []
705+
},
706+
{
707+
__typename: 'ConfigurableProductOptionsValues',
708+
uid: 'c2',
709+
default_label: 'B',
710+
label: 'B',
711+
store_label: 'B',
712+
use_default_value: true,
713+
value_index: 11,
714+
swatch_data: null,
715+
media_gallery_entries: []
716+
}
717+
]
718+
},
719+
{
720+
attribute_code: 'size',
721+
attribute_id: '190',
722+
id: 2,
723+
label: 'Size',
724+
values: [
725+
{
726+
__typename: 'ConfigurableProductOptionsValues',
727+
uid: 's1',
728+
default_label: 'S',
729+
label: 'S',
730+
store_label: 'S',
731+
use_default_value: true,
732+
value_index: 100,
733+
swatch_data: null,
734+
media_gallery_entries: []
735+
},
736+
{
737+
__typename: 'ConfigurableProductOptionsValues',
738+
uid: 's2',
739+
default_label: 'M',
740+
label: 'M',
741+
store_label: 'M',
742+
use_default_value: true,
743+
value_index: 101,
744+
swatch_data: null,
745+
media_gallery_entries: []
746+
}
747+
]
748+
}
749+
],
750+
variants: [
751+
{
752+
__typename: 'ConfigurableVariant',
753+
attributes: [
754+
{
755+
code: 'color',
756+
value_index: 10,
757+
__typename: 'ConfigurableAttributeOption'
758+
},
759+
{
760+
code: 'size',
761+
value_index: 100,
762+
__typename: 'ConfigurableAttributeOption'
763+
}
764+
],
765+
product: {
766+
__typename: 'SimpleProduct',
767+
sku: 'child-1',
768+
media_gallery_entries: [],
769+
price_range: {
770+
maximum_price: {
771+
final_price: {
772+
value: 10,
773+
currency: 'USD'
774+
},
775+
discount: {
776+
amount_off: 0
777+
}
778+
}
779+
},
780+
custom_attributes: []
781+
}
782+
}
783+
]
784+
}
785+
};
786+
670787
describe('shouldShowConfigurableProductOutOfStockButton', () => {
671788
test('is false if product is in stock and no option is selected but disabled', () => {
672789
const tree = createTestInstance(
@@ -739,6 +856,34 @@ describe('shouldShowConfigurableProductOutOfStockButton', () => {
739856
expect(talonProps.isOutOfStock).toBeTruthy();
740857
expect(talonProps.isAddToCartDisabled).toBeTruthy();
741858
});
859+
860+
test('is false when sparse catalog omits child stock_status but selection is salable', () => {
861+
const tree = createTestInstance(
862+
<Component
863+
{...configurableSparseVariantMissingChildStockStatusProps}
864+
/>
865+
);
866+
867+
const { root } = tree;
868+
869+
act(() => {
870+
root.findByType('i').props.talonProps.handleSelectionChange(
871+
'179',
872+
10
873+
);
874+
});
875+
act(() => {
876+
root.findByType('i').props.talonProps.handleSelectionChange(
877+
'190',
878+
100
879+
);
880+
});
881+
882+
const { talonProps } = root.findByType('i').props;
883+
884+
expect(talonProps.isOutOfStock).toBeFalsy();
885+
expect(talonProps.isAddToCartDisabled).toBeFalsy();
886+
});
742887
});
743888

744889
describe('shouldShowWishlistButton', () => {
@@ -1040,13 +1185,13 @@ test('calls generic mutation when no deprecated operation props are passed', asy
10401185
Object {
10411186
"variables": Object {
10421187
"cartId": "ThisIsMyCart",
1043-
"entered_options": Array [
1044-
Object {
1045-
"uid": "NDA=",
1046-
"value": "Strive Shoulder Pac",
1047-
},
1048-
],
10491188
"product": Object {
1189+
"entered_options": Array [
1190+
Object {
1191+
"uid": "NDA=",
1192+
"value": "Strive Shoulder Pac",
1193+
},
1194+
],
10501195
"quantity": 2,
10511196
"sku": "MySimpleProductSku",
10521197
},
@@ -1055,6 +1200,65 @@ test('calls generic mutation when no deprecated operation props are passed', asy
10551200
`);
10561201
});
10571202

1203+
test('sends selected_options inside product for configurable add to cart (no entered_options)', async () => {
1204+
const mockAddProductToCart = jest.fn().mockResolvedValue({});
1205+
let useMutationCall = 0;
1206+
// useProductFullDetail registers four useMutation hooks per render (configurable,
1207+
// simple, addProductToCart, createEmptyCart). Slot 2 is addProductsToCart.
1208+
useMutation.mockImplementation(() => {
1209+
const slot = useMutationCall % 4;
1210+
useMutationCall += 1;
1211+
if (slot === 2) {
1212+
return [mockAddProductToCart, { error: null, loading: false }];
1213+
}
1214+
return [jest.fn(), { error: null, loading: false }];
1215+
});
1216+
1217+
try {
1218+
const tree = createTestInstance(
1219+
<Component
1220+
product={configurableProductWithTwoOptionGroupProps.product}
1221+
/>
1222+
);
1223+
const { root } = tree;
1224+
1225+
act(() => {
1226+
root.findByType('i').props.talonProps.handleSelectionChange(
1227+
'179',
1228+
14
1229+
);
1230+
});
1231+
act(() => {
1232+
root.findByType('i').props.talonProps.handleSelectionChange(
1233+
'190',
1234+
45
1235+
);
1236+
});
1237+
1238+
await act(async () => {
1239+
await root.findByType('i').props.talonProps.handleAddToCart({
1240+
quantity: 1
1241+
});
1242+
});
1243+
1244+
expect(mockAddProductToCart).toHaveBeenCalledTimes(1);
1245+
const { variables } = mockAddProductToCart.mock.calls[0][0];
1246+
expect(variables.product).toMatchObject({
1247+
sku: configurableProductWithTwoOptionGroupProps.product.sku,
1248+
quantity: 1,
1249+
selected_options: ['20', '80']
1250+
});
1251+
expect(variables.product.entered_options).toBeUndefined();
1252+
} finally {
1253+
useMutation.mockImplementation(() => [
1254+
jest.fn(),
1255+
{
1256+
error: null
1257+
}
1258+
]);
1259+
}
1260+
});
1261+
10581262
test('it returns text when render prop is executed', () => {
10591263
const tree = createTestInstance(<Component {...defaultProps} />);
10601264
const { root } = tree;

0 commit comments

Comments
 (0)