diff --git a/packages/peregrine/lib/talons/CartPage/__tests__/useCartPage.spec.js b/packages/peregrine/lib/talons/CartPage/__tests__/useCartPage.spec.js index bc04700152..52dd175881 100644 --- a/packages/peregrine/lib/talons/CartPage/__tests__/useCartPage.spec.js +++ b/packages/peregrine/lib/talons/CartPage/__tests__/useCartPage.spec.js @@ -1,18 +1,28 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import { createTestInstance } from '@magento/peregrine'; +import { useQuery } from '@apollo/react-hooks'; import { useCartPage } from '../useCartPage'; +jest.mock('react', () => { + const React = jest.requireActual('react'); + const spy = jest.spyOn(React, 'useState'); + + return { + ...React, + useState: spy + }; +}); + jest.mock('@apollo/react-hooks', () => { - const runQuery = jest.fn(); const queryResult = { + called: false, data: null, - error: null, loading: false }; - const useLazyQuery = jest.fn(() => [runQuery, queryResult]); + const useQuery = jest.fn(() => queryResult); - return { useLazyQuery }; + return { useQuery }; }); jest.mock('@magento/peregrine/lib/context/app', () => { @@ -67,6 +77,43 @@ test('it returns the proper shape', () => { handleSignIn: expect.any(Function), isCartUpdating: expect.any(Boolean), isSignedIn: expect.any(Boolean), - setIsCartUpdating: expect.any(Function) + setIsCartUpdating: expect.any(Function), + shouldShowLoadingIndicator: expect.any(Boolean) }); }); + +test('it calls setIsCartUpdating true when loading is true', () => { + // Arrange. + useQuery.mockReturnValueOnce({ + called: true, + data: { cart: { total_quantity: 0 } }, + loading: true + }); + // isCartUpdating + useState.mockReturnValueOnce([false, jest.fn()]); + + // Act. + createTestInstance(); + + // Assert. + const { setIsCartUpdating } = log.mock.calls[0][0]; + expect(setIsCartUpdating).toBeCalledWith(true); +}); + +test('it calls setIsCartUpdating false when loading is false', () => { + // Arrange. + useQuery.mockReturnValueOnce({ + called: true, + data: { cart: { total_quantity: 0 } }, + loading: false + }); + // isCartUpdating + useState.mockReturnValueOnce([false, jest.fn()]); + + // Act. + createTestInstance(); + + // Assert. + const { setIsCartUpdating } = log.mock.calls[0][0]; + expect(setIsCartUpdating).toBeCalledWith(false); +}); diff --git a/packages/peregrine/lib/talons/CartPage/useCartPage.js b/packages/peregrine/lib/talons/CartPage/useCartPage.js index e026777cca..2ce2d33f9f 100644 --- a/packages/peregrine/lib/talons/CartPage/useCartPage.js +++ b/packages/peregrine/lib/talons/CartPage/useCartPage.js @@ -1,5 +1,5 @@ import { useCallback, useEffect, useState } from 'react'; -import { useLazyQuery } from '@apollo/react-hooks'; +import { useQuery } from '@apollo/react-hooks'; import { useAppContext } from '@magento/peregrine/lib/context/app'; import { useUserContext } from '@magento/peregrine/lib/context/user'; @@ -16,10 +16,11 @@ export const useCartPage = props => { const [isCartUpdating, setIsCartUpdating] = useState(false); - const [fetchCartData, { data }] = useLazyQuery(getCartDetails, { - // TODO: Purposely overfetch and hit the network until all components - // are correctly updating the cache. Will be fixed by PWA-321. - fetchPolicy: 'cache-and-network' + const { called, data, loading } = useQuery(getCartDetails, { + fetchPolicy: 'cache-and-network', + // Don't make this call if we don't have a cartId + skip: !cartId, + variables: { cartId } }); const handleSignIn = useCallback(() => { @@ -28,20 +29,19 @@ export const useCartPage = props => { }, [toggleDrawer]); useEffect(() => { - if (cartId) { - fetchCartData({ - variables: { - cartId - } - }); - } - }, [cartId, fetchCartData]); + // Let the cart page know it is updating while we're waiting on network data. + setIsCartUpdating(loading); + }, [loading]); + + const hasItems = !!(data && data.cart.total_quantity); + const shouldShowLoadingIndicator = called && loading && !hasItems; return { - hasItems: !!(data && data.cart.total_quantity), + hasItems, handleSignIn, isSignedIn, isCartUpdating, - setIsCartUpdating + setIsCartUpdating, + shouldShowLoadingIndicator }; }; diff --git a/packages/venia-ui/lib/components/CartPage/__tests__/__snapshots__/cartPage.spec.js.snap b/packages/venia-ui/lib/components/CartPage/__tests__/__snapshots__/cartPage.spec.js.snap index 8d20aa53a3..983c165bb7 100644 --- a/packages/venia-ui/lib/components/CartPage/__tests__/__snapshots__/cartPage.spec.js.snap +++ b/packages/venia-ui/lib/components/CartPage/__tests__/__snapshots__/cartPage.spec.js.snap @@ -1,5 +1,75 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`renders a loading indicator when talon indicates 1`] = ` +
+ + + + + + + + + + + + + + Fetching Data... + +
+`; + exports[`renders components if cart has items 1`] = `
@@ -7,7 +77,7 @@ exports[`renders components if cart has items 1`] = ` Cart - ) : null; - }, [classes.sign_in, handleSignIn, isSignedIn]); + if (shouldShowLoadingIndicator) { + return fullPageLoadingIndicator; + } + + const signInDisplay = !isSignedIn ? ( + + ) : null; const productListing = hasItems ? (