Migrate StateInput, CountryInput and custom fields to native `<select>` (#48180)
This commit is contained in:
parent
c31e274616
commit
9fa32b4f2b
|
@ -33,9 +33,9 @@ import { AddressFormProps, AddressFormFields } from './types';
|
|||
import prepareFormFields from './prepare-form-fields';
|
||||
import validateShippingCountry from './validate-shipping-country';
|
||||
import customValidationHandler from './custom-validation-handler';
|
||||
import Combobox from '../../combobox';
|
||||
import AddressLineFields from './address-line-fields';
|
||||
import { createFieldProps, getFieldData } from './utils';
|
||||
import { Select } from '../../select';
|
||||
|
||||
/**
|
||||
* Checkout form.
|
||||
|
@ -228,9 +228,10 @@ const Form = < T extends AddressFormValues | ContactFormValues >( {
|
|||
}
|
||||
|
||||
return (
|
||||
<Combobox
|
||||
<Select
|
||||
key={ field.key }
|
||||
{ ...fieldProps }
|
||||
label={ fieldProps.label || '' }
|
||||
className={ clsx(
|
||||
'wc-block-components-select-input',
|
||||
`wc-block-components-select-input-${ field.key }`.replaceAll(
|
||||
|
|
|
@ -46,7 +46,7 @@ const primaryAddress = {
|
|||
};
|
||||
const secondaryAddress = {
|
||||
country: 'Austria', // We use Austria because it doesn't have states.
|
||||
countryKey: 'AU',
|
||||
countryKey: 'AT',
|
||||
city: 'Vienna',
|
||||
postcode: 'DCBA',
|
||||
};
|
||||
|
@ -57,23 +57,29 @@ const tertiaryAddress = {
|
|||
state: 'Ontario',
|
||||
postcode: 'EFGH',
|
||||
};
|
||||
const quaternaryAddress = {
|
||||
country: 'Japan',
|
||||
countryKey: 'JP',
|
||||
city: 'Tokyo',
|
||||
postcode: 'IJKL',
|
||||
};
|
||||
|
||||
const countryRegExp = /country/i;
|
||||
const cityRegExp = /city/i;
|
||||
const stateRegExp = /county|province|state/i;
|
||||
const postalCodeRegExp = /postal code|postcode|zip/i;
|
||||
|
||||
const inputAddress = async ( {
|
||||
country = null,
|
||||
countryKey = null,
|
||||
city = null,
|
||||
state = null,
|
||||
postcode = null,
|
||||
} ) => {
|
||||
if ( country ) {
|
||||
const countryInput = screen.queryByRole( 'combobox', {
|
||||
name: countryRegExp,
|
||||
} );
|
||||
await userEvent.type( countryInput, country + '{arrowdown}{enter}' );
|
||||
if ( countryKey ) {
|
||||
const countryInput = screen.getByLabelText( 'Country/Region' );
|
||||
|
||||
if ( countryInput ) {
|
||||
await userEvent.selectOptions( countryInput, countryKey );
|
||||
}
|
||||
}
|
||||
if ( city ) {
|
||||
const cityInput = screen.getByLabelText( cityRegExp );
|
||||
|
@ -81,15 +87,12 @@ const inputAddress = async ( {
|
|||
}
|
||||
|
||||
if ( state ) {
|
||||
const stateButton = screen.queryByRole( 'combobox', {
|
||||
name: stateRegExp,
|
||||
const stateButton = screen.queryByLabelText( stateRegExp, {
|
||||
selector: 'select',
|
||||
} );
|
||||
// State input might be a select or a text input.
|
||||
if ( stateButton ) {
|
||||
await userEvent.click( stateButton );
|
||||
await userEvent.click(
|
||||
screen.getByRole( 'option', { name: state } )
|
||||
);
|
||||
await userEvent.selectOptions( stateButton, state );
|
||||
} else {
|
||||
const stateInput = screen.getByLabelText( stateRegExp );
|
||||
await userEvent.type( stateInput, state );
|
||||
|
@ -182,24 +185,16 @@ describe( 'Form Component', () => {
|
|||
it( 'input values are reset after changing the country', async () => {
|
||||
renderInCheckoutProvider( <WrappedAddressForm type="shipping" /> );
|
||||
|
||||
// First enter an address with no state, but fill the city.
|
||||
await act( async () => {
|
||||
await inputAddress( secondaryAddress );
|
||||
} );
|
||||
|
||||
// Only update `country` to verify other values are reset.
|
||||
// Update country to another country without state.
|
||||
await act( async () => {
|
||||
await inputAddress( { country: primaryAddress.country } );
|
||||
await inputAddress( { countryKey: quaternaryAddress.countryKey } );
|
||||
} );
|
||||
|
||||
expect( screen.getByLabelText( stateRegExp ).value ).toBe( '' );
|
||||
|
||||
// Repeat the test with an address which has a select for the state.
|
||||
await act( async () => {
|
||||
await inputAddress( tertiaryAddress );
|
||||
} );
|
||||
await act( async () => {
|
||||
await inputAddress( { country: primaryAddress.country } );
|
||||
} );
|
||||
expect( screen.getByLabelText( stateRegExp ).value ).toBe( '' );
|
||||
expect( screen.getByLabelText( postalCodeRegExp ).value ).toBe( '' );
|
||||
} );
|
||||
} );
|
||||
|
|
|
@ -10,7 +10,10 @@ import CountryInput from './country-input';
|
|||
import type { CountryInputProps } from './CountryInputProps';
|
||||
|
||||
const BillingCountryInput = ( props: CountryInputProps ): JSX.Element => {
|
||||
return <CountryInput countries={ ALLOWED_COUNTRIES } { ...props } />;
|
||||
// TODO - are errorMessage and errorId still relevant when select always has a value?
|
||||
const { errorMessage: _, errorId: __, ...restOfProps } = props;
|
||||
|
||||
return <CountryInput countries={ ALLOWED_COUNTRIES } { ...restOfProps } />;
|
||||
};
|
||||
|
||||
export default BillingCountryInput;
|
||||
|
|
|
@ -2,16 +2,15 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { useMemo } from '@wordpress/element';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { decodeEntities } from '@wordpress/html-entities';
|
||||
import clsx from 'clsx';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import Combobox from '../combobox';
|
||||
import './style.scss';
|
||||
import type { CountryInputWithCountriesProps } from './CountryInputProps';
|
||||
import { Select } from '../select';
|
||||
|
||||
export const CountryInput = ( {
|
||||
className,
|
||||
|
@ -22,8 +21,6 @@ export const CountryInput = ( {
|
|||
value = '',
|
||||
autoComplete = 'off',
|
||||
required = false,
|
||||
errorId,
|
||||
errorMessage = __( 'Please select a country', 'woocommerce' ),
|
||||
}: CountryInputWithCountriesProps ): JSX.Element => {
|
||||
const options = useMemo(
|
||||
() =>
|
||||
|
@ -40,14 +37,12 @@ export const CountryInput = ( {
|
|||
<div
|
||||
className={ clsx( className, 'wc-block-components-country-input' ) }
|
||||
>
|
||||
<Combobox
|
||||
<Select
|
||||
id={ id }
|
||||
label={ label }
|
||||
label={ label || '' }
|
||||
onChange={ onChange }
|
||||
options={ options }
|
||||
value={ value }
|
||||
errorId={ errorId }
|
||||
errorMessage={ errorMessage }
|
||||
required={ required }
|
||||
autoComplete={ autoComplete }
|
||||
/>
|
||||
|
|
|
@ -23,6 +23,7 @@ export * from './product-rating';
|
|||
export * from './quantity-selector';
|
||||
export * from './read-more';
|
||||
export * from './reviews';
|
||||
export * from './select';
|
||||
export * from './sidebar-layout';
|
||||
export * from './snackbar-list';
|
||||
export * from './state-input';
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Icon, chevronDown } from '@wordpress/icons';
|
||||
import { useCallback, useId } from '@wordpress/element';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './style.scss';
|
||||
|
||||
type SelectProps = Omit<
|
||||
React.SelectHTMLAttributes< HTMLSelectElement >,
|
||||
'onChange'
|
||||
> & {
|
||||
options: { value: string; label: string }[];
|
||||
label: string;
|
||||
onChange: ( newVal: string ) => void;
|
||||
};
|
||||
|
||||
export const Select = ( props: SelectProps ) => {
|
||||
const { onChange, options, label, value, className, size, ...restOfProps } =
|
||||
props;
|
||||
|
||||
const selectOnChange = useCallback(
|
||||
( event: React.ChangeEvent< HTMLSelectElement > ) => {
|
||||
onChange( event.target.value );
|
||||
},
|
||||
[ onChange ]
|
||||
);
|
||||
|
||||
const generatedId = useId();
|
||||
|
||||
const inputId =
|
||||
restOfProps.id || `wc-blocks-components-select-${ generatedId }`;
|
||||
|
||||
return (
|
||||
<div className={ `wc-blocks-components-select ${ className || '' }` }>
|
||||
<div className="wc-blocks-components-select__container">
|
||||
<label
|
||||
htmlFor={ inputId }
|
||||
className="wc-blocks-components-select__label"
|
||||
>
|
||||
{ label }
|
||||
</label>
|
||||
<select
|
||||
className="wc-blocks-components-select__select"
|
||||
id={ inputId }
|
||||
size={ size !== undefined ? size : 1 }
|
||||
onChange={ selectOnChange }
|
||||
value={ value }
|
||||
{ ...restOfProps }
|
||||
>
|
||||
{ options.map( ( option ) => (
|
||||
<option
|
||||
key={ option.value }
|
||||
value={ option.value }
|
||||
data-alternate-values={ `[${ option.label }]` }
|
||||
>
|
||||
{ option.label }
|
||||
</option>
|
||||
) ) }
|
||||
</select>
|
||||
<Icon
|
||||
className="wc-blocks-components-select__expand"
|
||||
icon={ chevronDown }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,78 @@
|
|||
.wc-blocks-components-select {
|
||||
width: 100%;
|
||||
|
||||
.wc-blocks-components-select__container {
|
||||
border-radius: $universal-border-radius;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid $universal-border-light;
|
||||
background: #fff;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
position: relative;
|
||||
|
||||
.has-dark-controls & {
|
||||
background-color: $input-background-dark;
|
||||
border-color: $input-border-dark;
|
||||
color: $input-text-dark;
|
||||
|
||||
&:focus {
|
||||
background-color: $input-background-dark;
|
||||
color: $input-text-dark;
|
||||
box-shadow: 0 0 0 2px $input-border-gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wc-blocks-components-select__select {
|
||||
@include reset-typography();
|
||||
@include font-size(regular);
|
||||
border-radius: $universal-border-radius;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
appearance: none;
|
||||
background: none;
|
||||
padding: em($gap) em($gap-smaller) 0;
|
||||
color: currentColor;
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
box-shadow: 0 0 0 1px currentColor;
|
||||
}
|
||||
}
|
||||
|
||||
.wc-blocks-components-select__label {
|
||||
@include reset-typography();
|
||||
@include font-size(regular);
|
||||
position: absolute;
|
||||
line-height: 1.25; // =20px when font-size is 16px.
|
||||
left: em($gap-smaller);
|
||||
top: 0;
|
||||
transform-origin: top left;
|
||||
transition: all 200ms ease;
|
||||
color: currentColor;
|
||||
z-index: 1;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: calc(100% - #{2 * $gap});
|
||||
white-space: nowrap;
|
||||
|
||||
.has-dark-controls & {
|
||||
color: $input-placeholder-dark;
|
||||
}
|
||||
@media screen and (prefers-reduced-motion: reduce) {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
transform: translateY(15%) scale(0.75);
|
||||
}
|
||||
|
||||
.wc-blocks-components-select__expand {
|
||||
position: absolute;
|
||||
transform: translate(0%, -50%);
|
||||
top: 50%;
|
||||
right: $gap-small;
|
||||
pointer-events: none;
|
||||
fill: currentColor;
|
||||
}
|
||||
}
|
|
@ -10,7 +10,10 @@ import StateInput from './state-input';
|
|||
import type { StateInputProps } from './StateInputProps';
|
||||
|
||||
const BillingStateInput = ( props: StateInputProps ): JSX.Element => {
|
||||
return <StateInput states={ ALLOWED_STATES } { ...props } />;
|
||||
// TODO - are errorMessage and errorId still relevant when select always has a value?
|
||||
const { errorMessage: _, errorId: __, ...restOfProps } = props;
|
||||
|
||||
return <StateInput states={ ALLOWED_STATES } { ...restOfProps } />;
|
||||
};
|
||||
|
||||
export default BillingStateInput;
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { decodeEntities } from '@wordpress/html-entities';
|
||||
import { useCallback, useMemo, useEffect, useRef } from '@wordpress/element';
|
||||
import clsx from 'clsx';
|
||||
import { ValidatedTextInput } from '@woocommerce/blocks-components';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import Combobox from '../combobox';
|
||||
import './style.scss';
|
||||
import type { StateInputWithStatesProps } from './StateInputProps';
|
||||
import { Select } from '../select';
|
||||
|
||||
const optionMatcher = (
|
||||
value: string,
|
||||
|
@ -36,7 +34,6 @@ const StateInput = ( {
|
|||
autoComplete = 'off',
|
||||
value = '',
|
||||
required = false,
|
||||
errorId = '',
|
||||
}: StateInputWithStatesProps ): JSX.Element => {
|
||||
const countryStates = states[ country ];
|
||||
const options = useMemo(
|
||||
|
@ -91,20 +88,17 @@ const StateInput = ( {
|
|||
|
||||
if ( options.length > 0 ) {
|
||||
return (
|
||||
<Combobox
|
||||
className={ clsx(
|
||||
className,
|
||||
'wc-block-components-state-input'
|
||||
) }
|
||||
id={ id }
|
||||
label={ label }
|
||||
onChange={ onChangeState }
|
||||
<Select
|
||||
options={ options }
|
||||
label={ label || '' }
|
||||
className={ `wc-block-components-state-input ${
|
||||
className || ''
|
||||
}` }
|
||||
id={ id }
|
||||
onChange={ onChangeState }
|
||||
value={ value }
|
||||
errorMessage={ __( 'Please select a state.', 'woocommerce' ) }
|
||||
errorId={ errorId }
|
||||
required={ required }
|
||||
autoComplete={ autoComplete }
|
||||
required={ required }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
.wc-block-components-state-input {
|
||||
.wc-blocks-components-select__container {
|
||||
margin-top: $gap;
|
||||
}
|
||||
|
|
|
@ -14,8 +14,7 @@ class AddSplitChunkDependencies {
|
|||
apply( compiler ) {
|
||||
compiler.hooks.thisCompilation.tap(
|
||||
'AddStableChunksToAssets',
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- not used.
|
||||
( compilation, callback ) => {
|
||||
( compilation ) => {
|
||||
compilation.hooks.processAssets.tap(
|
||||
{
|
||||
name: 'AddStableChunksToAssets',
|
||||
|
|
|
@ -330,8 +330,7 @@ const getFrontConfig = ( options = {} ) => {
|
|||
// translations which we must avoid.
|
||||
// @see https://github.com/Automattic/jetpack/pull/20926
|
||||
chunkFilename: `[name]-frontend${ fileSuffix }.js?ver=[contenthash]`,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- not used.
|
||||
filename: ( pathData ) => {
|
||||
filename: () => {
|
||||
return `[name]-frontend${ fileSuffix }.js`;
|
||||
},
|
||||
uniqueName: 'webpackWcBlocksFrontendJsonp',
|
||||
|
|
|
@ -76,11 +76,6 @@ test.describe( 'Shopper → Additional Checkout Fields', () => {
|
|||
'Please enter a valid government id'
|
||||
)
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
checkoutPageObject.page.getByText(
|
||||
'Please select a valid option'
|
||||
)
|
||||
).toBeVisible();
|
||||
} );
|
||||
|
||||
test( 'Shopper can fill in the checkout form with additional fields and can have different value for same field in shipping and billing address', async ( {
|
||||
|
@ -122,13 +117,13 @@ test.describe( 'Shopper → Additional Checkout Fields', () => {
|
|||
name: 'Shipping address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
.fill( 'wide' );
|
||||
.selectOption( 'wide' );
|
||||
await checkoutPageObject.page
|
||||
.getByRole( 'group', {
|
||||
name: 'Billing address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
.fill( 'narrow' );
|
||||
.selectOption( 'narrow' );
|
||||
|
||||
await checkoutPageObject.page.evaluate(
|
||||
'document.activeElement.blur()'
|
||||
|
@ -217,7 +212,7 @@ test.describe( 'Shopper → Additional Checkout Fields', () => {
|
|||
.getByLabel(
|
||||
'Is this a personal purchase or a business purchase?'
|
||||
)
|
||||
).toHaveValue( 'Business' );
|
||||
).toHaveValue( 'business' );
|
||||
await expect(
|
||||
checkoutPageObject.page
|
||||
.getByRole( 'group', {
|
||||
|
@ -252,7 +247,7 @@ test.describe( 'Shopper → Additional Checkout Fields', () => {
|
|||
name: 'Shipping address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
).toHaveValue( 'Wide' );
|
||||
).toHaveValue( 'wide' );
|
||||
await expect(
|
||||
checkoutPageObject.page
|
||||
.getByRole( 'group', {
|
||||
|
@ -280,7 +275,7 @@ test.describe( 'Shopper → Additional Checkout Fields', () => {
|
|||
name: 'Billing address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
).toHaveValue( 'Narrow' );
|
||||
).toHaveValue( 'narrow' );
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
|
|
|
@ -70,13 +70,13 @@ test.describe( 'Merchant → Additional Checkout Fields', () => {
|
|||
name: 'Shipping address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
.fill( 'wide' );
|
||||
.selectOption( 'wide' );
|
||||
await checkoutPageObject.page
|
||||
.getByRole( 'group', {
|
||||
name: 'Billing address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
.fill( 'narrow' );
|
||||
.selectOption( 'narrow' );
|
||||
|
||||
await checkoutPageObject.page.evaluate(
|
||||
'document.activeElement.blur()'
|
||||
|
@ -206,13 +206,13 @@ test.describe( 'Merchant → Additional Checkout Fields', () => {
|
|||
name: 'Shipping address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
.fill( 'wide' );
|
||||
.selectOption( 'wide' );
|
||||
await checkoutPageObject.page
|
||||
.getByRole( 'group', {
|
||||
name: 'Billing address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
.fill( 'narrow' );
|
||||
.selectOption( 'narrow' );
|
||||
|
||||
await checkoutPageObject.page.evaluate(
|
||||
'document.activeElement.blur()'
|
||||
|
|
|
@ -73,13 +73,13 @@ test.describe( 'Shopper → Additional Checkout Fields', () => {
|
|||
name: 'Shipping address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
.fill( 'wide' );
|
||||
.selectOption( 'wide' );
|
||||
await checkoutPageObject.page
|
||||
.getByRole( 'group', {
|
||||
name: 'Billing address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
.fill( 'narrow' );
|
||||
.selectOption( 'narrow' );
|
||||
|
||||
await checkoutPageObject.page.evaluate(
|
||||
'document.activeElement.blur()'
|
||||
|
@ -155,7 +155,7 @@ test.describe( 'Shopper → Additional Checkout Fields', () => {
|
|||
.getByLabel(
|
||||
'Is this a personal purchase or a business purchase?'
|
||||
)
|
||||
).toHaveValue( 'Business' );
|
||||
).toHaveValue( 'business' );
|
||||
await expect(
|
||||
checkoutPageObject.page
|
||||
.getByRole( 'group', {
|
||||
|
@ -190,7 +190,7 @@ test.describe( 'Shopper → Additional Checkout Fields', () => {
|
|||
name: 'Shipping address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
).toHaveValue( 'Wide' );
|
||||
).toHaveValue( 'wide' );
|
||||
await expect(
|
||||
checkoutPageObject.page
|
||||
.getByRole( 'group', {
|
||||
|
@ -218,7 +218,7 @@ test.describe( 'Shopper → Additional Checkout Fields', () => {
|
|||
name: 'Billing address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
).toHaveValue( 'Narrow' );
|
||||
).toHaveValue( 'narrow' );
|
||||
} );
|
||||
|
||||
test( 'Shopper can change the values of fields multiple times and place the order', async ( {
|
||||
|
@ -261,13 +261,13 @@ test.describe( 'Shopper → Additional Checkout Fields', () => {
|
|||
name: 'Shipping address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
.fill( 'wide' );
|
||||
.selectOption( 'wide' );
|
||||
await checkoutPageObject.page
|
||||
.getByRole( 'group', {
|
||||
name: 'Billing address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
.fill( 'narrow' );
|
||||
.selectOption( 'narrow' );
|
||||
await checkoutPageObject.waitForCustomerDataUpdate();
|
||||
|
||||
// Change the shipping and billing select fields again.
|
||||
|
@ -276,13 +276,13 @@ test.describe( 'Shopper → Additional Checkout Fields', () => {
|
|||
name: 'Billing address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
.fill( 'wide' );
|
||||
.selectOption( 'wide' );
|
||||
await checkoutPageObject.page
|
||||
.getByRole( 'group', {
|
||||
name: 'Shipping address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
.fill( 'super-wide' );
|
||||
.selectOption( 'super-wide' );
|
||||
await checkoutPageObject.waitForCustomerDataUpdate();
|
||||
|
||||
await checkoutPageObject.page
|
||||
|
@ -354,11 +354,9 @@ test.describe( 'Shopper → Additional Checkout Fields', () => {
|
|||
.getByRole( 'group', {
|
||||
name: 'Additional order information',
|
||||
} )
|
||||
.locator(
|
||||
'ul.components-form-token-field__suggestions-list > li'
|
||||
)
|
||||
.locator( 'select' )
|
||||
.first()
|
||||
.click();
|
||||
.selectOption( { index: 0 } );
|
||||
await checkoutPageObject.waitForCustomerDataUpdate();
|
||||
|
||||
await checkoutPageObject.placeOrder();
|
||||
|
@ -445,13 +443,13 @@ test.describe( 'Shopper → Additional Checkout Fields', () => {
|
|||
name: 'Shipping address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
.fill( 'wide' );
|
||||
.selectOption( 'wide' );
|
||||
await checkoutPageObject.page
|
||||
.getByRole( 'group', {
|
||||
name: 'Billing address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
.fill( 'narrow' );
|
||||
.selectOption( 'narrow' );
|
||||
|
||||
await checkoutPageObject.page.evaluate(
|
||||
'document.activeElement.blur()'
|
||||
|
@ -527,7 +525,7 @@ test.describe( 'Shopper → Additional Checkout Fields', () => {
|
|||
.getByLabel(
|
||||
'Is this a personal purchase or a business purchase?'
|
||||
)
|
||||
).toHaveValue( 'Business' );
|
||||
).toHaveValue( 'business' );
|
||||
await expect(
|
||||
checkoutPageObject.page
|
||||
.getByRole( 'group', {
|
||||
|
@ -562,7 +560,7 @@ test.describe( 'Shopper → Additional Checkout Fields', () => {
|
|||
name: 'Shipping address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
).toHaveValue( 'Wide' );
|
||||
).toHaveValue( 'wide' );
|
||||
await expect(
|
||||
checkoutPageObject.page
|
||||
.getByRole( 'group', {
|
||||
|
@ -590,7 +588,7 @@ test.describe( 'Shopper → Additional Checkout Fields', () => {
|
|||
name: 'Billing address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
).toHaveValue( 'Narrow' );
|
||||
).toHaveValue( 'narrow' );
|
||||
} );
|
||||
|
||||
test( 'Shopper can see server-side validation errors', async ( {
|
||||
|
@ -682,13 +680,13 @@ test.describe( 'Shopper → Additional Checkout Fields', () => {
|
|||
name: 'Shipping address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
.fill( 'wide' );
|
||||
.selectOption( 'wide' );
|
||||
await checkoutPageObject.page
|
||||
.getByRole( 'group', {
|
||||
name: 'Billing address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
.fill( 'narrow' );
|
||||
.selectOption( 'narrow' );
|
||||
await checkoutPageObject.page.evaluate(
|
||||
'document.activeElement.blur()'
|
||||
);
|
||||
|
@ -766,13 +764,13 @@ test.describe( 'Shopper → Additional Checkout Fields', () => {
|
|||
name: 'Shipping address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
.fill( 'wide' );
|
||||
.selectOption( 'wide' );
|
||||
await checkoutPageObject.page
|
||||
.getByRole( 'group', {
|
||||
name: 'Billing address',
|
||||
} )
|
||||
.getByLabel( 'How wide is your road?' )
|
||||
.fill( 'narrow' );
|
||||
.selectOption( 'narrow' );
|
||||
|
||||
// Blur after editing the select fields since they need to be blurred to save.
|
||||
await checkoutPageObject.page.evaluate(
|
||||
|
@ -925,7 +923,7 @@ test.describe( 'Shopper → Additional Checkout Fields', () => {
|
|||
await govIdInput.fill( '11111' );
|
||||
await confirmGovIdInput.fill( '11111' );
|
||||
await shippingTruckFittingCheckbox.uncheck();
|
||||
await shippingRoadSizeSelect.selectOption( 'Narrow' );
|
||||
await shippingRoadSizeSelect.selectOption( 'narrow' );
|
||||
await checkoutPageObject.page.getByText( 'Save address' ).click();
|
||||
|
||||
// Check the updated values are visible in the addresses.
|
||||
|
|
|
@ -228,6 +228,7 @@ test.describe( 'Shopper → Shipping and Billing Addresses', () => {
|
|||
city: 'San Francisco',
|
||||
state: 'California',
|
||||
country: 'United Kingdom',
|
||||
countryKey: 'GB',
|
||||
postcode: 'SW1 1AA',
|
||||
phone: '123456789',
|
||||
email: 'john.doe@example.com',
|
||||
|
@ -241,6 +242,7 @@ test.describe( 'Shopper → Shipping and Billing Addresses', () => {
|
|||
city: 'Los Angeles',
|
||||
phone: '987654321',
|
||||
country: 'Albania',
|
||||
countryKey: 'AL',
|
||||
state: 'Berat',
|
||||
postcode: '1234',
|
||||
};
|
||||
|
@ -349,7 +351,7 @@ test.describe( 'Shopper → Shipping (customer user)', () => {
|
|||
lastname: 'Perez',
|
||||
addressfirstline: '123 Test Street',
|
||||
addresssecondline: 'Apartment 6',
|
||||
country: 'ES',
|
||||
countryKey: 'ES',
|
||||
city: 'Madrid',
|
||||
postcode: '08830',
|
||||
state: 'M',
|
||||
|
@ -546,6 +548,7 @@ test.describe( 'Billing Address Form', () => {
|
|||
addressfirstline: '123 Easy Street',
|
||||
addresssecondline: 'Testville',
|
||||
country: 'United States (US)',
|
||||
countryKey: 'US',
|
||||
city: 'New York',
|
||||
state: 'New York',
|
||||
postcode: '90210',
|
||||
|
@ -571,14 +574,14 @@ test.describe( 'Billing Address Form', () => {
|
|||
shippingForm.getByLabel( 'Apartment, suite, etc. (optional)' )
|
||||
).toHaveValue( 'Testville' );
|
||||
await expect(
|
||||
shippingForm.getByLabel( 'United States (US), Country/' )
|
||||
).toHaveValue( 'United States (US)' );
|
||||
shippingForm.getByLabel( 'Country/Region' )
|
||||
).toHaveValue( 'US' );
|
||||
await expect( shippingForm.getByLabel( 'City' ) ).toHaveValue(
|
||||
'New York'
|
||||
);
|
||||
await expect(
|
||||
shippingForm.getByLabel( 'New York, State' )
|
||||
).toHaveValue( 'New York' );
|
||||
await expect( shippingForm.getByLabel( 'State' ) ).toHaveValue(
|
||||
'NY'
|
||||
);
|
||||
await expect( shippingForm.getByLabel( 'ZIP Code' ) ).toHaveValue(
|
||||
'90210'
|
||||
);
|
||||
|
@ -605,12 +608,12 @@ test.describe( 'Billing Address Form', () => {
|
|||
} )
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
billingForm.getByLabel( 'United States (US), Country/' )
|
||||
).toHaveValue( 'United States (US)' );
|
||||
billingForm.getByLabel( 'Country/Region' )
|
||||
).toHaveValue( 'US' );
|
||||
await expect( billingForm.getByLabel( 'City' ) ).toHaveValue( '' );
|
||||
await expect(
|
||||
billingForm.getByLabel( 'New York, State' )
|
||||
).toHaveValue( 'New York' );
|
||||
await expect( billingForm.getByLabel( 'State' ) ).toHaveValue(
|
||||
'NY'
|
||||
);
|
||||
await expect( billingForm.getByLabel( 'ZIP Code' ) ).toHaveValue(
|
||||
''
|
||||
);
|
||||
|
|
|
@ -23,6 +23,7 @@ export class CheckoutPage {
|
|||
addressfirstline: '123 Easy Street',
|
||||
addresssecondline: 'Testville',
|
||||
country: 'United States (US)',
|
||||
countryKey: 'US',
|
||||
city: 'New York',
|
||||
state: 'New York',
|
||||
postcode: '90210',
|
||||
|
@ -124,7 +125,16 @@ export class CheckoutPage {
|
|||
// Rest of additional data passed in from the overrideData object.
|
||||
for ( const [ label, value ] of Object.entries( additionalFields ) ) {
|
||||
const field = contactSection.getByLabel( label );
|
||||
await field.fill( value );
|
||||
|
||||
const tagName = await field.evaluate( ( element ) =>
|
||||
element.tagName.toLowerCase()
|
||||
);
|
||||
|
||||
if ( tagName === 'select' ) {
|
||||
await field.selectOption( value );
|
||||
} else {
|
||||
await field.fill( value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,7 +148,16 @@ export class CheckoutPage {
|
|||
// Rest of additional data passed in from the overrideData object.
|
||||
for ( const [ label, value ] of Object.entries( additionalFields ) ) {
|
||||
const field = contactSection.getByLabel( label );
|
||||
await field.fill( value );
|
||||
|
||||
const tagName = await field.evaluate( ( element ) =>
|
||||
element.tagName.toLowerCase()
|
||||
);
|
||||
|
||||
if ( tagName === 'select' ) {
|
||||
await field.selectOption( value );
|
||||
} else {
|
||||
await field.fill( value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,7 +170,16 @@ export class CheckoutPage {
|
|||
// Rest of additional data passed in from the overrideData object.
|
||||
for ( const { label, value } of additionalFields ) {
|
||||
const field = this.page.getByLabel( label );
|
||||
await field.fill( value );
|
||||
|
||||
const tagName = await field.evaluate( ( element ) =>
|
||||
element.tagName.toLowerCase()
|
||||
);
|
||||
|
||||
if ( tagName === 'select' ) {
|
||||
await field.selectOption( value );
|
||||
} else {
|
||||
await field.fill( value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -337,7 +365,7 @@ export class CheckoutPage {
|
|||
await email.fill( customerBillingDetails.email );
|
||||
await firstName.fill( customerBillingDetails.firstname );
|
||||
await lastName.fill( customerBillingDetails.lastname );
|
||||
await country.fill( customerBillingDetails.country );
|
||||
await country.selectOption( customerBillingDetails.countryKey );
|
||||
await address1.fill( customerBillingDetails.addressfirstline );
|
||||
|
||||
if ( customerBillingDetails.addresssecondline ) {
|
||||
|
@ -360,10 +388,17 @@ export class CheckoutPage {
|
|||
} );
|
||||
const county = billingForm.getByLabel( 'County' );
|
||||
|
||||
await state
|
||||
.or( province )
|
||||
.or( county )
|
||||
.fill( customerBillingDetails.state );
|
||||
const elementToFill = state.or( province ).or( county );
|
||||
const tagName = await elementToFill.evaluate( ( element ) =>
|
||||
element.tagName.toLowerCase()
|
||||
);
|
||||
if ( tagName === 'select' ) {
|
||||
await elementToFill.selectOption(
|
||||
customerBillingDetails.state
|
||||
);
|
||||
} else {
|
||||
await elementToFill.fill( customerBillingDetails.state );
|
||||
}
|
||||
}
|
||||
|
||||
if ( customerBillingDetails.postcode ) {
|
||||
|
@ -376,7 +411,16 @@ export class CheckoutPage {
|
|||
// Rest of additional data passed in from the overrideData object.
|
||||
for ( const [ label, value ] of Object.entries( additionalFields ) ) {
|
||||
const field = billingForm.getByLabel( label, { exact: true } );
|
||||
await field.fill( value );
|
||||
|
||||
const tagName = await field.evaluate( ( element ) =>
|
||||
element.tagName.toLowerCase()
|
||||
);
|
||||
|
||||
if ( tagName === 'select' ) {
|
||||
await field.selectOption( value );
|
||||
} else {
|
||||
await field.fill( value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -407,7 +451,7 @@ export class CheckoutPage {
|
|||
|
||||
await firstName.fill( customerShippingDetails.firstname );
|
||||
await lastName.fill( customerShippingDetails.lastname );
|
||||
await country.fill( customerShippingDetails.country );
|
||||
await country.selectOption( customerShippingDetails.country );
|
||||
await address1.fill( customerShippingDetails.addressfirstline );
|
||||
|
||||
if ( customerShippingDetails.addresssecondline ) {
|
||||
|
@ -430,10 +474,17 @@ export class CheckoutPage {
|
|||
} );
|
||||
const county = shippingForm.getByLabel( 'County' );
|
||||
|
||||
await state
|
||||
.or( province )
|
||||
.or( county )
|
||||
.fill( customerShippingDetails.state );
|
||||
const elementToFill = state.or( province ).or( county );
|
||||
const tagName = await elementToFill.evaluate( ( element ) =>
|
||||
element.tagName.toLowerCase()
|
||||
);
|
||||
if ( tagName === 'select' ) {
|
||||
await elementToFill.selectOption(
|
||||
customerShippingDetails.state
|
||||
);
|
||||
} else {
|
||||
await elementToFill.fill( customerShippingDetails.state );
|
||||
}
|
||||
}
|
||||
|
||||
if ( customerShippingDetails.postcode ) {
|
||||
|
@ -446,7 +497,16 @@ export class CheckoutPage {
|
|||
// Rest of additional data passed in from the overrideData object.
|
||||
for ( const [ label, value ] of Object.entries( additionalFields ) ) {
|
||||
const field = shippingForm.getByLabel( label, { exact: true } );
|
||||
await field.fill( value );
|
||||
|
||||
const tagName = await field.evaluate( ( element ) =>
|
||||
element.tagName.toLowerCase()
|
||||
);
|
||||
|
||||
if ( tagName === 'select' ) {
|
||||
await field.selectOption( value );
|
||||
} else {
|
||||
await field.fill( value );
|
||||
}
|
||||
}
|
||||
|
||||
// Blur active field to trigger customer address update.
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: update
|
||||
|
||||
Migrate the cart and checkout block's state, country and custom field input to a native select
|
|
@ -142,7 +142,10 @@ test.describe(
|
|||
|
||||
// Set shipping country to Netherlands
|
||||
await page.getByLabel( 'Add an address for shipping' ).click();
|
||||
await page.getByRole( 'combobox' ).first().fill( 'Netherlands' );
|
||||
await page
|
||||
.getByRole( 'combobox' )
|
||||
.first()
|
||||
.selectOption( 'Netherlands' );
|
||||
await page.getByLabel( 'Postal code' ).fill( '1011AA' );
|
||||
await page.getByLabel( 'City' ).fill( 'Amsterdam' );
|
||||
await page.getByRole( 'button', { name: 'Update' } ).click();
|
||||
|
@ -171,7 +174,10 @@ test.describe(
|
|||
|
||||
// Set shipping country to Portugal
|
||||
await page.getByLabel( 'Add an address for shipping' ).click();
|
||||
await page.getByRole( 'combobox' ).first().fill( 'Portugal' );
|
||||
await page
|
||||
.getByRole( 'combobox' )
|
||||
.first()
|
||||
.selectOption( 'Portugal' );
|
||||
await page.getByLabel( 'Postal code' ).fill( '1000-001' );
|
||||
await page.getByLabel( 'City' ).fill( 'Lisbon' );
|
||||
await page.getByRole( 'button', { name: 'Update' } ).click();
|
||||
|
@ -207,7 +213,10 @@ test.describe(
|
|||
|
||||
// Set shipping country to Portugal
|
||||
await page.getByLabel( 'Add an address for shipping' ).click();
|
||||
await page.getByRole( 'combobox' ).first().fill( 'Portugal' );
|
||||
await page
|
||||
.getByRole( 'combobox' )
|
||||
.first()
|
||||
.selectOption( 'Portugal' );
|
||||
await page.getByLabel( 'Postal code' ).fill( '1000-001' );
|
||||
await page.getByLabel( 'City' ).fill( 'Lisbon' );
|
||||
await page.getByRole( 'button', { name: 'Update' } ).click();
|
||||
|
@ -238,7 +247,10 @@ test.describe(
|
|||
|
||||
// Set shipping country to Portugal
|
||||
await page.getByLabel( 'Add an address for shipping' ).click();
|
||||
await page.getByRole( 'combobox' ).first().fill( 'Portugal' );
|
||||
await page
|
||||
.getByRole( 'combobox' )
|
||||
.first()
|
||||
.selectOption( 'Portugal' );
|
||||
await page.getByLabel( 'Postal code' ).fill( '1000-001' );
|
||||
await page.getByLabel( 'City' ).fill( 'Lisbon' );
|
||||
await page.getByRole( 'button', { name: 'Update' } ).click();
|
||||
|
|
|
@ -376,12 +376,8 @@ test.describe(
|
|||
await expect(
|
||||
page.getByText( '+ Add apartment, suite, etc.' )
|
||||
).toBeEnabled();
|
||||
await expect(
|
||||
page.getByLabel( 'United States (US), Country/Region' )
|
||||
).toBeEditable();
|
||||
await expect(
|
||||
page.getByLabel( 'California, State' )
|
||||
).toBeEditable();
|
||||
await expect( page.getByLabel( 'Country/Region' ) ).toBeEnabled();
|
||||
await expect( page.getByLabel( 'State' ) ).toBeEnabled();
|
||||
await expect( page.getByLabel( 'City' ) ).toBeEditable();
|
||||
await expect( page.getByLabel( 'ZIP Code' ) ).toBeEnabled();
|
||||
await expect(
|
||||
|
|
Loading…
Reference in New Issue