2022-04-08 13:47:19 +00:00
|
|
|
// We need to disable the following eslint check as it's only applicable
|
|
|
|
// to testing-library/react not `react-test-renderer` used here
|
|
|
|
/* eslint-disable testing-library/await-async-query */
|
2019-08-02 11:56:53 +00:00
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
|
|
|
import TestRenderer from 'react-test-renderer';
|
2020-09-02 08:21:46 +00:00
|
|
|
import * as mockUtils from '@woocommerce/editor-components/utils';
|
2019-08-02 11:56:53 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal dependencies
|
|
|
|
*/
|
|
|
|
import withProduct from '../with-product';
|
2019-09-04 16:07:00 +00:00
|
|
|
import * as mockBaseUtils from '../../base/utils/errors';
|
2019-08-02 11:56:53 +00:00
|
|
|
|
2020-09-02 08:21:46 +00:00
|
|
|
jest.mock( '@woocommerce/editor-components/utils', () => ( {
|
2019-08-02 11:56:53 +00:00
|
|
|
getProduct: jest.fn(),
|
|
|
|
} ) );
|
|
|
|
|
2019-09-04 16:07:00 +00:00
|
|
|
jest.mock( '../../base/utils/errors', () => ( {
|
|
|
|
formatError: jest.fn(),
|
|
|
|
} ) );
|
|
|
|
|
2019-08-02 11:56:53 +00:00
|
|
|
const mockProduct = { name: 'T-Shirt' };
|
|
|
|
const attributes = { productId: 1 };
|
|
|
|
const TestComponent = withProduct( ( props ) => {
|
2019-09-05 15:09:31 +00:00
|
|
|
return (
|
|
|
|
<div
|
2023-09-07 10:01:15 +00:00
|
|
|
data-error={ props.error }
|
|
|
|
data-getProduct={ props.getProduct }
|
|
|
|
data-isLoading={ props.isLoading }
|
|
|
|
data-product={ props.product }
|
2019-08-02 11:56:53 +00:00
|
|
|
/>
|
|
|
|
);
|
2019-09-05 15:09:31 +00:00
|
|
|
} );
|
|
|
|
const render = () => {
|
|
|
|
return TestRenderer.create( <TestComponent attributes={ attributes } /> );
|
2019-08-02 11:56:53 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
describe( 'withProduct Component', () => {
|
|
|
|
let renderer;
|
|
|
|
afterEach( () => {
|
|
|
|
mockUtils.getProduct.mockReset();
|
|
|
|
} );
|
|
|
|
|
|
|
|
describe( 'lifecycle events', () => {
|
|
|
|
beforeEach( () => {
|
|
|
|
mockUtils.getProduct.mockImplementation( () => Promise.resolve() );
|
|
|
|
renderer = render();
|
|
|
|
} );
|
|
|
|
|
2019-09-04 16:07:00 +00:00
|
|
|
it( 'getProduct is called on mount with passed in product id', () => {
|
|
|
|
const { getProduct } = mockUtils;
|
2019-08-02 11:56:53 +00:00
|
|
|
|
2019-09-04 16:07:00 +00:00
|
|
|
expect( getProduct ).toHaveBeenCalledWith( attributes.productId );
|
|
|
|
expect( getProduct ).toHaveBeenCalledTimes( 1 );
|
2019-08-02 11:56:53 +00:00
|
|
|
} );
|
|
|
|
|
2019-09-04 16:07:00 +00:00
|
|
|
it( 'getProduct is called on component update', () => {
|
|
|
|
const { getProduct } = mockUtils;
|
|
|
|
const newAttributes = { ...attributes, productId: 2 };
|
2019-09-05 15:09:31 +00:00
|
|
|
renderer.update( <TestComponent attributes={ newAttributes } /> );
|
2019-08-02 11:56:53 +00:00
|
|
|
|
2019-09-05 15:09:31 +00:00
|
|
|
expect( getProduct ).toHaveBeenNthCalledWith(
|
|
|
|
2,
|
|
|
|
newAttributes.productId
|
|
|
|
);
|
2019-09-04 16:07:00 +00:00
|
|
|
expect( getProduct ).toHaveBeenCalledTimes( 2 );
|
|
|
|
} );
|
2019-08-02 11:56:53 +00:00
|
|
|
|
2019-09-04 16:07:00 +00:00
|
|
|
it( 'getProduct is hooked to the prop', () => {
|
|
|
|
const { getProduct } = mockUtils;
|
|
|
|
const props = renderer.root.findByType( 'div' ).props;
|
|
|
|
|
2023-09-07 10:01:15 +00:00
|
|
|
props[ 'data-getProduct' ]();
|
2019-09-04 16:07:00 +00:00
|
|
|
|
|
|
|
expect( getProduct ).toHaveBeenCalledTimes( 2 );
|
2019-08-02 11:56:53 +00:00
|
|
|
} );
|
|
|
|
} );
|
|
|
|
|
|
|
|
describe( 'when the API returns product data', () => {
|
|
|
|
beforeEach( () => {
|
2019-09-05 15:09:31 +00:00
|
|
|
mockUtils.getProduct.mockImplementation( ( productId ) =>
|
|
|
|
Promise.resolve( { ...mockProduct, id: productId } )
|
2019-08-02 11:56:53 +00:00
|
|
|
);
|
|
|
|
renderer = render();
|
|
|
|
} );
|
|
|
|
|
|
|
|
it( 'sets the product props', () => {
|
|
|
|
const props = renderer.root.findByType( 'div' ).props;
|
|
|
|
|
2023-09-07 10:01:15 +00:00
|
|
|
expect( props[ 'data-error' ] ).toBeNull();
|
|
|
|
expect( typeof props[ 'data-getProduct' ] ).toBe( 'function' );
|
|
|
|
expect( props[ 'data-isLoading' ] ).toBe( false );
|
|
|
|
expect( props[ 'data-product' ] ).toEqual( {
|
2019-09-05 15:09:31 +00:00
|
|
|
...mockProduct,
|
|
|
|
id: attributes.productId,
|
|
|
|
} );
|
2019-08-02 11:56:53 +00:00
|
|
|
} );
|
|
|
|
} );
|
|
|
|
|
|
|
|
describe( 'when the API returns an error', () => {
|
2019-09-04 16:07:00 +00:00
|
|
|
const error = { message: 'There was an error.' };
|
|
|
|
const getProductPromise = Promise.reject( error );
|
|
|
|
const formattedError = { message: 'There was an error.', type: 'api' };
|
|
|
|
|
2019-08-02 11:56:53 +00:00
|
|
|
beforeEach( () => {
|
2019-09-05 15:09:31 +00:00
|
|
|
mockUtils.getProduct.mockImplementation( () => getProductPromise );
|
2019-09-09 10:52:48 +00:00
|
|
|
mockBaseUtils.formatError.mockImplementation(
|
|
|
|
() => formattedError
|
|
|
|
);
|
2019-08-02 11:56:53 +00:00
|
|
|
renderer = render();
|
|
|
|
} );
|
|
|
|
|
2019-12-10 17:17:46 +00:00
|
|
|
test( 'sets the error prop', async () => {
|
|
|
|
await expect( () => getProductPromise() ).toThrow();
|
2019-08-02 11:56:53 +00:00
|
|
|
|
2019-12-10 17:17:46 +00:00
|
|
|
const { formatError } = mockBaseUtils;
|
|
|
|
const props = renderer.root.findByType( 'div' ).props;
|
2019-09-04 16:07:00 +00:00
|
|
|
|
2019-12-10 17:17:46 +00:00
|
|
|
expect( formatError ).toHaveBeenCalledWith( error );
|
|
|
|
expect( formatError ).toHaveBeenCalledTimes( 1 );
|
2023-09-07 10:01:15 +00:00
|
|
|
expect( props[ 'data-error' ] ).toEqual( formattedError );
|
|
|
|
expect( typeof props[ 'data-getProduct' ] ).toBe( 'function' );
|
|
|
|
expect( props[ 'data-isLoading' ] ).toBe( false );
|
|
|
|
expect( props[ 'data-product' ] ).toBeNull();
|
2019-08-02 11:56:53 +00:00
|
|
|
} );
|
|
|
|
} );
|
|
|
|
} );
|