Merged in feature/MAW-855-import-code-into-aws (pull request #2)
code import from pantheon * code import from pantheon
This commit is contained in:
@@ -5,3 +5,7 @@ export { default as withProduct } from './with-product';
|
||||
export { default as withProductVariations } from './with-product-variations';
|
||||
export { default as withSearchedProducts } from './with-searched-products';
|
||||
export { default as withTransformSingleSelectToMultipleSelect } from './with-transform-single-select-to-multiple-select';
|
||||
export {
|
||||
SelectedOption,
|
||||
WithMaybeSelectedOption,
|
||||
} from './with-transform-single-select-to-multiple-select';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// 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 */
|
||||
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
@@ -28,9 +29,9 @@ const mockCategories = [
|
||||
const TestComponent = withCategories( ( props ) => {
|
||||
return (
|
||||
<div
|
||||
error={ props.error }
|
||||
isLoading={ props.isLoading }
|
||||
categories={ props.categories }
|
||||
data-error={ props.error }
|
||||
data-isLoading={ props.isLoading }
|
||||
data-categories={ props.categories }
|
||||
/>
|
||||
);
|
||||
} );
|
||||
@@ -69,9 +70,9 @@ describe( 'withCategories Component', () => {
|
||||
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 );
|
||||
expect( props[ 'data-error' ] ).toBeNull();
|
||||
expect( props[ 'data-isLoading' ] ).toBe( false );
|
||||
expect( props[ 'data-categories' ] ).toEqual( mockCategories );
|
||||
} );
|
||||
} );
|
||||
|
||||
@@ -98,9 +99,9 @@ describe( 'withCategories Component', () => {
|
||||
|
||||
expect( formatError ).toHaveBeenCalledWith( error );
|
||||
expect( formatError ).toHaveBeenCalledTimes( 1 );
|
||||
expect( props.error ).toEqual( formattedError );
|
||||
expect( props.isLoading ).toBe( false );
|
||||
expect( props.categories ).toEqual( [] );
|
||||
expect( props[ 'data-error' ] ).toEqual( formattedError );
|
||||
expect( props[ 'data-isLoading' ] ).toBe( false );
|
||||
expect( props[ 'data-categories' ] ).toEqual( [] );
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
@@ -26,10 +26,10 @@ const attributes = { categoryId: 1 };
|
||||
const TestComponent = withCategory( ( props ) => {
|
||||
return (
|
||||
<div
|
||||
error={ props.error }
|
||||
getCategory={ props.getCategory }
|
||||
isLoading={ props.isLoading }
|
||||
category={ props.category }
|
||||
data-error={ props.error }
|
||||
data-getCategory={ props.getCategory }
|
||||
data-isLoading={ props.isLoading }
|
||||
data-category={ props.category }
|
||||
/>
|
||||
);
|
||||
} );
|
||||
@@ -72,7 +72,7 @@ describe( 'withCategory Component', () => {
|
||||
const { getCategory } = mockUtils;
|
||||
const props = renderer.root.findByType( 'div' ).props;
|
||||
|
||||
props.getCategory();
|
||||
props[ 'data-getCategory' ]();
|
||||
|
||||
expect( getCategory ).toHaveBeenCalledTimes( 2 );
|
||||
} );
|
||||
@@ -89,10 +89,10 @@ describe( 'withCategory Component', () => {
|
||||
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( {
|
||||
expect( props[ 'data-error' ] ).toBeNull();
|
||||
expect( typeof props[ 'data-getCategory' ] ).toBe( 'function' );
|
||||
expect( props[ 'data-isLoading' ] ).toBe( false );
|
||||
expect( props[ 'data-category' ] ).toEqual( {
|
||||
...mockCategory,
|
||||
id: attributes.categoryId,
|
||||
} );
|
||||
@@ -122,10 +122,10 @@ describe( 'withCategory Component', () => {
|
||||
|
||||
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();
|
||||
expect( props[ 'data-error' ] ).toEqual( formattedError );
|
||||
expect( typeof props[ 'data-getCategory' ] ).toBe( 'function' );
|
||||
expect( props[ 'data-isLoading' ] ).toBe( false );
|
||||
expect( props[ 'data-category' ] ).toBeNull();
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
@@ -32,11 +32,11 @@ const mockVariations = [
|
||||
const TestComponent = withProductVariations( ( props ) => {
|
||||
return (
|
||||
<div
|
||||
error={ props.error }
|
||||
expandedProduct={ props.expandedProduct }
|
||||
isLoading={ props.isLoading }
|
||||
variations={ props.variations }
|
||||
variationsLoading={ props.variationsLoading }
|
||||
data-error={ props.error }
|
||||
data-expandedProduct={ props.expandedProduct }
|
||||
data-isLoading={ props.isLoading }
|
||||
data-variations={ props.variations }
|
||||
data-variationsLoading={ props.variationsLoading }
|
||||
/>
|
||||
);
|
||||
} );
|
||||
@@ -148,9 +148,9 @@ describe( 'withProductVariations Component', () => {
|
||||
],
|
||||
};
|
||||
|
||||
expect( props.error ).toBeNull();
|
||||
expect( props.isLoading ).toBe( false );
|
||||
expect( props.variations ).toEqual( expectedVariations );
|
||||
expect( props[ 'data-error' ] ).toBeNull();
|
||||
expect( props[ 'data-isLoading' ] ).toBe( false );
|
||||
expect( props[ 'data-variations' ] ).toEqual( expectedVariations );
|
||||
} );
|
||||
} );
|
||||
|
||||
@@ -177,9 +177,9 @@ describe( 'withProductVariations Component', () => {
|
||||
|
||||
expect( formatError ).toHaveBeenCalledWith( error );
|
||||
expect( formatError ).toHaveBeenCalledTimes( 1 );
|
||||
expect( props.error ).toEqual( formattedError );
|
||||
expect( props.isLoading ).toBe( false );
|
||||
expect( props.variations ).toEqual( { 1: null } );
|
||||
expect( props[ 'data-error' ] ).toEqual( formattedError );
|
||||
expect( props[ 'data-isLoading' ] ).toBe( false );
|
||||
expect( props[ 'data-variations' ] ).toEqual( { 1: null } );
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
@@ -26,10 +26,10 @@ const attributes = { productId: 1 };
|
||||
const TestComponent = withProduct( ( props ) => {
|
||||
return (
|
||||
<div
|
||||
error={ props.error }
|
||||
getProduct={ props.getProduct }
|
||||
isLoading={ props.isLoading }
|
||||
product={ props.product }
|
||||
data-error={ props.error }
|
||||
data-getProduct={ props.getProduct }
|
||||
data-isLoading={ props.isLoading }
|
||||
data-product={ props.product }
|
||||
/>
|
||||
);
|
||||
} );
|
||||
@@ -72,7 +72,7 @@ describe( 'withProduct Component', () => {
|
||||
const { getProduct } = mockUtils;
|
||||
const props = renderer.root.findByType( 'div' ).props;
|
||||
|
||||
props.getProduct();
|
||||
props[ 'data-getProduct' ]();
|
||||
|
||||
expect( getProduct ).toHaveBeenCalledTimes( 2 );
|
||||
} );
|
||||
@@ -89,10 +89,10 @@ describe( 'withProduct Component', () => {
|
||||
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( {
|
||||
expect( props[ 'data-error' ] ).toBeNull();
|
||||
expect( typeof props[ 'data-getProduct' ] ).toBe( 'function' );
|
||||
expect( props[ 'data-isLoading' ] ).toBe( false );
|
||||
expect( props[ 'data-product' ] ).toEqual( {
|
||||
...mockProduct,
|
||||
id: attributes.productId,
|
||||
} );
|
||||
@@ -120,10 +120,10 @@ describe( 'withProduct Component', () => {
|
||||
|
||||
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();
|
||||
expect( props[ 'data-error' ] ).toEqual( formattedError );
|
||||
expect( typeof props[ 'data-getProduct' ] ).toBe( 'function' );
|
||||
expect( props[ 'data-isLoading' ] ).toBe( false );
|
||||
expect( props[ 'data-product' ] ).toBeNull();
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
@@ -6,13 +6,24 @@
|
||||
*/
|
||||
import TestRenderer, { act } from 'react-test-renderer';
|
||||
import * as mockUtils from '@woocommerce/editor-components/utils';
|
||||
import * as mockUseDebounce from 'use-debounce';
|
||||
import { useDebouncedCallback } from 'use-debounce';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import withSearchedProducts from '../with-searched-products';
|
||||
|
||||
// Add a mock implementation of debounce for testing so we can spy on the onSearch call.
|
||||
jest.mock( 'use-debounce', () => {
|
||||
return {
|
||||
useDebouncedCallback: jest
|
||||
.fn()
|
||||
.mockImplementation(
|
||||
( search ) => () => mockUtils.getProducts( search )
|
||||
),
|
||||
};
|
||||
} );
|
||||
|
||||
jest.mock( '@woocommerce/block-settings', () => ( {
|
||||
__esModule: true,
|
||||
blocksConfig: {
|
||||
@@ -28,25 +39,20 @@ mockUtils.getProducts = jest.fn().mockImplementation( () =>
|
||||
] )
|
||||
);
|
||||
|
||||
// Add a mock implementation of debounce for testing so we can spy on the onSearch call.
|
||||
mockUseDebounce.useDebouncedCallback = jest
|
||||
.fn()
|
||||
.mockImplementation( ( search ) => () => mockUtils.getProducts( search ) );
|
||||
|
||||
describe( 'withSearchedProducts Component', () => {
|
||||
const { getProducts } = mockUtils;
|
||||
afterEach( () => {
|
||||
mockUseDebounce.useDebouncedCallback.mockClear();
|
||||
useDebouncedCallback.mockClear();
|
||||
mockUtils.getProducts.mockClear();
|
||||
} );
|
||||
const TestComponent = withSearchedProducts(
|
||||
( { selected, products, isLoading, onSearch } ) => {
|
||||
return (
|
||||
<div
|
||||
products={ products }
|
||||
selected={ selected }
|
||||
isLoading={ isLoading }
|
||||
onSearch={ onSearch }
|
||||
data-products={ products }
|
||||
data-selected={ selected }
|
||||
data-isLoading={ isLoading }
|
||||
data-onSearch={ onSearch }
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -63,8 +69,8 @@ describe( 'withSearchedProducts Component', () => {
|
||||
|
||||
it( 'has expected values for props', () => {
|
||||
props = renderer.root.findByType( 'div' ).props;
|
||||
expect( props.selected ).toEqual( selected );
|
||||
expect( props.products ).toEqual( [
|
||||
expect( props[ 'data-selected' ] ).toEqual( selected );
|
||||
expect( props[ 'data-products' ] ).toEqual( [
|
||||
{ id: 10, name: 'foo', parent: 0 },
|
||||
{ id: 20, name: 'bar', parent: 0 },
|
||||
] );
|
||||
@@ -74,10 +80,10 @@ describe( 'withSearchedProducts Component', () => {
|
||||
props = renderer.root.findByType( 'div' ).props;
|
||||
|
||||
act( () => {
|
||||
props.onSearch();
|
||||
props[ 'data-onSearch' ]();
|
||||
} );
|
||||
|
||||
expect( mockUseDebounce.useDebouncedCallback ).toHaveBeenCalled();
|
||||
expect( useDebouncedCallback ).toHaveBeenCalled();
|
||||
expect( getProducts ).toHaveBeenCalledTimes( 1 );
|
||||
} );
|
||||
} );
|
||||
@@ -7,7 +7,7 @@ import { getAttributes, getTerms } from '@woocommerce/editor-components/utils';
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { formatError } from '../base/utils/errors.js';
|
||||
import { formatError } from '../base/utils/errors';
|
||||
|
||||
/**
|
||||
* Get attribute data (name, taxonomy etc) from server data.
|
||||
|
||||
@@ -8,7 +8,7 @@ import { getCategories } from '@woocommerce/editor-components/utils';
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { formatError } from '../base/utils/errors.js';
|
||||
import { formatError } from '../base/utils/errors';
|
||||
|
||||
/**
|
||||
* HOC that queries categories for a component.
|
||||
|
||||
@@ -8,7 +8,7 @@ import { getCategory } from '@woocommerce/editor-components/utils';
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { formatError } from '../base/utils/errors.js';
|
||||
import { formatError } from '../base/utils/errors';
|
||||
|
||||
/**
|
||||
* HOC that queries a category for a component.
|
||||
|
||||
@@ -10,7 +10,7 @@ import { getProductVariations } from '@woocommerce/editor-components/utils';
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { formatError } from '../base/utils/errors.js';
|
||||
import { formatError } from '../base/utils/errors';
|
||||
|
||||
/**
|
||||
* HOC that queries variations for a component.
|
||||
|
||||
@@ -8,7 +8,7 @@ import { getProduct } from '@woocommerce/editor-components/utils';
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { formatError } from '../base/utils/errors.js';
|
||||
import { formatError } from '../base/utils/errors';
|
||||
|
||||
/**
|
||||
* HOC that queries a product for a component.
|
||||
|
||||
@@ -5,20 +5,29 @@ import { useEffect, useState, useCallback, useRef } from '@wordpress/element';
|
||||
import { blocksConfig } from '@woocommerce/block-settings';
|
||||
import { getProducts } from '@woocommerce/editor-components/utils';
|
||||
import { useDebouncedCallback } from 'use-debounce';
|
||||
import type { ProductResponseItem } from '@woocommerce/types';
|
||||
import type {
|
||||
ProductResponseItem,
|
||||
WithInjectedSearchedProducts,
|
||||
} from '@woocommerce/types';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { formatError } from '../base/utils/errors.js';
|
||||
import { formatError } from '../base/utils/errors';
|
||||
|
||||
interface WithSearchedProductProps {
|
||||
selected: number[];
|
||||
}
|
||||
|
||||
/**
|
||||
* A higher order component that enhances the provided component with products from a search query.
|
||||
*/
|
||||
const withSearchedProducts = (
|
||||
OriginalComponent: React.FunctionComponent< Record< string, unknown > >
|
||||
const withSearchedProducts = <
|
||||
T extends Record< string, unknown > & WithSearchedProductProps
|
||||
>(
|
||||
OriginalComponent: React.ComponentType< T & WithInjectedSearchedProducts >
|
||||
) => {
|
||||
return ( { selected, ...props }: { selected: number[] } ): JSX.Element => {
|
||||
return ( { selected, ...props }: T ): JSX.Element => {
|
||||
const [ isLoading, setIsLoading ] = useState( true );
|
||||
const [ error, setError ] = useState< {
|
||||
message: string;
|
||||
@@ -71,7 +80,7 @@ const withSearchedProducts = (
|
||||
|
||||
return (
|
||||
<OriginalComponent
|
||||
{ ...props }
|
||||
{ ...( props as T ) }
|
||||
selected={ selected }
|
||||
error={ error }
|
||||
products={ productsList }
|
||||
|
||||
@@ -6,21 +6,21 @@
|
||||
// eslint-disable-next-line
|
||||
import { FunctionComponent } from '@wordpress/element';
|
||||
|
||||
type SelectedOption = number | string | null | number[] | string[];
|
||||
export type SelectedOption = number | string | null | number[] | string[];
|
||||
|
||||
interface OriginalComponentProps {
|
||||
export interface WithMaybeSelectedOption {
|
||||
selected?: SelectedOption;
|
||||
}
|
||||
|
||||
/**
|
||||
* HOC that transforms a single select to a multiple select.
|
||||
*
|
||||
* @param {FunctionComponent< Record< string, unknown > >} OriginalComponent Component being wrapped.
|
||||
*/
|
||||
const withTransformSingleSelectToMultipleSelect = (
|
||||
OriginalComponent: FunctionComponent< Record< string, unknown > >
|
||||
const withTransformSingleSelectToMultipleSelect = <
|
||||
T extends Record< string, unknown >
|
||||
>(
|
||||
OriginalComponent: FunctionComponent< T & WithMaybeSelectedOption >
|
||||
) => {
|
||||
return ( props: OriginalComponentProps ): JSX.Element => {
|
||||
return ( props: T & WithMaybeSelectedOption ): JSX.Element => {
|
||||
let { selected } = props;
|
||||
selected = selected === undefined ? null : selected;
|
||||
const isNil = selected === null;
|
||||
|
||||
Reference in New Issue
Block a user