Skip to content

Commit

Permalink
Sync phone changes with WooPay phone field (#9464)
Browse files Browse the repository at this point in the history
  • Loading branch information
alefesouza authored Sep 28, 2024
1 parent f024d90 commit 7b746b8
Show file tree
Hide file tree
Showing 10 changed files with 187 additions and 147 deletions.
4 changes: 4 additions & 0 deletions changelog/fix-sync-woopay-phone-field
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fix

Sync phone changes with WooPay phone field.
89 changes: 73 additions & 16 deletions client/components/woopay/save-user/checkout-page-save-user.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,10 @@
/**
* External dependencies
*/
import React, { useEffect, useState, useCallback } from 'react';
import React, { useEffect, useState, useCallback, useRef } from 'react';
import { __ } from '@wordpress/i18n';
import { useDispatch, useSelect } from '@wordpress/data';
import {
extensionCartUpdate,
ValidationInputError,
} from '@woocommerce/blocks-checkout'; // eslint-disable-line import/no-unresolved
import { ValidationInputError } from '@woocommerce/blocks-checkout'; // eslint-disable-line import/no-unresolved
import {
VALIDATION_STORE_KEY,
CHECKOUT_STORE_KEY,
Expand All @@ -20,10 +17,12 @@ import {
*/
import PhoneNumberInput from 'settings/phone-input';
import { getConfig } from 'utils/checkout';
import { buildAjaxURL } from 'utils/express-checkout';
import AdditionalInformation from './additional-information';
import Agreement from './agreement';
import Container from './container';
import useWooPayUser from '../hooks/use-woopay-user';
import request from '../../../checkout/utils/request';
import useSelectedPaymentMethod from '../hooks/use-selected-payment-method';
import { recordUserEvent } from 'tracks';
import './style.scss';
Expand All @@ -42,11 +41,16 @@ const CheckoutPageSaveUser = ( { isBlocksCheckout } ) => {
const [ phoneNumber, setPhoneNumber ] = useState( '' );
const [ isPhoneValid, onPhoneValidationChange ] = useState( null );
const [ userDataSent, setUserDataSent ] = useState( false );
const isPhoneNumberTouched = useRef( false );

const checkoutIsProcessing = useSelect( ( select ) =>
select( CHECKOUT_STORE_KEY ).isProcessing()
);

const isBillingSameAsShipping = useSelect( ( select ) =>
select( CHECKOUT_STORE_KEY ).getUseShippingAsBilling()
);

const isRegisteredUser = useWooPayUser();
const { isWCPayChosen, isNewPaymentTokenChosen } = useSelectedPaymentMethod(
isBlocksCheckout
Expand Down Expand Up @@ -91,9 +95,8 @@ const CheckoutPageSaveUser = ( { isBlocksCheckout } ) => {
if ( isBlocksCheckout ) {
phoneFieldValue =
document.getElementById( 'phone' )?.value ||
document.getElementById( 'shipping-phone' )?.value ||
// in case of virtual products, the shipping phone is not available. So we also need to check the billing phone.
document.getElementById( 'billing-phone' )?.value ||
document.getElementById( 'shipping-phone' )?.value ||
'';
} else {
// for classic checkout.
Expand All @@ -114,22 +117,28 @@ const CheckoutPageSaveUser = ( { isBlocksCheckout } ) => {
const sendExtensionData = useCallback(
( shouldClearData = false ) => {
const data = shouldClearData
? {}
? { empty: 1 }
: {
save_user_in_woopay: isSaveDetailsChecked,
save_user_in_woopay: isSaveDetailsChecked ? 1 : 0,
woopay_source_url:
wcSettings?.storePages?.checkout?.permalink,
woopay_is_blocks: true,
woopay_is_blocks: 1,
woopay_viewport: `${ viewportWidth }x${ viewportHeight }`,
woopay_user_phone_field: {
full: phoneNumber,
},
};

extensionCartUpdate( {
namespace: 'woopay',
data: data,
} )?.then( () => {
request(
buildAjaxURL(
getConfig( 'wcAjaxUrl' ),
'set_woopay_phone_number'
),
{
_ajax_nonce: getConfig( 'woopaySessionNonce' ),
...data,
}
).then( () => {
setUserDataSent( ! shouldClearData );
} );
},
Expand Down Expand Up @@ -218,9 +227,54 @@ const CheckoutPageSaveUser = ( { isBlocksCheckout } ) => {
? isWCPayChosen
: isWCPayChosen && isNewPaymentTokenChosen;

useEffect( () => {
const updatePhoneNumber = useCallback( () => {
if ( isPhoneNumberTouched.current ) {
return;
}

setPhoneNumber( getPhoneFieldValue() );
}, [ getPhoneFieldValue, isWCPayWithNewTokenChosen ] );
}, [ setPhoneNumber, getPhoneFieldValue, isPhoneNumberTouched ] );

useEffect( () => {
updatePhoneNumber();
}, [ updatePhoneNumber ] );

// Update the WooPay phone number on the phone field blur event.
useEffect( () => {
if ( ! isBlocksCheckout ) {
document
.querySelector( '#billing_phone' )
?.addEventListener( 'blur', updatePhoneNumber );
return;
}

updatePhoneNumber();

if ( isBillingSameAsShipping ) {
document
.querySelector( '#billing-phone' )
?.removeEventListener( 'blur', updatePhoneNumber );

document
.querySelector( '#shipping-phone' )
?.addEventListener( 'blur', updatePhoneNumber );
return;
}

document
.querySelector( '#shipping-phone' )
?.removeEventListener( 'blur', updatePhoneNumber );

document
.querySelector( '#billing-phone' )
?.addEventListener( 'blur', updatePhoneNumber );
}, [
isBillingSameAsShipping,
updatePhoneNumber,
isPhoneNumberTouched,
getPhoneFieldValue,
isBlocksCheckout,
] );

if (
! getConfig( 'forceNetworkSavedCards' ) ||
Expand Down Expand Up @@ -313,6 +367,9 @@ const CheckoutPageSaveUser = ( { isBlocksCheckout } ) => {
onCountryDropdownClick={
handleCountryDropdownClick
}
onClick={ () =>
( isPhoneNumberTouched.current = true )
}
inputProps={ {
name:
'woopay_user_phone_field[no-country-code]',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
// eslint-disable-next-line import/no-unresolved
import { extensionCartUpdate } from '@woocommerce/blocks-checkout';
import { addAction } from '@wordpress/hooks';

/**
Expand All @@ -14,6 +13,7 @@ import { addAction } from '@wordpress/hooks';
import CheckoutPageSaveUser from '../checkout-page-save-user';
import useWooPayUser from '../../hooks/use-woopay-user';
import useSelectedPaymentMethod from '../../hooks/use-selected-payment-method';
import request from '../../../../checkout/utils/request';
import { getConfig } from 'utils/checkout';
import { useDispatch } from '@wordpress/data';

Expand Down Expand Up @@ -49,13 +49,13 @@ jest.mock( 'utils/checkout', () => ( {
jest.mock(
'@woocommerce/blocks-checkout',
() => ( {
extensionCartUpdate: jest.fn(),
ValidationInputError: () => {
return <div>Dummy error element</div>;
},
} ),
{ virtual: true }
);
jest.mock( '../../../../checkout/utils/request', () => jest.fn() );

jest.mock( '@wordpress/data' );

Expand Down Expand Up @@ -116,8 +116,8 @@ describe( 'CheckoutPageSaveUser', () => {
} );

useWooPayUser.mockImplementation( () => false );
extensionCartUpdate.mockResolvedValue( {} );
extensionCartUpdate.mockClear();
request.mockImplementation( () => ( { then() {} } ) );
request.mockClear();

useSelectedPaymentMethod.mockImplementation( () => ( {
isWCPayChosen: true,
Expand Down Expand Up @@ -237,12 +237,10 @@ describe( 'CheckoutPageSaveUser', () => {
expect( screen.queryByTestId( 'save-user-form' ) ).toBeInTheDocument();
} );

it( 'should not call `extensionCartUpdate` on classic checkout when checkbox is clicked', () => {
extensionCartUpdate.mockResolvedValue( {} );

it( 'should not call `request` on classic checkout when checkbox is clicked', () => {
render( <CheckoutPageSaveUser isBlocksCheckout={ false } /> );

expect( extensionCartUpdate ).not.toHaveBeenCalled();
expect( request ).not.toHaveBeenCalled();

// click on the checkbox
userEvent.click(
Expand All @@ -251,10 +249,10 @@ describe( 'CheckoutPageSaveUser', () => {
)
);

expect( extensionCartUpdate ).not.toHaveBeenCalled();
expect( request ).not.toHaveBeenCalled();
} );

it( 'call `extensionCartUpdate` on blocks checkout when checkbox is clicked', async () => {
it( 'call `request` on blocks checkout when checkbox is clicked', async () => {
render( <CheckoutPageSaveUser isBlocksCheckout={ true } />, {
wrapper: BlocksCheckoutEnvironmentMock,
} );
Expand All @@ -264,23 +262,21 @@ describe( 'CheckoutPageSaveUser', () => {
);

expect( label ).not.toBeChecked();
expect( extensionCartUpdate ).not.toHaveBeenCalled();
expect( request ).not.toHaveBeenCalled();

// click on the checkbox to select
userEvent.click( label );

expect( label ).toBeChecked();
await waitFor( () =>
expect( extensionCartUpdate ).toHaveBeenCalledWith( {
namespace: 'woopay',
data: {
save_user_in_woopay: true,
woopay_source_url: 'http://localhost/',
woopay_is_blocks: true,
woopay_viewport: '0x0',
woopay_user_phone_field: {
full: '+12015555551',
},
expect( request ).toHaveBeenLastCalledWith( 'false', {
_ajax_nonce: false,
save_user_in_woopay: 1,
woopay_source_url: 'http://localhost/',
woopay_is_blocks: 1,
woopay_viewport: '0x0',
woopay_user_phone_field: {
full: '+12015555551',
},
} )
);
Expand All @@ -290,9 +286,9 @@ describe( 'CheckoutPageSaveUser', () => {

expect( label ).not.toBeChecked();
await waitFor( () =>
expect( extensionCartUpdate ).toHaveBeenCalledWith( {
namespace: 'woopay',
data: {},
expect( request ).toHaveBeenLastCalledWith( 'false', {
_ajax_nonce: false,
empty: 1,
} )
);
} );
Expand All @@ -318,39 +314,39 @@ describe( 'CheckoutPageSaveUser', () => {
// click on the checkbox to hide/show it again (and reset the previously entered values)
userEvent.click( saveMyInfoCheckbox );
document.getElementById( 'phone' ).remove();
await waitFor( () => expect( extensionCartUpdate ).toHaveBeenCalled() );
await waitFor( () => expect( request ).toHaveBeenCalled() );

userEvent.click( saveMyInfoCheckbox );
expect( saveMyInfoCheckbox ).toBeChecked();
expect( screen.getByLabelText( 'Mobile phone number' ).value ).toEqual(
'2015555552'
'2015555553'
);

// click on the checkbox to hide/show it again (and reset the previously entered values)
userEvent.click( saveMyInfoCheckbox );
document.getElementById( 'shipping-phone' ).remove();
await waitFor( () => expect( extensionCartUpdate ).toHaveBeenCalled() );
document.getElementById( 'billing-phone' ).remove();
await waitFor( () => expect( request ).toHaveBeenCalled() );

// click on the checkbox to hide/show it again (and reset the previously entered values)
userEvent.click( saveMyInfoCheckbox );
expect( saveMyInfoCheckbox ).toBeChecked();
expect( screen.getByLabelText( 'Mobile phone number' ).value ).toEqual(
'2015555553'
'2015555552'
);

// click on the checkbox to hide/show it again (and reset the previously entered values)
userEvent.click( saveMyInfoCheckbox );
document.getElementById( 'billing-phone' ).remove();
await waitFor( () => expect( extensionCartUpdate ).toHaveBeenCalled() );
document.getElementById( 'shipping-phone' ).remove();
await waitFor( () => expect( request ).toHaveBeenCalled() );

userEvent.click( saveMyInfoCheckbox );
expect( saveMyInfoCheckbox ).toBeChecked();
expect( screen.getByLabelText( 'Mobile phone number' ).value ).toEqual(
''
);
await waitFor( () => expect( extensionCartUpdate ).toHaveBeenCalled() );
await waitFor( () => expect( request ).toHaveBeenCalled() );
} );

it( 'call `extensionCartUpdate` on blocks checkout when checkbox is clicked with a phone without country code', async () => {
it( 'call `request` on blocks checkout when checkbox is clicked with a phone without country code', async () => {
render( <CheckoutPageSaveUser isBlocksCheckout={ true } />, {
wrapper: BlocksCheckoutEnvironmentMock,
} );
Expand All @@ -360,23 +356,21 @@ describe( 'CheckoutPageSaveUser', () => {
);

expect( label ).not.toBeChecked();
expect( extensionCartUpdate ).not.toHaveBeenCalled();
expect( request ).not.toHaveBeenCalled();

// click on the checkbox to select
userEvent.click( label );

expect( label ).toBeChecked();
await waitFor( () =>
expect( extensionCartUpdate ).toHaveBeenCalledWith( {
namespace: 'woopay',
data: {
save_user_in_woopay: true,
woopay_source_url: 'http://localhost/',
woopay_is_blocks: true,
woopay_viewport: '0x0',
woopay_user_phone_field: {
full: '+12015555551',
},
expect( request ).toHaveBeenLastCalledWith( 'false', {
_ajax_nonce: false,
save_user_in_woopay: 1,
woopay_source_url: 'http://localhost/',
woopay_is_blocks: 1,
woopay_viewport: '0x0',
woopay_user_phone_field: {
full: '+12015555551',
},
} )
);
Expand All @@ -386,9 +380,9 @@ describe( 'CheckoutPageSaveUser', () => {

expect( label ).not.toBeChecked();
await waitFor( () =>
expect( extensionCartUpdate ).toHaveBeenCalledWith( {
namespace: 'woopay',
data: {},
expect( request ).toHaveBeenLastCalledWith( 'false', {
_ajax_nonce: false,
empty: 1,
} )
);
} );
Expand Down
2 changes: 2 additions & 0 deletions client/settings/phone-input/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ const PhoneNumberInput = ( {
hiddenInput: 'full',
utilsScript: utils,
dropdownContainer: document.body,
formatOnDisplay: false,
...phoneCountries,
} );
setInputInstance( iti );
Expand Down Expand Up @@ -149,6 +150,7 @@ const PhoneNumberInput = ( {
inputRef.current &&
( focusLost || inputInstance.getNumber() )
) {
inputInstance.setNumber( value );
onValidationChange( inputInstance.isValidNumber() );
}
}, [ value, inputInstance, inputRef, onValidationChange, focusLost ] );
Expand Down
Loading

0 comments on commit 7b746b8

Please sign in to comment.