44 createCheckoutService ,
55} from '@bigcommerce/checkout-sdk' ;
66import { noop } from 'lodash' ;
7- import React from 'react' ;
7+ import React , { type FunctionComponent } from 'react' ;
88
99import {
1010 CapabilitiesContext ,
@@ -35,26 +35,28 @@ describe('PaymentBillingForm', () => {
3535 let setEnsureBillingAddressSaved : jest . Mock ;
3636 let defaultProps : PaymentBillingFormProps ;
3737
38+ const PaymentBillingFormTest : FunctionComponent < PaymentBillingFormProps > = ( props ) => (
39+ < CheckoutProvider checkoutService = { checkoutService } >
40+ < LocaleContext . Provider value = { localeContext } >
41+ < CapabilitiesContext . Provider value = { defaultCapabilities } >
42+ < PaymentContext . Provider
43+ value = { {
44+ registerEnsureBillingAddressSaved,
45+ disableSubmit : jest . fn ( ) ,
46+ setSubmit : jest . fn ( ) ,
47+ setValidationSchema : jest . fn ( ) ,
48+ hidePaymentSubmitButton : jest . fn ( ) ,
49+ } }
50+ >
51+ < PaymentBillingForm { ...props } />
52+ </ PaymentContext . Provider >
53+ </ CapabilitiesContext . Provider >
54+ </ LocaleContext . Provider >
55+ </ CheckoutProvider >
56+ ) ;
57+
3858 const renderForm = ( props : PaymentBillingFormProps ) =>
39- render (
40- < CheckoutProvider checkoutService = { checkoutService } >
41- < LocaleContext . Provider value = { localeContext } >
42- < CapabilitiesContext . Provider value = { defaultCapabilities } >
43- < PaymentContext . Provider
44- value = { {
45- setEnsureBillingAddressSaved,
46- disableSubmit : jest . fn ( ) ,
47- setSubmit : jest . fn ( ) ,
48- setValidationSchema : jest . fn ( ) ,
49- hidePaymentSubmitButton : jest . fn ( ) ,
50- } }
51- >
52- < PaymentBillingForm { ...props } />
53- </ PaymentContext . Provider >
54- </ CapabilitiesContext . Provider >
55- </ LocaleContext . Provider >
56- </ CheckoutProvider > ,
57- ) ;
59+ render ( < PaymentBillingFormTest { ...props } /> ) ;
5860
5961 beforeEach ( ( ) => {
6062 checkoutService = createCheckoutService ( ) ;
@@ -81,7 +83,9 @@ describe('PaymentBillingForm', () => {
8183 billingAddress : getBillingAddress ( ) ,
8284 customerMessage : '' ,
8385 getFields : ( ) => getFormFields ( ) ,
86+ isBillingSameAsShipping : false ,
8487 isLoading : false ,
88+ onBillingSameAsShippingChange : jest . fn ( ) ,
8589 onPersist,
8690 onUnhandledError : noop ,
8791 } ;
@@ -168,6 +172,20 @@ describe('PaymentBillingForm', () => {
168172 expect ( onPersist ) . not . toHaveBeenCalled ( ) ;
169173 } ) ;
170174
175+ it ( 'does not include the same-as-shipping flag in the persisted billing values' , async ( ) => {
176+ renderForm ( defaultProps ) ;
177+
178+ await waitFor ( ( ) =>
179+ expect ( capturedEnsureBillingAddressSaved ) . toEqual ( expect . any ( Function ) ) ,
180+ ) ;
181+
182+ await capturedEnsureBillingAddressSaved ?.( ) ;
183+
184+ expect ( onPersist ) . toHaveBeenCalledWith (
185+ expect . not . objectContaining ( { billingSameAsShipping : expect . anything ( ) } ) ,
186+ ) ;
187+ } ) ;
188+
171189 it ( 'reports a persist failure via onUnhandledError and resolves false without throwing' , async ( ) => {
172190 const error = new Error ( 'failed to save billing address' ) ;
173191 const onUnhandledError = jest . fn ( ) ;
@@ -183,4 +201,78 @@ describe('PaymentBillingForm', () => {
183201 await expect ( capturedEnsureBillingAddressSaved ?.( ) ) . resolves . toBe ( false ) ;
184202 expect ( onUnhandledError ) . toHaveBeenCalledWith ( error ) ;
185203 } ) ;
204+
205+ describe ( 'billing same as shipping toggle' , ( ) => {
206+ it ( 'renders the toggle with the payment-step label' , ( ) => {
207+ renderForm ( defaultProps ) ;
208+
209+ expect ( screen . getByTestId ( 'billingSameAsShipping' ) ) . toBeInTheDocument ( ) ;
210+ expect ( screen . getByText ( 'Same as shipping address' ) ) . toBeInTheDocument ( ) ;
211+ } ) ;
212+
213+ it ( 'collapses the billing address fields when checked' , ( ) => {
214+ renderForm ( { ...defaultProps , isBillingSameAsShipping : true } ) ;
215+
216+ expect ( screen . getByTestId ( 'billingSameAsShipping' ) ) . toBeInTheDocument ( ) ;
217+ expect ( screen . queryByText ( 'First Name' ) ) . not . toBeInTheDocument ( ) ;
218+ } ) ;
219+
220+ it ( 'shows the billing address fields when unchecked' , ( ) => {
221+ renderForm ( { ...defaultProps , isBillingSameAsShipping : false } ) ;
222+
223+ expect ( screen . getByText ( 'First Name' ) ) . toBeInTheDocument ( ) ;
224+ } ) ;
225+
226+ it ( 'resolves true without persisting when checked (billing mirrors shipping)' , async ( ) => {
227+ renderForm ( { ...defaultProps , isBillingSameAsShipping : true } ) ;
228+
229+ await waitFor ( ( ) =>
230+ expect ( capturedEnsureBillingAddressSaved ) . toEqual ( expect . any ( Function ) ) ,
231+ ) ;
232+
233+ await expect ( capturedEnsureBillingAddressSaved ?.( ) ) . resolves . toBe ( true ) ;
234+ expect ( onPersist ) . not . toHaveBeenCalled ( ) ;
235+ } ) ;
236+
237+ it ( 'hides the toggle for static-address methods (e.g. Amazon Pay)' , ( ) => {
238+ renderForm ( { ...defaultProps , methodId : 'amazonpay' } ) ;
239+
240+ expect ( screen . queryByTestId ( 'billingSameAsShipping' ) ) . not . toBeInTheDocument ( ) ;
241+ } ) ;
242+
243+ it ( 'stays unchecked and does not re-fire on a billing address reinitialize' , async ( ) => {
244+ const onBillingSameAsShippingChange = jest . fn ( ) ;
245+ const props = {
246+ ...defaultProps ,
247+ isBillingSameAsShipping : false ,
248+ billingAddress : getBillingAddress ( ) ,
249+ onBillingSameAsShippingChange,
250+ } ;
251+
252+ const { rerender } = renderForm ( props ) ;
253+
254+ expect ( screen . getByText ( 'First Name' ) ) . toBeInTheDocument ( ) ;
255+
256+ rerender (
257+ < PaymentBillingFormTest { ...props } billingAddress = { getEmptyBillingAddress ( ) } /> ,
258+ ) ;
259+
260+ expect ( await screen . findByText ( 'First Name' ) ) . toBeInTheDocument ( ) ;
261+ expect ( onBillingSameAsShippingChange ) . not . toHaveBeenCalledWith ( true ) ;
262+ } ) ;
263+
264+ it ( 'notifies onBillingSameAsShippingChange when the shopper checks it' , async ( ) => {
265+ const onBillingSameAsShippingChange = jest . fn ( ) ;
266+
267+ renderForm ( {
268+ ...defaultProps ,
269+ isBillingSameAsShipping : false ,
270+ onBillingSameAsShippingChange,
271+ } ) ;
272+
273+ fireEvent . click ( screen . getByTestId ( 'billingSameAsShipping' ) ) ;
274+
275+ await waitFor ( ( ) => expect ( onBillingSameAsShippingChange ) . toHaveBeenCalledWith ( true ) ) ;
276+ } ) ;
277+ } ) ;
186278} ) ;
0 commit comments