Skip to content

Commit a7f1f96

Browse files
committed
W-21005976 Newly registered user can change payment (#3608)
1 parent db41b6e commit a7f1f96

File tree

2 files changed

+127
-12
lines changed

2 files changed

+127
-12
lines changed

packages/template-retail-react-app/app/pages/checkout-one-click/partials/one-click-payment.jsx

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -243,17 +243,6 @@ const Payment = ({
243243
}
244244
setShowRegistrationNotice(true)
245245
setShouldSavePaymentMethod(true)
246-
try {
247-
const values = paymentMethodForm?.getValues?.()
248-
const hasEnteredCard = values?.number && values?.holder && values?.expiry
249-
const hasApplied = (currentBasketQuery?.data?.paymentInstruments?.length || 0) > 0
250-
if (hasEnteredCard && !hasApplied && newBasketId) {
251-
await onPaymentSubmit(values, newBasketId)
252-
await currentBasketQuery.refetch()
253-
}
254-
} catch (_e) {
255-
// non-blocking
256-
}
257246
showToast({
258247
variant: 'subtle',
259248
title: formatMessage({
@@ -265,7 +254,7 @@ const Payment = ({
265254
isClosable: true
266255
})
267256
},
268-
[paymentMethodForm, currentBasketQuery, onPaymentSubmit, showToast, formatMessage]
257+
[showToast, formatMessage]
269258
)
270259

271260
// Auto-select a saved payment instrument for registered customers (run at most once)

packages/template-retail-react-app/app/pages/checkout-one-click/partials/one-click-payment.test.js

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,132 @@ describe('Payment Component', () => {
666666
expect(checkboxAfter).toBeChecked()
667667
})
668668

669+
test('does not add payment again during registration when payment already exists on basket', async () => {
670+
const user = userEvent.setup()
671+
const mockAddPaymentInstrument = jest.fn().mockResolvedValue({})
672+
673+
const basketWithPayment = {
674+
...mockBasket,
675+
paymentInstruments: [mockPaymentInstruments[0]]
676+
}
677+
678+
useShopperBasketsMutation.mockImplementation((mutationType) => {
679+
switch (mutationType) {
680+
case 'addPaymentInstrumentToBasket':
681+
return {mutateAsync: mockAddPaymentInstrument}
682+
case 'updateBillingAddressForBasket':
683+
return {mutateAsync: jest.fn().mockResolvedValue({})}
684+
case 'removePaymentInstrumentFromBasket':
685+
return {mutateAsync: jest.fn().mockResolvedValue({})}
686+
default:
687+
return {mutateAsync: jest.fn()}
688+
}
689+
})
690+
691+
render(
692+
<TestWrapper
693+
basketData={basketWithPayment}
694+
enableUserRegistration={true}
695+
paymentMethodForm={{
696+
handleSubmit: jest.fn((callback) => (e) => {
697+
e?.preventDefault?.()
698+
callback({})
699+
}),
700+
watch: jest.fn(() => ({unsubscribe: jest.fn()})),
701+
getValues: jest.fn(() => ({
702+
number: '4111111111111111',
703+
holder: 'John Doe',
704+
expiry: '12/25'
705+
})),
706+
formState: {isSubmitting: false, isValid: true}
707+
}}
708+
/>
709+
)
710+
711+
// Find and trigger user registration
712+
const registrationComponent = screen.getByTestId('user-registration')
713+
const triggerRegistrationButton =
714+
within(registrationComponent).getByTestId('trigger-registration')
715+
716+
// Trigger registration
717+
await user.click(triggerRegistrationButton)
718+
719+
// Wait for registration to complete
720+
await waitFor(() => {
721+
expect(screen.getByTestId('user-registration')).toBeInTheDocument()
722+
})
723+
724+
// Verify payment was NOT added again (payment already exists on basket)
725+
// Payment should be transferred during basket merge, not added again
726+
expect(mockAddPaymentInstrument).not.toHaveBeenCalled()
727+
})
728+
729+
test('does not add payment during registration even when payment form has values', async () => {
730+
const user = userEvent.setup()
731+
const mockAddPaymentInstrument = jest.fn().mockResolvedValue({})
732+
733+
// Basket without payment initially, but payment will be on basket before registration
734+
// (since registration checkbox is disabled until payment is filled)
735+
const basketWithPayment = {
736+
...mockBasket,
737+
paymentInstruments: [mockPaymentInstruments[0]]
738+
}
739+
740+
useShopperBasketsMutation.mockImplementation((mutationType) => {
741+
switch (mutationType) {
742+
case 'addPaymentInstrumentToBasket':
743+
return {mutateAsync: mockAddPaymentInstrument}
744+
case 'updateBillingAddressForBasket':
745+
return {mutateAsync: jest.fn().mockResolvedValue({})}
746+
case 'removePaymentInstrumentFromBasket':
747+
return {mutateAsync: jest.fn().mockResolvedValue({})}
748+
default:
749+
return {mutateAsync: jest.fn()}
750+
}
751+
})
752+
753+
const mockPaymentMethodForm = {
754+
handleSubmit: jest.fn((callback) => (e) => {
755+
e?.preventDefault?.()
756+
callback({})
757+
}),
758+
watch: jest.fn(() => ({unsubscribe: jest.fn()})),
759+
getValues: jest.fn(() => ({
760+
number: '4111111111111111',
761+
holder: 'John Doe',
762+
expiry: '12/25',
763+
cardType: 'Visa'
764+
})),
765+
formState: {isSubmitting: false, isValid: true}
766+
}
767+
768+
render(
769+
<TestWrapper
770+
basketData={basketWithPayment}
771+
enableUserRegistration={true}
772+
paymentMethodForm={mockPaymentMethodForm}
773+
/>
774+
)
775+
776+
// Find and trigger user registration
777+
const registrationComponent = screen.getByTestId('user-registration')
778+
const triggerRegistrationButton =
779+
within(registrationComponent).getByTestId('trigger-registration')
780+
781+
// Trigger registration
782+
await user.click(triggerRegistrationButton)
783+
784+
// Wait for registration to complete
785+
await waitFor(() => {
786+
expect(screen.getByTestId('user-registration')).toBeInTheDocument()
787+
})
788+
789+
// Verify payment was NOT added again
790+
// Payment is already on basket (registration requires payment to be filled first)
791+
// Basket transfer/merge will preserve the payment, no need to add it again
792+
expect(mockAddPaymentInstrument).not.toHaveBeenCalled()
793+
})
794+
669795
test('disables user registration checkbox when payment is not filled in', () => {
670796
const mockPaymentMethodForm = {
671797
handleSubmit: jest.fn((callback) => (e) => {

0 commit comments

Comments
 (0)