From 52f902c7fd95a618988926ab0bba95b6b4b6f122 Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Mon, 23 Jan 2023 22:36:31 +0400 Subject: [PATCH 01/25] Remove hardcoded notices & change display shipping calculator condition - Replace hardcoded notices with text for Cart and Checkout block. - Fix shipping placeholder for the Checkout block when no shipping rates are available. - Created a function in base/utils to format Shipping address. - Remove the condition to check default customer address. Display the "Add shipping address" link only when there is no address available. - Hide shipping calculator if default shipping are defined. --- .../cart-checkout/shipping-location/index.tsx | 45 ++-------------- .../cart-checkout/totals/shipping/index.tsx | 4 ++ .../totals/shipping/shipping-address.tsx | 7 ++- .../totals/shipping/shipping-placeholder.tsx | 4 ++ .../shipping/shipping-rate-selector.tsx | 23 ++++---- assets/js/base/utils/address.ts | 52 +++++++++++++++++++ .../checkout-order-summary-shipping/block.tsx | 1 + .../checkout-shipping-methods-block/block.tsx | 37 +++++++------ 8 files changed, 103 insertions(+), 70 deletions(-) diff --git a/assets/js/base/components/cart-checkout/shipping-location/index.tsx b/assets/js/base/components/cart-checkout/shipping-location/index.tsx index b57fc0985d1..5005a0349c0 100644 --- a/assets/js/base/components/cart-checkout/shipping-location/index.tsx +++ b/assets/js/base/components/cart-checkout/shipping-location/index.tsx @@ -2,56 +2,21 @@ * External dependencies */ import { __, sprintf } from '@wordpress/i18n'; -import { ShippingAddress, getSetting } from '@woocommerce/settings'; -import { decodeEntities } from '@wordpress/html-entities'; interface ShippingLocationProps { - address: ShippingAddress; + formattedLocation: string | null; } /** * Shows a formatted shipping location. * - * @param {Object} props Incoming props for the component. - * @param {Object} props.address Incoming address information. + * @param {Object} props Incoming props for the component. + * @param {string} props.formattedLocation Formatted location. + * @return {JSX.Element|null} The component. */ const ShippingLocation = ( { - address, + formattedLocation, }: ShippingLocationProps ): JSX.Element | null => { - // we bail early if we don't have an address. - if ( Object.values( address ).length === 0 ) { - return null; - } - const shippingCountries = getSetting( 'shippingCountries', {} ) as Record< - string, - string - >; - const shippingStates = getSetting( 'shippingStates', {} ) as Record< - string, - Record< string, string > - >; - const formattedCountry = - typeof shippingCountries[ address.country ] === 'string' - ? decodeEntities( shippingCountries[ address.country ] ) - : ''; - - const formattedState = - typeof shippingStates[ address.country ] === 'object' && - typeof shippingStates[ address.country ][ address.state ] === 'string' - ? decodeEntities( - shippingStates[ address.country ][ address.state ] - ) - : address.state; - - const addressParts = []; - - addressParts.push( address.postcode.toUpperCase() ); - addressParts.push( address.city ); - addressParts.push( formattedState ); - addressParts.push( formattedCountry ); - - const formattedLocation = addressParts.filter( Boolean ).join( ', ' ); - if ( ! formattedLocation ) { return null; } diff --git a/assets/js/base/components/cart-checkout/totals/shipping/index.tsx b/assets/js/base/components/cart-checkout/totals/shipping/index.tsx index 06febfcafd9..ea22130f9f1 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/index.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/index.tsx @@ -10,6 +10,7 @@ import type { Currency } from '@woocommerce/price-format'; import { ShippingVia } from '@woocommerce/base-components/cart-checkout/totals/shipping/shipping-via'; import { useSelect } from '@wordpress/data'; import { CHECKOUT_STORE_KEY } from '@woocommerce/block-data'; +import { formatShippingAddress } from '@woocommerce/base-utils'; /** * Internal dependencies @@ -67,6 +68,8 @@ export const TotalsShipping = ( { } ); + const isAddressComplete = !! formatShippingAddress( shippingAddress ); + return (
) }
diff --git a/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx b/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx index 0df38408184..452126adc45 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx @@ -3,6 +3,7 @@ */ import { __ } from '@wordpress/i18n'; import { EnteredAddress } from '@woocommerce/settings'; +import { formatShippingAddress } from '@woocommerce/base-utils'; /** * Internal dependencies @@ -23,9 +24,13 @@ export const ShippingAddress = ( { setIsShippingCalculatorOpen, shippingAddress, }: ShippingAddressProps ): JSX.Element | null => { + const formattedLocation = formatShippingAddress( shippingAddress ); + if ( ! formattedLocation ) { + return null; + } return ( <> - + { showCalculator && ( diff --git a/assets/js/base/components/cart-checkout/totals/shipping/shipping-rate-selector.tsx b/assets/js/base/components/cart-checkout/totals/shipping/shipping-rate-selector.tsx index 78fcf12a674..0b8eae03983 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/shipping-rate-selector.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/shipping-rate-selector.tsx @@ -2,8 +2,6 @@ * External dependencies */ import { __ } from '@wordpress/i18n'; -import { Notice } from 'wordpress-components'; -import classnames from 'classnames'; import type { CartResponseShippingRate } from '@woocommerce/types'; /** @@ -15,12 +13,14 @@ export interface ShippingRateSelectorProps { hasRates: boolean; shippingRates: CartResponseShippingRate[]; isLoadingRates: boolean; + isAddressComplete: boolean; } export const ShippingRateSelector = ( { hasRates, shippingRates, isLoadingRates, + isAddressComplete, }: ShippingRateSelectorProps ): JSX.Element => { const legend = hasRates ? __( 'Shipping options', 'woo-gutenberg-products-block' ) @@ -31,18 +31,13 @@ export const ShippingRateSelector = ( { - { __( - 'No shipping options were found.', - 'woo-gutenberg-products-block' - ) } - + <> + { isAddressComplete && + __( + 'No shipping options were found.', + 'woo-gutenberg-products-block' + ) } + } shippingRates={ shippingRates } isLoadingRates={ isLoadingRates } diff --git a/assets/js/base/utils/address.ts b/assets/js/base/utils/address.ts index e3738fb614b..ee078d659fd 100644 --- a/assets/js/base/utils/address.ts +++ b/assets/js/base/utils/address.ts @@ -11,7 +11,9 @@ import { defaultAddressFields, ShippingAddress, BillingAddress, + getSetting, } from '@woocommerce/settings'; +import { decodeEntities } from '@wordpress/html-entities'; /** * Compare two addresses and see if they are the same. @@ -100,3 +102,53 @@ export const emptyHiddenAddressFields = < return newAddress; }; + +/* + * Formats a shipping address for display. + * + * @param {Object} address The address to format. + * @return {string | null} The formatted address or null if no address is provided. + */ +export const formatShippingAddress = ( + address: ShippingAddress | BillingAddress +): string | null => { + // we bail early if we don't have an address. + if ( Object.values( address ).length === 0 ) { + return null; + } + const shippingCountries = getSetting( 'shippingCountries', {} ) as Record< + string, + string + >; + const shippingStates = getSetting( 'shippingStates', {} ) as Record< + string, + Record< string, string > + >; + const formattedCountry = + typeof shippingCountries[ address.country ] === 'string' + ? decodeEntities( shippingCountries[ address.country ] ) + : ''; + + const formattedState = + typeof shippingStates[ address.country ] === 'object' && + typeof shippingStates[ address.country ][ address.state ] === 'string' + ? decodeEntities( + shippingStates[ address.country ][ address.state ] + ) + : address.state; + + const addressParts = []; + + addressParts.push( address.postcode.toUpperCase() ); + addressParts.push( address.city ); + addressParts.push( formattedState ); + addressParts.push( formattedCountry ); + + const formattedLocation = addressParts.filter( Boolean ).join( ', ' ); + + if ( ! formattedLocation ) { + return null; + } + + return formattedLocation; +}; diff --git a/assets/js/blocks/checkout/inner-blocks/checkout-order-summary-shipping/block.tsx b/assets/js/blocks/checkout/inner-blocks/checkout-order-summary-shipping/block.tsx index 84fd6e36b67..7ca7678c2b1 100644 --- a/assets/js/blocks/checkout/inner-blocks/checkout-order-summary-shipping/block.tsx +++ b/assets/js/blocks/checkout/inner-blocks/checkout-order-summary-shipping/block.tsx @@ -26,6 +26,7 @@ const Block = ( { showRateSelector={ false } values={ cartTotals } currency={ totalsCurrency } + isCheckout={ true } /> ); diff --git a/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx b/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx index 067d17ee057..59deda3612c 100644 --- a/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx +++ b/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx @@ -4,19 +4,22 @@ import { __ } from '@wordpress/i18n'; import { useShippingData } from '@woocommerce/base-context/hooks'; import { ShippingRatesControl } from '@woocommerce/base-components/cart-checkout'; -import { getShippingRatesPackageCount } from '@woocommerce/base-utils'; +import { + getShippingRatesPackageCount, + formatShippingAddress, +} from '@woocommerce/base-utils'; import { getCurrencyFromPriceResponse } from '@woocommerce/price-format'; import FormattedMonetaryAmount from '@woocommerce/base-components/formatted-monetary-amount'; import { useEditorContext, noticeContexts } from '@woocommerce/base-context'; import { StoreNoticesContainer } from '@woocommerce/blocks-checkout'; import { decodeEntities } from '@wordpress/html-entities'; -import { Notice } from 'wordpress-components'; -import classnames from 'classnames'; import { getSetting } from '@woocommerce/settings'; import type { PackageRateOption, CartShippingPackageShippingRate, } from '@woocommerce/types'; +import { CART_STORE_KEY } from '@woocommerce/block-data'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -73,10 +76,15 @@ const Block = (): JSX.Element | null => { } ) : shippingRates; + const shippingAddress = useSelect( ( select ) => { + return select( CART_STORE_KEY ).getCustomerData()?.shippingAddress; + } ); + if ( ! needsShipping ) { return null; } + const addressComplete = !! formatShippingAddress( shippingAddress ); const shippingRatesPackageCount = getShippingRatesPackageCount( shippingRates ); @@ -105,18 +113,17 @@ const Block = (): JSX.Element | null => { ) : ( - { __( - 'There are no shipping options available. Please check your shipping address.', - 'woo-gutenberg-products-block' - ) } - + <> + { addressComplete + ? __( + 'There are no shipping options available. Please check your shipping address.', + 'woo-gutenberg-products-block' + ) + : __( + 'Add a shipping address to view shipping options.', + 'woo-gutenberg-products-block' + ) } + } renderOption={ renderShippingRatesControlOption } collapsible={ false } From bfe198637b97c970be2759cd45145c1efa5eb4c2 Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Fri, 27 Jan 2023 13:49:26 +0400 Subject: [PATCH 02/25] Fix the label of the calculator button and TypeScript - Change the label of the calculator button from "Add an address for shipping rates" to "Add an address for shipping options". - Fix the TypeScript of the utils/address file. - Remove the docblock comments from shipping location block --- .../cart-checkout/shipping-location/index.tsx | 8 +------- .../totals/shipping/shipping-placeholder.tsx | 2 +- assets/js/base/utils/address.ts | 16 ++++++++-------- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/assets/js/base/components/cart-checkout/shipping-location/index.tsx b/assets/js/base/components/cart-checkout/shipping-location/index.tsx index 5005a0349c0..4f0c4f0b5b0 100644 --- a/assets/js/base/components/cart-checkout/shipping-location/index.tsx +++ b/assets/js/base/components/cart-checkout/shipping-location/index.tsx @@ -7,13 +7,7 @@ interface ShippingLocationProps { formattedLocation: string | null; } -/** - * Shows a formatted shipping location. - * - * @param {Object} props Incoming props for the component. - * @param {string} props.formattedLocation Formatted location. - * @return {JSX.Element|null} The component. - */ +// Shows a formatted shipping location. const ShippingLocation = ( { formattedLocation, }: ShippingLocationProps ): JSX.Element | null => { diff --git a/assets/js/base/components/cart-checkout/totals/shipping/shipping-placeholder.tsx b/assets/js/base/components/cart-checkout/totals/shipping/shipping-placeholder.tsx index 046baa5691c..23c97c31169 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/shipping-placeholder.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/shipping-placeholder.tsx @@ -40,7 +40,7 @@ export const ShippingPlaceholder = ( { return ( ; - const shippingStates = getSetting( 'shippingStates', {} ) as Record< - string, - Record< string, string > - >; + const shippingCountries = getSetting< Record< string, string > >( + 'shippingCountries', + {} + ); + const shippingStates = getSetting< Record< string, string > >( + 'shippingStates', + {} + ); const formattedCountry = typeof shippingCountries[ address.country ] === 'string' ? decodeEntities( shippingCountries[ address.country ] ) From 0b0d6186cb874acc7a039a1eb05aaf042acb5d90 Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Mon, 30 Jan 2023 18:42:38 +0400 Subject: [PATCH 03/25] Change the link style and fix editor issue - If no shipping rates are available, we will display a link instead of a button. - Display change address button when we're in Editor as some e2e tests are dependent on it --- .../totals/shipping/calculator-button.tsx | 29 +++++++++++++++++-- .../totals/shipping/shipping-address.tsx | 6 +++- .../totals/shipping/shipping-placeholder.tsx | 1 + .../cart-checkout/totals/shipping/style.scss | 3 ++ 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx b/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx index 9607ab9fd7f..09d9958932a 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx @@ -5,25 +5,48 @@ import { __ } from '@wordpress/i18n'; export interface CalculatorButtonProps { label?: string; + hasRates?: boolean | undefined; isShippingCalculatorOpen: boolean; setIsShippingCalculatorOpen: ( isShippingCalculatorOpen: boolean ) => void; } export const CalculatorButton = ( { label = __( 'Calculate', 'woo-gutenberg-products-block' ), + hasRates = true, isShippingCalculatorOpen, setIsShippingCalculatorOpen, }: CalculatorButtonProps ): JSX.Element => { + // If shipping rates are available. We want to show a button instead of a link. + if ( hasRates ) { + return ( + + ); + } + + // If no shipping rates are available, we want to show a link instead of a button. + // This is because the style of the link will match the link style of the theme like "Add a coupon". return ( - + ); }; diff --git a/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx b/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx index 452126adc45..2fa1d7143d7 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx @@ -4,6 +4,7 @@ import { __ } from '@wordpress/i18n'; import { EnteredAddress } from '@woocommerce/settings'; import { formatShippingAddress } from '@woocommerce/base-utils'; +import { useEditorContext } from '@woocommerce/base-context'; /** * Internal dependencies @@ -25,7 +26,10 @@ export const ShippingAddress = ( { shippingAddress, }: ShippingAddressProps ): JSX.Element | null => { const formattedLocation = formatShippingAddress( shippingAddress ); - if ( ! formattedLocation ) { + const { isEditor } = useEditorContext(); + + // If there is no address, and we're not in the editor, don't show anything. + if ( ! formattedLocation && ! isEditor ) { return null; } return ( diff --git a/assets/js/base/components/cart-checkout/totals/shipping/shipping-placeholder.tsx b/assets/js/base/components/cart-checkout/totals/shipping/shipping-placeholder.tsx index 23c97c31169..95446630773 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/shipping-placeholder.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/shipping-placeholder.tsx @@ -45,6 +45,7 @@ export const ShippingPlaceholder = ( { ) } isShippingCalculatorOpen={ isShippingCalculatorOpen } setIsShippingCalculatorOpen={ setIsShippingCalculatorOpen } + hasRates={ false } /> ); }; diff --git a/assets/js/base/components/cart-checkout/totals/shipping/style.scss b/assets/js/base/components/cart-checkout/totals/shipping/style.scss index 9562503f8bf..d91bcabc8c2 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/style.scss +++ b/assets/js/base/components/cart-checkout/totals/shipping/style.scss @@ -26,6 +26,9 @@ margin: 0 0 em($gap-small); } + .wc-block-components-totals-shipping__change-address__link { + font-weight: normal; + } .wc-block-components-totals-shipping__change-address-button { @include link-button(); From 33f7c2d4d92dd5c1248236f57fe72498886e0c58 Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Sat, 4 Feb 2023 02:07:19 +0100 Subject: [PATCH 04/25] Prevent default for the add address link Add the prevent default for the add address link so that the URL in the browser won't get updated. --- .../cart-checkout/totals/shipping/calculator-button.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx b/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx index 09d9958932a..be9777176c7 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx @@ -39,7 +39,8 @@ export const CalculatorButton = ( { href="#wc-block-components-shipping-calculator-address__link" className="wc-block-components-totals-shipping__change-address__link" id="wc-block-components-totals-shipping__change-address__link" - onClick={ () => { + onClick={ ( e ) => { + e.preventDefault(); setIsShippingCalculatorOpen( ! isShippingCalculatorOpen ); } } aria-label={ label } From 00d9526e29c376af7314433e70ad1025a63f994c Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Mon, 23 Jan 2023 22:36:31 +0400 Subject: [PATCH 05/25] Remove hardcoded notices & change display shipping calculator codition - Replace hardcoded notices with text for Cart and Checkout block. - Fix shipping placeholder for the Chec --- .../cart-checkout/shipping-location/index.tsx | 45 ++-------------- .../cart-checkout/totals/shipping/index.tsx | 4 ++ .../totals/shipping/shipping-address.tsx | 7 ++- .../totals/shipping/shipping-placeholder.tsx | 4 ++ .../shipping/shipping-rate-selector.tsx | 23 ++++---- assets/js/base/utils/address.ts | 52 +++++++++++++++++++ .../checkout-order-summary-shipping/block.tsx | 1 + .../checkout-shipping-methods-block/block.tsx | 33 +++++++----- 8 files changed, 100 insertions(+), 69 deletions(-) diff --git a/assets/js/base/components/cart-checkout/shipping-location/index.tsx b/assets/js/base/components/cart-checkout/shipping-location/index.tsx index b57fc0985d1..5005a0349c0 100644 --- a/assets/js/base/components/cart-checkout/shipping-location/index.tsx +++ b/assets/js/base/components/cart-checkout/shipping-location/index.tsx @@ -2,56 +2,21 @@ * External dependencies */ import { __, sprintf } from '@wordpress/i18n'; -import { ShippingAddress, getSetting } from '@woocommerce/settings'; -import { decodeEntities } from '@wordpress/html-entities'; interface ShippingLocationProps { - address: ShippingAddress; + formattedLocation: string | null; } /** * Shows a formatted shipping location. * - * @param {Object} props Incoming props for the component. - * @param {Object} props.address Incoming address information. + * @param {Object} props Incoming props for the component. + * @param {string} props.formattedLocation Formatted location. + * @return {JSX.Element|null} The component. */ const ShippingLocation = ( { - address, + formattedLocation, }: ShippingLocationProps ): JSX.Element | null => { - // we bail early if we don't have an address. - if ( Object.values( address ).length === 0 ) { - return null; - } - const shippingCountries = getSetting( 'shippingCountries', {} ) as Record< - string, - string - >; - const shippingStates = getSetting( 'shippingStates', {} ) as Record< - string, - Record< string, string > - >; - const formattedCountry = - typeof shippingCountries[ address.country ] === 'string' - ? decodeEntities( shippingCountries[ address.country ] ) - : ''; - - const formattedState = - typeof shippingStates[ address.country ] === 'object' && - typeof shippingStates[ address.country ][ address.state ] === 'string' - ? decodeEntities( - shippingStates[ address.country ][ address.state ] - ) - : address.state; - - const addressParts = []; - - addressParts.push( address.postcode.toUpperCase() ); - addressParts.push( address.city ); - addressParts.push( formattedState ); - addressParts.push( formattedCountry ); - - const formattedLocation = addressParts.filter( Boolean ).join( ', ' ); - if ( ! formattedLocation ) { return null; } diff --git a/assets/js/base/components/cart-checkout/totals/shipping/index.tsx b/assets/js/base/components/cart-checkout/totals/shipping/index.tsx index 06febfcafd9..ea22130f9f1 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/index.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/index.tsx @@ -10,6 +10,7 @@ import type { Currency } from '@woocommerce/price-format'; import { ShippingVia } from '@woocommerce/base-components/cart-checkout/totals/shipping/shipping-via'; import { useSelect } from '@wordpress/data'; import { CHECKOUT_STORE_KEY } from '@woocommerce/block-data'; +import { formatShippingAddress } from '@woocommerce/base-utils'; /** * Internal dependencies @@ -67,6 +68,8 @@ export const TotalsShipping = ( { } ); + const isAddressComplete = !! formatShippingAddress( shippingAddress ); + return (
) }
diff --git a/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx b/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx index 0df38408184..452126adc45 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx @@ -3,6 +3,7 @@ */ import { __ } from '@wordpress/i18n'; import { EnteredAddress } from '@woocommerce/settings'; +import { formatShippingAddress } from '@woocommerce/base-utils'; /** * Internal dependencies @@ -23,9 +24,13 @@ export const ShippingAddress = ( { setIsShippingCalculatorOpen, shippingAddress, }: ShippingAddressProps ): JSX.Element | null => { + const formattedLocation = formatShippingAddress( shippingAddress ); + if ( ! formattedLocation ) { + return null; + } return ( <> - + { showCalculator && ( diff --git a/assets/js/base/components/cart-checkout/totals/shipping/shipping-rate-selector.tsx b/assets/js/base/components/cart-checkout/totals/shipping/shipping-rate-selector.tsx index 78fcf12a674..0b8eae03983 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/shipping-rate-selector.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/shipping-rate-selector.tsx @@ -2,8 +2,6 @@ * External dependencies */ import { __ } from '@wordpress/i18n'; -import { Notice } from 'wordpress-components'; -import classnames from 'classnames'; import type { CartResponseShippingRate } from '@woocommerce/types'; /** @@ -15,12 +13,14 @@ export interface ShippingRateSelectorProps { hasRates: boolean; shippingRates: CartResponseShippingRate[]; isLoadingRates: boolean; + isAddressComplete: boolean; } export const ShippingRateSelector = ( { hasRates, shippingRates, isLoadingRates, + isAddressComplete, }: ShippingRateSelectorProps ): JSX.Element => { const legend = hasRates ? __( 'Shipping options', 'woo-gutenberg-products-block' ) @@ -31,18 +31,13 @@ export const ShippingRateSelector = ( { - { __( - 'No shipping options were found.', - 'woo-gutenberg-products-block' - ) } - + <> + { isAddressComplete && + __( + 'No shipping options were found.', + 'woo-gutenberg-products-block' + ) } + } shippingRates={ shippingRates } isLoadingRates={ isLoadingRates } diff --git a/assets/js/base/utils/address.ts b/assets/js/base/utils/address.ts index e3738fb614b..ee078d659fd 100644 --- a/assets/js/base/utils/address.ts +++ b/assets/js/base/utils/address.ts @@ -11,7 +11,9 @@ import { defaultAddressFields, ShippingAddress, BillingAddress, + getSetting, } from '@woocommerce/settings'; +import { decodeEntities } from '@wordpress/html-entities'; /** * Compare two addresses and see if they are the same. @@ -100,3 +102,53 @@ export const emptyHiddenAddressFields = < return newAddress; }; + +/* + * Formats a shipping address for display. + * + * @param {Object} address The address to format. + * @return {string | null} The formatted address or null if no address is provided. + */ +export const formatShippingAddress = ( + address: ShippingAddress | BillingAddress +): string | null => { + // we bail early if we don't have an address. + if ( Object.values( address ).length === 0 ) { + return null; + } + const shippingCountries = getSetting( 'shippingCountries', {} ) as Record< + string, + string + >; + const shippingStates = getSetting( 'shippingStates', {} ) as Record< + string, + Record< string, string > + >; + const formattedCountry = + typeof shippingCountries[ address.country ] === 'string' + ? decodeEntities( shippingCountries[ address.country ] ) + : ''; + + const formattedState = + typeof shippingStates[ address.country ] === 'object' && + typeof shippingStates[ address.country ][ address.state ] === 'string' + ? decodeEntities( + shippingStates[ address.country ][ address.state ] + ) + : address.state; + + const addressParts = []; + + addressParts.push( address.postcode.toUpperCase() ); + addressParts.push( address.city ); + addressParts.push( formattedState ); + addressParts.push( formattedCountry ); + + const formattedLocation = addressParts.filter( Boolean ).join( ', ' ); + + if ( ! formattedLocation ) { + return null; + } + + return formattedLocation; +}; diff --git a/assets/js/blocks/checkout/inner-blocks/checkout-order-summary-shipping/block.tsx b/assets/js/blocks/checkout/inner-blocks/checkout-order-summary-shipping/block.tsx index 84fd6e36b67..7ca7678c2b1 100644 --- a/assets/js/blocks/checkout/inner-blocks/checkout-order-summary-shipping/block.tsx +++ b/assets/js/blocks/checkout/inner-blocks/checkout-order-summary-shipping/block.tsx @@ -26,6 +26,7 @@ const Block = ( { showRateSelector={ false } values={ cartTotals } currency={ totalsCurrency } + isCheckout={ true } /> ); diff --git a/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx b/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx index 6827e06a266..d24caaa23f5 100644 --- a/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx +++ b/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx @@ -7,19 +7,20 @@ import { ShippingRatesControl } from '@woocommerce/base-components/cart-checkout import { getShippingRatesPackageCount, hasCollectableRate, + formatShippingAddress, } from '@woocommerce/base-utils'; import { getCurrencyFromPriceResponse } from '@woocommerce/price-format'; import FormattedMonetaryAmount from '@woocommerce/base-components/formatted-monetary-amount'; import { useEditorContext, noticeContexts } from '@woocommerce/base-context'; import { StoreNoticesContainer } from '@woocommerce/blocks-checkout'; import { decodeEntities } from '@wordpress/html-entities'; -import { Notice } from 'wordpress-components'; -import classnames from 'classnames'; import { getSetting } from '@woocommerce/settings'; import type { PackageRateOption, CartShippingPackageShippingRate, } from '@woocommerce/types'; +import { CART_STORE_KEY } from '@woocommerce/block-data'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -77,10 +78,15 @@ const Block = (): JSX.Element | null => { } ) : shippingRates; + const shippingAddress = useSelect( ( select ) => { + return select( CART_STORE_KEY ).getCustomerData()?.shippingAddress; + } ); + if ( ! needsShipping ) { return null; } + const addressComplete = !! formatShippingAddress( shippingAddress ); const shippingRatesPackageCount = getShippingRatesPackageCount( shippingRates ); @@ -109,18 +115,17 @@ const Block = (): JSX.Element | null => { ) : ( - { __( - 'There are no shipping options available. Please check your shipping address.', - 'woo-gutenberg-products-block' - ) } - + <> + { addressComplete + ? __( + 'There are no shipping options available. Please check your shipping address.', + 'woo-gutenberg-products-block' + ) + : __( + 'Add a shipping address to view shipping options.', + 'woo-gutenberg-products-block' + ) } + } renderOption={ renderShippingRatesControlOption } collapsible={ false } From 0853d6cbee92e8330644305118628cc80b3def7c Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Fri, 27 Jan 2023 13:49:26 +0400 Subject: [PATCH 06/25] Fix the label of the calculator button and TypeScript - Change the label of the calculator button from "Add an address for shipping rates" to "Add an address for shipping options". - Fix the TypeScript of the utils/address file. - Remove the docblock comments from shipping location block --- .../cart-checkout/shipping-location/index.tsx | 8 +------- .../totals/shipping/shipping-placeholder.tsx | 2 +- assets/js/base/utils/address.ts | 16 ++++++++-------- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/assets/js/base/components/cart-checkout/shipping-location/index.tsx b/assets/js/base/components/cart-checkout/shipping-location/index.tsx index 5005a0349c0..4f0c4f0b5b0 100644 --- a/assets/js/base/components/cart-checkout/shipping-location/index.tsx +++ b/assets/js/base/components/cart-checkout/shipping-location/index.tsx @@ -7,13 +7,7 @@ interface ShippingLocationProps { formattedLocation: string | null; } -/** - * Shows a formatted shipping location. - * - * @param {Object} props Incoming props for the component. - * @param {string} props.formattedLocation Formatted location. - * @return {JSX.Element|null} The component. - */ +// Shows a formatted shipping location. const ShippingLocation = ( { formattedLocation, }: ShippingLocationProps ): JSX.Element | null => { diff --git a/assets/js/base/components/cart-checkout/totals/shipping/shipping-placeholder.tsx b/assets/js/base/components/cart-checkout/totals/shipping/shipping-placeholder.tsx index 046baa5691c..23c97c31169 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/shipping-placeholder.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/shipping-placeholder.tsx @@ -40,7 +40,7 @@ export const ShippingPlaceholder = ( { return ( ; - const shippingStates = getSetting( 'shippingStates', {} ) as Record< - string, - Record< string, string > - >; + const shippingCountries = getSetting< Record< string, string > >( + 'shippingCountries', + {} + ); + const shippingStates = getSetting< Record< string, string > >( + 'shippingStates', + {} + ); const formattedCountry = typeof shippingCountries[ address.country ] === 'string' ? decodeEntities( shippingCountries[ address.country ] ) From e7b13d84cba5e123e61f13c78bce98ea451527fa Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Mon, 30 Jan 2023 18:42:38 +0400 Subject: [PATCH 07/25] Change the link style and fix editor issue - If no shipping rates are available, we will display a link instead of a button. - Display change address button when we're in Editor as some e2e tests are dependent on it --- .../totals/shipping/calculator-button.tsx | 29 +++++++++++++++++-- .../totals/shipping/shipping-address.tsx | 6 +++- .../totals/shipping/shipping-placeholder.tsx | 1 + .../cart-checkout/totals/shipping/style.scss | 3 ++ 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx b/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx index 9607ab9fd7f..09d9958932a 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx @@ -5,25 +5,48 @@ import { __ } from '@wordpress/i18n'; export interface CalculatorButtonProps { label?: string; + hasRates?: boolean | undefined; isShippingCalculatorOpen: boolean; setIsShippingCalculatorOpen: ( isShippingCalculatorOpen: boolean ) => void; } export const CalculatorButton = ( { label = __( 'Calculate', 'woo-gutenberg-products-block' ), + hasRates = true, isShippingCalculatorOpen, setIsShippingCalculatorOpen, }: CalculatorButtonProps ): JSX.Element => { + // If shipping rates are available. We want to show a button instead of a link. + if ( hasRates ) { + return ( + + ); + } + + // If no shipping rates are available, we want to show a link instead of a button. + // This is because the style of the link will match the link style of the theme like "Add a coupon". return ( - + ); }; diff --git a/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx b/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx index 452126adc45..2fa1d7143d7 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx @@ -4,6 +4,7 @@ import { __ } from '@wordpress/i18n'; import { EnteredAddress } from '@woocommerce/settings'; import { formatShippingAddress } from '@woocommerce/base-utils'; +import { useEditorContext } from '@woocommerce/base-context'; /** * Internal dependencies @@ -25,7 +26,10 @@ export const ShippingAddress = ( { shippingAddress, }: ShippingAddressProps ): JSX.Element | null => { const formattedLocation = formatShippingAddress( shippingAddress ); - if ( ! formattedLocation ) { + const { isEditor } = useEditorContext(); + + // If there is no address, and we're not in the editor, don't show anything. + if ( ! formattedLocation && ! isEditor ) { return null; } return ( diff --git a/assets/js/base/components/cart-checkout/totals/shipping/shipping-placeholder.tsx b/assets/js/base/components/cart-checkout/totals/shipping/shipping-placeholder.tsx index 23c97c31169..95446630773 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/shipping-placeholder.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/shipping-placeholder.tsx @@ -45,6 +45,7 @@ export const ShippingPlaceholder = ( { ) } isShippingCalculatorOpen={ isShippingCalculatorOpen } setIsShippingCalculatorOpen={ setIsShippingCalculatorOpen } + hasRates={ false } /> ); }; diff --git a/assets/js/base/components/cart-checkout/totals/shipping/style.scss b/assets/js/base/components/cart-checkout/totals/shipping/style.scss index 9562503f8bf..d91bcabc8c2 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/style.scss +++ b/assets/js/base/components/cart-checkout/totals/shipping/style.scss @@ -26,6 +26,9 @@ margin: 0 0 em($gap-small); } + .wc-block-components-totals-shipping__change-address__link { + font-weight: normal; + } .wc-block-components-totals-shipping__change-address-button { @include link-button(); From 140f9c2752af105b24c4122df282583bb5f8b440 Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Sat, 4 Feb 2023 02:07:19 +0100 Subject: [PATCH 08/25] Prevent default for the add address link Add the prevent default for the add address link so that the URL in the browser won't get updated. --- .../cart-checkout/totals/shipping/calculator-button.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx b/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx index 09d9958932a..be9777176c7 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx @@ -39,7 +39,8 @@ export const CalculatorButton = ( { href="#wc-block-components-shipping-calculator-address__link" className="wc-block-components-totals-shipping__change-address__link" id="wc-block-components-totals-shipping__change-address__link" - onClick={ () => { + onClick={ ( e ) => { + e.preventDefault(); setIsShippingCalculatorOpen( ! isShippingCalculatorOpen ); } } aria-label={ label } From 9cddc47205e7403ee434ea45c2b92efb7b75d4c6 Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Tue, 21 Feb 2023 00:39:48 +0400 Subject: [PATCH 09/25] Add error notice when no shipping rates available for the given address - Add error notice when no shipping rates available for the given address. - Remove conditions display button instead of the link for shipping calculator. - Replace calculator button with link to match "Add a coupon" link style. --- .../totals/shipping/calculator-button.tsx | 19 ----------- .../cart-checkout/totals/shipping/index.tsx | 33 ++++++++++--------- .../totals/shipping/shipping-address.tsx | 2 +- .../totals/shipping/shipping-placeholder.tsx | 1 - .../shipping/shipping-rate-selector.tsx | 21 +++++++++--- 5 files changed, 35 insertions(+), 41 deletions(-) diff --git a/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx b/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx index be9777176c7..887f34dbe31 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/calculator-button.tsx @@ -5,34 +5,15 @@ import { __ } from '@wordpress/i18n'; export interface CalculatorButtonProps { label?: string; - hasRates?: boolean | undefined; isShippingCalculatorOpen: boolean; setIsShippingCalculatorOpen: ( isShippingCalculatorOpen: boolean ) => void; } export const CalculatorButton = ( { label = __( 'Calculate', 'woo-gutenberg-products-block' ), - hasRates = true, isShippingCalculatorOpen, setIsShippingCalculatorOpen, }: CalculatorButtonProps ): JSX.Element => { - // If shipping rates are available. We want to show a button instead of a link. - if ( hasRates ) { - return ( - - ); - } - - // If no shipping rates are available, we want to show a link instead of a button. - // This is because the style of the link will match the link style of the theme like "Add a coupon". return ( - ) + hasRates && cartHasCalculatedShipping + ? totalShippingValue + : // if address is not complete, display the link to add an address. + ! isAddressComplete && ( + + ) } description={ - hasRates && cartHasCalculatedShipping ? ( + // If address is complete, display the shipping address. + ( hasRates && cartHasCalculatedShipping ) || + isAddressComplete ? ( <> ); }; diff --git a/assets/js/base/components/cart-checkout/totals/shipping/shipping-rate-selector.tsx b/assets/js/base/components/cart-checkout/totals/shipping/shipping-rate-selector.tsx index 0b8eae03983..3a189bd4fa5 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/shipping-rate-selector.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/shipping-rate-selector.tsx @@ -3,6 +3,8 @@ */ import { __ } from '@wordpress/i18n'; import type { CartResponseShippingRate } from '@woocommerce/types'; +import { Notice } from 'wordpress-components'; +import classnames from 'classnames'; /** * Internal dependencies @@ -32,11 +34,20 @@ export const ShippingRateSelector = ( { className="wc-block-components-totals-shipping__options" noResultsMessage={ <> - { isAddressComplete && - __( - 'No shipping options were found.', - 'woo-gutenberg-products-block' - ) } + { isAddressComplete && ( + + { __( + 'There are no shipping options available. Please check your shipping address.', + 'woo-gutenberg-products-block' + ) } + + ) } } shippingRates={ shippingRates } From c5242c6b4b8f2fd854bae3717cba2a9028a29ae6 Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Tue, 21 Feb 2023 01:18:26 +0400 Subject: [PATCH 10/25] Remove hasRates prop from shipping placeholder --- .../cart-checkout/totals/shipping/shipping-placeholder.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/assets/js/base/components/cart-checkout/totals/shipping/shipping-placeholder.tsx b/assets/js/base/components/cart-checkout/totals/shipping/shipping-placeholder.tsx index 95446630773..23c97c31169 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/shipping-placeholder.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/shipping-placeholder.tsx @@ -45,7 +45,6 @@ export const ShippingPlaceholder = ( { ) } isShippingCalculatorOpen={ isShippingCalculatorOpen } setIsShippingCalculatorOpen={ setIsShippingCalculatorOpen } - hasRates={ false } /> ); }; From 6f1c5280b9c24477d2deace263d8113633ab13e8 Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Tue, 21 Feb 2023 14:43:34 +0400 Subject: [PATCH 11/25] Replace Notice with text message in Cart - Replace Notice with text message in Cart. - Change the variable name from addressComplete to isAddressComplete to keep it consistent. --- .../shipping/shipping-rate-selector.tsx | 21 +++++-------------- .../checkout-shipping-methods-block/block.tsx | 4 ++-- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/assets/js/base/components/cart-checkout/totals/shipping/shipping-rate-selector.tsx b/assets/js/base/components/cart-checkout/totals/shipping/shipping-rate-selector.tsx index 3a189bd4fa5..a6bbe6dcdad 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/shipping-rate-selector.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/shipping-rate-selector.tsx @@ -3,8 +3,6 @@ */ import { __ } from '@wordpress/i18n'; import type { CartResponseShippingRate } from '@woocommerce/types'; -import { Notice } from 'wordpress-components'; -import classnames from 'classnames'; /** * Internal dependencies @@ -34,20 +32,11 @@ export const ShippingRateSelector = ( { className="wc-block-components-totals-shipping__options" noResultsMessage={ <> - { isAddressComplete && ( - - { __( - 'There are no shipping options available. Please check your shipping address.', - 'woo-gutenberg-products-block' - ) } - - ) } + { isAddressComplete && + __( + 'There are no shipping options available. Please check your shipping address.', + 'woo-gutenberg-products-block' + ) } } shippingRates={ shippingRates } diff --git a/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx b/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx index d24caaa23f5..24be33d54c5 100644 --- a/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx +++ b/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx @@ -86,7 +86,7 @@ const Block = (): JSX.Element | null => { return null; } - const addressComplete = !! formatShippingAddress( shippingAddress ); + const isAddressComplete = !! formatShippingAddress( shippingAddress ); const shippingRatesPackageCount = getShippingRatesPackageCount( shippingRates ); @@ -116,7 +116,7 @@ const Block = (): JSX.Element | null => { - { addressComplete + { isAddressComplete ? __( 'There are no shipping options available. Please check your shipping address.', 'woo-gutenberg-products-block' From c4dcdf15a3f9a06236c1516d84ba2603e331f396 Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Tue, 21 Feb 2023 20:34:29 +0400 Subject: [PATCH 12/25] Add margin-top to shipping rate selector on Cart block --- .../js/base/components/cart-checkout/totals/shipping/style.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/js/base/components/cart-checkout/totals/shipping/style.scss b/assets/js/base/components/cart-checkout/totals/shipping/style.scss index d91bcabc8c2..5e9cf3b2b20 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/style.scss +++ b/assets/js/base/components/cart-checkout/totals/shipping/style.scss @@ -20,6 +20,7 @@ flex-basis: 100%; text-align: left; } + margin-top: ($gap-small); } .wc-block-components-shipping-rates-control__no-results-notice { From a82b40a904dece39ba413812518fb176eab1b024 Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Fri, 24 Feb 2023 23:08:23 +0400 Subject: [PATCH 13/25] Add unit cases for isAddressComplete and formatShippingAddress functions - Add isAddressComplete as formatShippingAddress was returning false for the empty address. - Replace formatShippingAddress function with isAddressComplete to validate the address. - Add unit cases for isAddressComplete and formatShippingAddress functions --- .../cart-checkout/totals/shipping/index.tsx | 10 +- .../totals/shipping/shipping-address.tsx | 10 +- assets/js/base/utils/address.ts | 9 ++ assets/js/base/utils/test/address.ts | 104 +++++++++++++++++- .../checkout-shipping-methods-block/block.tsx | 6 +- 5 files changed, 127 insertions(+), 12 deletions(-) diff --git a/assets/js/base/components/cart-checkout/totals/shipping/index.tsx b/assets/js/base/components/cart-checkout/totals/shipping/index.tsx index 30e6fa43128..5b2fade1a9e 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/index.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/index.tsx @@ -10,7 +10,7 @@ import type { Currency } from '@woocommerce/price-format'; import { ShippingVia } from '@woocommerce/base-components/cart-checkout/totals/shipping/shipping-via'; import { useSelect } from '@wordpress/data'; import { CHECKOUT_STORE_KEY } from '@woocommerce/block-data'; -import { formatShippingAddress } from '@woocommerce/base-utils'; +import { isAddressComplete } from '@woocommerce/base-utils'; /** * Internal dependencies @@ -68,7 +68,7 @@ export const TotalsShipping = ( { } ); - const isAddressComplete = !! formatShippingAddress( shippingAddress ); + const addressComplete = isAddressComplete( shippingAddress ); return (
) }
diff --git a/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx b/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx index d9aa0b2bd94..18781bd7f45 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx @@ -3,7 +3,10 @@ */ import { __ } from '@wordpress/i18n'; import { EnteredAddress } from '@woocommerce/settings'; -import { formatShippingAddress } from '@woocommerce/base-utils'; +import { + formatShippingAddress, + isAddressComplete, +} from '@woocommerce/base-utils'; import { useEditorContext } from '@woocommerce/base-context'; /** @@ -25,13 +28,14 @@ export const ShippingAddress = ( { setIsShippingCalculatorOpen, shippingAddress, }: ShippingAddressProps ): JSX.Element | null => { - const formattedLocation = formatShippingAddress( shippingAddress ); + const addressComplete = isAddressComplete( shippingAddress ); const { isEditor } = useEditorContext(); // If there is no address, and we're not in the editor, don't show anything. - if ( ! formattedLocation && ! isEditor ) { + if ( ! addressComplete && ! isEditor ) { return null; } + const formattedLocation = formatShippingAddress( shippingAddress ); return ( <> diff --git a/assets/js/base/utils/address.ts b/assets/js/base/utils/address.ts index f9b5a2da883..8a3059f5b4b 100644 --- a/assets/js/base/utils/address.ts +++ b/assets/js/base/utils/address.ts @@ -152,3 +152,12 @@ export const formatShippingAddress = ( return formattedLocation; }; + +/** + * Returns true if the address have city, country and postcode. + */ +export const isAddressComplete = ( + address: ShippingAddress | BillingAddress +): boolean => { + return !! address.city && !! address.country && !! address.postcode; +}; diff --git a/assets/js/base/utils/test/address.ts b/assets/js/base/utils/test/address.ts index 8f454ad2058..fad11ff02d2 100644 --- a/assets/js/base/utils/test/address.ts +++ b/assets/js/base/utils/test/address.ts @@ -1,7 +1,11 @@ /** * External dependencies */ -import { emptyHiddenAddressFields } from '@woocommerce/base-utils'; +import { + emptyHiddenAddressFields, + isAddressComplete, + formatShippingAddress, +} from '@woocommerce/base-utils'; describe( 'emptyHiddenAddressFields', () => { it( "Removes state from an address where the country doesn't use states", () => { @@ -22,3 +26,101 @@ describe( 'emptyHiddenAddressFields', () => { expect( filteredAddress ).toHaveProperty( 'state', '' ); } ); } ); + +describe( 'isAddressComplete', () => { + it( 'correctly checks address is empty', () => { + const address = { + first_name: '', + last_name: '', + company: '', + address_1: '', + address_2: '', + city: '', + postcode: '', + country: '', + state: '', + email: '', + phone: '', + }; + expect( isAddressComplete( address ) ).toBe( false ); + } ); + + it( 'correctly checks is not complete', () => { + const address = { + first_name: 'John', + last_name: 'Deo', + company: 'Company', + address_1: '409 Main Street', + address_2: 'Apt 1', + city: '', + postcode: '', + country: '', + state: '', + email: 'john.deo@company', + phone: '+1234567890', + }; + expect( isAddressComplete( address ) ).toBe( false ); + + address.city = 'London'; + expect( isAddressComplete( address ) ).toBe( false ); + + address.postcode = 'W1T 4JG'; + address.country = 'GB'; + expect( isAddressComplete( address ) ).toBe( true ); + } ); + + it( 'correctly checks is complete', () => { + const address = { + first_name: 'John', + last_name: 'Deo', + company: 'Company', + address_1: '409 Main Street', + address_2: 'Apt 1', + city: 'London', + postcode: 'W1T 4JG', + country: 'GB', + state: '', + email: 'john.deo@company', + phone: '+1234567890', + }; + expect( isAddressComplete( address ) ).toBe( true ); + } ); +} ); + +describe( 'formatShippingAddress', () => { + it( 'correctly returns null address is empty', () => { + const address = { + first_name: '', + last_name: '', + company: '', + address_1: '', + address_2: '', + city: '', + postcode: '', + country: '', + state: '', + email: '', + phone: '', + }; + expect( formatShippingAddress( address ) ).toBe( null ); + } ); + + it( 'correctly returns the formatted address', () => { + const address = { + first_name: 'John', + last_name: 'Deo', + company: 'Company', + address_1: '409 Main Street', + address_2: 'Apt 1', + city: 'London', + postcode: 'W1T 4JG', + country: 'GB', + state: '', + email: 'john.deo@company', + phone: '+1234567890', + }; + expect( formatShippingAddress( address ) ).toBe( + 'W1T 4JG, London, United Kingdom (UK)' + ); + } ); +} ); diff --git a/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx b/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx index 24be33d54c5..fb4abea2d73 100644 --- a/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx +++ b/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx @@ -7,7 +7,7 @@ import { ShippingRatesControl } from '@woocommerce/base-components/cart-checkout import { getShippingRatesPackageCount, hasCollectableRate, - formatShippingAddress, + isAddressComplete, } from '@woocommerce/base-utils'; import { getCurrencyFromPriceResponse } from '@woocommerce/price-format'; import FormattedMonetaryAmount from '@woocommerce/base-components/formatted-monetary-amount'; @@ -86,7 +86,7 @@ const Block = (): JSX.Element | null => { return null; } - const isAddressComplete = !! formatShippingAddress( shippingAddress ); + const addressComplete = isAddressComplete( shippingAddress ); const shippingRatesPackageCount = getShippingRatesPackageCount( shippingRates ); @@ -116,7 +116,7 @@ const Block = (): JSX.Element | null => { - { isAddressComplete + { addressComplete ? __( 'There are no shipping options available. Please check your shipping address.', 'woo-gutenberg-products-block' From 2d239cabc71bfccd5db6f0bf8cded3f3ff2947f5 Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Mon, 27 Feb 2023 11:35:29 +0400 Subject: [PATCH 14/25] Update assets/js/base/utils/test/address.ts Co-authored-by: Thomas Roberts <5656702+opr@users.noreply.github.com> --- assets/js/base/utils/test/address.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/base/utils/test/address.ts b/assets/js/base/utils/test/address.ts index fad11ff02d2..348b2308026 100644 --- a/assets/js/base/utils/test/address.ts +++ b/assets/js/base/utils/test/address.ts @@ -69,7 +69,7 @@ describe( 'isAddressComplete', () => { expect( isAddressComplete( address ) ).toBe( true ); } ); - it( 'correctly checks is complete', () => { + it( 'correctly checks complete addresses', () => { const address = { first_name: 'John', last_name: 'Deo', From cd63d7790e3bf6e7291bd4a558f4e46d043af25c Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Mon, 27 Feb 2023 11:35:37 +0400 Subject: [PATCH 15/25] Update assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx Co-authored-by: Thomas Roberts <5656702+opr@users.noreply.github.com> --- .../cart-checkout/totals/shipping/shipping-address.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx b/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx index 18781bd7f45..c2be8f15954 100644 --- a/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx +++ b/assets/js/base/components/cart-checkout/totals/shipping/shipping-address.tsx @@ -31,7 +31,7 @@ export const ShippingAddress = ( { const addressComplete = isAddressComplete( shippingAddress ); const { isEditor } = useEditorContext(); - // If there is no address, and we're not in the editor, don't show anything. + // If the address is incomplete, and we're not in the editor, don't show anything. if ( ! addressComplete && ! isEditor ) { return null; } From fb385aa75fcd012ba645392b8cbf384bc9091b1d Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Mon, 27 Feb 2023 11:35:53 +0400 Subject: [PATCH 16/25] Update assets/js/base/utils/test/address.ts Co-authored-by: Thomas Roberts <5656702+opr@users.noreply.github.com> --- assets/js/base/utils/test/address.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/base/utils/test/address.ts b/assets/js/base/utils/test/address.ts index 348b2308026..d44247c6fcb 100644 --- a/assets/js/base/utils/test/address.ts +++ b/assets/js/base/utils/test/address.ts @@ -28,7 +28,7 @@ describe( 'emptyHiddenAddressFields', () => { } ); describe( 'isAddressComplete', () => { - it( 'correctly checks address is empty', () => { + it( 'correctly checks empty addresses', () => { const address = { first_name: '', last_name: '', From 5bef4543c786fa7e383f7edc4ef1a92bf55519e4 Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Mon, 27 Feb 2023 11:36:01 +0400 Subject: [PATCH 17/25] Update assets/js/base/utils/address.ts Co-authored-by: Thomas Roberts <5656702+opr@users.noreply.github.com> --- assets/js/base/utils/address.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/base/utils/address.ts b/assets/js/base/utils/address.ts index 8a3059f5b4b..1b2c8d6cfff 100644 --- a/assets/js/base/utils/address.ts +++ b/assets/js/base/utils/address.ts @@ -112,7 +112,7 @@ export const emptyHiddenAddressFields = < export const formatShippingAddress = ( address: ShippingAddress | BillingAddress ): string | null => { - // we bail early if we don't have an address. + // We bail early if we don't have an address. if ( Object.values( address ).length === 0 ) { return null; } From 163eff15ed487b21987a462654e6f9b8f8bb0896 Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Mon, 27 Feb 2023 11:36:10 +0400 Subject: [PATCH 18/25] Update assets/js/base/utils/address.ts Co-authored-by: Thomas Roberts <5656702+opr@users.noreply.github.com> --- assets/js/base/utils/address.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/base/utils/address.ts b/assets/js/base/utils/address.ts index 1b2c8d6cfff..46b0ada28de 100644 --- a/assets/js/base/utils/address.ts +++ b/assets/js/base/utils/address.ts @@ -154,7 +154,7 @@ export const formatShippingAddress = ( }; /** - * Returns true if the address have city, country and postcode. + * Returns true if the address has a city, country, and postcode. */ export const isAddressComplete = ( address: ShippingAddress | BillingAddress From 4525d35b9c9827cbc6614488d89e5195740cdfbc Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Mon, 27 Feb 2023 11:36:18 +0400 Subject: [PATCH 19/25] Update assets/js/base/utils/test/address.ts Co-authored-by: Thomas Roberts <5656702+opr@users.noreply.github.com> --- assets/js/base/utils/test/address.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/base/utils/test/address.ts b/assets/js/base/utils/test/address.ts index d44247c6fcb..da9b1df7728 100644 --- a/assets/js/base/utils/test/address.ts +++ b/assets/js/base/utils/test/address.ts @@ -88,7 +88,7 @@ describe( 'isAddressComplete', () => { } ); describe( 'formatShippingAddress', () => { - it( 'correctly returns null address is empty', () => { + it( 'returns null if address is empty', () => { const address = { first_name: '', last_name: '', From 3d7e976ec032c917a31987869a5dfbc045ac3535 Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Mon, 27 Feb 2023 11:36:28 +0400 Subject: [PATCH 20/25] Update assets/js/base/utils/test/address.ts Co-authored-by: Thomas Roberts <5656702+opr@users.noreply.github.com> --- assets/js/base/utils/test/address.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/base/utils/test/address.ts b/assets/js/base/utils/test/address.ts index da9b1df7728..cca82bb5b44 100644 --- a/assets/js/base/utils/test/address.ts +++ b/assets/js/base/utils/test/address.ts @@ -45,7 +45,7 @@ describe( 'isAddressComplete', () => { expect( isAddressComplete( address ) ).toBe( false ); } ); - it( 'correctly checks is not complete', () => { + it( 'correctly checks incomplete addresses', () => { const address = { first_name: 'John', last_name: 'Deo', From 45f9199b8309a65cb075711d23b85c81b71d1172 Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Tue, 28 Feb 2023 22:58:21 +0400 Subject: [PATCH 21/25] Fix typo in unit test data - Fix typo in unit test data by changing the customer name from "John Deo" to " John Doe". - Fix typo in surname for email in unit test data. --- assets/js/base/utils/test/address.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/js/base/utils/test/address.ts b/assets/js/base/utils/test/address.ts index cca82bb5b44..27d31eef5b0 100644 --- a/assets/js/base/utils/test/address.ts +++ b/assets/js/base/utils/test/address.ts @@ -48,7 +48,7 @@ describe( 'isAddressComplete', () => { it( 'correctly checks incomplete addresses', () => { const address = { first_name: 'John', - last_name: 'Deo', + last_name: 'Doe', company: 'Company', address_1: '409 Main Street', address_2: 'Apt 1', @@ -56,7 +56,7 @@ describe( 'isAddressComplete', () => { postcode: '', country: '', state: '', - email: 'john.deo@company', + email: 'john.doe@company', phone: '+1234567890', }; expect( isAddressComplete( address ) ).toBe( false ); @@ -72,7 +72,7 @@ describe( 'isAddressComplete', () => { it( 'correctly checks complete addresses', () => { const address = { first_name: 'John', - last_name: 'Deo', + last_name: 'Doe', company: 'Company', address_1: '409 Main Street', address_2: 'Apt 1', @@ -80,7 +80,7 @@ describe( 'isAddressComplete', () => { postcode: 'W1T 4JG', country: 'GB', state: '', - email: 'john.deo@company', + email: 'john.doe@company', phone: '+1234567890', }; expect( isAddressComplete( address ) ).toBe( true ); @@ -108,7 +108,7 @@ describe( 'formatShippingAddress', () => { it( 'correctly returns the formatted address', () => { const address = { first_name: 'John', - last_name: 'Deo', + last_name: 'Doe', company: 'Company', address_1: '409 Main Street', address_2: 'Apt 1', @@ -116,7 +116,7 @@ describe( 'formatShippingAddress', () => { postcode: 'W1T 4JG', country: 'GB', state: '', - email: 'john.deo@company', + email: 'john.doe@company', phone: '+1234567890', }; expect( formatShippingAddress( address ) ).toBe( From d52f9373723b64c91bb5e6aef77c7740228aa8e9 Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Tue, 28 Feb 2023 23:01:35 +0400 Subject: [PATCH 22/25] Remove postcode from isAddressComplete check - Some countries like UAE doesn't have post code. The isAddressComplete function was returning false for these countries. Remove postcode check from isAddressComplete function to make sure it works for all the countries. We already have the postcode validation in shipping calculator that works for the countries which requires postcode. --- assets/js/base/utils/address.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/js/base/utils/address.ts b/assets/js/base/utils/address.ts index 46b0ada28de..f894db86997 100644 --- a/assets/js/base/utils/address.ts +++ b/assets/js/base/utils/address.ts @@ -154,10 +154,10 @@ export const formatShippingAddress = ( }; /** - * Returns true if the address has a city, country, and postcode. + * Returns true if the address has a city and country. */ export const isAddressComplete = ( address: ShippingAddress | BillingAddress ): boolean => { - return !! address.city && !! address.country && !! address.postcode; + return !! address.city && !! address.country; }; From 3b1e4c8a0249d058f78aa4cf34ee4f69675abd00 Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Mon, 13 Mar 2023 12:07:50 +0530 Subject: [PATCH 23/25] Add unit tests for shipping rate calculator (#8621) * Add further unit tests * Add useStoreCart to mocked values and wrap in SlotFillProvider * Add test for 2nd and 3rd scenario * Remove AsyncModeProvider mock Remove AsyncModeProvider mock since we are requiring @wordpress/data in setup-globals.js --------- Co-authored-by: Thomas Roberts --- .../totals/shipping/test/index.tsx | 282 ++++++++++++++++++ .../shipping/test/shipping-placeholder.tsx | 36 +++ tests/js/setup-globals.js | 1 + 3 files changed, 319 insertions(+) create mode 100644 assets/js/base/components/cart-checkout/totals/shipping/test/index.tsx create mode 100644 assets/js/base/components/cart-checkout/totals/shipping/test/shipping-placeholder.tsx diff --git a/assets/js/base/components/cart-checkout/totals/shipping/test/index.tsx b/assets/js/base/components/cart-checkout/totals/shipping/test/index.tsx new file mode 100644 index 00000000000..daa43f4a967 --- /dev/null +++ b/assets/js/base/components/cart-checkout/totals/shipping/test/index.tsx @@ -0,0 +1,282 @@ +/** + * External dependencies + */ +import { screen, render } from '@testing-library/react'; +import { SlotFillProvider } from '@woocommerce/blocks-checkout'; +import { previewCart as mockPreviewCart } from '@woocommerce/resource-previews'; +import * as wpData from '@wordpress/data'; +import * as baseContextHooks from '@woocommerce/base-context/hooks'; + +/** + * Internal dependencies + */ +import { TotalsShipping } from '../index'; + +jest.mock( '@wordpress/data', () => ( { + __esModule: true, + ...jest.requireActual( '@wordpress/data' ), + useSelect: jest.fn(), +} ) ); + +wpData.useSelect.mockImplementation( () => { + return { prefersCollection: false }; +} ); + +const shippingAddress = { + first_name: 'John', + last_name: 'Doe', + company: 'Company', + address_1: '409 Main Street', + address_2: 'Apt 1', + city: 'London', + postcode: 'W1T 4JG', + country: 'GB', + state: '', + email: 'john.doe@company', + phone: '+1234567890', +}; + +jest.mock( '@woocommerce/base-context/hooks', () => { + return { + __esModule: true, + ...jest.requireActual( '@woocommerce/base-context/hooks' ), + useShippingData: jest.fn(), + useStoreCart: jest.fn(), + }; +} ); +baseContextHooks.useShippingData.mockReturnValue( { + needsShipping: true, + shippingRates: [ + { + package_id: 0, + name: 'Shipping method', + destination: { + address_1: '', + address_2: '', + city: '', + state: '', + postcode: '', + country: '', + }, + items: [ + { + key: 'fb0c0a746719a7596f296344b80cb2b6', + name: 'Hoodie - Blue, Yes', + quantity: 1, + }, + { + key: '1f0e3dad99908345f7439f8ffabdffc4', + name: 'Beanie', + quantity: 1, + }, + ], + shipping_rates: [ + { + rate_id: 'flat_rate:1', + name: 'Flat rate', + description: '', + delivery_time: '', + price: '500', + taxes: '0', + instance_id: 1, + method_id: 'flat_rate', + meta_data: [ + { + key: 'Items', + value: 'Hoodie - Blue, Yes × 1, Beanie × 1', + }, + ], + selected: false, + currency_code: 'USD', + currency_symbol: '$', + currency_minor_unit: 2, + currency_decimal_separator: '.', + currency_thousand_separator: ',', + currency_prefix: '$', + currency_suffix: '', + }, + { + rate_id: 'local_pickup:2', + name: 'Local pickup', + description: '', + delivery_time: '', + price: '0', + taxes: '0', + instance_id: 2, + method_id: 'local_pickup', + meta_data: [ + { + key: 'Items', + value: 'Hoodie - Blue, Yes × 1, Beanie × 1', + }, + ], + selected: false, + currency_code: 'USD', + currency_symbol: '$', + currency_minor_unit: 2, + currency_decimal_separator: '.', + currency_thousand_separator: ',', + currency_prefix: '$', + currency_suffix: '', + }, + { + rate_id: 'free_shipping:5', + name: 'Free shipping', + description: '', + delivery_time: '', + price: '0', + taxes: '0', + instance_id: 5, + method_id: 'free_shipping', + meta_data: [ + { + key: 'Items', + value: 'Hoodie - Blue, Yes × 1, Beanie × 1', + }, + ], + selected: true, + currency_code: 'USD', + currency_symbol: '$', + currency_minor_unit: 2, + currency_decimal_separator: '.', + currency_thousand_separator: ',', + currency_prefix: '$', + currency_suffix: '', + }, + ], + }, + ], +} ); +baseContextHooks.useStoreCart.mockReturnValue( { + cartItems: mockPreviewCart.items, + cartTotals: [ mockPreviewCart.totals ], + cartCoupons: mockPreviewCart.coupons, + cartFees: mockPreviewCart.fees, + cartNeedsShipping: mockPreviewCart.needs_shipping, + shippingRates: [], + shippingAddress, + billingAddress: mockPreviewCart.billing_address, + cartHasCalculatedShipping: mockPreviewCart.has_calculated_shipping, + isLoadingRates: false, +} ); + +describe( 'TotalsShipping', () => { + it( 'should show correct calculator button label if address is complete', () => { + render( + + + + ); + expect( + screen.getByText( + 'Shipping to W1T 4JG, London, United Kingdom (UK)' + ) + ).toBeInTheDocument(); + expect( screen.getByText( 'Change address' ) ).toBeInTheDocument(); + } ); + it( 'should show correct calculator button label if address is incomplete', () => { + baseContextHooks.useStoreCart.mockReturnValue( { + cartItems: mockPreviewCart.items, + cartTotals: [ mockPreviewCart.totals ], + cartCoupons: mockPreviewCart.coupons, + cartFees: mockPreviewCart.fees, + cartNeedsShipping: mockPreviewCart.needs_shipping, + shippingRates: [], + shippingAddress: { + ...shippingAddress, + city: '', + country: '', + postcode: '', + }, + billingAddress: mockPreviewCart.billing_address, + cartHasCalculatedShipping: mockPreviewCart.has_calculated_shipping, + isLoadingRates: false, + } ); + render( + + + + ); + expect( + screen.queryByText( 'Change address' ) + ).not.toBeInTheDocument(); + expect( + screen.getByText( 'Add an address for shipping options' ) + ).toBeInTheDocument(); + } ); + it( 'does not show the calculator button when default rates are available and no address has been entered', () => { + baseContextHooks.useStoreCart.mockReturnValue( { + cartItems: mockPreviewCart.items, + cartTotals: [ mockPreviewCart.totals ], + cartCoupons: mockPreviewCart.coupons, + cartFees: mockPreviewCart.fees, + cartNeedsShipping: mockPreviewCart.needs_shipping, + shippingRates: mockPreviewCart.shipping_rates, + shippingAddress: { + ...shippingAddress, + city: '', + country: '', + postcode: '', + }, + billingAddress: mockPreviewCart.billing_address, + cartHasCalculatedShipping: mockPreviewCart.has_calculated_shipping, + isLoadingRates: false, + } ); + render( + + + + ); + expect( + screen.queryByText( 'Change address' ) + ).not.toBeInTheDocument(); + expect( + screen.queryByText( 'Add an address for shipping options' ) + ).not.toBeInTheDocument(); + } ); +} ); diff --git a/assets/js/base/components/cart-checkout/totals/shipping/test/shipping-placeholder.tsx b/assets/js/base/components/cart-checkout/totals/shipping/test/shipping-placeholder.tsx new file mode 100644 index 00000000000..469bb35d61a --- /dev/null +++ b/assets/js/base/components/cart-checkout/totals/shipping/test/shipping-placeholder.tsx @@ -0,0 +1,36 @@ +/** + * External dependencies + */ +import { screen, render } from '@testing-library/react'; + +/** + * Internal dependencies + */ +import ShippingPlaceholder from '../shipping-placeholder'; + +describe( 'ShippingPlaceholder', () => { + it( 'should show correct text if showCalculator is false', () => { + const { rerender } = render( + + ); + expect( + screen.getByText( 'No shipping options available' ) + ).toBeInTheDocument(); + rerender( + + ); + expect( + screen.getByText( 'Calculated during checkout' ) + ).toBeInTheDocument(); + } ); +} ); diff --git a/tests/js/setup-globals.js b/tests/js/setup-globals.js index 7a6c01a4c3b..c0ffaa1c46c 100644 --- a/tests/js/setup-globals.js +++ b/tests/js/setup-globals.js @@ -1,5 +1,6 @@ // Set up `wp.*` aliases. Doing this because any tests importing wp stuff will likely run into this. global.wp = {}; +require( '@wordpress/data' ); // wcSettings is required by @woocommerce/* packages global.wcSettings = { From 7a13f4f205fcdbbf360bd7048ea04d30ea94797d Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Thu, 16 Mar 2023 12:16:07 +0400 Subject: [PATCH 24/25] Fix linting error Fix linting error that got introduced while resolving the merge conflict. --- .../inner-blocks/checkout-shipping-methods-block/block.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx b/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx index c9558ca6b05..93974f7dad5 100644 --- a/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx +++ b/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx @@ -22,8 +22,6 @@ import type { import { CART_STORE_KEY } from '@woocommerce/block-data'; import { useSelect } from '@wordpress/data'; import type { ReactElement } from 'react'; -import { useSelect } from '@wordpress/data'; -import { CART_STORE_KEY } from '@woocommerce/block-data'; /** * Internal dependencies @@ -96,7 +94,9 @@ const Block = ( { return null; } - const shippingAddressIsComplete = ! shippingAddressHasValidationErrors() && isAddressComplete( shippingAddress ); + const shippingAddressIsComplete = + ! shippingAddressHasValidationErrors() && + isAddressComplete( shippingAddress ); const shippingRatesPackageCount = getShippingRatesPackageCount( shippingRates ); From 1922c035b76f60c3c0b8fe98f89d909ad76c2e41 Mon Sep 17 00:00:00 2001 From: Tarun Vijwani Date: Thu, 16 Mar 2023 12:31:44 +0400 Subject: [PATCH 25/25] Display correct message in checkout when address shipping is complete - Rename the isShippingAddressComplete variable to shippingAddressHasErrors as it only checks validation errors. - Use isAddressComplete function to check if address is complete. --- .../checkout-shipping-methods-block/block.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx b/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx index 93974f7dad5..86f26557eed 100644 --- a/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx +++ b/assets/js/blocks/checkout/inner-blocks/checkout-shipping-methods-block/block.tsx @@ -94,9 +94,8 @@ const Block = ( { return null; } - const shippingAddressIsComplete = - ! shippingAddressHasValidationErrors() && - isAddressComplete( shippingAddress ); + const shippingAddressHasErrors = ! shippingAddressHasValidationErrors(); + const addressComplete = isAddressComplete( shippingAddress ); const shippingRatesPackageCount = getShippingRatesPackageCount( shippingRates ); @@ -104,7 +103,7 @@ const Block = ( { if ( ( ! hasCalculatedShipping && ! shippingRatesPackageCount ) || ( shippingCostRequiresAddress && - ( ! shippingAddressPushed || ! shippingAddressIsComplete ) ) + ( ! shippingAddressPushed || ! shippingAddressHasErrors ) ) ) { return (

@@ -127,7 +126,7 @@ const Block = ( { - { shippingAddressIsComplete + { addressComplete ? __( 'There are no shipping options available. Please check your shipping address.', 'woo-gutenberg-products-block'