Update woocommerce shipping promo banner [wc-shipping-188] (#50970)

* Make sure the WC Shipping slug is used for installation

* Make sure the check to show banner metabox work for HPOS as well

* Make ShippingLabelBannerDisplayRules::order_has_shippable_products work with HPOS as well

* Remove Jetpack plugin specific checks in ShippingLabelBannerDisplayRules

* Use correct variable names for dotcom connection

* Fix comments

* Remove depenency on WCS&T for showing WC Shipping promo banner

* Remove WC Tax and WC Shipping from incompatible plugins

* Vary action button label if WCS&T is already installed

* Inject config and render label purchase app after activation

* Open the purchase modal after adding it to DOM

* Render Shipment tracking metabox

* Use a different headline when WCS&T is already installed

* Fix UX when a none-compatible WCS&T is already active

* Fix CSS linting issues

* Fix Jslint issues

* Improve around usage of localized variables

* Fix and update JS tests

* Address phpcs issues

* Delete metaboxes of compatible WCS&T

* Remove redundant variable assignment

* Remove css and js of WCS&T if a compatible version is installed

* Fix failing legacy PHPUnit tests

* Only open the new label purchase modal if WCS&T is not active

* Remove redundant code around TOS acceptance for showing the banner

* Remove redundant test for Jetpack version checking

* Make sure target passed to MutationObserver.observe is available

* Add changelog file

* Add openWcsModal to component's prototype

* Add more js unit tests

* Address PHP notice

* Remove redundant variable assignments

* Rename wcsPluginSlug to more clear wcShippingPluginSlug

* Add a link to plugins page if incompatible WCS&T is already installed

* Remove unused function parameters

* Fix API resource path

* Handle a case where none compatible version of WCShipping is installed
This commit is contained in:
Sam Najian 2024-09-02 14:23:52 +02:00 committed by GitHub
parent 74e96d689b
commit 8b35b0785c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 514 additions and 443 deletions

View File

@ -1,17 +1,17 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { __, sprintf } from '@wordpress/i18n';
import { Component } from '@wordpress/element';
import { Button, ExternalLink } from '@wordpress/components';
import { compose } from '@wordpress/compose';
import interpolateComponents from '@automattic/interpolate-components';
import PropTypes from 'prop-types';
import { get, isArray } from 'lodash';
import { PLUGINS_STORE_NAME } from '@woocommerce/data';
import { withDispatch, withSelect } from '@wordpress/data';
import { recordEvent } from '@woocommerce/tracks';
import { getSetting } from '@woocommerce/settings';
import { getSetting, getAdminLink } from '@woocommerce/settings';
import { Link } from '@woocommerce/components';
/**
* Internal dependencies
@ -19,29 +19,28 @@ import { getSetting } from '@woocommerce/settings';
import '../style.scss';
import DismissModal from '../dismiss-modal';
import SetupNotice, { setupErrorTypes } from '../setup-notice';
import { getWcsAssets, acceptWcsTos } from '../wcs-api';
import {
getWcsAssets,
acceptWcsTos,
getWcsLabelPurchaseConfigs,
} from '../wcs-api';
const wcAssetUrl = getSetting( 'wcAssetUrl', '' );
const wcsPluginSlug = 'woocommerce-services';
const wcShippingPluginSlug = 'woocommerce-shipping';
const wcstPluginSlug = 'woocommerce-services';
export class ShippingBanner extends Component {
constructor( props ) {
super( props );
const orderId = new URL( window.location.href ).searchParams.get(
'post'
);
this.state = {
showShippingBanner: true,
isDismissModalOpen: false,
setupErrorReason: setupErrorTypes.SETUP,
orderId: parseInt( orderId, 10 ),
wcsAssetsLoaded: false,
wcsAssetsLoading: false,
wcsSetupError: false,
isShippingLabelButtonBusy: false,
installText: this.getInstallText(),
isWcsModalOpen: false,
};
}
@ -76,8 +75,8 @@ export class ShippingBanner extends Component {
const { activePlugins } = this.props;
this.setState( { isShippingLabelButtonBusy: true } );
this.trackElementClicked( 'shipping_banner_create_label' );
if ( ! activePlugins.includes( wcsPluginSlug ) ) {
this.installAndActivatePlugins( wcsPluginSlug );
if ( ! activePlugins.includes( wcShippingPluginSlug ) ) {
this.installAndActivatePlugins( wcShippingPluginSlug );
} else {
this.acceptTosAndGetWCSAssets();
}
@ -85,7 +84,14 @@ export class ShippingBanner extends Component {
async installAndActivatePlugins( pluginSlug ) {
// Avoid double activating.
const { installPlugins, activatePlugins, isRequesting } = this.props;
const {
installPlugins,
activatePlugins,
isRequesting,
activePlugins,
isWcstCompatible,
isIncompatibleWCShippingInstalled,
} = this.props;
if ( isRequesting ) {
return false;
}
@ -107,7 +113,25 @@ export class ShippingBanner extends Component {
return;
}
this.acceptTosAndGetWCSAssets();
/**
* If a incompatible version of the WooCommerce Shipping plugin is installed, the necessary endpoints
* are not available, so we need to reload the page to ensure to make the plugin usable.
*/
if ( isIncompatibleWCShippingInstalled ) {
window.location.reload( true );
return;
}
if (
! activePlugins.includes( wcShippingPluginSlug ) &&
isWcstCompatible
) {
this.acceptTosAndGetWCSAssets();
} else {
this.setState( {
showShippingBanner: false,
} );
}
}
woocommerceServiceLinkClicked = () => {
@ -120,7 +144,7 @@ export class ShippingBanner extends Component {
banner_name: 'wcadmin_install_wcs_prompt',
jetpack_installed: activePlugins.includes( 'jetpack' ),
jetpack_connected: isJetpackConnected,
wcs_installed: activePlugins.includes( wcsPluginSlug ),
wcs_installed: activePlugins.includes( wcShippingPluginSlug ),
...customProps,
} );
};
@ -135,16 +159,21 @@ export class ShippingBanner extends Component {
} );
};
acceptTosAndGetWCSAssets() {
acceptTosAndGetWCSAssets = () => {
return acceptWcsTos()
.then( () => getWcsLabelPurchaseConfigs( this.props.orderId ) )
.then( ( configs ) => {
window.WCShipping_Config = configs.config;
return configs;
} )
.then( () => getWcsAssets() )
.then( ( wcsAssets ) => this.loadWcsAssets( wcsAssets ) )
.catch( () => this.setState( { wcsSetupError: true } ) );
}
.catch( () => {
this.setState( { wcsSetupError: true } );
} );
};
generateMetaBoxHtml( nodeId, title, args ) {
const argsJsonString = JSON.stringify( args ).replace( /"/g, '"' ); // JS has no native html_entities so we just replace.
const togglePanelText = __( 'Toggle panel:', 'woocommerce' );
return `
@ -159,8 +188,7 @@ export class ShippingBanner extends Component {
</div>
</div>
<div class="inside">
<div class="wcc-root woocommerce wc-connect-create-shipping-label" data-args="${ argsJsonString }">
</div>
<div class="wcc-root woocommerce woocommerce-shipping-shipping-label" id="woocommerce-shipping-shipping-label-${ args.context }"></div>
</div>
</div>
`;
@ -174,27 +202,24 @@ export class ShippingBanner extends Component {
this.setState( { wcsAssetsLoading: true } );
const jsPath = assets.wc_connect_admin_script;
const stylePath = assets.wc_connect_admin_style;
const labelPurchaseMetaboxId = 'woocommerce-order-label';
const shipmentTrackingMetaboxId = 'woocommerce-order-shipment-tracking';
const jsPath = assets.wcshipping_create_label_script;
const stylePath = assets.wcshipping_create_label_style;
if ( undefined === window.wcsPluginData ) {
const assetPath = jsPath.substring(
0,
jsPath.lastIndexOf( '/' ) + 1
);
window.wcsPluginData = { assetPath };
}
const shipmentTrackingJsPath =
assets.wcshipping_shipment_tracking_script;
const shipmentTrackingStylePath =
assets.wcshipping_shipment_tracking_style;
const { orderId } = this.state;
const { itemsCount } = this.props;
const { activePlugins } = this.props;
document.getElementById( labelPurchaseMetaboxId )?.remove();
const shippingLabelContainerHtml = this.generateMetaBoxHtml(
'woocommerce-order-label',
labelPurchaseMetaboxId,
__( 'Shipping Label', 'woocommerce' ),
{
order: { id: orderId },
context: 'shipping_label',
items: itemsCount,
}
);
// Insert shipping label metabox just above main order details box.
@ -202,13 +227,12 @@ export class ShippingBanner extends Component {
.getElementById( 'woocommerce-order-data' )
.insertAdjacentHTML( 'beforebegin', shippingLabelContainerHtml );
document.getElementById( shipmentTrackingMetaboxId )?.remove();
const shipmentTrackingHtml = this.generateMetaBoxHtml(
'woocommerce-order-shipment-tracking',
shipmentTrackingMetaboxId,
__( 'Shipment Tracking', 'woocommerce' ),
{
order: { id: orderId },
context: 'shipment_tracking',
items: itemsCount,
}
);
// Insert tracking metabox in the side after the order actions.
@ -224,6 +248,13 @@ export class ShippingBanner extends Component {
window.jQuery( '#woocommerce-order-label' ).hide();
}
document
.querySelectorAll( 'script[src*="/woocommerce-services/"]' )
.forEach( ( node ) => node.remove?.() );
document
.querySelectorAll( 'link[href*="/woocommerce-services/"]' )
.forEach( ( node ) => node.remove?.() );
Promise.all( [
new Promise( ( resolve, reject ) => {
const script = document.createElement( 'script' );
@ -233,9 +264,16 @@ export class ShippingBanner extends Component {
script.onerror = reject;
document.body.appendChild( script );
} ),
new Promise( ( resolve, reject ) => {
const script = document.createElement( 'script' );
script.src = shipmentTrackingJsPath;
script.async = true;
script.onload = resolve;
script.onerror = reject;
document.body.appendChild( script );
} ),
new Promise( ( resolve, reject ) => {
if ( stylePath !== '' ) {
const head = document.getElementsByTagName( 'head' )[ 0 ];
const link = document.createElement( 'link' );
link.rel = 'stylesheet';
link.type = 'text/css';
@ -243,7 +281,23 @@ export class ShippingBanner extends Component {
link.media = 'all';
link.onload = resolve;
link.onerror = reject;
head.appendChild( link );
link.id = 'wcshipping-injected-styles';
document.head.appendChild( link );
} else {
resolve();
}
} ),
new Promise( ( resolve, reject ) => {
if ( shipmentTrackingStylePath !== '' ) {
const link = document.createElement( 'link' );
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = shipmentTrackingStylePath;
link.media = 'all';
link.onload = resolve;
link.onerror = reject;
link.id = 'wcshipping-injected-styles';
document.head.appendChild( link );
} else {
resolve();
}
@ -254,133 +308,61 @@ export class ShippingBanner extends Component {
wcsAssetsLoading: false,
isShippingLabelButtonBusy: false,
} );
this.openWcsModal();
// Reshow the shipping label metabox.
if ( window.jQuery ) {
window.jQuery( '#woocommerce-order-label' ).show();
}
document.getElementById(
'woocommerce-admin-print-label'
).style.display = 'none';
/**
* We'll only get to this point if either WCS&T is not active or is active but compatible with WooCommerce Shipping
* so once we check if the WCS&T is not active, we can open the label purchase modal immediately.
*/
if ( ! activePlugins.includes( wcstPluginSlug ) ) {
this.openWcsModal();
}
} );
}
getInstallText = () => {
const { activePlugins } = this.props;
if ( activePlugins.includes( wcsPluginSlug ) ) {
// If WCS is active, then the only remaining step is to agree to the ToS.
return __(
'You\'ve already installed WooCommerce Shipping. By clicking "Create shipping label", you agree to its {{tosLink}}Terms of Service{{/tosLink}}.',
'woocommerce'
);
}
return __(
'By clicking "Create shipping label", {{wcsLink}}WooCommerce Shipping{{/wcsLink}} will be installed and you agree to its {{tosLink}}Terms of Service{{/tosLink}}.',
'woocommerce'
);
};
openWcsModal() {
if ( window.wcsGetAppStoreAsync ) {
window
.wcsGetAppStoreAsync( 'wc-connect-create-shipping-label' )
.then( ( wcsStore ) => {
const state = wcsStore.getState();
const { orderId } = this.state;
const siteId = state.ui.selectedSiteId;
// Since the button is dynamically added, we need to wait for it to become selectable and then click it.
const wcsStoreUnsubscribe = wcsStore.subscribe( () => {
const latestState = wcsStore.getState();
const buttonSelector =
'#woocommerce-shipping-shipping-label-shipping_label button';
if ( window.MutationObserver ) {
const observer = new window.MutationObserver(
( mutationsList, observing ) => {
const button = document.querySelector( buttonSelector );
if ( button ) {
button.click();
observing.disconnect();
}
}
);
const shippingLabelState = get(
latestState,
[
'extensions',
'woocommerce',
'woocommerceServices',
siteId,
'shippingLabel',
orderId,
],
null
);
const labelSettingsState = get(
latestState,
[
'extensions',
'woocommerce',
'woocommerceServices',
siteId,
'labelSettings',
],
null
);
const packageState = get(
latestState,
[
'extensions',
'woocommerce',
'woocommerceServices',
siteId,
'packages',
],
null
);
const locationsState = get( latestState, [
'extensions',
'woocommerce',
'sites',
siteId,
'data',
'locations',
] );
if (
shippingLabelState &&
labelSettingsState &&
labelSettingsState.meta &&
packageState &&
locationsState
) {
if (
shippingLabelState.loaded &&
labelSettingsState.meta.isLoaded &&
packageState.isLoaded &&
isArray( locationsState ) &&
! this.state.isWcsModalOpen
) {
if ( window.jQuery ) {
this.setState( { isWcsModalOpen: true } );
window
.jQuery(
'.shipping-label__new-label-button'
)
.click();
}
wcsStore.dispatch( {
type: 'NOTICE_CREATE',
notice: {
duration: 10000,
status: 'is-success',
text: __(
'Plugin installed and activated',
'woocommerce'
),
},
} );
} else if (
shippingLabelState.showPurchaseDialog
) {
wcsStoreUnsubscribe();
if ( window.jQuery ) {
window
.jQuery( '#woocommerce-order-label' )
.show();
}
}
}
} );
document.getElementById(
'woocommerce-admin-print-label'
).style.display = 'none';
} );
observer.observe(
document.getElementById(
'woocommerce-shipping-shipping-label-shipping_label'
) ??
document.getElementById( 'wpbody-content' ) ??
document.body,
{
childList: true,
subtree: true,
}
);
} else {
const interval = setInterval( () => {
const targetElement = document.querySelector( buttonSelector );
if ( targetElement ) {
targetElement.click();
clearInterval( interval );
}
}, 300 );
}
}
@ -390,10 +372,40 @@ export class ShippingBanner extends Component {
showShippingBanner,
isShippingLabelButtonBusy,
} = this.state;
const { isWcstCompatible } = this.props;
if ( ! showShippingBanner && ! isWcstCompatible ) {
document
.getElementById( 'woocommerce-admin-print-label' )
.classList.add( 'error' );
return (
<p>
<strong>
{ interpolateComponents( {
mixedString: __(
'Please {{pluginPageLink}}update{{/pluginPageLink}} the WooCommerce Shipping & Tax plugin to the latest version to ensure compatibility with WooCommerce Shipping.',
'woocommerce'
),
components: {
pluginPageLink: (
<Link
href={ getAdminLink( 'plugins.php' ) }
target="_blank"
type="wp-admin"
/>
),
},
} ) }
</strong>
</p>
);
}
if ( ! showShippingBanner ) {
return null;
}
const { actionButtonLabel, headline } = this.props;
return (
<div>
<div className="wc-admin-shipping-banner-container">
@ -403,15 +415,17 @@ export class ShippingBanner extends Component {
alt={ __( 'Shipping ', 'woocommerce' ) }
/>
<div className="wc-admin-shipping-banner-blob">
<h3>
{ __(
'Print discounted shipping labels with a click.',
'woocommerce'
) }
</h3>
<h3>{ headline }</h3>
<p>
{ interpolateComponents( {
mixedString: this.state.installText,
mixedString: sprintf(
// translators: %s is the action button label.
__(
'By clicking "%s", {{wcsLink}}WooCommerce Shipping{{/wcsLink}} will be installed and you agree to its {{tosLink}}Terms of Service{{/tosLink}}.',
'woocommerce'
),
actionButtonLabel
),
components: {
tosLink: (
<ExternalLink
@ -445,7 +459,7 @@ export class ShippingBanner extends Component {
isBusy={ isShippingLabelButtonBusy }
onClick={ this.createShippingLabelClicked }
>
{ __( 'Create shipping label', 'woocommerce' ) }
{ actionButtonLabel }
</Button>
<button
@ -471,12 +485,13 @@ export class ShippingBanner extends Component {
}
ShippingBanner.propTypes = {
itemsCount: PropTypes.number.isRequired,
isJetpackConnected: PropTypes.bool.isRequired,
activePlugins: PropTypes.array.isRequired,
activatePlugins: PropTypes.func.isRequired,
installPlugins: PropTypes.func.isRequired,
isRequesting: PropTypes.bool.isRequired,
orderId: PropTypes.number.isRequired,
isWcstCompatible: PropTypes.bool.isRequired,
};
export default compose(
@ -487,11 +502,32 @@ export default compose(
const isRequesting =
isPluginsRequesting( 'activatePlugins' ) ||
isPluginsRequesting( 'installPlugins' );
const activePlugins = getActivePlugins();
const actionButtonLabel = activePlugins.includes( wcstPluginSlug )
? __( 'Install WooCommerce Shipping', 'woocommerce' )
: __( 'Create shipping label', 'woocommerce' );
const headline = activePlugins.includes( wcstPluginSlug )
? __(
'Print discounted shipping labels with a click, now with the dedicated plugin!',
'woocommerce'
)
: __(
'Print discounted shipping labels with a click.',
'woocommerce'
);
return {
isRequesting,
isJetpackConnected: isJetpackConnected(),
activePlugins: getActivePlugins(),
activePlugins,
actionButtonLabel,
headline,
orderId: parseInt( window.wcShippingCoreData.order_id, 10 ),
isWcstCompatible: [ 1, '1' ].includes(
window.wcShippingCoreData.is_wcst_compatible
),
isIncompatibleWCShippingInstalled: [ 1, '1' ].includes(
window.wcShippingCoreData.is_incompatible_wcshipping_installed
),
};
} ),
withDispatch( ( dispatch ) => {

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { createElement, Fragment } from '@wordpress/element';
import { Fragment } from '@wordpress/element';
import { recordEvent } from '@woocommerce/tracks';
import { render, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
@ -9,7 +9,11 @@ import userEvent from '@testing-library/user-event';
/**
* Internal dependencies
*/
import { acceptWcsTos, getWcsAssets } from '../../wcs-api.js';
import {
acceptWcsTos,
getWcsAssets,
getWcsLabelPurchaseConfigs,
} from '../../wcs-api.js';
import { ShippingBanner } from '../index.js';
jest.mock( '../../wcs-api.js' );
@ -18,25 +22,28 @@ acceptWcsTos.mockReturnValue( Promise.resolve() );
jest.mock( '@woocommerce/tracks' );
const wcsPluginSlug = 'woocommerce-services';
const wcsPluginSlug = 'woocommerce-shipping';
const wcstPluginSlug = 'woocommerce-services';
describe( 'Tracking impression in shippingBanner', () => {
const expectedTrackingData = {
banner_name: 'wcadmin_install_wcs_prompt',
jetpack_connected: true,
jetpack_installed: true,
wcs_installed: true,
wcs_installed: false,
};
it( 'should record an event when user sees banner loaded', () => {
render(
<ShippingBanner
isJetpackConnected={ true }
activePlugins={ [ wcsPluginSlug, 'jetpack' ] }
activePlugins={ [ wcstPluginSlug, 'jetpack' ] }
itemsCount={ 1 }
activatePlugins={ jest.fn() }
installPlugins={ jest.fn() }
isRequesting={ false }
isWcstCompatible={ true }
orderId={ 1 }
/>
);
expect( recordEvent ).toHaveBeenCalledTimes( 1 );
@ -59,25 +66,31 @@ describe( 'Tracking clicks in shippingBanner', () => {
};
it( 'should record an event when user clicks "Create shipping label"', async () => {
const actionButtonLabel = 'Create shipping label';
const { getByRole } = render(
<ShippingBanner
isJetpackConnected={ true }
activePlugins={ [ wcsPluginSlug, 'jetpack' ] }
installPlugins={ jest.fn() }
activatePlugins={ jest.fn() }
activePlugins={ [ 'jetpack' ] }
installPlugins={ jest
.fn()
.mockResolvedValue( { success: true } ) }
activatePlugins={ jest
.fn()
.mockResolvedValue( { success: true } ) }
isRequesting={ false }
itemsCount={ 1 }
orderId={ 1 }
isWcstCompatible={ true }
actionButtonLabel={ actionButtonLabel }
/>
);
userEvent.click(
getByRole( 'button', { name: 'Create shipping label' } )
);
userEvent.click( getByRole( 'button', { name: actionButtonLabel } ) );
await waitFor( () =>
expect( recordEvent ).toHaveBeenCalledWith(
'banner_element_clicked',
getExpectedTrackingData( 'shipping_banner_create_label' )
getExpectedTrackingData( 'shipping_banner_create_label', false )
)
);
} );
@ -92,6 +105,8 @@ describe( 'Tracking clicks in shippingBanner', () => {
activatePlugins={ jest.fn() }
isRequesting={ false }
itemsCount={ 1 }
orderId={ 1 }
isWcstCompatible={ true }
/>
);
@ -114,11 +129,13 @@ describe( 'Tracking clicks in shippingBanner', () => {
const { getByRole } = render(
<ShippingBanner
isJetpackConnected={ true }
activePlugins={ [ wcsPluginSlug, 'jetpack' ] }
activePlugins={ [ wcstPluginSlug, 'jetpack' ] }
installPlugins={ jest.fn() }
activatePlugins={ jest.fn() }
isRequesting={ false }
itemsCount={ 1 }
orderId={ 1 }
isWcstCompatible={ true }
/>
);
@ -129,7 +146,7 @@ describe( 'Tracking clicks in shippingBanner', () => {
await waitFor( () =>
expect( recordEvent ).toHaveBeenCalledWith(
'banner_element_clicked',
getExpectedTrackingData( 'shipping_banner_dimiss' )
getExpectedTrackingData( 'shipping_banner_dimiss', false )
)
);
} );
@ -148,6 +165,8 @@ describe( 'Create shipping label button', () => {
};
it( 'should install WooCommerce Shipping when button is clicked', async () => {
const actionButtonLabel = 'Create shipping label';
const { getByRole } = render(
<ShippingBanner
isJetpackConnected={ true }
@ -156,22 +175,26 @@ describe( 'Create shipping label button', () => {
installPlugins={ installPlugins }
isRequesting={ false }
itemsCount={ 1 }
orderId={ 1 }
isWcstCompatible={ true }
actionButtonLabel={ actionButtonLabel }
/>
);
userEvent.click(
getByRole( 'button', {
name: 'Create shipping label',
name: actionButtonLabel,
} )
);
await waitFor( () =>
expect( installPlugins ).toHaveBeenCalledWith( [
'woocommerce-services',
'woocommerce-shipping',
] )
);
} );
it( 'should activate WooCommerce Shipping when installation finishes', async () => {
const actionButtonLabel = 'Create shipping label';
const { getByRole } = render(
<ShippingBanner
isJetpackConnected={ true }
@ -180,38 +203,46 @@ describe( 'Create shipping label button', () => {
installPlugins={ installPlugins }
isRequesting={ false }
itemsCount={ 1 }
orderId={ 1 }
isWcstCompatible={ true }
actionButtonLabel={ actionButtonLabel }
/>
);
userEvent.click(
getByRole( 'button', {
name: 'Create shipping label',
name: actionButtonLabel,
} )
);
await waitFor( () =>
expect( activatePlugins ).toHaveBeenCalledWith( [
'woocommerce-services',
'woocommerce-shipping',
] )
);
} );
it( 'should perform a request to accept the TOS and get WCS assets to load', async () => {
getWcsLabelPurchaseConfigs.mockReturnValueOnce( Promise.resolve( {} ) );
getWcsAssets.mockReturnValueOnce( Promise.resolve( {} ) );
const actionButtonLabel = 'Create shipping label';
const { getByRole } = render(
<ShippingBanner
isJetpackConnected={ true }
activatePlugins={ activatePlugins }
activePlugins={ [ wcsPluginSlug ] }
activePlugins={ [ wcstPluginSlug ] }
installPlugins={ installPlugins }
isRequesting={ false }
itemsCount={ 1 }
orderId={ 1 }
isWcstCompatible={ true }
actionButtonLabel={ actionButtonLabel }
/>
);
userEvent.click(
getByRole( 'button', {
name: 'Create shipping label',
name: actionButtonLabel,
} )
);
@ -220,9 +251,16 @@ describe( 'Create shipping label button', () => {
} );
it( 'should load WCS assets when a path is provided', async () => {
const actionButtonLabel = 'Create shipping label';
getWcsLabelPurchaseConfigs.mockReturnValueOnce( Promise.resolve( {} ) );
const mockAssets = {
wc_connect_admin_script: '/path/to/wcs.js',
wc_connect_admin_style: '/path/to/wcs.css',
wcshipping_create_label_script: '/path/to/wcs.js',
wcshipping_create_label_style: '/path/to/wcs.css',
wcshipping_shipment_tracking_script:
'/wcshipping_shipment_tracking_script',
wcshipping_shipment_tracking_style:
'/wcshipping_shipment_tracking_style',
};
getWcsAssets.mockReturnValueOnce(
Promise.resolve( {
@ -237,17 +275,20 @@ describe( 'Create shipping label button', () => {
<ShippingBanner
isJetpackConnected={ true }
activatePlugins={ activatePlugins }
activePlugins={ [ wcsPluginSlug, 'jetpack' ] }
activePlugins={ [ wcstPluginSlug, 'jetpack' ] }
installPlugins={ installPlugins }
isRequesting={ false }
itemsCount={ 1 }
orderId={ 1 }
isWcstCompatible={ true }
actionButtonLabel={ actionButtonLabel }
/>
</Fragment>
);
userEvent.click(
getByRole( 'button', {
name: 'Create shipping label',
name: actionButtonLabel,
} )
);
@ -263,40 +304,44 @@ describe( 'Create shipping label button', () => {
).toBeInTheDocument();
// Check that the script and style elements have been created.
expect( document.getElementsByTagName( 'script' )[ 0 ].src ).toBe(
'http://localhost' + mockAssets.wc_connect_admin_script
const allScriptSrcs = Array.from(
document.querySelectorAll( 'script' )
).map( ( script ) => script.src );
const allLinkHrefs = Array.from(
document.querySelectorAll( 'link' )
).map( ( link ) => link.href );
expect( allScriptSrcs ).toContain(
'http://localhost' + mockAssets.wcshipping_create_label_script
);
expect( document.getElementsByTagName( 'link' )[ 0 ].href ).toBe(
'http://localhost' + mockAssets.wc_connect_admin_style
expect( allScriptSrcs ).toContain(
'http://localhost' + mockAssets.wcshipping_shipment_tracking_script
);
expect( allLinkHrefs ).toContain(
'http://localhost' + mockAssets.wcshipping_create_label_style
);
expect( allLinkHrefs ).toContain(
'http://localhost' + mockAssets.wcshipping_shipment_tracking_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',
},
} );
const actionButtonLabel = 'Create shipping label';
getWcsLabelPurchaseConfigs.mockReturnValueOnce( Promise.resolve( {} ) );
getWcsAssets.mockReturnValueOnce(
Promise.resolve( {
assets: {
// Easy to identify string in our hijacked setter function.
wc_connect_admin_script: 'wc_connect_admin_script',
wcshipping_create_label_script:
'wcshipping_create_label_script',
wcshipping_shipment_tracking_script:
'wcshipping_create_label_script',
// Empty string to avoid creating a script tag we also have to hijack.
wc_connect_admin_style: '',
wcshipping_create_label_style: '',
wcshipping_shipment_tracking_style: '',
},
} )
);
@ -306,8 +351,15 @@ describe( 'Create shipping label button', () => {
// const scriptSrcProperty = window.HTMLScriptElement.prototype.src;
Object.defineProperty( window.HTMLScriptElement.prototype, 'src', {
set( src ) {
if ( src === 'wc_connect_admin_script' ) {
setTimeout( () => this.onload() );
if (
[
'wcshipping_create_label_script',
'wcshipping_shipment_tracking_script',
].includes( src )
) {
setTimeout( () => {
this.onload();
}, 1 );
}
},
} );
@ -324,33 +376,38 @@ describe( 'Create shipping label button', () => {
installPlugins={ installPlugins }
isRequesting={ false }
itemsCount={ 1 }
orderId={ 1 }
isWcstCompatible={ true }
actionButtonLabel={ actionButtonLabel }
/>
</Fragment>
);
const openWcsModalSpy = jest.spyOn(
ShippingBanner.prototype,
'openWcsModal'
);
// Initiate the loading of WCS assets on first click.
userEvent.click(
getByRole( 'button', {
name: 'Create shipping label',
name: actionButtonLabel,
} )
);
await waitFor( () =>
expect( window.wcsGetAppStoreAsync ).toHaveBeenCalledWith(
'wc-connect-create-shipping-label'
)
);
await waitFor( () => expect( getState ).toHaveBeenCalledTimes( 1 ) );
await waitFor( () => expect( subscribe ).toHaveBeenCalledTimes( 1 ) );
await waitFor( () => {
expect(
document.getElementById( 'woocommerce-admin-print-label' )
).not.toBeVisible();
} );
expect(
document.getElementById( 'woocommerce-admin-print-label' )
).not.toBeVisible();
expect( openWcsModalSpy ).toHaveBeenCalledTimes( 1 );
} );
} );
describe( 'In the process of installing, activating, loading assets for WooCommerce Service', () => {
it( 'should show a busy loading state on "Create shipping label" and should disable "Close Print Label Banner"', async () => {
const actionButtonLabel = 'Create shipping label';
const { getByRole } = render(
<ShippingBanner
isJetpackConnected={ true }
@ -359,24 +416,25 @@ describe( 'In the process of installing, activating, loading assets for WooComme
installPlugins={ jest.fn() }
isRequesting={ true }
itemsCount={ 1 }
orderId={ 1 }
isWcstCompatible={ true }
actionButtonLabel={ actionButtonLabel }
/>
);
expect(
getByRole( 'button', { name: 'Create shipping label' } )
getByRole( 'button', { name: actionButtonLabel } )
).not.toHaveClass( 'is-busy' );
expect(
getByRole( 'button', { name: 'Close Print Label Banner.' } )
).toBeEnabled();
userEvent.click(
getByRole( 'button', { name: 'Create shipping label' } )
);
userEvent.click( getByRole( 'button', { name: actionButtonLabel } ) );
await waitFor( () =>
expect(
getByRole( 'button', { name: 'Create shipping label' } )
getByRole( 'button', { name: actionButtonLabel } )
).toHaveClass( 'is-busy' )
);
@ -396,6 +454,9 @@ describe( 'Setup error message', () => {
installPlugins={ jest.fn() }
itemsCount={ 1 }
isRequesting={ false }
orderId={ 1 }
isWcstCompatible={ true }
actionButtonLabel="Create shipping label"
/>
);
@ -407,6 +468,7 @@ describe( 'Setup error message', () => {
} );
it( 'should show if there is installation error', async () => {
const actionButtonLabel = 'Create shipping label';
const { getByRole, getByText } = render(
<ShippingBanner
isJetpackConnected={ true }
@ -417,12 +479,13 @@ describe( 'Setup error message', () => {
} ) }
itemsCount={ 1 }
isRequesting={ false }
orderId={ 1 }
isWcstCompatible={ true }
actionButtonLabel={ actionButtonLabel }
/>
);
userEvent.click(
getByRole( 'button', { name: 'Create shipping label' } )
);
userEvent.click( getByRole( 'button', { name: actionButtonLabel } ) );
await waitFor( () =>
expect(
@ -434,6 +497,8 @@ describe( 'Setup error message', () => {
} );
it( 'should show if there is activation error', async () => {
const actionButtonLabel = 'Create shipping label';
const { getByRole, getByText } = render(
<ShippingBanner
isJetpackConnected={ true }
@ -446,12 +511,13 @@ describe( 'Setup error message', () => {
} ) }
itemsCount={ 1 }
isRequesting={ false }
orderId={ 1 }
isWcstCompatible={ true }
actionButtonLabel={ actionButtonLabel }
/>
);
userEvent.click(
getByRole( 'button', { name: 'Create shipping label' } )
);
userEvent.click( getByRole( 'button', { name: actionButtonLabel } ) );
await waitFor( () =>
expect(
@ -471,16 +537,16 @@ describe( 'The message in the banner', () => {
activatePlugins={ jest.fn() }
activePlugins={ activePlugins }
installPlugins={ jest.fn() }
wcsPluginSlug={ 'woocommerce-services' }
isRequesting={ true }
itemsCount={ 1 }
orderId={ 1 }
isWcstCompatible={ true }
actionButtonLabel="Create shipping label"
/>
);
const notActivatedMessage =
'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 =
'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.', () => {
const { container } = createShippingBannerWrapper( {
@ -502,11 +568,13 @@ describe( 'The message in the banner', () => {
<ShippingBanner
isJetpackConnected={ true }
activatePlugins={ jest.fn() }
activePlugins={ [ 'woocommerce-services' ] }
activePlugins={ [ wcstPluginSlug ] }
installPlugins={ jest.fn() }
wcsPluginSlug={ 'woocommerce-services' }
isRequesting={ true }
itemsCount={ 1 }
orderId={ 1 }
isWcstCompatible={ true }
actionButtonLabel="Create shipping label"
/>
);
@ -515,15 +583,71 @@ describe( 'The message in the banner', () => {
.textContent
).toBe( notActivatedMessage );
} );
} );
it( 'should show install text "By clicking "You\'ve already installed WooCommerce Shipping."..." when WooCommerce Service is already installed.', () => {
const { container } = createShippingBannerWrapper( {
activePlugins: [ 'woocommerce-services' ],
describe( 'If incompatible WCS&T is active', () => {
const installPlugins = jest.fn().mockReturnValue( {
success: true,
} );
const activatePlugins = jest.fn().mockReturnValue( {
success: true,
} );
beforeEach( () => {
acceptWcsTos.mockClear();
} );
it( 'should install and activate but show an error notice when an incompatible version of WCS&T is installed', async () => {
const actionButtonLabel = 'Install WooCommerce Shipping';
const { getByRole, getByText } = render(
<Fragment>
<div id="woocommerce-order-data" />
<div id="woocommerce-order-actions" />
<div id="woocommerce-admin-print-label" />
<ShippingBanner
isJetpackConnected={ true }
activatePlugins={ activatePlugins }
activePlugins={ [ wcstPluginSlug, 'jetpack' ] }
installPlugins={ installPlugins }
itemsCount={ 1 }
isRequesting={ false }
orderId={ 1 }
isWcstCompatible={ false }
actionButtonLabel={ actionButtonLabel }
/>
</Fragment>
);
userEvent.click( getByRole( 'button', { name: actionButtonLabel } ) );
await waitFor( () => {
expect( installPlugins ).toHaveBeenCalledWith( [ wcsPluginSlug ] );
} );
await waitFor( () => {
expect( activatePlugins ).toHaveBeenCalledWith( [ wcsPluginSlug ] );
} );
expect(
container.querySelector( '.wc-admin-shipping-banner-blob p' )
.textContent
).toBe( activatedMessage );
await waitFor( () => {
expect( acceptWcsTos ).not.toHaveBeenCalled();
} );
const notice = getByText( ( _, element ) => {
const hasText = ( node ) =>
node.textContent ===
'Please update the WooCommerce Shipping & Tax plugin to the latest version to ensure compatibility with WooCommerce Shipping.';
const nodeHasText = hasText( element );
const childrenDontHaveText = Array.from( element.children ).every(
( child ) => ! hasText( child )
);
return nodeHasText && childrenDontHaveText;
} );
await waitFor( () => expect( notice ).toBeInTheDocument() );
// Assert that the "update" link is present
const updateLink = getByText( /update/i );
expect( updateLink ).toBeInTheDocument();
expect( updateLink.tagName ).toBe( 'A' ); // Ensures it's a link
} );
} );

View File

@ -66,6 +66,16 @@
.components-external-link__icon {
display: none;
}
&.error {
min-height: auto;
.inside {
padding-bottom: 6px;
p {
font-size: 13px;
}
}
}
}
.components-modal__frame.wc-admin-shipping-banner__dismiss-modal {

View File

@ -4,7 +4,7 @@
import apiFetch from '@wordpress/api-fetch';
export function acceptWcsTos() {
const path = '/wc/v1/connect/tos';
const path = '/wcshipping/v1/tos';
return apiFetch( {
path,
method: 'POST',
@ -13,7 +13,15 @@ export function acceptWcsTos() {
}
export function getWcsAssets() {
const path = '/wc/v1/connect/assets';
const path = '/wcshipping/v1/assets';
return apiFetch( {
path,
method: 'GET',
} );
}
export function getWcsLabelPurchaseConfigs( orderId ) {
const path = `wcshipping/v1/config/label-purchase/${ orderId }`;
return apiFetch( {
path,
method: 'GET',

View File

@ -0,0 +1,4 @@
Significance: minor
Type: update
Update WooCommerce Shipping Promo Banner to install the latest version of WooCommerce Shipping instead of WCS&T.

View File

@ -6,6 +6,8 @@
namespace Automattic\WooCommerce\Internal\Admin;
use Automattic\Jetpack\Connection\Manager as Jetpack_Connection_Manager;
use Automattic\WooCommerce\Utilities\OrderUtil;
use function WP_CLI\Utils\get_plugin_name;
/**
* Shows print shipping label banner on edit order page.
@ -19,6 +21,9 @@ class ShippingLabelBanner {
*/
private $shipping_label_banner_display_rules;
private const MIN_COMPATIBLE_WCST_VERSION = '2.7.0';
private const MIN_COMPATIBLE_WCSHIPPING_VERSION = '1.1.0';
/**
* Constructor
*/
@ -36,40 +41,26 @@ class ShippingLabelBanner {
*/
private function should_show_meta_box() {
if ( ! $this->shipping_label_banner_display_rules ) {
$jetpack_version = null;
$jetpack_connected = null;
$wcs_version = null;
$wcs_tos_accepted = null;
if ( defined( 'JETPACK__VERSION' ) ) {
$jetpack_version = JETPACK__VERSION;
}
$dotcom_connected = null;
$wcs_version = null;
if ( class_exists( Jetpack_Connection_Manager::class ) ) {
$jetpack_connected = ( new Jetpack_Connection_Manager() )->has_connected_owner();
$dotcom_connected = ( new Jetpack_Connection_Manager() )->has_connected_owner();
}
if ( class_exists( '\WC_Connect_Loader' ) ) {
$wcs_version = \WC_Connect_Loader::get_wcs_version();
}
if ( class_exists( '\WC_Connect_Options' ) ) {
$wcs_tos_accepted = \WC_Connect_Options::get_option( 'tos_accepted' );
if ( class_exists( '\Automattic\WCShipping\Utils' ) ) {
$wcs_version = \Automattic\WCShipping\Utils::get_wcshipping_version();
}
$incompatible_plugins = class_exists( '\WC_Shipping_Fedex_Init' ) ||
class_exists( '\WC_Shipping_UPS_Init' ) ||
class_exists( '\WC_Integration_ShippingEasy' ) ||
class_exists( '\WC_ShipStation_Integration' ) ||
class_exists( '\Automattic\WCShipping\Loader' ) ||
class_exists( '\Automattic\WCTax\Loader' );
class_exists( '\WC_ShipStation_Integration' );
$this->shipping_label_banner_display_rules =
new ShippingLabelBannerDisplayRules(
$jetpack_version,
$jetpack_connected,
$dotcom_connected,
$wcs_version,
$wcs_tos_accepted,
$incompatible_plugins
);
}
@ -79,15 +70,12 @@ class ShippingLabelBanner {
/**
* Add metabox to order page.
*
* @param string $post_type current post type.
* @param \WP_Post $post Current post object.
*/
public function add_meta_boxes( $post_type, $post ) {
if ( 'shop_order' !== $post_type ) {
public function add_meta_boxes() {
if ( ! OrderUtil::is_order_edit_screen() ) {
return;
}
$order = wc_get_order( $post );
if ( $this->should_show_meta_box() ) {
add_meta_box(
'woocommerce-admin-print-label',
@ -98,8 +86,6 @@ class ShippingLabelBanner {
'high',
array(
'context' => 'shipping_label',
'order' => $post->ID,
'items' => $this->count_shippable_items( $order ),
)
);
add_action( 'admin_enqueue_scripts', array( $this, 'add_print_shipping_label_script' ) );
@ -132,14 +118,30 @@ class ShippingLabelBanner {
public function add_print_shipping_label_script( $hook ) {
WCAdminAssets::register_style( 'print-shipping-label-banner', 'style', array( 'wp-components' ) );
WCAdminAssets::register_script( 'wp-admin-scripts', 'print-shipping-label-banner', true );
$wcst_version = null;
$wcshipping_installed_version = null;
$order = wc_get_order();
if ( class_exists( '\WC_Connect_Loader' ) ) {
$wcst_version = \WC_Connect_Loader::get_wcs_version();
}
$wc_shipping_plugin_file = WP_PLUGIN_DIR . '/woocommerce-shipping/woocommerce-shipping.php';
if ( file_exists( $wc_shipping_plugin_file ) ) {
$plugin_data = get_plugin_data( $wc_shipping_plugin_file );
$wcshipping_installed_version = $plugin_data['Version'];
}
$payload = array(
'nonce' => wp_create_nonce( 'wp_rest' ),
'baseURL' => get_rest_url(),
'wcs_server_connection' => true,
// If WCS&T is not installed, it's considered compatible.
'is_wcst_compatible' => $wcst_version ? (int) version_compare( $wcst_version, self::MIN_COMPATIBLE_WCST_VERSION, '>=' ) : 1,
'order_id' => $order ? $order->get_id() : null,
// The banner is shown if the plugin is installed but not active, so we need to check if the installed version is compatible.
'is_incompatible_wcshipping_installed' => $wcshipping_installed_version ?
(int) version_compare( $wcshipping_installed_version, self::MIN_COMPATIBLE_WCSHIPPING_VERSION, '<' )
: 0,
);
wp_localize_script( 'print-shipping-label-banner', 'wcConnectData', $payload );
wp_localize_script( 'wc-admin-print-shipping-label-banner', 'wcShippingCoreData', $payload );
}
/**

View File

@ -6,24 +6,23 @@
namespace Automattic\WooCommerce\Internal\Admin;
/**
* Determines whether or not the Shipping Label Banner should be displayed
* Determines whether the Shipping Label Banner should be displayed
*/
class ShippingLabelBannerDisplayRules {
/**
* Holds the installed Jetpack version.
*
* @var string
*/
private $jetpack_version;
/**
* Whether or not the installed Jetpack is connected.
* Whether the site is connected to wordpress.com.
*
* @var bool
*/
private $jetpack_connected;
private $dotcom_connected;
/**
* Whether installed plugins are incompatible with the banner.
*
* @var bool
*/
private $no_incompatible_plugins_installed;
/**
* Holds the installed WooCommerce Shipping & Tax version.
@ -32,34 +31,6 @@ class ShippingLabelBannerDisplayRules {
*/
private $wcs_version;
/**
* Whether or not there're plugins installed incompatible with the banner.
*
* @var bool
*/
private $no_incompatible_plugins_installed;
/**
* Whether or not the WooCommerce Shipping & Tax ToS has been accepted.
*
* @var bool
*/
private $wcs_tos_accepted;
/**
* Minimum supported Jetpack version.
*
* @var string
*/
private $min_jetpack_version = '4.4';
/**
* Minimum supported WooCommerce Shipping & Tax version.
*
* @var string
*/
private $min_wcs_version = '1.22.5';
/**
* Supported countries by USPS, see: https://webpmt.usps.gov/pmt010.cfm
*
@ -78,17 +49,13 @@ class ShippingLabelBannerDisplayRules {
/**
* Constructor.
*
* @param string $jetpack_version Installed Jetpack version to check.
* @param bool $jetpack_connected Is Jetpack connected?.
* @param string $wcs_version Installed WooCommerce Shipping & Tax version to check.
* @param bool $wcs_tos_accepted WooCommerce Shipping & Tax Terms of Service accepted?.
* @param bool $incompatible_plugins_installed Are there any incompatible plugins installed?.
* @param bool $dotcom_connected Is site connected to wordpress.com?.
* @param string|null $wcs_version Installed WooCommerce Shipping version to check, null if not installed.
* @param bool $incompatible_plugins_installed Are there any incompatible plugins installed?.
*/
public function __construct( $jetpack_version, $jetpack_connected, $wcs_version, $wcs_tos_accepted, $incompatible_plugins_installed ) {
$this->jetpack_version = $jetpack_version;
$this->jetpack_connected = $jetpack_connected;
public function __construct( $dotcom_connected, $wcs_version, $incompatible_plugins_installed ) {
$this->dotcom_connected = $dotcom_connected;
$this->wcs_version = $wcs_version;
$this->wcs_tos_accepted = $wcs_tos_accepted;
$this->no_incompatible_plugins_installed = ! $incompatible_plugins_installed;
}
@ -97,15 +64,11 @@ class ShippingLabelBannerDisplayRules {
*/
public function should_display_banner() {
return $this->banner_not_dismissed() &&
$this->jetpack_installed_and_active() &&
$this->jetpack_up_to_date() &&
$this->jetpack_connected &&
$this->dotcom_connected &&
$this->no_incompatible_plugins_installed &&
$this->order_has_shippable_products() &&
$this->store_in_us_and_usd() &&
( $this->wcs_not_installed() || (
$this->wcs_up_to_date() && ! $this->wcs_tos_accepted
) );
$this->wcs_not_installed();
}
/**
@ -129,36 +92,13 @@ class ShippingLabelBannerDisplayRules {
return ! $dismissed_for_good && ! $dismissed_24h;
}
/**
* Checks if jetpack is installed and active.
*
* @return bool
*/
private function jetpack_installed_and_active() {
return ! ! $this->jetpack_version;
}
/**
* Checks if Jetpack version is supported.
*
* @return bool
*/
private function jetpack_up_to_date() {
return version_compare( $this->jetpack_version, $this->min_jetpack_version, '>=' );
}
/**
* Checks if there's a shippable product in the current order.
*
* @return bool
*/
private function order_has_shippable_products() {
$post = get_post();
if ( ! $post ) {
return false;
}
$order = wc_get_order( get_post()->ID );
$order = wc_get_order();
if ( ! $order ) {
return false;
@ -197,11 +137,4 @@ class ShippingLabelBannerDisplayRules {
private function wcs_not_installed() {
return ! $this->wcs_version;
}
/**
* Checks if WooCommerce Shipping & Tax is up to date.
*/
private function wcs_up_to_date() {
return $this->wcs_version && version_compare( $this->wcs_version, $this->min_wcs_version, '>=' );
}
}

View File

@ -12,13 +12,6 @@ use Automattic\WooCommerce\Internal\Admin\ShippingLabelBannerDisplayRules;
*/
class WC_Admin_Tests_Shipping_Label_Banner_Display_Rules extends WC_Unit_Test_Case {
/**
* Jetpack version to test the display manager.
*
* @var string
*/
private $valid_jetpack_version = '4.4';
/**
* Stores the default WordPress options stored in the database.
*
@ -66,7 +59,6 @@ class WC_Admin_Tests_Shipping_Label_Banner_Display_Rules extends WC_Unit_Test_Ca
/**
* Test if the banner is displayed when all conditions are satisfied:
* - Banner NOT dismissed
* - Jetpack >= 4.4 installed and active
* - Jetpack Connected
* - No incompatible extensions installed:
* - Shipstation not installed
@ -76,13 +68,12 @@ class WC_Admin_Tests_Shipping_Label_Banner_Display_Rules extends WC_Unit_Test_Ca
* - Order contains physical products which need to be shipped (we should check that the order status is not set to complete)
* - Store is located in US
* - Store currency is set to USD
* - WCS plugin not installed OR WCS is installed *AND* ToS have NOT been accepted *AND* WCS version is 1.22.5 or greater
* (The 1.22.5 or greater requirement is so we can launch the shipping modal from the banner)
* - WCS plugin not installed OR WCS is installed
*/
public function test_display_banner_if_all_conditions_are_met() {
$this->with_order(
function( $that ) {
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( '4.4', true, '1.22.5', false, false );
function ( $that ) {
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( true, null, false );
$that->assertEquals( $shipping_label_banner_display_rules->should_display_banner(), true );
}
@ -93,7 +84,7 @@ class WC_Admin_Tests_Shipping_Label_Banner_Display_Rules extends WC_Unit_Test_Ca
* Test if the banner is hidden when Jetpack is not active.
*/
public function test_if_banner_hidden_when_jetpack_disconnected() {
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( null, null, null, null, null );
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( null, null, null );
$this->assertEquals( $shipping_label_banner_display_rules->should_display_banner(), false );
}
@ -103,7 +94,7 @@ class WC_Admin_Tests_Shipping_Label_Banner_Display_Rules extends WC_Unit_Test_Ca
*/
public function test_if_banner_hidden_when_dismiss_option_enabled() {
update_option( 'woocommerce_shipping_dismissed_timestamp', -1 );
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( '4.4', true, '1.22.5', false, false );
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( true, '1.22.5', false );
$this->assertEquals( $shipping_label_banner_display_rules->should_display_banner(), false );
}
@ -115,7 +106,7 @@ class WC_Admin_Tests_Shipping_Label_Banner_Display_Rules extends WC_Unit_Test_Ca
$two_hours_from_ago = ( time() - 2 * 60 * 60 ) * 1000;
update_option( 'woocommerce_shipping_dismissed_timestamp', $two_hours_from_ago );
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( '4.4', true, '1.22.5', false, false );
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( true, '1.22.5', false );
$this->assertEquals( $shipping_label_banner_display_rules->should_display_banner(), false );
}
@ -128,8 +119,8 @@ class WC_Admin_Tests_Shipping_Label_Banner_Display_Rules extends WC_Unit_Test_Ca
update_option( 'woocommerce_shipping_dismissed_timestamp', $twenty_four_hours_one_sec_ago );
$this->with_order(
function( $that ) {
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( '4.4', true, '1.22.5', false, false );
function ( $that ) {
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( true, null, false, false );
$that->assertEquals( $shipping_label_banner_display_rules->should_display_banner(), true );
}
@ -140,7 +131,7 @@ class WC_Admin_Tests_Shipping_Label_Banner_Display_Rules extends WC_Unit_Test_Ca
* Test if the banner is hidden when no shippable product available.
*/
public function test_if_banner_hidden_when_no_shippable_product() {
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( '4.4', true, '1.22.5', false, false );
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( true, '1.22.5', false );
$this->assertEquals( $shipping_label_banner_display_rules->should_display_banner(), false );
}
@ -151,8 +142,8 @@ class WC_Admin_Tests_Shipping_Label_Banner_Display_Rules extends WC_Unit_Test_Ca
public function test_if_banner_hidden_when_store_is_not_in_us() {
update_option( 'woocommerce_default_country', 'ES' );
$this->with_order(
function( $that ) {
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( '4.4', true, '1.22.5', false, false );
function ( $that ) {
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( true, '1.22.5', false, false );
$that->assertEquals( $shipping_label_banner_display_rules->should_display_banner(), false );
}
@ -165,8 +156,8 @@ class WC_Admin_Tests_Shipping_Label_Banner_Display_Rules extends WC_Unit_Test_Ca
public function test_if_banner_hidden_when_currency_is_not_usd() {
update_option( 'woocommerce_currency', 'EUR' );
$this->with_order(
function( $that ) {
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( '4.4', true, '1.22.5', false, false );
function ( $that ) {
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( true, '1.22.5', false );
$that->assertEquals( $shipping_label_banner_display_rules->should_display_banner(), false );
}
@ -178,34 +169,8 @@ class WC_Admin_Tests_Shipping_Label_Banner_Display_Rules extends WC_Unit_Test_Ca
*/
public function test_if_banner_hidden_when_incompatible_plugin_installed() {
$this->with_order(
function( $that ) {
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( '4.4', true, '1.22.5', false, true );
$that->assertEquals( $shipping_label_banner_display_rules->should_display_banner(), false );
}
);
}
/**
* Test if the banner is hidden when Jetpack version is not at least 4.4.
*/
public function test_if_banner_hidden_when_jetpack_version_is_old() {
$this->with_order(
function( $that ) {
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( '4.3', true, '1.22.5', false, false );
$that->assertEquals( $shipping_label_banner_display_rules->should_display_banner(), false );
}
);
}
/**
* Test if the banner is hidden when the WooCommerce Shipping & Tax Terms of Service has been already accepted.
*/
public function test_if_banner_hidden_when_wcs_tos_accepted() {
$this->with_order(
function( $that ) {
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( '4.4', true, '1.22.5', true, false );
function ( $that ) {
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( true, '1.22.5', false, true );
$that->assertEquals( $shipping_label_banner_display_rules->should_display_banner(), false );
}
@ -217,8 +182,8 @@ class WC_Admin_Tests_Shipping_Label_Banner_Display_Rules extends WC_Unit_Test_Ca
*/
public function test_if_banner_hidden_when_wcs_not_installed() {
$this->with_order(
function( $that ) {
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( '4.4', true, '1.22.4', false, false );
function ( $that ) {
$shipping_label_banner_display_rules = new ShippingLabelBannerDisplayRules( true, '1.22.4', false );
$that->assertEquals( $shipping_label_banner_display_rules->should_display_banner(), false );
}
@ -230,20 +195,10 @@ class WC_Admin_Tests_Shipping_Label_Banner_Display_Rules extends WC_Unit_Test_Ca
*/
private function create_order() {
$product = WC_Helper_Product::create_simple_product();
$product->set_props( array( 'virtual' => true ) );
$order = new WC_Order();
$order_item = new WC_Order_Item_Product();
$order_item->set_props( array( 'product' => $product ) );
$order->add_item( $order_item );
$order->save();
global $post;
// phpcs:disable WordPress.WP.GlobalVariablesOverride.Prohibited
$post = new \stdClass();
$post->ID = $order->get_id();
$order = WC_Helper_Order::create_order( 1, $product );
global $theorder;
$theorder = $order;
return $order;
}
@ -274,5 +229,4 @@ class WC_Admin_Tests_Shipping_Label_Banner_Display_Rules extends WC_Unit_Test_Ca
$this->destroy_order( $order );
}
}