This commit is contained in:
KhaiNguyen
2020-02-13 10:39:37 +07:00
commit 59401cb805
12867 changed files with 4646216 additions and 0 deletions

View File

@@ -0,0 +1,157 @@
/**
* External dependencies
*/
import TestRenderer from 'react-test-renderer';
/**
* Internal dependencies
*/
import withAttributes from '../with-attributes';
import * as mockUtils from '../../components/utils';
import * as mockBaseUtils from '../../base/utils/errors';
jest.mock( '../../components/utils', () => ( {
getAttributes: jest.fn(),
getTerms: jest.fn(),
} ) );
jest.mock( '../../base/utils/errors', () => ( {
formatError: jest.fn(),
} ) );
jest.mock( 'lodash', () => ( {
...jest.requireActual( 'lodash' ),
debounce: ( func ) => func,
} ) );
const mockAttributes = [
{ id: 1, name: 'Color', slug: 'color' },
{ id: 2, name: 'Size', slug: 'size' },
];
const mockAttributesWithParent = [
{ id: 1, name: 'Color', slug: 'color', parent: 0 },
{ id: 2, name: 'Size', slug: 'size', parent: 0 },
];
const selected = [ { id: 11, attr_slug: 'color' } ];
const TestComponent = withAttributes( ( props ) => {
return (
<div
attributes={ props.attributes }
error={ props.error }
expandedAttribute={ props.expandedAttribute }
onExpandAttribute={ props.onExpandAttribute }
isLoading={ props.isLoading }
termsAreLoading={ props.termsAreLoading }
termsList={ props.termsList }
/>
);
} );
describe( 'withAttributes Component', () => {
afterEach( () => {
mockUtils.getAttributes.mockReset();
mockUtils.getTerms.mockReset();
mockBaseUtils.formatError.mockReset();
} );
describe( 'lifecycle events', () => {
let getAttributesPromise;
beforeEach( () => {
getAttributesPromise = Promise.resolve( mockAttributes );
mockUtils.getAttributes.mockImplementation(
() => getAttributesPromise
);
mockUtils.getTerms.mockImplementation( () =>
Promise.resolve( [] )
);
} );
it( 'getAttributes is called on mount', () => {
TestRenderer.create( <TestComponent /> );
const { getAttributes } = mockUtils;
expect( getAttributes ).toHaveBeenCalledTimes( 1 );
} );
it( 'getTerms is called on component update', () => {
const renderer = TestRenderer.create( <TestComponent /> );
let props = renderer.root.findByType( 'div' ).props;
props.onExpandAttribute( 1 );
const { getTerms } = mockUtils;
props = renderer.root.findByType( 'div' ).props;
expect( getTerms ).toHaveBeenCalledWith( 1 );
expect( getTerms ).toHaveBeenCalledTimes( 1 );
expect( props.expandedAttribute ).toBe( 1 );
} );
it( 'getTerms is called on mount if there was an attribute selected', ( done ) => {
const renderer = TestRenderer.create(
<TestComponent selected={ selected } />
);
getAttributesPromise.then( () => {
const { getTerms } = mockUtils;
const props = renderer.root.findByType( 'div' ).props;
expect( getTerms ).toHaveBeenCalledWith( 1 );
expect( getTerms ).toHaveBeenCalledTimes( 1 );
expect( props.expandedAttribute ).toBe( 1 );
done();
} );
} );
} );
describe( 'when the API returns attributes data', () => {
let renderer;
beforeEach( () => {
mockUtils.getAttributes.mockImplementation( () =>
Promise.resolve( mockAttributes )
);
renderer = TestRenderer.create( <TestComponent /> );
} );
it( 'sets the attributes props', () => {
const props = renderer.root.findByType( 'div' ).props;
expect( props.error ).toBeNull();
expect( props.isLoading ).toBe( false );
expect( props.attributes ).toEqual( mockAttributesWithParent );
} );
} );
describe( 'when the API returns an error', () => {
const error = { message: 'There was an error.' };
const getAttributesPromise = Promise.reject( error );
const formattedError = { message: 'There was an error.', type: 'api' };
let renderer;
beforeEach( () => {
mockUtils.getAttributes.mockImplementation(
() => getAttributesPromise
);
mockBaseUtils.formatError.mockImplementation(
() => formattedError
);
renderer = TestRenderer.create( <TestComponent /> );
} );
it( 'sets the error prop', ( done ) => {
const { formatError } = mockBaseUtils;
getAttributesPromise.catch( () => {
const props = renderer.root.findByType( 'div' ).props;
expect( formatError ).toHaveBeenCalledWith( error );
expect( formatError ).toHaveBeenCalledTimes( 1 );
expect( props.error ).toEqual( formattedError );
expect( props.isLoading ).toBe( false );
expect( props.attributes ).toEqual( [] );
done();
} );
} );
} );
} );

View File

@@ -0,0 +1,106 @@
/**
* External dependencies
*/
import TestRenderer from 'react-test-renderer';
/**
* Internal dependencies
*/
import withCategories from '../with-categories';
import * as mockUtils from '../../components/utils';
import * as mockBaseUtils from '../../base/utils/errors';
jest.mock( '../../components/utils', () => ( {
getCategories: jest.fn(),
} ) );
jest.mock( '../../base/utils/errors', () => ( {
formatError: jest.fn(),
} ) );
const mockCategories = [ { id: 1, name: 'Clothing' }, { id: 2, name: 'Food' } ];
const TestComponent = withCategories( ( props ) => {
return (
<div
error={ props.error }
isLoading={ props.isLoading }
categories={ props.categories }
/>
);
} );
const render = () => {
return TestRenderer.create( <TestComponent /> );
};
describe( 'withCategories Component', () => {
let renderer;
afterEach( () => {
mockUtils.getCategories.mockReset();
} );
describe( 'lifecycle events', () => {
beforeEach( () => {
mockUtils.getCategories.mockImplementation( () =>
Promise.resolve()
);
renderer = render();
} );
it( 'getCategories is called on mount', () => {
const { getCategories } = mockUtils;
expect( getCategories ).toHaveBeenCalledWith( {
show_review_count: false,
} );
expect( getCategories ).toHaveBeenCalledTimes( 1 );
} );
} );
describe( 'when the API returns categories data', () => {
beforeEach( () => {
mockUtils.getCategories.mockImplementation( () =>
Promise.resolve( mockCategories )
);
renderer = render();
} );
it( 'sets the categories props', () => {
const props = renderer.root.findByType( 'div' ).props;
expect( props.error ).toBeNull();
expect( props.isLoading ).toBe( false );
expect( props.categories ).toEqual( mockCategories );
} );
} );
describe( 'when the API returns an error', () => {
const error = { message: 'There was an error.' };
const getCategoriesPromise = Promise.reject( error );
const formattedError = { message: 'There was an error.', type: 'api' };
beforeEach( () => {
mockUtils.getCategories.mockImplementation(
() => getCategoriesPromise
);
mockBaseUtils.formatError.mockImplementation(
() => formattedError
);
renderer = render();
} );
it( 'sets the error prop', ( done ) => {
const { formatError } = mockBaseUtils;
getCategoriesPromise.catch( () => {
const props = renderer.root.findByType( 'div' ).props;
expect( formatError ).toHaveBeenCalledWith( error );
expect( formatError ).toHaveBeenCalledTimes( 1 );
expect( props.error ).toEqual( formattedError );
expect( props.isLoading ).toBe( false );
expect( props.categories ).toBeNull();
done();
} );
} );
} );
} );

View File

@@ -0,0 +1,130 @@
/**
* External dependencies
*/
import TestRenderer from 'react-test-renderer';
/**
* Internal dependencies
*/
import withCategory from '../with-category';
import * as mockUtils from '../../components/utils';
import * as mockBaseUtils from '../../base/utils/errors';
jest.mock( '../../components/utils', () => ( {
getCategory: jest.fn(),
} ) );
jest.mock( '../../base/utils/errors', () => ( {
formatError: jest.fn(),
} ) );
const mockCategory = { name: 'Clothing' };
const attributes = { categoryId: 1 };
const TestComponent = withCategory( ( props ) => {
return (
<div
error={ props.error }
getCategory={ props.getCategory }
isLoading={ props.isLoading }
category={ props.category }
/>
);
} );
const render = () => {
return TestRenderer.create( <TestComponent attributes={ attributes } /> );
};
describe( 'withCategory Component', () => {
let renderer;
afterEach( () => {
mockUtils.getCategory.mockReset();
} );
describe( 'lifecycle events', () => {
beforeEach( () => {
mockUtils.getCategory.mockImplementation( () => Promise.resolve() );
renderer = render();
} );
it( 'getCategory is called on mount with passed in category id', () => {
const { getCategory } = mockUtils;
expect( getCategory ).toHaveBeenCalledWith( attributes.categoryId );
expect( getCategory ).toHaveBeenCalledTimes( 1 );
} );
it( 'getCategory is called on component update', () => {
const { getCategory } = mockUtils;
const newAttributes = { ...attributes, categoryId: 2 };
renderer.update( <TestComponent attributes={ newAttributes } /> );
expect( getCategory ).toHaveBeenNthCalledWith(
2,
newAttributes.categoryId
);
expect( getCategory ).toHaveBeenCalledTimes( 2 );
} );
it( 'getCategory is hooked to the prop', () => {
const { getCategory } = mockUtils;
const props = renderer.root.findByType( 'div' ).props;
props.getCategory();
expect( getCategory ).toHaveBeenCalledTimes( 2 );
} );
} );
describe( 'when the API returns category data', () => {
beforeEach( () => {
mockUtils.getCategory.mockImplementation( ( categoryId ) =>
Promise.resolve( { ...mockCategory, id: categoryId } )
);
renderer = render();
} );
it( 'sets the category props', () => {
const props = renderer.root.findByType( 'div' ).props;
expect( props.error ).toBeNull();
expect( typeof props.getCategory ).toBe( 'function' );
expect( props.isLoading ).toBe( false );
expect( props.category ).toEqual( {
...mockCategory,
id: attributes.categoryId,
} );
} );
} );
describe( 'when the API returns an error', () => {
const error = { message: 'There was an error.' };
const getCategoryPromise = Promise.reject( error );
const formattedError = { message: 'There was an error.', type: 'api' };
beforeEach( () => {
mockUtils.getCategory.mockImplementation(
() => getCategoryPromise
);
mockBaseUtils.formatError.mockImplementation(
() => formattedError
);
renderer = render();
} );
it( 'sets the error prop', ( done ) => {
const { formatError } = mockBaseUtils;
getCategoryPromise.catch( () => {
const props = renderer.root.findByType( 'div' ).props;
expect( formatError ).toHaveBeenCalledWith( error );
expect( formatError ).toHaveBeenCalledTimes( 1 );
expect( props.error ).toEqual( formattedError );
expect( typeof props.getCategory ).toBe( 'function' );
expect( props.isLoading ).toBe( false );
expect( props.category ).toBeNull();
done();
} );
} );
} );
} );

View File

@@ -0,0 +1,181 @@
/**
* External dependencies
*/
import TestRenderer from 'react-test-renderer';
/**
* Internal dependencies
*/
import withProductVariations from '../with-product-variations';
import * as mockUtils from '../../components/utils';
import * as mockBaseUtils from '../../base/utils/errors';
jest.mock( '../../components/utils', () => ( {
getProductVariations: jest.fn(),
} ) );
jest.mock( '../../base/utils/errors', () => ( {
formatError: jest.fn(),
} ) );
const mockProducts = [
{ id: 1, name: 'Hoodie', variations: [ 3, 4 ] },
{ id: 2, name: 'Backpack' },
];
const mockVariations = [ { id: 3, name: 'Blue' }, { id: 4, name: 'Red' } ];
const TestComponent = withProductVariations( ( props ) => {
return (
<div
error={ props.error }
expandedProduct={ props.expandedProduct }
isLoading={ props.isLoading }
variations={ props.variations }
variationsLoading={ props.variationsLoading }
/>
);
} );
const render = () => {
return TestRenderer.create(
<TestComponent
error={ null }
isLoading={ false }
products={ mockProducts }
selected={ [ 1 ] }
showVariations={ true }
/>
);
};
describe( 'withProductVariations Component', () => {
let renderer;
afterEach( () => {
mockUtils.getProductVariations.mockReset();
} );
describe( 'lifecycle events', () => {
beforeEach( () => {
mockUtils.getProductVariations.mockImplementation( () =>
Promise.resolve( mockVariations )
);
} );
it( 'getProductVariations is called on mount', () => {
renderer = render();
const { getProductVariations } = mockUtils;
expect( getProductVariations ).toHaveBeenCalledWith( 1 );
expect( getProductVariations ).toHaveBeenCalledTimes( 1 );
} );
it( 'getProductVariations is called on component update', () => {
renderer = TestRenderer.create(
<TestComponent
error={ null }
isLoading={ false }
products={ mockProducts }
/>
);
const { getProductVariations } = mockUtils;
expect( getProductVariations ).toHaveBeenCalledTimes( 0 );
renderer.update(
<TestComponent
error={ null }
isLoading={ false }
products={ mockProducts }
selected={ [ 1 ] }
showVariations={ true }
/>
);
expect( getProductVariations ).toHaveBeenCalledWith( 1 );
expect( getProductVariations ).toHaveBeenCalledTimes( 1 );
} );
it( 'getProductVariations is not called if selected product has no variations', () => {
TestRenderer.create(
<TestComponent
error={ null }
isLoading={ false }
products={ mockProducts }
selected={ [ 2 ] }
showVariations={ true }
/>
);
const { getProductVariations } = mockUtils;
expect( getProductVariations ).toHaveBeenCalledTimes( 0 );
} );
it( 'getProductVariations is called if selected product is a variation', () => {
TestRenderer.create(
<TestComponent
error={ null }
isLoading={ false }
products={ mockProducts }
selected={ [ 3 ] }
showVariations={ true }
/>
);
const { getProductVariations } = mockUtils;
expect( getProductVariations ).toHaveBeenCalledWith( 1 );
expect( getProductVariations ).toHaveBeenCalledTimes( 1 );
} );
} );
describe( 'when the API returns variations data', () => {
beforeEach( () => {
mockUtils.getProductVariations.mockImplementation( () =>
Promise.resolve( mockVariations )
);
renderer = render();
} );
it( 'sets the variations props', () => {
const props = renderer.root.findByType( 'div' ).props;
const expectedVariations = {
1: [
{ id: 3, name: 'Blue', parent: 1 },
{ id: 4, name: 'Red', parent: 1 },
],
};
expect( props.error ).toBeNull();
expect( props.isLoading ).toBe( false );
expect( props.variations ).toEqual( expectedVariations );
} );
} );
describe( 'when the API returns an error', () => {
const error = { message: 'There was an error.' };
const getProductVariationsPromise = Promise.reject( error );
const formattedError = { message: 'There was an error.', type: 'api' };
beforeEach( () => {
mockUtils.getProductVariations.mockImplementation(
() => getProductVariationsPromise
);
mockBaseUtils.formatError.mockImplementation(
() => formattedError
);
renderer = render();
} );
it( 'sets the error prop', ( done ) => {
const { formatError } = mockBaseUtils;
getProductVariationsPromise.catch( () => {
const props = renderer.root.findByType( 'div' ).props;
expect( formatError ).toHaveBeenCalledWith( error );
expect( formatError ).toHaveBeenCalledTimes( 1 );
expect( props.error ).toEqual( formattedError );
expect( props.isLoading ).toBe( false );
expect( props.variations ).toEqual( { 1: null } );
done();
} );
} );
} );
} );

View File

@@ -0,0 +1,128 @@
/**
* External dependencies
*/
import TestRenderer from 'react-test-renderer';
/**
* Internal dependencies
*/
import withProduct from '../with-product';
import * as mockUtils from '../../components/utils';
import * as mockBaseUtils from '../../base/utils/errors';
jest.mock( '../../components/utils', () => ( {
getProduct: jest.fn(),
} ) );
jest.mock( '../../base/utils/errors', () => ( {
formatError: jest.fn(),
} ) );
const mockProduct = { name: 'T-Shirt' };
const attributes = { productId: 1 };
const TestComponent = withProduct( ( props ) => {
return (
<div
error={ props.error }
getProduct={ props.getProduct }
isLoading={ props.isLoading }
product={ props.product }
/>
);
} );
const render = () => {
return TestRenderer.create( <TestComponent attributes={ attributes } /> );
};
describe( 'withProduct Component', () => {
let renderer;
afterEach( () => {
mockUtils.getProduct.mockReset();
} );
describe( 'lifecycle events', () => {
beforeEach( () => {
mockUtils.getProduct.mockImplementation( () => Promise.resolve() );
renderer = render();
} );
it( 'getProduct is called on mount with passed in product id', () => {
const { getProduct } = mockUtils;
expect( getProduct ).toHaveBeenCalledWith( attributes.productId );
expect( getProduct ).toHaveBeenCalledTimes( 1 );
} );
it( 'getProduct is called on component update', () => {
const { getProduct } = mockUtils;
const newAttributes = { ...attributes, productId: 2 };
renderer.update( <TestComponent attributes={ newAttributes } /> );
expect( getProduct ).toHaveBeenNthCalledWith(
2,
newAttributes.productId
);
expect( getProduct ).toHaveBeenCalledTimes( 2 );
} );
it( 'getProduct is hooked to the prop', () => {
const { getProduct } = mockUtils;
const props = renderer.root.findByType( 'div' ).props;
props.getProduct();
expect( getProduct ).toHaveBeenCalledTimes( 2 );
} );
} );
describe( 'when the API returns product data', () => {
beforeEach( () => {
mockUtils.getProduct.mockImplementation( ( productId ) =>
Promise.resolve( { ...mockProduct, id: productId } )
);
renderer = render();
} );
it( 'sets the product props', () => {
const props = renderer.root.findByType( 'div' ).props;
expect( props.error ).toBeNull();
expect( typeof props.getProduct ).toBe( 'function' );
expect( props.isLoading ).toBe( false );
expect( props.product ).toEqual( {
...mockProduct,
id: attributes.productId,
} );
} );
} );
describe( 'when the API returns an error', () => {
const error = { message: 'There was an error.' };
const getProductPromise = Promise.reject( error );
const formattedError = { message: 'There was an error.', type: 'api' };
beforeEach( () => {
mockUtils.getProduct.mockImplementation( () => getProductPromise );
mockBaseUtils.formatError.mockImplementation(
() => formattedError
);
renderer = render();
} );
it( 'sets the error prop', ( done ) => {
const { formatError } = mockBaseUtils;
getProductPromise.catch( () => {
const props = renderer.root.findByType( 'div' ).props;
expect( formatError ).toHaveBeenCalledWith( error );
expect( formatError ).toHaveBeenCalledTimes( 1 );
expect( props.error ).toEqual( formattedError );
expect( typeof props.getProduct ).toBe( 'function' );
expect( props.isLoading ).toBe( false );
expect( props.product ).toBeNull();
done();
} );
} );
} );
} );

View File

@@ -0,0 +1,92 @@
/**
* External dependencies
*/
import TestRenderer from 'react-test-renderer';
import _ from 'lodash';
/**
* Internal dependencies
*/
import withSearchedProducts from '../with-searched-products';
import * as mockedUtils from '../../components/utils';
jest.mock( '@woocommerce/block-settings', () => ( {
IS_LARGE_CATALOG: true,
} ) );
// Mock the getProducts and isLargeCatalog values for tests.
mockedUtils.getProducts = jest
.fn()
.mockImplementation( () =>
Promise.resolve( [
{ id: 10, name: 'foo', parent: 0 },
{ id: 20, name: 'bar', parent: 0 },
] )
);
// Add a mock implementation of debounce for testing so we can spy on
// the onSearch call.
const debouncedCancel = jest.fn();
const debouncedAction = jest.fn();
_.debounce = ( onSearch ) => {
const debounced = debouncedAction.mockImplementation( () => {
onSearch();
} );
debounced.cancel = debouncedCancel;
return debounced;
};
describe( 'withSearchedProducts Component', () => {
const { getProducts } = mockedUtils;
afterEach( () => {
debouncedCancel.mockClear();
debouncedAction.mockClear();
mockedUtils.getProducts.mockClear();
} );
const TestComponent = withSearchedProducts(
( { selected, products, isLoading, onSearch } ) => {
return (
<div
products={ products }
selected={ selected }
isLoading={ isLoading }
onSearch={ onSearch }
/>
);
}
);
describe( 'lifecycle tests', () => {
const selected = [ 10 ];
const renderer = TestRenderer.create(
<TestComponent selected={ selected } />
);
let props;
it(
'getProducts is called on mount with passed in selected ' +
'values',
() => {
expect( getProducts ).toHaveBeenCalledWith( { selected } );
expect( getProducts ).toHaveBeenCalledTimes( 1 );
}
);
it( 'has expected values for props', () => {
props = renderer.root.findByType( 'div' ).props;
expect( props.selected ).toEqual( selected );
expect( props.products ).toEqual( [
{ id: 10, name: 'foo', parent: 0 },
{ id: 20, name: 'bar', parent: 0 },
] );
} );
it( 'debounce and getProducts is called on search event', () => {
props = renderer.root.findByType( 'div' ).props;
props.onSearch();
expect( debouncedAction ).toHaveBeenCalled();
expect( getProducts ).toHaveBeenCalledTimes( 1 );
} );
it( 'debounce is cancelled on unmount', () => {
renderer.unmount();
expect( debouncedCancel ).toHaveBeenCalled();
expect( getProducts ).toHaveBeenCalledTimes( 0 );
} );
} );
} );

View File

@@ -0,0 +1,34 @@
/**
* External dependencies
*/
import TestRenderer from 'react-test-renderer';
/**
* Internal dependencies
*/
import withTransformSingleSelectToMultipleSelect from '../with-transform-single-select-to-multiple-select';
const TestComponent = withTransformSingleSelectToMultipleSelect( ( props ) => {
return <div selected={ props.selected } />;
} );
describe( 'withTransformSingleSelectToMultipleSelect Component', () => {
describe( 'when the API returns an error', () => {
it( 'converts the selected value into an array', () => {
const selected = 123;
const renderer = TestRenderer.create(
<TestComponent selected={ selected } />
);
const props = renderer.root.findByType( 'div' ).props;
expect( props.selected ).toEqual( [ selected ] );
} );
it( 'passes an empty array as the selected prop if selected was null', () => {
const renderer = TestRenderer.create(
<TestComponent selected={ null } />
);
const props = renderer.root.findByType( 'div' ).props;
expect( props.selected ).toEqual( [] );
} );
} );
} );