Skip to content
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d2f93de
Stripe Tax extension promotional banner
wjrosa Nov 13, 2025
daf2b8f
Unit tests
wjrosa Nov 13, 2025
37d3f35
Merge branch 'develop' into add/stripe-tax-extension-promotional-banner
wjrosa Nov 14, 2025
eefa91d
Adding the banner illustration
wjrosa Nov 14, 2025
dd66c61
Merge branch 'develop' into add/stripe-tax-extension-promotional-banner
wjrosa Nov 17, 2025
4553399
Splitting paragraphs
wjrosa Nov 17, 2025
2ab87ee
Formatting update + fix tests
wjrosa Nov 17, 2025
82ef6dd
Tracking button click
wjrosa Nov 17, 2025
8ecfa03
Merge branch 'develop' into add/stripe-tax-extension-promotional-banner
wjrosa Nov 18, 2025
58b6830
Opening extension URL in a new tab
wjrosa Nov 18, 2025
22a35b6
Merge branch 'develop' into add/stripe-tax-extension-promotional-banner
wjrosa Nov 19, 2025
48426b3
Merge branch 'develop' into add/stripe-tax-extension-promotional-banner
wjrosa Nov 19, 2025
780b48d
Merge branch 'develop' into add/stripe-tax-extension-promotional-banner
wjrosa Nov 28, 2025
38a4e42
Merge branch 'develop' into add/stripe-tax-extension-promotional-banner
daledupreez Nov 28, 2025
71a9080
Update client/settings/payment-settings/promotional-banner/stripe-tax…
wjrosa Dec 1, 2025
25dc935
Merge branch 'develop' into add/stripe-tax-extension-promotional-banner
wjrosa Dec 1, 2025
ae2ba31
Update client/settings/payment-settings/promotional-banner/stripe-tax…
wjrosa Dec 1, 2025
be2c673
Moving the external URL to the href attr + external icon
wjrosa Dec 1, 2025
4fef8d1
Removing important declaration
wjrosa Dec 1, 2025
ac1a62a
Merge branch 'develop' into add/stripe-tax-extension-promotional-banner
wjrosa Dec 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* Fix - Ensure state and postal code are optional in express checkout for Gulf countries (UAE, Bahrain, Kuwait, Oman, Qatar)
* Dev - Removes the `_wcstripe_feature_upe` feature flag and the related method from the `WC_Stripe_Feature_Flags` class
* Dev - Fixes some incorrect subscriptions support implementations for payment methods
* Add - New promotional banner to highlight the Stripe Tax extension for OCS-enabled merchants
* Fix - Ensure correct express checkout prices in block cart and checkout with non-default decimal configuration
* Fix - Disable express checkout when Amazon Pay is disabled and the only method
* Fix - Don't allow WP-Cron jobs to detach payment methods on staging sites
Expand Down
1 change: 1 addition & 0 deletions client/settings/payment-settings/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export const NEW_CHECKOUT_EXPERIENCE_APMS_BANNER =
'new-checkout-experience-apms';
export const BNPL_PROMOTION_BANNER = 'bnpl_promotion_banner';
export const OC_PROMOTION_BANNER = 'oc_promotion_banner';
export const STRIPE_TAX_BANNER = 'stripe-tax-banner';
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
NEW_CHECKOUT_EXPERIENCE_BANNER,
OC_PROMOTION_BANNER,
RECONNECT_BANNER,
STRIPE_TAX_BANNER,
} from 'wcstripe/settings/payment-settings/constants';
import {
PAYMENT_METHOD_CARD,
Expand Down Expand Up @@ -33,6 +34,30 @@ describe( 'getPromotionalBannerType', () => {
)
).toBe( RECONNECT_BANNER );
} );
it( 'Stripe Tax banner', () => {
global.wc_stripe_settings_params = {
is_oc_available: true,
};

const accountData = {
testmode: false,
oauth_connections: {
live: { connected: true },
},
};
const isUpeEnabled = true;
const isOCEnabled = true;
const enabledPaymentMethodIds = [ PAYMENT_METHOD_CARD ];

expect(
getPromotionalBannerType(
accountData,
isUpeEnabled,
isOCEnabled,
enabledPaymentMethodIds
)
).toBe( STRIPE_TAX_BANNER );
} );
it( 'OC promotion banner', () => {
global.wc_stripe_settings_params = {
is_oc_available: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,6 @@ describe( 'OC promotional banner', () => {
} );

it( 'should make an API call to dismiss the banner on button click', async () => {
// Keep the original function.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just removing this as it is not needed

const reload = window.location.reload;
Object.defineProperty( window, 'location', {
value: { reload: jest.fn() },
} );

const dismissNoticeMock = jest.fn( () =>
Promise.resolve( { data: {} } )
);
Expand All @@ -77,11 +71,6 @@ describe( 'OC promotional banner', () => {
await userEvent.click( dismissButton );
} );
expect( dismissNoticeMock ).toHaveBeenCalled();

// Set the original function back to keep further tests working as expected.
Object.defineProperty( window, 'location', {
value: { reload },
} );
} );

it( 'should attempt to enable OC when clicking the "Activate now" button', async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { act, render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { StripeTaxBanner } from '../stripe-tax-banner';
import apiFetch from '@wordpress/api-fetch';
import { recordEvent } from 'wcstripe/tracking';

jest.mock( '@wordpress/api-fetch' );

jest.mock( 'wcstripe/tracking', () => ( {
recordEvent: jest.fn(),
} ) );

describe( 'Stripe Tax banner', () => {
const setShowPromotionalBanner = jest.fn();

beforeEach( () => {
apiFetch.mockImplementation(
jest.fn( () => Promise.resolve( { data: {} } ) )
);
} );

afterEach( () => {
jest.clearAllMocks();
} );

it( 'should render the Stripe Tax banner', () => {
const { getByText } = render(
<StripeTaxBanner
setShowPromotionalBanner={ setShowPromotionalBanner }
/>
);
expect(
getByText( 'Automate tax compliance with Stripe Tax' )
).toBeInTheDocument();
expect(
getByText(
/Automatically calculate and collect sales tax, value-added tax \(VAT\), and goods and services tax \(GST\) wherever you sell./
)
).toBeInTheDocument();
} );

it( 'should make an API call to dismiss the banner on button click', async () => {
const dismissNoticeMock = jest.fn( () =>
Promise.resolve( { data: {} } )
);
apiFetch.mockImplementation( dismissNoticeMock );

const { getByText } = render(
<StripeTaxBanner
setShowPromotionalBanner={ setShowPromotionalBanner }
/>
);
const dismissButton = getByText( 'Dismiss' );

await act( async () => {
await userEvent.click( dismissButton );
} );
expect( dismissNoticeMock ).toHaveBeenCalled();
} );

it( 'should open the main page when clicking the "Get Stripe Tax" button', async () => {
// Keep the original function at hand.
const open = window.open;

Object.defineProperty( window, 'open', {
value: jest.fn(),
} );

const { getByText } = render(
<StripeTaxBanner
setShowPromotionalBanner={ setShowPromotionalBanner }
/>
);
const activateButton = getByText( 'Get Stripe Tax' );

await act( async () => {
await userEvent.click( activateButton );
} );

expect( recordEvent ).toHaveBeenCalledWith(
'wcstripe_stripe_tax_banner_button_click',
{}
);

expect( window.open ).toHaveBeenCalledWith(
'https://woocommerce.com/products/stripe-tax/',
'_blank'
);

// Set the original function back to keep further tests working as expected.
Object.defineProperty( window, 'open', {
value: open,
} );
} );
} );
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
NEW_CHECKOUT_EXPERIENCE_BANNER,
OC_PROMOTION_BANNER,
RECONNECT_BANNER,
STRIPE_TAX_BANNER,
} from 'wcstripe/settings/payment-settings/constants';
import {
BNPL_METHODS,
Expand Down Expand Up @@ -39,6 +40,12 @@ export const getPromotionalBannerType = (

if ( oauthConnected === false ) {
return RECONNECT_BANNER;
} else if (
// eslint-disable-next-line camelcase
wc_stripe_settings_params?.is_oc_available &&
isOCEnabled
) {
return STRIPE_TAX_BANNER;
} else if (
// eslint-disable-next-line camelcase
wc_stripe_settings_params?.is_oc_available &&
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions client/settings/payment-settings/promotional-banner/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import {
BNPL_PROMOTION_BANNER,
NEW_CHECKOUT_EXPERIENCE_APMS_BANNER,
OC_PROMOTION_BANNER,
STRIPE_TAX_BANNER,
} from '../constants';
import { ReConnectAccountBanner } from 'wcstripe/settings/payment-settings/promotional-banner/re-connect-account-banner';
import { NewCheckoutExperienceAPMsBanner } from 'wcstripe/settings/payment-settings/promotional-banner/new-checkout-experience-apms-banner';
import { NewCheckoutExperienceBanner } from 'wcstripe/settings/payment-settings/promotional-banner/new-checkout-experience-banner';
import { BNPLPromotionBanner } from 'wcstripe/settings/payment-settings/promotional-banner/bnpl-promotion-banner';
import { BannerCard } from 'wcstripe/settings/payment-settings/promotional-banner/banner-layout';
import { OCPromotionBanner } from 'wcstripe/settings/payment-settings/promotional-banner/oc-promotion-banner';
import { StripeTaxBanner } from 'wcstripe/settings/payment-settings/promotional-banner/stripe-tax-banner';

const PromotionalBanner = ( {
setShowPromotionalBanner,
Expand All @@ -31,6 +33,13 @@ const PromotionalBanner = ( {
/>
);
break;
case STRIPE_TAX_BANNER:
BannerContent = (
<StripeTaxBanner
setShowPromotionalBanner={ setShowPromotionalBanner }
/>
);
break;
case OC_PROMOTION_BANNER:
BannerContent = (
<OCPromotionBanner
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ export const OCPromotionBanner = ( {
) }
</TitleBNPL>
<p>
{ __( '', 'woocommerce-gateway-stripe' ) }
{ interpolateComponents( {
mixedString: __(
"Optimize your checkout experience for more sales by dynamically displaying the most relevant payment methods you've enabled for each customer. {{docLink}}Learn more{{/docLink}} about Stripe's Optimized Checkout Suite.",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { React } from 'react';
import styled from '@emotion/styled';
import interpolateComponents from '@automattic/interpolate-components';
import { __ } from '@wordpress/i18n';
import apiFetch from '@wordpress/api-fetch';
import CardBody from 'wcstripe/settings/card-body';
import illustration from 'wcstripe/settings/payment-settings/promotional-banner/illustrations/stripe-tax.svg';
import {
BannerIllustration,
ButtonsRow,
CardColumn,
CardInner,
DismissButton,
MainCTALink,
} from 'wcstripe/settings/payment-settings/promotional-banner/banner-layout';
import { recordEvent } from 'wcstripe/tracking';
import { ExternalLink } from '@wordpress/components';

const BannerIllustrationStripeTax = styled( BannerIllustration )`
width: 80px;
margin: 10px;
@media ( min-width: 600px ) {
margin-bottom: -30px;
}
`;

const ButtonsRowStripeTax = styled( ButtonsRow )`
@media ( min-width: 600px ) {
margin-bottom: 0.7em;
}
`;

const ColumnIllustration = styled( CardColumn )`
@media ( max-width: 599px ) {
text-align: center;
}
`;

const TitleStripeTax = styled.h4`
margin-top: 0.6em !important;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this !important? Please add a comment as to why, as it looks very suspicious otherwise.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is just an inherited style (from previous banners) to make it look exactly like the Figma previews. But I just removed it, and it did not make a visual difference for me.

What do you mean by "suspicious"?

font-weight: 500;
`;

export const StripeTaxBanner = ( { setShowPromotionalBanner } ) => {
const handleBannerDismiss = () => {
apiFetch( {
path: '/wc/v3/wc_stripe/settings/notice',
method: 'POST',
data: { wc_stripe_show_stripe_tax_banner: 'no' },
} ).finally( () => {
setShowPromotionalBanner( false );
} );
};

const handleButtonClick = () => {
recordEvent( 'wcstripe_stripe_tax_banner_button_click', {} );
window.open( 'https://woocommerce.com/products/stripe-tax/', '_blank' );
};

return (
<CardBody>
<CardInner>
<CardColumn>
<TitleStripeTax>
{ __(
'Automate tax compliance with Stripe Tax',
'woocommerce-gateway-stripe'
) }
</TitleStripeTax>
<p>
{ interpolateComponents( {
mixedString: __(
'Automatically calculate and collect sales tax, value-added tax (VAT), and goods and services tax (GST) wherever you sell. {{docLink}}Learn more{{/docLink}} about how Stripe Tax keeps you compliant.',
'woocommerce-gateway-stripe'
),
components: {
docLink: (
<ExternalLink href="https://stripe.com/tax" />
),
},
} ) }
</p>
</CardColumn>
<ColumnIllustration>
<BannerIllustrationStripeTax
src={ illustration }
alt={ __(
'Get Stripe Tax',
'woocommerce-gateway-stripe'
) }
/>
</ColumnIllustration>
</CardInner>
<ButtonsRowStripeTax>
<MainCTALink variant="secondary" onClick={ handleButtonClick }>
{ __( 'Get Stripe Tax', 'woocommerce-gateway-stripe' ) }
</MainCTALink>
<DismissButton
variant="secondary"
onClick={ handleBannerDismiss }
data-testid="dismiss"
>
{ __( 'Dismiss', 'woocommerce-gateway-stripe' ) }
</DismissButton>
</ButtonsRowStripeTax>
</CardBody>
);
};
8 changes: 8 additions & 0 deletions client/settings/settings-manager/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { getPromotionalBannerType } from 'wcstripe/settings/payment-settings/pro
import {
BNPL_PROMOTION_BANNER,
OC_PROMOTION_BANNER,
STRIPE_TAX_BANNER,
} from 'wcstripe/settings/payment-settings/constants';

const StyledTabPanel = styled( TabPanel )`
Expand Down Expand Up @@ -59,6 +60,13 @@ const SettingsManager = () => {
) {
initialBannerState = true;
}
if (
promotionalBannerType === STRIPE_TAX_BANNER &&
// eslint-disable-next-line camelcase
wc_stripe_settings_params?.show_stripe_tax_banner === '1'
) {
initialBannerState = true;
}
if (
promotionalBannerType === OC_PROMOTION_BANNER &&
// eslint-disable-next-line camelcase
Expand Down
5 changes: 5 additions & 0 deletions includes/admin/class-wc-stripe-settings-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,10 @@ public function admin_scripts( $hook_suffix ) {
// Show the OC promotional banner only if OC is disabled
&& ! $is_oc_enabled;

$show_stripe_tax_banner = get_option( 'wc_stripe_show_stripe_tax_banner', 'yes' ) === 'yes'
// Show the Stripe Tax banner only if OC is enabled
&& $is_oc_enabled;

$params = [
'time' => time(),
'i18n_out_of_sync' => $message,
Expand All @@ -273,6 +277,7 @@ public function admin_scripts( $hook_suffix ) {
'show_optimized_checkout_notice' => get_option( 'wc_stripe_show_optimized_checkout_notice', 'yes' ) === 'yes' ? true : false,
'show_bnpl_promotional_banner' => $show_bnpl_promotion_banner,
'show_oc_promotional_banner' => $show_oc_promotion_banner,
'show_stripe_tax_banner' => $show_stripe_tax_banner,
'is_test_mode' => $this->get_gateway()->is_in_test_mode(),
'plugin_version' => WC_STRIPE_VERSION,
'account_country' => $this->account->get_account_country(),
Expand Down
1 change: 1 addition & 0 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ If you get stuck, you can ask for help in the [Plugin Forum](https://wordpress.o
* Fix - Ensure state and postal code are optional in express checkout for Gulf countries (UAE, Bahrain, Kuwait, Oman, Qatar)
* Dev - Removes the `_wcstripe_feature_upe` feature flag and the related method from the `WC_Stripe_Feature_Flags` class
* Dev - Fixes some incorrect subscriptions support implementations for payment methods
* Add - New promotional banner to highlight the Stripe Tax extension for OCS-enabled merchants
* Fix - Ensure correct express checkout prices in block cart and checkout with non-default decimal configuration
* Fix - Disable express checkout when Amazon Pay is disabled and the only method
* Fix - Don't allow WP-Cron jobs to detach payment methods on staging sites
Expand Down
Loading