Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PWA-1101] Add support for Configurable Product Image Setting #2909

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a3571bd
PWA-1101: Add support for Configurable Product Image Setting
eug123 Nov 18, 2020
9dd3440
Merge remote-tracking branch 'mainline/develop' into PWA-1101
eug123 Dec 7, 2020
e3473b3
Merge remote-tracking branch 'mainline/develop' into PWA-1101
eug123 Dec 8, 2020
62c5f31
Merge remote-tracking branch 'mainline/develop' into PWA-1101
eug123 Dec 9, 2020
9761eec
PWA-1101: Add support for Configurable Product Image Setting
eug123 Dec 10, 2020
c177fdf
PWA-1101: Add support for Configurable Product Image Setting
eug123 Dec 15, 2020
a13ee69
PWA-1101: Add support for Configurable Product Image Setting
eug123 Dec 16, 2020
9ed01f9
PWA-1101: Add support for Configurable Product Image Setting
eug123 Dec 17, 2020
df03d74
Merge remote-tracking branch 'mainline/develop' into PWA-1101-alt
eug123 Dec 17, 2020
3e4a315
PWA-1101: Add support for Configurable Product Image Setting
eug123 Dec 18, 2020
e5d0883
Merge remote-tracking branch 'mainline/develop' into PWA-1101-alt
eug123 Dec 18, 2020
2e47d29
PWA-1101: Add support for Configurable Product Image Setting
eug123 Dec 18, 2020
4832fec
PWA-1101: Add support for Configurable Product Image Setting
eug123 Dec 21, 2020
4f42be9
Merge remote-tracking branch 'mainline/develop' into PWA-1101-alt
eug123 Dec 21, 2020
fbde172
PWA-1101: Add support for Configurable Product Image Setting
eug123 Dec 22, 2020
c87f224
PWA-1101: Add support for Configurable Product Image Setting
eug123 Dec 23, 2020
54690fb
Merge remote-tracking branch 'mainline/develop' into PWA-1101-alt
eug123 Dec 23, 2020
684e775
PWA-1101: Add support for Configurable Product Image Setting
eug123 Jan 7, 2021
94ed636
Merge remote-tracking branch 'mainline/develop' into PWA-1101-alt
eug123 Jan 7, 2021
d86361c
PWA-1101: Add support for Configurable Product Image Setting
eug123 Jan 7, 2021
2fa663a
Merge branch 'develop' into PWA-1101-alt
dpatil-magento Jan 19, 2021
6da2ab0
Merge branch 'develop' into PWA-1101-alt
dpatil-magento Jan 19, 2021
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`it returns the proper shape 1`] = `
<i
talonProps={
Object {
"errorMessage": "",
"handleEditItem": [Function],
"handleRemoveFromCart": [Function],
"handleToggleFavorites": [Function],
"handleUpdateItemQuantity": [Function],
"isEditable": false,
"isFavorite": false,
"product": Object {
"currency": "USD",
"image": "test.webp",
"name": "unit test",
"options": Array [],
"quantity": 7,
"stockStatus": undefined,
"unitPrice": 99,
"urlKey": undefined,
"urlSuffix": undefined,
},
}
}
/>
`;

exports[`it returns the proper shape when use variant image is configured 1`] = `
<i
talonProps={
Object {
"errorMessage": "",
"handleEditItem": [Function],
"handleRemoveFromCart": [Function],
"handleToggleFavorites": [Function],
"handleUpdateItemQuantity": [Function],
"isEditable": true,
"isFavorite": false,
"product": Object {
"currency": "USD",
"image": "variant1.webp",
"name": "unit test",
"options": Array [
Object {
"id": 22,
"option_label": "Color",
"value_id": 2,
"value_label": "red",
},
],
"quantity": 7,
"stockStatus": undefined,
"unitPrice": 99,
"urlKey": undefined,
"urlSuffix": undefined,
},
}
}
/>
`;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';

import { createTestInstance } from '@magento/peregrine';
import { useMutation } from '@apollo/client';
import { useMutation, useQuery } from '@apollo/client';
import { useAppContext } from '@magento/peregrine/lib/context/app';

import { useProduct } from '../useProduct';
Expand Down Expand Up @@ -31,7 +31,18 @@ jest.mock('@apollo/client', () => {
]);

return {
ApolloClient,
...ApolloClient,
useQuery: jest.fn().mockReturnValue({
called: false,
error: null,
loading: false,
data: {
storeConfig: {
id: 1,
configurable_thumbnail_source: 'parent'
}
}
}),
useMutation: spy
};
});
Expand Down Expand Up @@ -97,20 +108,70 @@ test('it returns the proper shape', () => {
useMutation.mockReturnValueOnce([jest.fn(), {}]);
useMutation.mockReturnValueOnce([jest.fn(), {}]);

// Act.
createTestInstance(<Component {...props} />);
const tree = createTestInstance(<Component {...props} />);
expect(tree.toJSON()).toMatchSnapshot();
});

// Assert.
expect(log).toHaveBeenCalledWith({
errorMessage: '',
handleEditItem: expect.any(Function),
handleRemoveFromCart: expect.any(Function),
handleToggleFavorites: expect.any(Function),
handleUpdateItemQuantity: expect.any(Function),
isEditable: expect.any(Boolean),
isFavorite: expect.any(Boolean),
product: expect.any(Object)
test('it returns the proper shape when use variant image is configured', () => {
// Arrange.
useMutation.mockReturnValueOnce([jest.fn(), {}]);
useMutation.mockReturnValueOnce([jest.fn(), {}]);
useQuery.mockReturnValueOnce({
called: false,
error: null,
loading: false,
data: {
storeConfig: {
id: 1,
configurable_thumbnail_source: 'itself'
}
}
});
const configurableProps = {
item: {
...props.item,
product: {
...props.item.product,
variants: [
{
attributes: [
{
uid: 'Y29uZmlndXJhYmxlLzIyLzI='
}
],
product: {
small_image: {
url: 'variant1.webp'
}
}
},
{
attributes: [
{
uid: 'Y29uZmlndXJhYmxlLzIyLzM='
}
],
product: {
small_image: {
url: 'variant2.webp'
}
}
}
]
},
configurable_options: [
{
id: 22,
option_label: 'Color',
value_label: 'red',
value_id: 2
}
]
}
};

const tree = createTestInstance(<Component {...configurableProps} />);
expect(tree.toJSON()).toMatchSnapshot();
});

test('it returns the correct error message when the error is not graphql', async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { gql } from '@apollo/client';

export const GET_CONFIGURABLE_THUMBNAIL_SOURCE = gql`
query getConfigurableThumbnailSource {
storeConfig {
id
configurable_thumbnail_source
}
}
`;

export default {
getConfigurableThumbnailSource: GET_CONFIGURABLE_THUMBNAIL_SOURCE
};
45 changes: 35 additions & 10 deletions packages/peregrine/lib/talons/CartPage/ProductListing/useProduct.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useMutation } from '@apollo/client';
import { useMutation, useQuery } from '@apollo/client';
import { useCartContext } from '@magento/peregrine/lib/context/cart';
import { deriveErrorMessage } from '../../../util/deriveErrorMessage';
import configuredVariant from '@magento/peregrine/lib/util/configuredVariant';
import mergeOperations from '../../../util/shallowMerge';
import DEFAULT_OPERATIONS from './product.gql';

/**
* This talon contains logic for a product component used in a product listing component.
Expand All @@ -15,7 +18,7 @@ import { deriveErrorMessage } from '../../../util/deriveErrorMessage';
*
* @param {Object} props
* @param {ProductItem} props.item Product item data
* @param {ProductMutations} props.mutations GraphQL mutations for a product in a cart
* @param {ProductMutations} props.operations GraphQL mutations for a product in a cart
* @param {function} props.setActiveEditItem Function for setting the actively editing item
* @param {function} props.setIsCartUpdating Function for setting the updating state of the cart
*
Expand All @@ -24,15 +27,32 @@ import { deriveErrorMessage } from '../../../util/deriveErrorMessage';
* @example <caption>Importing into your project</caption>
* import { useProduct } from '@magento/peregrine/lib/talons/CartPage/ProductListing/useProduct';
*/

export const useProduct = props => {
const { item, setActiveEditItem, setIsCartUpdating } = props;

const operations = mergeOperations(DEFAULT_OPERATIONS, props.operations);
const {
item,
mutations: { removeItemMutation, updateItemQuantityMutation },
setActiveEditItem,
setIsCartUpdating
} = props;
removeItemMutation,
updateItemQuantityMutation,
getConfigurableThumbnailSource
} = operations;

const flatProduct = flattenProduct(item);
const { data: configurableThumbnailSourceData } = useQuery(
getConfigurableThumbnailSource,
{
fetchPolicy: 'cache-and-network'
}
);

const configurableThumbnailSource = useMemo(() => {
if (configurableThumbnailSourceData) {
return configurableThumbnailSourceData.storeConfig
.configurable_thumbnail_source;
}
}, [configurableThumbnailSourceData]);

const flatProduct = flattenProduct(item, configurableThumbnailSource);

const [
removeItem,
Expand Down Expand Up @@ -141,14 +161,16 @@ export const useProduct = props => {
};
};

const flattenProduct = item => {
const flattenProduct = (item, configurableThumbnailSource) => {
const {
configurable_options: options = [],
prices,
product,
quantity
} = item;

const configured_variant = configuredVariant(options, product);

const { price } = prices;
const { value: unitPrice, currency } = price;

Expand All @@ -159,7 +181,10 @@ const flattenProduct = item => {
url_key: urlKey,
url_suffix: urlSuffix
} = product;
const { url: image } = small_image;
const { url: image } =
configurableThumbnailSource === 'itself' && configured_variant
? configured_variant.small_image
: small_image;

return {
currency,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

exports[`returns correct shape 1`] = `
Object {
"configurableThumbnailSource": "parent",
"hasErrors": false,
"isLoading": true,
"items": Array [],
Expand All @@ -13,6 +14,7 @@ Object {

exports[`uses static data if provided 1`] = `
Object {
"configurableThumbnailSource": "parent",
"hasErrors": false,
"isLoading": true,
"items": Array [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import React from 'react';
import { useLazyQuery } from '@apollo/client';
import { useLazyQuery, useQuery } from '@apollo/client';

import createTestInstance from '../../../../../lib/util/createTestInstance';
import { useItemsReview } from '../useItemsReview';

import cartItems from '../__fixtures__/cartItems';

jest.mock('@apollo/client', () => ({
useLazyQuery: jest.fn().mockReturnValue([
() => {},
{
data: null,
error: null,
loading: true
}
])
}));
jest.mock('@apollo/client', () => {
const apolloClient = jest.requireActual('@apollo/client');

return {
...apolloClient,
useQuery: jest.fn(),
useLazyQuery: jest.fn()
};
});

jest.mock('../../../../context/cart', () => {
const state = {
Expand All @@ -27,6 +26,25 @@ jest.mock('../../../../context/cart', () => {
return { useCartContext };
});

beforeAll(() => {
useLazyQuery.mockReturnValue([
() => {},
{
data: null,
error: null,
loading: true
}
]);
useQuery.mockReturnValue({
data: {
storeConfig: {
id: 1,
configurable_thumbnail_source: 'parent'
}
}
});
});

const Component = props => {
const talonProps = useItemsReview(props);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { gql } from '@apollo/client';

export const GET_CONFIGURABLE_THUMBNAIL_SOURCE = gql`
query getConfigurableThumbnailSource {
storeConfig {
id
configurable_thumbnail_source
}
}
`;

export default {
getConfigurableThumbnailSource: GET_CONFIGURABLE_THUMBNAIL_SOURCE
};
Loading