@@ -152,6 +152,7 @@ const mockStartConfirming = jest.fn()
152152const mockEndConfirming = jest . fn ( )
153153const mockCheckoutConfirm = jest . fn ( )
154154const mockCheckoutDestroy = jest . fn ( )
155+ const mockUpdateAmount = jest . fn ( )
155156
156157jest . mock ( '@salesforce/retail-react-app/app/hooks/use-sf-payments' , ( ) => {
157158 const actual = jest . requireActual ( '@salesforce/retail-react-app/app/hooks/use-sf-payments' )
@@ -161,7 +162,8 @@ jest.mock('@salesforce/retail-react-app/app/hooks/use-sf-payments', () => {
161162 sfp : {
162163 checkout : jest . fn ( ( ) => ( {
163164 confirm : mockCheckoutConfirm ,
164- destroy : mockCheckoutDestroy
165+ destroy : mockCheckoutDestroy ,
166+ updateAmount : mockUpdateAmount
165167 } ) )
166168 } ,
167169 metadata : { key : 'value' } ,
@@ -198,15 +200,16 @@ jest.mock('@salesforce/retail-react-app/app/components/address-display', () => {
198200} )
199201
200202jest . mock ( '@salesforce/retail-react-app/app/components/toggle-card' , ( ) => {
201- const ToggleCard = ( { children, title} ) => (
202- < div data-testid = "toggle-card" >
203+ const ToggleCard = ( { children, title, editing } ) => (
204+ < div data-testid = "toggle-card" data-editing = { editing ? 'true' : 'false' } >
203205 < h2 > { title } </ h2 >
204206 { children }
205207 </ div >
206208 )
207209 ToggleCard . propTypes = {
208210 children : ( ) => null ,
209- title : ( ) => null
211+ title : ( ) => null ,
212+ editing : ( ) => null
210213 }
211214
212215 const ToggleCardEdit = ( { children} ) => < div data-testid = "toggle-card-edit" > { children } </ div >
@@ -746,4 +749,170 @@ describe('SFPaymentsSheet', () => {
746749 expect ( mockOnRequiresPayButtonChange ) . not . toHaveBeenCalled ( )
747750 } )
748751 } )
752+
753+ describe ( 'container element persistence' , ( ) => {
754+ test ( 'payment container is rendered outside ToggleCardEdit to prevent unmounting' , ( ) => {
755+ renderWithCheckoutContext (
756+ < SFPaymentsSheet
757+ ref = { mockRef }
758+ onCreateOrder = { mockOnCreateOrder }
759+ onError = { mockOnError }
760+ />
761+ )
762+
763+ const toggleCard = screen . getByTestId ( 'toggle-card' )
764+
765+ expect ( toggleCard ) . toBeInTheDocument ( )
766+ expect ( toggleCard ) . toBeInTheDocument ( )
767+ } )
768+ } )
769+
770+ describe ( 'updateAmount' , ( ) => {
771+ beforeEach ( ( ) => {
772+ mockUpdateAmount . mockClear ( )
773+ } )
774+
775+ test ( 'calls updateAmount when basket orderTotal changes' , async ( ) => {
776+ const initialBasket = {
777+ ...mockBasket ,
778+ orderTotal : 100.0
779+ }
780+
781+ mockUseCurrentBasket . mockImplementation ( ( ) => ( {
782+ data : initialBasket ,
783+ derivedData : {
784+ totalItems : 2 ,
785+ isMissingShippingAddress : false ,
786+ isMissingShippingMethod : false ,
787+ totalDeliveryShipments : 1 ,
788+ totalPickupShipments : 0
789+ } ,
790+ isLoading : false
791+ } ) )
792+
793+ const { rerender} = renderWithCheckoutContext (
794+ < SFPaymentsSheet
795+ ref = { mockRef }
796+ onCreateOrder = { mockOnCreateOrder }
797+ onError = { mockOnError }
798+ />
799+ )
800+
801+ await waitFor ( ( ) => {
802+ expect ( screen . getByTestId ( 'toggle-card' ) ) . toBeInTheDocument ( )
803+ } )
804+
805+ await waitFor (
806+ ( ) => {
807+ expect ( mockUpdateAmount ) . toHaveBeenCalledWith ( 100.0 )
808+ } ,
809+ { timeout : 2000 }
810+ )
811+
812+ mockUpdateAmount . mockClear ( )
813+
814+ const updatedBasket = {
815+ ...initialBasket ,
816+ orderTotal : 150.0
817+ }
818+
819+ mockUseCurrentBasket . mockImplementation ( ( ) => ( {
820+ data : updatedBasket ,
821+ derivedData : {
822+ totalItems : 2 ,
823+ isMissingShippingAddress : false ,
824+ isMissingShippingMethod : false ,
825+ totalDeliveryShipments : 1 ,
826+ totalPickupShipments : 0
827+ } ,
828+ isLoading : false
829+ } ) )
830+
831+ rerender (
832+ < CheckoutProvider >
833+ < SFPaymentsSheet
834+ ref = { mockRef }
835+ onCreateOrder = { mockOnCreateOrder }
836+ onError = { mockOnError }
837+ />
838+ </ CheckoutProvider >
839+ )
840+
841+ await waitFor (
842+ ( ) => {
843+ expect ( mockUpdateAmount ) . toHaveBeenCalledWith ( 150.0 )
844+ } ,
845+ { timeout : 2000 }
846+ )
847+ } )
848+
849+ test ( 'does not call updateAmount when orderTotal is undefined' , async ( ) => {
850+ const basketWithoutOrderTotal = {
851+ ...mockBasket ,
852+ orderTotal : undefined
853+ }
854+
855+ mockUseCurrentBasket . mockImplementation ( ( ) => ( {
856+ data : basketWithoutOrderTotal ,
857+ derivedData : {
858+ totalItems : 2 ,
859+ isMissingShippingAddress : false ,
860+ isMissingShippingMethod : false ,
861+ totalDeliveryShipments : 1 ,
862+ totalPickupShipments : 0
863+ } ,
864+ isLoading : false
865+ } ) )
866+
867+ renderWithCheckoutContext (
868+ < SFPaymentsSheet
869+ ref = { mockRef }
870+ onCreateOrder = { mockOnCreateOrder }
871+ onError = { mockOnError }
872+ />
873+ )
874+
875+ await waitFor ( ( ) => {
876+ expect ( screen . getByTestId ( 'toggle-card' ) ) . toBeInTheDocument ( )
877+ } )
878+
879+ await new Promise ( ( resolve ) => setTimeout ( resolve , 100 ) )
880+
881+ expect ( mockUpdateAmount ) . not . toHaveBeenCalled ( )
882+ } )
883+
884+ test ( 'calls updateAmount with correct orderTotal value on initial render' , async ( ) => {
885+ const basketWithOrderTotal = {
886+ ...mockBasket ,
887+ orderTotal : 250.75
888+ }
889+
890+ mockUseCurrentBasket . mockImplementation ( ( ) => ( {
891+ data : basketWithOrderTotal ,
892+ derivedData : {
893+ totalItems : 2 ,
894+ isMissingShippingAddress : false ,
895+ isMissingShippingMethod : false ,
896+ totalDeliveryShipments : 1 ,
897+ totalPickupShipments : 0
898+ } ,
899+ isLoading : false
900+ } ) )
901+
902+ renderWithCheckoutContext (
903+ < SFPaymentsSheet
904+ ref = { mockRef }
905+ onCreateOrder = { mockOnCreateOrder }
906+ onError = { mockOnError }
907+ />
908+ )
909+
910+ await waitFor (
911+ ( ) => {
912+ expect ( mockUpdateAmount ) . toHaveBeenCalledWith ( 250.75 )
913+ } ,
914+ { timeout : 2000 }
915+ )
916+ } )
917+ } )
749918} )
0 commit comments