Add confirmation dialog before loading the sample products
This commit is contained in:
parent
86553fbe1f
commit
e2cc91dd60
|
@ -12,17 +12,16 @@ import './load-sample-product-confirm-modal.scss';
|
|||
|
||||
type Props = {
|
||||
onCancel: () => void;
|
||||
onOK: () => void;
|
||||
onImport: () => void;
|
||||
};
|
||||
|
||||
export const LoadSampleProductConfirmModal: React.VFC< Props > = ( {
|
||||
onCancel,
|
||||
onOK,
|
||||
onImport,
|
||||
} ) => {
|
||||
return (
|
||||
<Modal
|
||||
className="woocommerce-products-load-sample-product-confirm-modal"
|
||||
overlayClassName="woocommerce-products-load-sample-product-confirm-modal-overlay"
|
||||
title="Load sample products"
|
||||
onRequestClose={ onCancel }
|
||||
>
|
||||
|
@ -35,7 +34,7 @@ export const LoadSampleProductConfirmModal: React.VFC< Props > = ( {
|
|||
<Button isSecondary onClick={ onCancel }>
|
||||
{ __( 'Cancel' ) }
|
||||
</Button>
|
||||
<Button isPrimary onClick={ onOK }>
|
||||
<Button isPrimary onClick={ onImport }>
|
||||
{ __( 'Import sample products' ) }
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
@ -21,11 +21,16 @@ import useProductTypeListItems from '../experimental-products/use-product-types-
|
|||
import { getProductTypes } from '../experimental-products/utils';
|
||||
import LoadSampleProductModal from '../components/load-sample-product-modal';
|
||||
import useLoadSampleProducts from '../components/use-load-sample-products';
|
||||
import LoadSampleProductConfirmModal from '../components/load-sample-product-confirm-modal';
|
||||
import useRecordCompletionTime from '../use-record-completion-time';
|
||||
|
||||
export const Products = () => {
|
||||
const [ showStacks, setStackVisibility ] = useState< boolean >( false );
|
||||
const { recordCompletionTime } = useRecordCompletionTime( 'products' );
|
||||
const [
|
||||
isConfirmingLoadSampleProducts,
|
||||
setIsConfirmingLoadSampleProducts,
|
||||
] = useState( false );
|
||||
|
||||
const importTypesWithTimeRecord = useMemo(
|
||||
() =>
|
||||
|
@ -61,7 +66,9 @@ export const Products = () => {
|
|||
const StacksComponent = (
|
||||
<Stacks
|
||||
items={ productTypeListItems }
|
||||
onClickLoadSampleProduct={ loadSampleProduct }
|
||||
onClickLoadSampleProduct={ () =>
|
||||
setIsConfirmingLoadSampleProducts( true )
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -83,7 +90,21 @@ export const Products = () => {
|
|||
</Button>
|
||||
{ showStacks && StacksComponent }
|
||||
</div>
|
||||
{ isLoadingSampleProducts && <LoadSampleProductModal /> }
|
||||
{ isLoadingSampleProducts ? (
|
||||
<LoadSampleProductModal />
|
||||
) : (
|
||||
isConfirmingLoadSampleProducts && (
|
||||
<LoadSampleProductConfirmModal
|
||||
onCancel={ () =>
|
||||
setIsConfirmingLoadSampleProducts( false )
|
||||
}
|
||||
onImport={ () => {
|
||||
setIsConfirmingLoadSampleProducts( false );
|
||||
loadSampleProduct();
|
||||
} }
|
||||
/>
|
||||
)
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -11,6 +11,16 @@ import { Products } from '../';
|
|||
|
||||
jest.mock( '@woocommerce/tracks', () => ( { recordEvent: jest.fn() } ) );
|
||||
|
||||
global.fetch = jest.fn().mockImplementation( () =>
|
||||
Promise.resolve( {
|
||||
json: () => Promise.resolve( {} ),
|
||||
status: 200,
|
||||
} )
|
||||
);
|
||||
|
||||
const confirmModalText =
|
||||
"We'll import images from woocommerce.com to set up your sample products.";
|
||||
|
||||
describe( 'Products', () => {
|
||||
beforeEach( () => {
|
||||
( recordEvent as jest.Mock ).mockClear();
|
||||
|
@ -103,4 +113,57 @@ describe( 'Products', () => {
|
|||
);
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'should send a request to load sample products when the "Import sample products" button is clicked', async () => {
|
||||
const fetchMock = jest.spyOn( global, 'fetch' );
|
||||
const { queryByText, getByRole } = render( <Products /> );
|
||||
|
||||
userEvent.click(
|
||||
getByRole( 'button', { name: 'Or add your products from scratch' } )
|
||||
);
|
||||
expect( queryByText( 'Load Sample Products' ) ).toBeInTheDocument();
|
||||
|
||||
userEvent.click(
|
||||
getByRole( 'link', { name: 'Load Sample Products' } )
|
||||
);
|
||||
await waitFor( () =>
|
||||
expect( queryByText( confirmModalText ) ).toBeInTheDocument()
|
||||
);
|
||||
|
||||
userEvent.click(
|
||||
getByRole( 'button', { name: 'Import sample products' } )
|
||||
);
|
||||
await waitFor( () =>
|
||||
expect( queryByText( confirmModalText ) ).not.toBeInTheDocument()
|
||||
);
|
||||
|
||||
expect( fetchMock ).toHaveBeenCalledWith(
|
||||
'/wc-admin/onboarding/tasks/import_sample_products?_locale=user',
|
||||
{
|
||||
body: undefined,
|
||||
credentials: 'include',
|
||||
headers: { Accept: 'application/json, */*;q=0.1' },
|
||||
method: 'POST',
|
||||
}
|
||||
);
|
||||
} );
|
||||
|
||||
it( 'should close the confirmation modal when the cancel button is clicked', async () => {
|
||||
const { queryByText, getByRole } = render( <Products /> );
|
||||
|
||||
userEvent.click(
|
||||
getByRole( 'button', { name: 'Or add your products from scratch' } )
|
||||
);
|
||||
expect( queryByText( 'Load Sample Products' ) ).toBeInTheDocument();
|
||||
|
||||
userEvent.click(
|
||||
getByRole( 'link', { name: 'Load Sample Products' } )
|
||||
);
|
||||
await waitFor( () =>
|
||||
expect( queryByText( confirmModalText ) ).toBeInTheDocument()
|
||||
);
|
||||
|
||||
userEvent.click( getByRole( 'button', { name: 'Cancel' } ) );
|
||||
expect( queryByText( confirmModalText ) ).not.toBeInTheDocument();
|
||||
} );
|
||||
} );
|
||||
|
|
|
@ -25,6 +25,7 @@ import CardLayout from './card-layout';
|
|||
import { LoadSampleProductType } from './constants';
|
||||
import LoadSampleProductModal from '../components/load-sample-product-modal';
|
||||
import useLoadSampleProducts from '../components/use-load-sample-products';
|
||||
import LoadSampleProductConfirmModal from '../components/load-sample-product-confirm-modal';
|
||||
import useRecordCompletionTime from '../use-record-completion-time';
|
||||
import { getCountryCode } from '~/dashboard/utils';
|
||||
import { useProductTaskExperiment } from './use-product-layout-experiment';
|
||||
|
@ -54,6 +55,10 @@ const ViewControlButton: React.FC< {
|
|||
|
||||
export const Products = () => {
|
||||
const [ isExpanded, setIsExpanded ] = useState< boolean >( false );
|
||||
const [
|
||||
isConfirmingLoadSampleProducts,
|
||||
setIsConfirmingLoadSampleProducts,
|
||||
] = useState( false );
|
||||
const {
|
||||
isLoading: isLoadingExperiment,
|
||||
experimentLayout,
|
||||
|
@ -125,7 +130,7 @@ export const Products = () => {
|
|||
if ( experimentLayout === 'card' ) {
|
||||
surfacedProductTypes.push( {
|
||||
...LoadSampleProductType,
|
||||
onClick: loadSampleProduct,
|
||||
onClick: () => setIsConfirmingLoadSampleProducts( true ),
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +140,6 @@ export const Products = () => {
|
|||
isExpanded,
|
||||
productTypesWithTimeRecord,
|
||||
experimentLayout,
|
||||
loadSampleProduct,
|
||||
] );
|
||||
|
||||
return (
|
||||
|
@ -159,7 +163,9 @@ export const Products = () => {
|
|||
{ experimentLayout === 'stacked' ? (
|
||||
<Stack
|
||||
items={ visibleProductTypes }
|
||||
onClickLoadSampleProduct={ loadSampleProduct }
|
||||
onClickLoadSampleProduct={ () =>
|
||||
setIsConfirmingLoadSampleProducts( true )
|
||||
}
|
||||
showOtherOptions={ isExpanded }
|
||||
/>
|
||||
) : (
|
||||
|
@ -178,7 +184,21 @@ export const Products = () => {
|
|||
/>
|
||||
<Footer />
|
||||
</div>
|
||||
{ isLoadingSampleProducts && <LoadSampleProductModal /> }
|
||||
{ isLoadingSampleProducts ? (
|
||||
<LoadSampleProductModal />
|
||||
) : (
|
||||
isConfirmingLoadSampleProducts && (
|
||||
<LoadSampleProductConfirmModal
|
||||
onCancel={ () =>
|
||||
setIsConfirmingLoadSampleProducts( false )
|
||||
}
|
||||
onImport={ () => {
|
||||
setIsConfirmingLoadSampleProducts( false );
|
||||
loadSampleProduct();
|
||||
} }
|
||||
/>
|
||||
)
|
||||
) }
|
||||
</>
|
||||
) }
|
||||
</div>
|
||||
|
|
|
@ -45,6 +45,9 @@ global.fetch = jest.fn().mockImplementation( () =>
|
|||
|
||||
jest.mock( '@woocommerce/tracks', () => ( { recordEvent: jest.fn() } ) );
|
||||
|
||||
const confirmModalText =
|
||||
"We'll import images from woocommerce.com to set up your sample products.";
|
||||
|
||||
describe( 'Products', () => {
|
||||
beforeEach( () => {
|
||||
jest.clearAllMocks();
|
||||
|
@ -238,21 +241,29 @@ describe( 'Products', () => {
|
|||
expect( queryByText( 'View less product types' ) ).toBeInTheDocument();
|
||||
} );
|
||||
|
||||
it( 'should send a request to load sample products when the link is clicked', async () => {
|
||||
it( 'should send a request to load sample products when the "Import sample products" button is clicked', async () => {
|
||||
const fetchMock = jest.spyOn( global, 'fetch' );
|
||||
const { queryByText, getByRole } = render( <Products /> );
|
||||
|
||||
userEvent.click(
|
||||
getByRole( 'button', { name: 'View more product types' } )
|
||||
);
|
||||
|
||||
expect( queryByText( 'Load Sample Products' ) ).toBeInTheDocument();
|
||||
|
||||
userEvent.click(
|
||||
getByRole( 'link', { name: 'Load Sample Products' } )
|
||||
);
|
||||
|
||||
await waitFor( () =>
|
||||
expect( queryByText( confirmModalText ) ).toBeInTheDocument()
|
||||
);
|
||||
|
||||
userEvent.click(
|
||||
getByRole( 'button', { name: 'Import sample products' } )
|
||||
);
|
||||
await waitFor( () =>
|
||||
expect( queryByText( confirmModalText ) ).not.toBeInTheDocument()
|
||||
);
|
||||
|
||||
expect( fetchMock ).toHaveBeenCalledWith(
|
||||
'/wc-admin/onboarding/tasks/import_sample_products?_locale=user',
|
||||
{
|
||||
|
@ -261,10 +272,28 @@ describe( 'Products', () => {
|
|||
headers: { Accept: 'application/json, */*;q=0.1' },
|
||||
method: 'POST',
|
||||
}
|
||||
)
|
||||
);
|
||||
} );
|
||||
|
||||
it( 'should close the confirmation modal when the cancel button is clicked', async () => {
|
||||
const { queryByText, getByRole } = render( <Products /> );
|
||||
|
||||
userEvent.click(
|
||||
getByRole( 'button', { name: 'View more product types' } )
|
||||
);
|
||||
expect( queryByText( 'Load Sample Products' ) ).toBeInTheDocument();
|
||||
|
||||
userEvent.click(
|
||||
getByRole( 'link', { name: 'Load Sample Products' } )
|
||||
);
|
||||
await waitFor( () =>
|
||||
expect( queryByText( confirmModalText ) ).toBeInTheDocument()
|
||||
);
|
||||
|
||||
userEvent.click( getByRole( 'button', { name: 'Cancel' } ) );
|
||||
expect( queryByText( confirmModalText ) ).not.toBeInTheDocument();
|
||||
} );
|
||||
|
||||
it( 'should show spinner when layout experiment is loading', async () => {
|
||||
( useProductTaskExperiment as jest.Mock ).mockImplementation( () => {
|
||||
return {
|
||||
|
|
Loading…
Reference in New Issue