diff --git a/client/components/woopay/save-user/checkout-page-save-user.js b/client/components/woopay/save-user/checkout-page-save-user.js index 070910114d2..52a24da0a0b 100644 --- a/client/components/woopay/save-user/checkout-page-save-user.js +++ b/client/components/woopay/save-user/checkout-page-save-user.js @@ -6,6 +6,7 @@ import React, { useEffect, useState, useCallback } from 'react'; import { __ } from '@wordpress/i18n'; // eslint-disable-next-line import/no-unresolved import { extensionCartUpdate } from '@woocommerce/blocks-checkout'; +import { validatePhoneNumber } from '@woocommerce/components/build/phone-number-input/validation'; /** * Internal dependencies @@ -92,9 +93,14 @@ const CheckoutPageSaveUser = ( { isBlocksCheckout } ) => { const handleCheckboxClick = ( e ) => { const isChecked = e.target.checked; if ( isChecked ) { - setPhoneNumber( getPhoneFieldValue() ); + const phoneFieldValue = getPhoneFieldValue(); + setPhoneNumber( phoneFieldValue ); + onPhoneValidationChange( + validatePhoneNumber( phoneFieldValue, '' ) + ); } else { setPhoneNumber( '' ); + onPhoneValidationChange( null ); if ( isBlocksCheckout ) { sendExtensionData( true ); } @@ -245,6 +251,7 @@ const CheckoutPageSaveUser = ( { isBlocksCheckout } ) => { inputProps={ { name: 'woopay_user_phone_field[no-country-code]', + id: 'woopay_user_phone_field_no_country_code', } } isBlocksCheckout={ isBlocksCheckout } /> diff --git a/client/components/woopay/save-user/test/checkout-page-save-user.test.js b/client/components/woopay/save-user/test/checkout-page-save-user.test.js index cabb3185666..b1146d46d3a 100644 --- a/client/components/woopay/save-user/test/checkout-page-save-user.test.js +++ b/client/components/woopay/save-user/test/checkout-page-save-user.test.js @@ -2,7 +2,12 @@ * External dependencies */ import React from 'react'; -import { render, screen, waitFor } from '@testing-library/react'; +import { + render, + screen, + waitFor, + queryByAttribute, +} from '@testing-library/react'; import userEvent from '@testing-library/user-event'; // eslint-disable-next-line import/no-unresolved import { extensionCartUpdate } from '@woocommerce/blocks-checkout'; @@ -248,9 +253,19 @@ describe( 'CheckoutPageSaveUser', () => { } ); it( 'fills the phone input on blocks checkout with phone number field fallback', async () => { - render( , { - wrapper: BlocksCheckoutEnvironmentMock, - } ); + const { container } = render( + , + { + wrapper: BlocksCheckoutEnvironmentMock, + } + ); + + const getPhoneInput = () => + queryByAttribute( + 'id', + container, + 'woopay_user_phone_field_no_country_code' + ); const saveMyInfoCheckbox = screen.getByLabelText( 'Securely save my information for 1-click checkout' @@ -261,9 +276,7 @@ describe( 'CheckoutPageSaveUser', () => { // click on the checkbox to show the phone field, input should be filled with the first phone input field userEvent.click( saveMyInfoCheckbox ); expect( saveMyInfoCheckbox ).toBeChecked(); - expect( screen.getByLabelText( 'Mobile phone number' ).value ).toEqual( - '2015555551' - ); + expect( getPhoneInput().value ).toEqual( '2015555551' ); // click on the checkbox to hide/show it again (and reset the previously entered values) userEvent.click( saveMyInfoCheckbox ); @@ -272,9 +285,7 @@ describe( 'CheckoutPageSaveUser', () => { userEvent.click( saveMyInfoCheckbox ); expect( saveMyInfoCheckbox ).toBeChecked(); - expect( screen.getByLabelText( 'Mobile phone number' ).value ).toEqual( - '2015555552' - ); + expect( getPhoneInput().value ).toEqual( '2015555552' ); // click on the checkbox to hide/show it again (and reset the previously entered values) userEvent.click( saveMyInfoCheckbox ); @@ -283,9 +294,7 @@ describe( 'CheckoutPageSaveUser', () => { userEvent.click( saveMyInfoCheckbox ); expect( saveMyInfoCheckbox ).toBeChecked(); - expect( screen.getByLabelText( 'Mobile phone number' ).value ).toEqual( - '2015555553' - ); + expect( getPhoneInput().value ).toEqual( '2015555553' ); // click on the checkbox to hide/show it again (and reset the previously entered values) userEvent.click( saveMyInfoCheckbox ); @@ -294,9 +303,7 @@ describe( 'CheckoutPageSaveUser', () => { userEvent.click( saveMyInfoCheckbox ); expect( saveMyInfoCheckbox ).toBeChecked(); - expect( screen.getByLabelText( 'Mobile phone number' ).value ).toEqual( - '' - ); + expect( getPhoneInput().value ).toEqual( '' ); await waitFor( () => expect( extensionCartUpdate ).toHaveBeenCalled() ); } ); diff --git a/client/settings/phone-input/index.tsx b/client/settings/phone-input/index.tsx index ae7c3c6c144..e45f535d437 100644 --- a/client/settings/phone-input/index.tsx +++ b/client/settings/phone-input/index.tsx @@ -1,7 +1,7 @@ /** * External dependencies */ -import React from 'react'; +import React, { useEffect } from 'react'; import { __ } from '@wordpress/i18n'; import { PhoneNumberInput } from '@woocommerce/components'; import { validatePhoneNumber } from '@woocommerce/components/build/phone-number-input/validation'; @@ -56,11 +56,6 @@ const PhoneInput = ( { { const handlePhoneNumberChangeMock = jest.fn(); const handlePhoneValidationChangeMock = jest.fn(); + const phoneInputId = 'phone-input-id'; beforeEach( () => { window.wcpaySettings = { @@ -22,15 +28,16 @@ describe( 'PhoneInput', () => { } ); it( 'should render phone number input', () => { - render( + const { container } = render( ); expect( - screen.queryByLabelText( 'Mobile phone number' ) + queryByAttribute( 'id', container, phoneInputId ) ).toBeInTheDocument(); } ); @@ -42,38 +49,38 @@ describe( 'PhoneInput', () => { value="123" /> ); - expect( - screen.queryByRole( 'combobox', { name: 'United States: +1' } ) - ).toBeInTheDocument(); + expect( screen.queryByText( '+1' ) ).toBeInTheDocument(); } ); it( 'should call the onValueChange with phone number including country code', () => { - render( + const { container } = render( ); expect( handlePhoneNumberChangeMock ).not.toHaveBeenCalled(); - const input = screen.queryByLabelText( 'Mobile phone number' ); // The label text for our input. + const input = queryByAttribute( 'id', container, phoneInputId ); fireEvent.change( input, { target: { value: '201' } } ); expect( handlePhoneNumberChangeMock ).toHaveBeenCalledWith( '+1201' ); } ); it( 'should call the onValidationChange with true if value is valid', () => { - render( + const { container } = render( ); - const input = screen.queryByLabelText( 'Mobile phone number' ); // The label text for our input. + const input = queryByAttribute( 'id', container, phoneInputId ); expect( handlePhoneValidationChangeMock ).toHaveBeenLastCalledWith( false diff --git a/client/settings/support-phone-input/index.js b/client/settings/support-phone-input/index.js index 11232a0728a..e96fae14bde 100644 --- a/client/settings/support-phone-input/index.js +++ b/client/settings/support-phone-input/index.js @@ -1,9 +1,10 @@ /** * External dependencies */ +import { validatePhoneNumber } from '@woocommerce/components/build/phone-number-input/validation'; import { BaseControl, Notice } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { useState, useEffect, useRef } from 'react'; +import { useState, useEffect, useRef, useMemo } from 'react'; /** * Internal dependencies @@ -22,12 +23,16 @@ const SupportPhoneInput = ( { setInputVallid } ) => { ?.account_business_support_phone?.message; const currentPhone = useRef( supportPhone ).current; + const currentPhoneValid = useMemo( + () => validatePhoneNumber( currentPhone ), + [ currentPhone ] + ); const isEmptyPhoneValid = supportPhone === '' && currentPhone === ''; const isDevModeEnabled = useDevMode(); const isTestPhoneValid = isDevModeEnabled && supportPhone === '+10000000000'; - const [ isPhoneValid, setPhoneValidity ] = useState( true ); + const [ isPhoneValid, setPhoneValidity ] = useState( currentPhoneValid ); if ( ! isTestPhoneValid && ! isPhoneValid && ! isEmptyPhoneValid ) { supportPhoneError = __( 'Please enter a valid phone number.', diff --git a/client/settings/support-phone-input/test/support-phone-input.test.js b/client/settings/support-phone-input/test/support-phone-input.test.js index a86c66ae12e..1da273690f4 100644 --- a/client/settings/support-phone-input/test/support-phone-input.test.js +++ b/client/settings/support-phone-input/test/support-phone-input.test.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { fireEvent, render, screen } from '@testing-library/react'; +import { fireEvent, render, queryByAttribute } from '@testing-library/react'; /** * Internal dependencies @@ -39,14 +39,22 @@ describe( 'SupportPhoneInput', () => { '+12345678901', setSupportPhone, ] ); - render( ); + const { container } = render( ); - const newPhone = '+12377778888'; - fireEvent.change( screen.getByLabelText( 'Support phone number' ), { - target: { value: newPhone }, - } ); + const expectedNewPhone = '+12377778888'; + const newPhone = expectedNewPhone.replace( '+1', '' ); + fireEvent.change( + queryByAttribute( + 'id', + container, + 'account-business-support-phone-input' + ), + { + target: { value: newPhone }, + } + ); - expect( setSupportPhone ).toHaveBeenCalledWith( newPhone ); + expect( setSupportPhone ).toHaveBeenCalledWith( expectedNewPhone ); } ); it( 'displays error message for empty phone input when it has been set', async () => { @@ -64,9 +72,16 @@ describe( 'SupportPhoneInput', () => { // Mock that the phone number input is set to empty. useAccountBusinessSupportPhone.mockReturnValue( [ '', jest.fn() ] ); - fireEvent.change( screen.getByLabelText( 'Support phone number' ), { - target: { value: '' }, - } ); + fireEvent.change( + queryByAttribute( + 'id', + container, + 'account-business-support-phone-input' + ), + { + target: { value: '' }, + } + ); // The error message is displayed. expect( diff --git a/client/settings/transactions/test/index.test.js b/client/settings/transactions/test/index.test.js index e5c2eea66c5..db617f3bb17 100644 --- a/client/settings/transactions/test/index.test.js +++ b/client/settings/transactions/test/index.test.js @@ -23,6 +23,9 @@ import { select } from '@wordpress/data'; jest.mock( '@wordpress/data', () => ( { select: jest.fn(), registerStore: jest.fn(), + dispatch: jest.fn().mockReturnValue( { + onLoad: jest.fn(), + } ), } ) ); const settingsMock = { account_country: 'US',