Make shipping total in Cart/Checkout block order summaries show FREE if shipping price is 0 (#47553)

* Make shipping total show FREE if price is 0

* Make free text uppercase in order summary

* Add test to check free/paid shipping displays as free or shows price

* Add changelog

* Update E2E test to make sure shipping is selected correctly

* Update shipping cost e2e tests

* Further fixes to e2e tests
This commit is contained in:
Thomas Roberts 2024-05-20 17:42:54 +01:00 committed by GitHub
parent b938331d87
commit d7ca80d6c8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 146 additions and 10 deletions

View File

@ -85,6 +85,13 @@ export const TotalsShipping = ( {
shippingRates
);
const valueToDisplay =
totalShippingValue === 0 ? (
<strong>{ __( 'Free', 'woocommerce' ) }</strong>
) : (
totalShippingValue
);
return (
<div
className={ classnames(
@ -97,7 +104,7 @@ export const TotalsShipping = ( {
value={
! shippingMethodsMissing && cartHasCalculatedShipping
? // if address is not complete, display the link to add an address.
totalShippingValue
valueToDisplay
: ( ! addressComplete || isCheckout ) && (
<ShippingPlaceholder
showCalculator={ showCalculator }

View File

@ -7,6 +7,11 @@
border: 0;
}
.wc-block-components-totals-item strong {
text-transform: uppercase;
}
.wc-block-components-shipping-address {
margin-top: $gap;
display: block;

View File

@ -177,6 +177,121 @@ baseContextHooks.useStoreCart.mockReturnValue( {
} );
describe( 'TotalsShipping', () => {
it( 'shows FREE if shipping cost is 0', () => {
baseContextHooks.useStoreCart.mockReturnValue( {
cartItems: mockPreviewCart.items,
cartTotals: [ mockPreviewCart.totals ],
cartCoupons: mockPreviewCart.coupons,
cartFees: mockPreviewCart.fees,
cartNeedsShipping: mockPreviewCart.needs_shipping,
shippingRates: [
{
package_id: 0,
name: 'Initial Shipment',
destination: {
address_1: '30 Test Street',
address_2: 'Apt 1 Shipping',
city: 'Liverpool',
state: '',
postcode: 'L1 0BP',
country: 'GB',
},
items: [
{
key: 'acf4b89d3d503d8252c9c4ba75ddbf6d',
name: 'Test product',
quantity: 1,
},
],
shipping_rates: [
{
rate_id: 'free_shipping:1',
name: 'Free shipping',
description: '',
delivery_time: '',
price: '0',
taxes: '0',
instance_id: 13,
method_id: 'free_shipping',
meta_data: [
{
key: 'Items',
value: 'Test product &times; 1',
},
],
selected: false,
currency_code: 'USD',
currency_symbol: '$',
currency_minor_unit: 2,
currency_decimal_separator: '.',
currency_thousand_separator: ',',
currency_prefix: '$',
currency_suffix: '',
},
],
},
],
shippingAddress,
billingAddress: mockPreviewCart.billing_address,
cartHasCalculatedShipping: mockPreviewCart.has_calculated_shipping,
isLoadingRates: false,
} );
const { rerender } = render(
<SlotFillProvider>
<TotalsShipping
currency={ {
code: 'USD',
symbol: '$',
minorUnit: 2,
decimalSeparator: '.',
prefix: '',
suffix: '',
thousandSeparator: ', ',
} }
values={ {
total_shipping: '0',
total_shipping_tax: '0',
} }
showCalculator={ true }
showRateSelector={ false }
isCheckout={ false }
className={ '' }
/>
</SlotFillProvider>
);
expect(
screen.getByText( 'Free', { exact: true } )
).toBeInTheDocument();
expect( screen.queryByText( '0.00' ) ).not.toBeInTheDocument();
rerender(
<SlotFillProvider>
<TotalsShipping
currency={ {
code: 'USD',
symbol: '$',
minorUnit: 2,
decimalSeparator: '.',
prefix: '',
suffix: '',
thousandSeparator: ', ',
} }
values={ {
total_shipping: '5678',
total_shipping_tax: '0',
} }
showCalculator={ true }
showRateSelector={ false }
isCheckout={ false }
className={ '' }
/>
</SlotFillProvider>
);
expect( screen.queryByText( 'Free' ) ).not.toBeInTheDocument();
expect( screen.getByText( '56.78' ) ).toBeInTheDocument();
} );
it( 'should show correct calculator button label if address is complete', () => {
render(
<SlotFillProvider>
@ -184,8 +299,11 @@ describe( 'TotalsShipping', () => {
currency={ {
code: 'USD',
symbol: '$',
position: 'left',
precision: 2,
minorUnit: 2,
decimalSeparator: '.',
prefix: '',
suffix: '',
thousandSeparator: ', ',
} }
values={ {
total_shipping: '0',

View File

@ -47,7 +47,7 @@ export class CheckoutPage {
.getByText( shippingName )
.isVisible();
const priceIsVisible = await shippingLine
.getByText( shippingPrice )
.getByText( shippingPrice, { exact: true } )
.isVisible();
return nameIsVisible && priceIsVisible;
}

View File

@ -1,7 +1,7 @@
export const SIMPLE_VIRTUAL_PRODUCT_NAME = 'Album';
export const SIMPLE_PHYSICAL_PRODUCT_NAME = 'Beanie';
export const FREE_SHIPPING_NAME = 'Free shipping';
export const FREE_SHIPPING_PRICE = '$0.00';
export const FREE_SHIPPING_PRICE = 'Free';
export const FLAT_RATE_SHIPPING_NAME = 'Flat rate shipping';
export const FLAT_RATE_SHIPPING_PRICE = '$10.00';
export const DISCOUNTED_PRODUCT_NAME = 'Cap';

View File

@ -0,0 +1,4 @@
Significance: minor
Type: update
When the total shipping cost is 0 the order summary in the Cart and Checkout blocks shows "FREE" instead of 0.00

View File

@ -148,8 +148,10 @@ baseTest.describe( 'Cart Block Calculate Shipping', () => {
await expect(
page.getByRole( 'group' ).getByText( 'Free shipping' )
).toBeVisible();
await expect( page.getByText( 'Free', { exact: true } ) ).toBeVisible();
await expect( page.getByText( '$' ).nth( 4 ) ).toContainText(
await expect(
page.getByRole( 'strong' ).getByText( 'Free', { exact: true } )
).toBeVisible();
await expect( page.getByText( '$' ).nth( 2 ) ).toContainText(
firstProductPrice
);
} );
@ -184,8 +186,8 @@ baseTest.describe( 'Cart Block Calculate Shipping', () => {
await page.getByRole( 'group' ).getByText( 'Local pickup' ).click();
// Verify updated shipping costs
await expect( page.getByText( 'Shipping$0.00Local' ) ).toBeVisible();
await expect( page.getByText( '$' ).nth( 5 ) ).toContainText(
await expect( page.getByText( 'ShippingFreeLocal' ) ).toBeVisible();
await expect( page.getByText( '$' ).nth( 2 ) ).toContainText(
firstProductPrice
);
} );
@ -257,7 +259,7 @@ baseTest.describe( 'Cart Block Calculate Shipping', () => {
await page.getByRole( 'group' ).getByText( 'Local pickup' ).click();
// Verify updated shipping costs
await expect( page.getByText( 'Shipping$0.00Local' ) ).toBeVisible();
await expect( page.getByText( 'ShippingFreeLocal' ) ).toBeVisible();
await expect(
page
.locator( 'div' )