diff --git a/docs/third-party-developers/extensibility/checkout-payment-methods/payment-method-integration.md b/docs/third-party-developers/extensibility/checkout-payment-methods/payment-method-integration.md index 730ac5e3a93..7878dea9620 100644 --- a/docs/third-party-developers/extensibility/checkout-payment-methods/payment-method-integration.md +++ b/docs/third-party-developers/extensibility/checkout-payment-methods/payment-method-integration.md @@ -4,21 +4,27 @@ The checkout block has an API interface for payment methods to integrate that co ## Table of Contents -- [Client Side integration](#client-side-integration) - - [Express payment methods - `registerExpressPaymentMethod( options )`](#express-payment-methods---registerexpresspaymentmethod-options-) - - [`name` (required)](#name-required) - - [`content` (required)](#content-required) - - [`edit` (required)](#edit-required) - - [`canMakePayment` (required):](#canmakepayment-required) - - [`paymentMethodId`](#paymentmethodid) - - [`supports:features`](#supportsfeatures) - - [Payment Methods - `registerPaymentMethod( options )`](#payment-methods---registerpaymentmethod-options-) - - [Props Fed to Payment Method Nodes](#props-fed-to-payment-method-nodes) -- [Server Side Integration](#server-side-integration) - - [Processing Payment](#processing-payment) - - [Registering Assets](#registering-assets) - - [Hooking into the Checkout processing by the Store API.](#hooking-into-the-checkout-processing-by-the-store-api) - - [Putting it all together](#putting-it-all-together) +- [Client Side integration](#client-side-integration) + - [Express payment methods - `registerExpressPaymentMethod( options )`](#express-payment-methods---registerexpresspaymentmethod-options-) + - [Aliased import](#aliased-import) + - [`wc global`](#wc-global) + - [The registration options](#the-registration-options) + - [`name` (required)](#name-required) + - [`content` (required)](#content-required) + - [`edit` (required)](#edit-required) + - [`canMakePayment` (required)](#canmakepayment-required) + - [`paymentMethodId`](#paymentmethodid) + - [`supports:features`](#supportsfeatures) + - [Payment Methods - `registerPaymentMethod( options )`](#payment-methods---registerpaymentmethod-options-) + - [Aliased import](#aliased-import-1) + - [`wc global`](#wc-global-1) + - [The registration options](#the-registration-options-1) + - [Props Fed to Payment Method Nodes](#props-fed-to-payment-method-nodes) +- [Server Side Integration](#server-side-integration) + - [Processing Payment](#processing-payment) + - [Registering Assets](#registering-assets) + - [Hooking into the Checkout processing by the Store API](#hooking-into-the-checkout-processing-by-the-store-api) + - [Putting it all together](#putting-it-all-together) ## Client Side integration @@ -45,6 +51,7 @@ import { registerExpressPaymentMethod } from '@woocommerce/blocks-registry'; ```js const { registerExpressPaymentMethod } = wc.wcBlocksRegistry; ``` + #### The registration options The registry function expects a JavaScript object with options specific to the payment method: @@ -131,6 +138,7 @@ import { registerPaymentMethod } from '@woocommerce/blocks-registry'; ```js const { registerPaymentMethod } = wc.wcBlocksRegistry; ``` + #### The registration options The registry function expects a JavaScript object with options specific to the payment method (see `PaymentMethodRegistrationOptions` typedef): @@ -153,8 +161,8 @@ The options you feed the configuration instance are the same as those for expres A big part of the payment method integration is the interface that is exposed for payment methods to use via props when the node provided is cloned and rendered on block mount. While all the props are listed below, you can find more details about what the props reference, their types etc via the [typedefs described in this file](../../../../assets/js/types/type-defs/payment-method-interface.ts). -| Property | Type | Description | Values | -| ------ | ------ | ------ | ------ | +| Property | Type | Description | Values | +| ------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | ------ | ------------------------------------------------------------- | ------------------------------------------------------- | | `activePaymentMethod` | String | The slug of the current active payment method in the checkout. | | `billing` | Object | Contains everything related to billing. | `billingData`, `cartTotal`, `currency`, `cartTotalItems`, `displayPricesIncludingTax`, `appliedCoupons`, `customerId` | | `cartData` | Object | Data exposed from the cart including items, fees, and any registered extension data. Note that this data should be treated as immutable (should not be modified/mutated) or it will result in errors in your application. | `cartItems`, `cartFees`, `extensions` | `checkoutStatus` | Object | The current checkout status exposed as various boolean state. | `isCalculating`, `isComplete`, `isIdle`, `isProcessing` | diff --git a/packages/checkout/components/text-input/validated-text-input.tsx b/packages/checkout/components/text-input/validated-text-input.tsx index 1853c4a2a0f..baf45d67300 100644 --- a/packages/checkout/components/text-input/validated-text-input.tsx +++ b/packages/checkout/components/text-input/validated-text-input.tsx @@ -124,8 +124,12 @@ const ValidatedTextInput = ( { ); /** + * Handle browser autofill / changes via data store. + * * Trigger validation on state change if the current element is not in focus. This is because autofilled elements do not * trigger the blur() event, and so values can be validated in the background if the state changes elsewhere. + * + * Errors are immediately visible. */ useEffect( () => { if ( @@ -141,14 +145,23 @@ const ValidatedTextInput = ( { }, [ value, previousValue, validateInput ] ); /** - * If the input is in pristine state on mount, focus the element. + * Validation on mount. + * + * If the input is in pristine state on mount, focus the element (if focusOnMount is enabled), and validate in the + * background. + * + * Errors are hidden until blur. */ useEffect( () => { - if ( isPristine && focusOnMount ) { + if ( ! isPristine ) { + return; + } + if ( focusOnMount ) { inputRef.current?.focus(); } + validateInput( true ); setIsPristine( false ); - }, [ focusOnMount, isPristine, setIsPristine ] ); + }, [ focusOnMount, isPristine, setIsPristine, validateInput ] ); // Remove validation errors when unmounted. useEffect( () => { diff --git a/tests/e2e/specs/shopper/cart-checkout/checkout.test.js b/tests/e2e/specs/shopper/cart-checkout/checkout.test.js index 652460a6efb..3265b1880f4 100644 --- a/tests/e2e/specs/shopper/cart-checkout/checkout.test.js +++ b/tests/e2e/specs/shopper/cart-checkout/checkout.test.js @@ -145,7 +145,7 @@ describe( 'Shopper → Checkout', () => { await expect( page ).toMatchElement( '#email ~ .wc-block-components-validation-error p', { - text: 'Please fill', + text: 'Please provide a valid email address', } ); await expect( page ).toMatchElement(