woocommerce/plugins/woocommerce-admin/client/wp-admin-scripts/print-shipping-label-banner/shipping-banner/test/index.js

530 lines
14 KiB
JavaScript
Raw Normal View History

/**
* External dependencies
*/
Allow packages to be built in isolation. (https://github.com/woocommerce/woocommerce-admin/pull/7286) * Use yarn instead of npm. In prep for workspaces, since we're locked to npm < 7. See: https://github.com/woocommerce/woocommerce-admin/pull/7126#issue-661287749 * Initial workspace creation. * Add initial tsc build to @woocommerce/number. * Attempt to build experimental package. * Try currency package. * Define all packages as workspaces. * Use tsconfig common to packages. * Fix currency package build. * Build csv-export with tsc. * Try to build customer-effort-score with tsc. * Fix JSX pragma. * Build data package with tsc. * Build date package with tsc. * Build experimental package with tsc. * Try to build explat package with tsc. * Build navigation package with tsc. * Build notices package with tsc. * Build onboarding package with tsc. * Build components package with tsc. * Swap in package JS build into main script. * Fix experimental package build. * Try per-package css build with components. * Try to run components package tests in isolation. Broken on JSX in test files not being transformed. * Move @woocommerce/wc-admin-settings into a package. * Try to fix components package tests. Fails because we aren't setting up the jest/jest-dom globals. * Move JS test code to reusable (private) package. * Enable incremental TS builds. * Use workspaces to run JS tests. * Use new jest configs for update snapshot scripts. * Fix style builds. * Fix package version in components. * Fix client test debug and watch scripts. * Update yarn lock. * Update test-staged behavior. * Try to fix storybook. * Fix storybook. * Update more npm commands to yarn. * Add changelog. * Fix lint errors. * Update packages readme script references. * Clean up unused gitignore match. * Fix another npm command. * Fix JS builds on watch. * Fix start script. * Fix start scripts for packages. * Use tsc to build packages before tests * yarn -> npm. # Conflicts: # package-lock.json # package.json * Fix linter error. * Remove workspace definitions. * Fix missing Fragment import. * Fix package lock. * Fix missing reference. * Only build commonjs module for js-tests helper. * Remove errant dependency from components. * Remove noop scripts. * Fix package JS build before testing. * Revert noisy formatting changes. * Fix precommit and test scripts. * Fix minimum expected recommended extension count. Japan test case breaks this. * Revert babel config changes. * chore(release): publish - @woocommerce/components@7.2.0 - @woocommerce/csv-export@1.4.0 - @woocommerce/currency@3.2.0 - @woocommerce/customer-effort-score@1.1.0 - @woocommerce/data@1.4.0 - @woocommerce/date@3.1.0 - @woocommerce/dependency-extraction-webpack-plugin@1.7.0 - @woocommerce/eslint-plugin@1.3.0 - @woocommerce/experimental@1.5.0 - @woocommerce/explat@1.1.0 - @woocommerce/js-tests@1.1.0 - @woocommerce/navigation@6.1.0 - @woocommerce/notices@3.1.0 - @woocommerce/number@2.2.0 - @woocommerce/onboarding@1.1.0 - @woocommerce/tracks@1.1.0 - @woocommerce/wc-admin-settings@1.1.0 * Add script for running 'start' in a package. * Remove yarn from gitignore. * Update package changelogs, prep versions for release. * Try to fix E2E tests after main merge. * Some cleanup. * Add changelog. Co-authored-by: Paul Sealock <psealock@gmail.com>
2021-07-14 20:38:57 +00:00
import { createElement, Fragment } from '@wordpress/element';
import { recordEvent } from '@woocommerce/tracks';
2020-10-15 12:41:39 +00:00
import { render, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
/**
* Internal dependencies
*/
import { acceptWcsTos, getWcsAssets } from '../../wcs-api.js';
2020-10-15 12:41:39 +00:00
import { ShippingBanner } from '../index.js';
jest.mock( '../../wcs-api.js' );
acceptWcsTos.mockReturnValue( Promise.resolve() );
jest.mock( '@woocommerce/tracks' );
2020-10-15 12:41:39 +00:00
const wcsPluginSlug = 'woocommerce-services';
describe( 'Tracking impression in shippingBanner', () => {
const expectedTrackingData = {
banner_name: 'wcadmin_install_wcs_prompt',
jetpack_connected: true,
jetpack_installed: true,
wcs_installed: true,
};
2020-10-15 12:41:39 +00:00
it( 'should record an event when user sees banner loaded', () => {
render(
<ShippingBanner
isJetpackConnected={ true }
activePlugins={ [ wcsPluginSlug, 'jetpack' ] }
itemsCount={ 1 }
activatePlugins={ jest.fn() }
installPlugins={ jest.fn() }
isRequesting={ false }
/>
);
expect( recordEvent ).toHaveBeenCalledTimes( 1 );
expect( recordEvent ).toHaveBeenCalledWith(
'banner_impression',
expectedTrackingData
);
} );
} );
describe( 'Tracking clicks in shippingBanner', () => {
2020-10-15 12:41:39 +00:00
const getExpectedTrackingData = ( element, wcsInstalled = true ) => {
return {
banner_name: 'wcadmin_install_wcs_prompt',
jetpack_connected: true,
jetpack_installed: true,
2020-10-15 12:41:39 +00:00
wcs_installed: wcsInstalled,
element,
};
};
2020-10-15 12:41:39 +00:00
it( 'should record an event when user clicks "Create shipping label"', async () => {
const { getByRole } = render(
<ShippingBanner
2020-10-15 12:41:39 +00:00
isJetpackConnected={ true }
activePlugins={ [ wcsPluginSlug, 'jetpack' ] }
installPlugins={ jest.fn() }
activatePlugins={ jest.fn() }
isRequesting={ false }
itemsCount={ 1 }
/>
);
2020-10-15 12:41:39 +00:00
userEvent.click(
getByRole( 'button', { name: 'Create shipping label' } )
);
await waitFor( () =>
expect( recordEvent ).toHaveBeenCalledWith(
'banner_element_clicked',
getExpectedTrackingData( 'shipping_banner_create_label' )
)
);
} );
2020-10-15 12:41:39 +00:00
it( 'should record an event when user clicks "WooCommerce Shipping"', async () => {
// Render the banner without WCS being active.
const { getByRole } = render(
<ShippingBanner
isJetpackConnected={ true }
activePlugins={ [ 'jetpack' ] }
installPlugins={ jest.fn() }
activatePlugins={ jest.fn() }
isRequesting={ false }
itemsCount={ 1 }
/>
);
userEvent.click(
getByRole( 'link', { name: /WooCommerce Shipping/ } )
);
await waitFor( () =>
expect( recordEvent ).toHaveBeenCalledWith(
'banner_element_clicked',
getExpectedTrackingData(
'shipping_banner_woocommerce_service_link',
false
)
)
);
} );
2020-10-15 12:41:39 +00:00
it( 'should record an event when user clicks "x" to dismiss the banner', async () => {
const { getByRole } = render(
<ShippingBanner
isJetpackConnected={ true }
activePlugins={ [ wcsPluginSlug, 'jetpack' ] }
installPlugins={ jest.fn() }
activatePlugins={ jest.fn() }
isRequesting={ false }
itemsCount={ 1 }
/>
);
2020-10-15 12:41:39 +00:00
userEvent.click(
getByRole( 'button', { name: 'Close Print Label Banner.' } )
);
await waitFor( () =>
expect( recordEvent ).toHaveBeenCalledWith(
'banner_element_clicked',
getExpectedTrackingData( 'shipping_banner_dimiss' )
)
);
} );
} );
describe( 'Create shipping label button', () => {
const installPlugins = jest.fn().mockReturnValue( {
success: true,
} );
const activatePlugins = jest.fn().mockReturnValue( {
success: true,
} );
delete window.location; // jsdom won't allow to rewrite window.location unless deleted first
window.location = {
href: 'http://wcship.test/wp-admin/post.php?post=1000&action=edit',
};
2020-10-15 12:41:39 +00:00
it( 'should install WooCommerce Shipping when button is clicked', async () => {
const { getByRole } = render(
<ShippingBanner
isJetpackConnected={ true }
activatePlugins={ activatePlugins }
activePlugins={ [] }
installPlugins={ installPlugins }
isRequesting={ false }
itemsCount={ 1 }
/>
);
2020-10-15 12:41:39 +00:00
userEvent.click(
getByRole( 'button', {
name: 'Create shipping label',
} )
);
2020-10-15 12:41:39 +00:00
await waitFor( () =>
expect( installPlugins ).toHaveBeenCalledWith( [
'woocommerce-services',
] )
);
} );
2020-10-15 12:41:39 +00:00
it( 'should activate WooCommerce Shipping when installation finishes', async () => {
const { getByRole } = render(
<ShippingBanner
isJetpackConnected={ true }
activatePlugins={ activatePlugins }
activePlugins={ [] }
installPlugins={ installPlugins }
isRequesting={ false }
itemsCount={ 1 }
/>
);
userEvent.click(
getByRole( 'button', {
name: 'Create shipping label',
} )
);
2020-10-15 12:41:39 +00:00
await waitFor( () =>
expect( activatePlugins ).toHaveBeenCalledWith( [
'woocommerce-services',
] )
);
} );
it( 'should perform a request to accept the TOS and get WCS assets to load', async () => {
2020-10-15 12:41:39 +00:00
getWcsAssets.mockReturnValueOnce( Promise.resolve( {} ) );
2020-10-15 12:41:39 +00:00
const { getByRole } = render(
<ShippingBanner
isJetpackConnected={ true }
activatePlugins={ activatePlugins }
activePlugins={ [ wcsPluginSlug ] }
installPlugins={ installPlugins }
isRequesting={ false }
itemsCount={ 1 }
/>
);
2020-10-15 12:41:39 +00:00
userEvent.click(
getByRole( 'button', {
name: 'Create shipping label',
} )
);
2020-10-15 12:41:39 +00:00
await waitFor( () => expect( acceptWcsTos ).toHaveBeenCalled() );
expect( getWcsAssets ).toHaveBeenCalled();
} );
2020-10-15 12:41:39 +00:00
it( 'should load WCS assets when a path is provided', async () => {
const mockAssets = {
wc_connect_admin_script: '/path/to/wcs.js',
wc_connect_admin_style: '/path/to/wcs.css',
};
2020-10-15 12:41:39 +00:00
getWcsAssets.mockReturnValueOnce(
Promise.resolve( {
assets: mockAssets,
} )
);
2020-10-15 12:41:39 +00:00
const { getByRole } = render(
<Fragment>
<div id="woocommerce-order-data" />
<div id="woocommerce-order-actions" />
<ShippingBanner
isJetpackConnected={ true }
activatePlugins={ activatePlugins }
activePlugins={ [ wcsPluginSlug, 'jetpack' ] }
installPlugins={ installPlugins }
isRequesting={ false }
itemsCount={ 1 }
/>
</Fragment>
);
2020-10-15 12:41:39 +00:00
userEvent.click(
getByRole( 'button', {
name: 'Create shipping label',
} )
);
2020-10-15 12:41:39 +00:00
// Check that the metaboxes have been created.
await waitFor( () =>
expect(
getByRole( 'heading', { level: 2, name: 'Shipping Label' } )
).toBeInTheDocument()
);
2020-10-15 12:41:39 +00:00
expect(
getByRole( 'heading', { level: 2, name: 'Shipment Tracking' } )
).toBeInTheDocument();
2020-10-15 12:41:39 +00:00
// Check that the script and style elements have been created.
expect( document.getElementsByTagName( 'script' )[ 0 ].src ).toBe(
'http://localhost' + mockAssets.wc_connect_admin_script
);
2020-10-15 12:41:39 +00:00
expect( document.getElementsByTagName( 'link' )[ 0 ].href ).toBe(
'http://localhost' + mockAssets.wc_connect_admin_style
);
} );
it( 'should open WCS modal', async () => {
window.wcsGetAppStoreAsync = jest.fn();
const getState = jest.fn();
const dispatch = jest.fn();
const subscribe = jest.fn();
window.wcsGetAppStoreAsync.mockReturnValueOnce(
Promise.resolve( {
getState,
dispatch,
subscribe,
} )
);
getState.mockReturnValueOnce( {
ui: {
selectedSiteId: 'SITE_ID',
},
} );
2020-10-15 12:41:39 +00:00
getWcsAssets.mockReturnValueOnce(
Promise.resolve( {
assets: {
// Easy to identify string in our hijacked setter function.
wc_connect_admin_script: 'wc_connect_admin_script',
// Empty string to avoid creating a script tag we also have to hijack.
wc_connect_admin_style: '',
},
} )
);
// Force the script tag to trigger its onload().
// Adapted from https://stackoverflow.com/a/49204336.
// const scriptSrcProperty = window.HTMLScriptElement.prototype.src;
Object.defineProperty( window.HTMLScriptElement.prototype, 'src', {
set( src ) {
if ( src === 'wc_connect_admin_script' ) {
setTimeout( () => this.onload() );
}
},
} );
2020-10-15 12:41:39 +00:00
const { getByRole } = render(
<Fragment>
<div id="woocommerce-order-data" />
<div id="woocommerce-order-actions" />
<div id="woocommerce-admin-print-label" />
<ShippingBanner
isJetpackConnected={ true }
activatePlugins={ activatePlugins }
activePlugins={ [ wcsPluginSlug, 'jetpack' ] }
installPlugins={ installPlugins }
isRequesting={ false }
itemsCount={ 1 }
/>
</Fragment>
);
2020-10-15 12:41:39 +00:00
// Initiate the loading of WCS assets on first click.
userEvent.click(
getByRole( 'button', {
name: 'Create shipping label',
} )
);
await waitFor( () =>
expect( window.wcsGetAppStoreAsync ).toHaveBeenCalledWith(
'wc-connect-create-shipping-label'
)
);
2020-10-15 12:41:39 +00:00
await waitFor( () => expect( getState ).toHaveBeenCalledTimes( 1 ) );
await waitFor( () => expect( subscribe ).toHaveBeenCalledTimes( 1 ) );
2020-10-15 12:41:39 +00:00
expect(
document.getElementById( 'woocommerce-admin-print-label' )
).not.toBeVisible();
} );
} );
describe( 'In the process of installing, activating, loading assets for WooCommerce Service', () => {
2020-10-15 12:41:39 +00:00
it( 'should show a busy loading state on "Create shipping label" and should disable "Close Print Label Banner"', async () => {
const { getByRole } = render(
<ShippingBanner
isJetpackConnected={ true }
activatePlugins={ jest.fn() }
2020-10-15 12:41:39 +00:00
activePlugins={ [ 'jetpack' ] }
installPlugins={ jest.fn() }
isRequesting={ true }
itemsCount={ 1 }
/>
);
2020-10-15 12:41:39 +00:00
expect(
getByRole( 'button', { name: 'Create shipping label' } )
).not.toHaveClass( 'is-busy' );
expect(
getByRole( 'button', { name: 'Close Print Label Banner.' } )
).toBeEnabled();
userEvent.click(
getByRole( 'button', { name: 'Create shipping label' } )
);
await waitFor( () =>
expect(
getByRole( 'button', { name: 'Create shipping label' } )
).toHaveClass( 'is-busy' )
);
2020-10-15 12:41:39 +00:00
expect(
getByRole( 'button', { name: 'Close Print Label Banner.' } )
).toBeDisabled();
} );
} );
describe( 'Setup error message', () => {
2020-10-15 12:41:39 +00:00
it( 'should not show if there is no error (no interaction)', () => {
const { container } = render(
<ShippingBanner
isJetpackConnected={ true }
2020-10-15 12:41:39 +00:00
activatePlugins={ jest.fn() }
activePlugins={ [ 'jetpack' ] }
2020-10-15 12:41:39 +00:00
installPlugins={ jest.fn() }
itemsCount={ 1 }
isRequesting={ false }
/>
);
2020-10-15 12:41:39 +00:00
expect(
container.getElementsByClassName(
'wc-admin-shipping-banner-install-error'
)
).toHaveLength( 0 );
} );
it( 'should show if there is installation error', async () => {
2020-10-15 12:41:39 +00:00
const { getByRole, getByText } = render(
<ShippingBanner
isJetpackConnected={ true }
activatePlugins={ jest.fn() }
activePlugins={ [ 'jetpack' ] }
installPlugins={ jest.fn().mockReturnValue( {
success: false,
} ) }
itemsCount={ 1 }
isRequesting={ false }
/>
);
2020-10-15 12:41:39 +00:00
userEvent.click(
getByRole( 'button', { name: 'Create shipping label' } )
);
await waitFor( () =>
expect(
getByText(
'Unable to install the plugin. Refresh the page and try again.'
)
).toBeInTheDocument()
);
} );
it( 'should show if there is activation error', async () => {
2020-10-15 12:41:39 +00:00
const { getByRole, getByText } = render(
<ShippingBanner
isJetpackConnected={ true }
2020-10-15 12:41:39 +00:00
activatePlugins={ jest.fn().mockReturnValue( {
success: false,
} ) }
activePlugins={ [ 'jetpack' ] }
installPlugins={ jest.fn().mockReturnValue( {
success: true,
} ) }
itemsCount={ 1 }
isRequesting={ false }
/>
);
2020-10-15 12:41:39 +00:00
userEvent.click(
getByRole( 'button', { name: 'Create shipping label' } )
);
2020-10-15 12:41:39 +00:00
await waitFor( () =>
expect(
getByText(
'Unable to activate the plugin. Refresh the page and try again.'
)
).toBeInTheDocument()
);
} );
} );
describe( 'The message in the banner', () => {
const createShippingBannerWrapper = ( { activePlugins } ) =>
2020-10-15 12:41:39 +00:00
render(
<ShippingBanner
isJetpackConnected={ true }
activatePlugins={ jest.fn() }
activePlugins={ activePlugins }
installPlugins={ jest.fn() }
wcsPluginSlug={ 'woocommerce-services' }
isRequesting={ true }
itemsCount={ 1 }
/>
);
const notActivatedMessage =
2020-10-15 12:41:39 +00:00
'By clicking "Create shipping label", WooCommerce Shipping(opens in a new tab) will be installed and you agree to its Terms of Service(opens in a new tab).';
const activatedMessage =
2020-10-15 12:41:39 +00:00
'You\'ve already installed WooCommerce Shipping. By clicking "Create shipping label", you agree to its Terms of Service(opens in a new tab).';
it( 'should show install text "By clicking "Create shipping label"..." when first loaded.', () => {
2020-10-15 12:41:39 +00:00
const { container } = createShippingBannerWrapper( {
activePlugins: [],
} );
2020-10-15 12:41:39 +00:00
expect(
container.querySelector( '.wc-admin-shipping-banner-blob p' )
.textContent
).toBe( notActivatedMessage );
} );
it( 'should continue to show the initial message "By clicking "Create shipping label"..." after WooCommerce Service is installed successfully.', () => {
2020-10-15 12:41:39 +00:00
const { container, rerender } = createShippingBannerWrapper( {
activePlugins: [],
} );
2020-10-15 12:41:39 +00:00
rerender(
<ShippingBanner
isJetpackConnected={ true }
activatePlugins={ jest.fn() }
activePlugins={ [ 'woocommerce-services' ] }
installPlugins={ jest.fn() }
wcsPluginSlug={ 'woocommerce-services' }
isRequesting={ true }
itemsCount={ 1 }
/>
);
expect(
container.querySelector( '.wc-admin-shipping-banner-blob p' )
.textContent
).toBe( notActivatedMessage );
} );
it( 'should show install text "By clicking "You\'ve already installed WooCommerce Shipping."..." when WooCommerce Service is already installed.', () => {
2020-10-15 12:41:39 +00:00
const { container } = createShippingBannerWrapper( {
activePlugins: [ 'woocommerce-services' ],
} );
2020-10-15 12:41:39 +00:00
expect(
container.querySelector( '.wc-admin-shipping-banner-blob p' )
.textContent
).toBe( activatedMessage );
} );
} );