diff --git a/packages/template-retail-react-app/CHANGELOG.md b/packages/template-retail-react-app/CHANGELOG.md
index 10b621b2cd..55f6dc9fcd 100644
--- a/packages/template-retail-react-app/CHANGELOG.md
+++ b/packages/template-retail-react-app/CHANGELOG.md
@@ -8,6 +8,7 @@
- Added support for Buy Online Pick up In Store (BOPIS) [#2646](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2646)
- Load active data scripts on demand only [#2623](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2623)
- Provide base image for convenient perf optimizations [#2642](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2642)
+- Support saving billing phone number on user registration from order confirmation [#2653](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2653)
- Support saving default shipping address on user registration from order confirmation [#2706](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2706)
## v6.1.0 (May 22, 2025)
diff --git a/packages/template-retail-react-app/app/pages/checkout/confirmation.jsx b/packages/template-retail-react-app/app/pages/checkout/confirmation.jsx
index ca3cfb7b23..5ef89c775e 100644
--- a/packages/template-retail-react-app/app/pages/checkout/confirmation.jsx
+++ b/packages/template-retail-react-app/app/pages/checkout/confirmation.jsx
@@ -128,7 +128,8 @@ const CheckoutConfirmation = () => {
firstName: data.firstName,
lastName: data.lastName,
email: data.email,
- login: data.email
+ login: data.email,
+ phoneHome: order.billingAddress.phone
},
password: data.password
}
diff --git a/packages/template-retail-react-app/app/pages/checkout/confirmation.test.js b/packages/template-retail-react-app/app/pages/checkout/confirmation.test.js
index 0eb0b87e6a..1181af13a3 100644
--- a/packages/template-retail-react-app/app/pages/checkout/confirmation.test.js
+++ b/packages/template-retail-react-app/app/pages/checkout/confirmation.test.js
@@ -126,31 +126,168 @@ test('Create Account form - successful submission results in redirect to the Acc
})
})
-test('Create Account form - successful submission results in redirect to the Account page even if shipping address is not saved', async () => {
- global.server.use(
- rest.post('*/customers', (_, res, ctx) => {
- return res(ctx.status(200), ctx.json(mockCustomer))
- }),
- rest.post('*/customers/:customerId/addresses', (_, res, ctx) => {
- const failedAddressCreation = {
- title: 'Invalid Customer',
- type: 'https://api.commercecloud.salesforce.com/documentation/error/v1/errors/invalid-customer',
- detail: 'The customer is invalid.'
- }
- return res(ctx.status(400), ctx.json(failedAddressCreation))
+describe('Account form', () => {
+ test('saves phone number from billing address to customer', async () => {
+ let registrationRequestBody = null
+
+ global.server.use(
+ rest.post('*/customers', (req, res, ctx) => {
+ registrationRequestBody = req.body
+ return res(
+ ctx.status(200),
+ ctx.json({
+ customerId: 'new-customer-id',
+ email: mockOrder.customerInfo.email,
+ firstName: mockOrder.billingAddress.firstName,
+ lastName: mockOrder.billingAddress.lastName,
+ phoneHome: mockOrder.shipments[0].shippingAddress.phone
+ })
+ )
+ }),
+ rest.post('*/customers/*/addresses', (_, res, ctx) => {
+ return res(ctx.status(200))
+ })
+ )
+
+ const {user} = renderWithProviders(, {
+ wrapperProps: {isGuest: true}
})
- )
- const {user} = renderWithProviders(, {
- wrapperProps: {isGuest: true}
+ const createAccountButton = await screen.findByRole('button', {name: /create account/i})
+ const password = screen.getByLabelText('Password')
+
+ // Fill out the form (firstName and lastName are hidden fields pre-filled from order data)
+ await user.type(password, 'P4ssword!')
+ await user.click(createAccountButton)
+
+ // Wait for the registration request to complete
+ await waitFor(() => {
+ expect(registrationRequestBody).not.toBeNull()
+ })
+
+ // Verify that the phone number from the order's billing address is included in the registration
+ expect(registrationRequestBody.customer.phoneHome).toBe(mockOrder.billingAddress.phone)
+ expect(registrationRequestBody.customer.phoneHome).toBe('(778) 888-8888')
+
+ // Verify other expected customer data (firstName/lastName come from order's billingAddress)
+ expect(registrationRequestBody.customer.firstName).toBe(mockOrder.billingAddress.firstName)
+ expect(registrationRequestBody.customer.lastName).toBe(mockOrder.billingAddress.lastName)
+ expect(registrationRequestBody.customer.email).toBe(mockOrder.customerInfo.email)
+ expect(registrationRequestBody.customer.login).toBe(mockOrder.customerInfo.email)
+ expect(registrationRequestBody.password).toBe('P4ssword!')
})
- const createAccountButton = await screen.findByRole('button', {name: /create account/i})
- const password = screen.getByLabelText('Password')
- await user.type(password, 'P4ssword!')
- await user.click(createAccountButton)
+ test('Integration test - phone number from order is visible in customer account after registration', async () => {
+ let savedCustomerData = null
- await waitFor(() => {
- expect(window.location.pathname).toBe('/uk/en-GB/account')
+ global.server.use(
+ // Mock customer registration
+ rest.post('*/customers', (req, res, ctx) => {
+ savedCustomerData = {
+ customerId: 'new-customer-id-123',
+ email: mockOrder.customerInfo.email,
+ firstName: mockOrder.billingAddress.firstName,
+ lastName: mockOrder.billingAddress.lastName,
+ phoneHome: mockOrder.billingAddress.phone,
+ login: mockOrder.customerInfo.email
+ }
+ return res(ctx.status(200), ctx.json(savedCustomerData))
+ }),
+ // Mock address creation
+ rest.post('*/customers/*/addresses', (_, res, ctx) => {
+ return res(ctx.status(200))
+ }),
+ // Mock customer profile fetch for account page
+ rest.get('*/customers/new-customer-id-123', (_, res, ctx) => {
+ return res(
+ ctx.status(200),
+ ctx.json({
+ ...savedCustomerData,
+ addresses: [
+ {
+ addressId: 'address-1',
+ firstName: mockOrder.billingAddress.firstName,
+ lastName: mockOrder.billingAddress.lastName,
+ address1: mockOrder.shipments[0].shippingAddress.address1,
+ city: mockOrder.shipments[0].shippingAddress.city,
+ phone: mockOrder.billingAddress.phone,
+ postalCode: mockOrder.shipments[0].shippingAddress.postalCode,
+ stateCode: mockOrder.shipments[0].shippingAddress.stateCode,
+ countryCode: mockOrder.shipments[0].shippingAddress.countryCode
+ }
+ ]
+ })
+ )
+ }),
+ // Mock any other account page dependencies
+ rest.get('*/customers/*/orders', (_, res, ctx) => {
+ return res(ctx.status(200), ctx.json({data: [], total: 0}))
+ }),
+ rest.get('*/customers/*/product-lists', (_, res, ctx) => {
+ return res(ctx.status(200), ctx.json({data: []}))
+ })
+ )
+
+ const {user} = renderWithProviders(, {
+ wrapperProps: {isGuest: true}
+ })
+
+ // Step 1: Fill out and submit the registration form
+ const createAccountButton = await screen.findByRole('button', {name: /create account/i})
+ const password = screen.getByLabelText('Password')
+
+ // Fill out the form (firstName and lastName are hidden fields pre-filled from order data)
+ await user.type(password, 'P4ssword!')
+ await user.click(createAccountButton)
+
+ // Step 2: Wait for redirect to account page
+ await waitFor(
+ () => {
+ expect(window.location.pathname).toBe('/uk/en-GB/account')
+ },
+ {timeout: 5000}
+ )
+
+ // Step 3: Verify that the customer data was saved correctly
+ expect(savedCustomerData).not.toBeNull()
+ expect(savedCustomerData.phoneHome).toBe('(778) 888-8888')
+
+ // Note: This test verifies the API calls and data flow.
+ // A full end-to-end test would require rendering the Account page component
+ // and verifying the phone number is displayed in the UI, but that would require
+ // additional setup of the Account page component and its dependencies.
+
+ // The key assertion is that the phone from the order's billing address
+ // is correctly saved to the customer's phoneHome field during registration
+ expect(savedCustomerData.phoneHome).toBe(mockOrder.billingAddress.phone)
+ })
+
+ test('successful submission redirects to the Account page even if shipping address is not saved', async () => {
+ global.server.use(
+ rest.post('*/customers', (_, res, ctx) => {
+ return res(ctx.status(200), ctx.json(mockCustomer))
+ }),
+ rest.post('*/customers/:customerId/addresses', (_, res, ctx) => {
+ const failedAddressCreation = {
+ title: 'Invalid Customer',
+ type: 'https://api.commercecloud.salesforce.com/documentation/error/v1/errors/invalid-customer',
+ detail: 'The customer is invalid.'
+ }
+ return res(ctx.status(400), ctx.json(failedAddressCreation))
+ })
+ )
+
+ const {user} = renderWithProviders(, {
+ wrapperProps: {isGuest: true}
+ })
+
+ const createAccountButton = await screen.findByRole('button', {name: /create account/i})
+ const password = screen.getByLabelText('Password')
+ await user.type(password, 'P4ssword!')
+ await user.click(createAccountButton)
+
+ await waitFor(() => {
+ expect(window.location.pathname).toBe('/uk/en-GB/account')
+ })
})
})