diff --git a/assets/js/base/components/cart-checkout/local-pickup-select/index.tsx b/assets/js/base/components/cart-checkout/local-pickup-select/index.tsx new file mode 100644 index 00000000000..3a4d42ba6cc --- /dev/null +++ b/assets/js/base/components/cart-checkout/local-pickup-select/index.tsx @@ -0,0 +1,57 @@ +/** + * External dependencies + */ +import { RadioControlOption } from '@woocommerce/base-components/radio-control/types'; +import { CartShippingPackageShippingRate } from '@woocommerce/types'; +/** + * Internal dependencies + */ +import RadioControl from '../../radio-control'; + +interface LocalPickupSelectProps { + title?: string | undefined; + setSelectedOption: ( value: string ) => void; + selectedOption: string; + pickupLocations: CartShippingPackageShippingRate[]; + onSelectRate: ( value: string ) => void; + renderPickupLocation: ( + location: CartShippingPackageShippingRate, + pickupLocationsCount: number + ) => RadioControlOption; + packageCount: number; +} +/** + * Local pickup select component, used to render a package title and local pickup options. + */ +export const LocalPickupSelect = ( { + title, + setSelectedOption, + selectedOption, + pickupLocations, + onSelectRate, + renderPickupLocation, + packageCount, +}: LocalPickupSelectProps ) => { + // Hacky way to check if there are multiple packages, this way is borrowed from `assets/js/base/components/cart-checkout/shipping-rates-control-package/index.tsx` + // We have no built-in way of checking if other extensions have added packages. + const multiplePackages = + document.querySelectorAll( + '.wc-block-components-local-pickup-select .wc-block-components-radio-control' + ).length > 1; + return ( +
+ { multiplePackages && title ?
{ title }
: false } + { + setSelectedOption( value ); + onSelectRate( value ); + } } + selected={ selectedOption } + options={ pickupLocations.map( ( location ) => + renderPickupLocation( location, packageCount ) + ) } + /> +
+ ); +}; +export default LocalPickupSelect; diff --git a/assets/js/base/components/cart-checkout/local-pickup-select/test/index.tsx b/assets/js/base/components/cart-checkout/local-pickup-select/test/index.tsx new file mode 100644 index 00000000000..6d3bd6da04a --- /dev/null +++ b/assets/js/base/components/cart-checkout/local-pickup-select/test/index.tsx @@ -0,0 +1,121 @@ +/** + * External dependencies + */ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +/** + * Internal dependencies + */ +import LocalPickupSelect from '..'; + +describe( 'LocalPickupSelect', () => { + const TestComponent = ( { + selectedOptionOverride = null, + onSelectRateOverride = null, + }: { + selectedOptionOverride?: null | ( ( value: string ) => void ); + onSelectRateOverride?: null | ( ( value: string ) => void ); + } ) => ( + { + return { + value: `${ location.rate_id }`, + onChange: jest.fn(), + label: `${ location.name }`, + description: `${ location.description }`, + }; + } } + /> + ); + it( 'Does not render the title if only one package is present on the page', () => { + render( ); + expect( screen.queryByText( 'Package 1' ) ).not.toBeInTheDocument(); + } ); + it( 'Does render the title if more than one package is present on the page', () => { + const { rerender } = render( +
+
+
+ ); + // Render twice so our component can check the DOM correctly. + rerender( + <> +
+
+
+ + + ); + rerender( + <> +
+
+
+ + + ); + + expect( screen.getByText( 'Package 1' ) ).toBeInTheDocument(); + } ); + it( 'Calls the correct functions when changing selected option', () => { + const setSelectedOption = jest.fn(); + const onSelectRate = jest.fn(); + render( + + ); + userEvent.click( screen.getByText( 'Store 2' ) ); + expect( setSelectedOption ).toHaveBeenLastCalledWith( '2' ); + expect( onSelectRate ).toHaveBeenLastCalledWith( '2' ); + userEvent.click( screen.getByText( 'Store 1' ) ); + expect( setSelectedOption ).toHaveBeenLastCalledWith( '1' ); + expect( onSelectRate ).toHaveBeenLastCalledWith( '1' ); + } ); +} );