diff --git a/package.json b/package.json index 3fc178b..2894f77 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,9 @@ "jest": { "testMatch": [ "**/tests/js/**/*.test.js" + ], + "setupFilesAfterEnv": [ + "./tests/js/setup.js" ] } } diff --git a/tests/js/add-payment-method.test.js b/tests/js/add-payment-method.test.js index ab22dad..2c36e1e 100644 --- a/tests/js/add-payment-method.test.js +++ b/tests/js/add-payment-method.test.js @@ -88,11 +88,6 @@ describe( 'add-payment-method', () => { setupFraudProtection(); loadScript(); - // Mock form.submit to prevent jsdom from incorrectly firing - // another submit event (real browsers don't fire submit on form.submit()). - const nativeSubmitSpy = jest.fn(); - form.submit = nativeSubmitSpy; - // First pass: blocks submission. const notCancelled = dispatchSubmit(); expect( notCancelled ).toBe( false ); @@ -109,16 +104,13 @@ describe( 'add-payment-method', () => { // Re-dispatch reached bubble phase, then native submit fallback fired. expect( bubbleSubmitSpy ).toHaveBeenCalledTimes( 1 ); - expect( nativeSubmitSpy ).toHaveBeenCalledTimes( 1 ); + expect( form.submit ).toHaveBeenCalledTimes( 1 ); } ); it( 'skips native submit when a gateway handler calls preventDefault', async () => { setupFraudProtection(); loadScript(); - const nativeSubmitSpy = jest.fn(); - form.submit = nativeSubmitSpy; - // Simulate a gateway handler (e.g. Stripe) that prevents default // to handle submission itself (tokenize, then submit). form.addEventListener( 'submit', ( e ) => e.preventDefault() ); @@ -126,7 +118,7 @@ describe( 'add-payment-method', () => { dispatchSubmit(); await flushPromises(); - expect( nativeSubmitSpy ).not.toHaveBeenCalled(); + expect( form.submit ).not.toHaveBeenCalled(); } ); it( 'stops other handlers via stopImmediatePropagation on first submission', () => { diff --git a/tests/js/pay-for-order.test.js b/tests/js/pay-for-order.test.js index 2c274ed..66c83f0 100644 --- a/tests/js/pay-for-order.test.js +++ b/tests/js/pay-for-order.test.js @@ -88,11 +88,6 @@ describe( 'pay-for-order', () => { setupFraudProtection(); loadScript(); - // Mock form.submit to prevent jsdom from incorrectly firing - // another submit event (real browsers don't fire submit on form.submit()). - const nativeSubmitSpy = jest.fn(); - form.submit = nativeSubmitSpy; - // First pass: blocks submission. const notCancelled = dispatchSubmit(); expect( notCancelled ).toBe( false ); @@ -109,16 +104,13 @@ describe( 'pay-for-order', () => { // Re-dispatch reached bubble phase, then native submit fallback fired. expect( bubbleSubmitSpy ).toHaveBeenCalledTimes( 1 ); - expect( nativeSubmitSpy ).toHaveBeenCalledTimes( 1 ); + expect( form.submit ).toHaveBeenCalledTimes( 1 ); } ); it( 'skips native submit when a gateway handler calls preventDefault', async () => { setupFraudProtection(); loadScript(); - const nativeSubmitSpy = jest.fn(); - form.submit = nativeSubmitSpy; - // Simulate a gateway handler (e.g. Stripe) that prevents default // to handle submission itself (tokenize, then submit). form.addEventListener( 'submit', ( e ) => e.preventDefault() ); @@ -126,7 +118,7 @@ describe( 'pay-for-order', () => { dispatchSubmit(); await flushPromises(); - expect( nativeSubmitSpy ).not.toHaveBeenCalled(); + expect( form.submit ).not.toHaveBeenCalled(); } ); it( 'stops other handlers via stopImmediatePropagation on first submission', () => { diff --git a/tests/js/setup.js b/tests/js/setup.js new file mode 100644 index 0000000..a04e0a7 --- /dev/null +++ b/tests/js/setup.js @@ -0,0 +1,7 @@ +// Stub HTMLFormElement.prototype.submit to prevent jsdom "Not implemented" errors. +// Individual tests can override form.submit with their own spy when they need to assert on it. +if ( typeof HTMLFormElement !== 'undefined' ) { + beforeEach( () => { + HTMLFormElement.prototype.submit = jest.fn(); + } ); +} diff --git a/tests/js/shortcode-checkout.test.js b/tests/js/shortcode-checkout.test.js index 060dc6f..9ac423c 100644 --- a/tests/js/shortcode-checkout.test.js +++ b/tests/js/shortcode-checkout.test.js @@ -25,17 +25,10 @@ let $; let $form; let mockAcquireSessionId; let mockReset; -let submitSpy; beforeEach( () => { document.body.innerHTML = '
'; - // Stub native submit on this specific form element — jsdom doesn't - // implement it and jQuery's trigger('submit') calls it after firing - // jQuery handlers. - submitSpy = jest.fn(); - document.querySelector( 'form.checkout' ).submit = submitSpy; - $ = require( 'jquery' ); window.jQuery = $; $form = $( 'form.checkout' ); @@ -84,7 +77,7 @@ describe( 'shortcode-checkout', () => { const result = $form.triggerHandler( 'checkout_place_order' ); expect( result ).toBe( false ); expect( mockAcquireSessionId ).toHaveBeenCalledTimes( 1 ); - expect( submitSpy ).not.toHaveBeenCalled(); + expect( document.querySelector( 'form.checkout' ).submit ).not.toHaveBeenCalled(); // Wait for the acquireSessionId promise to resolve. await flushPromises(); @@ -95,7 +88,7 @@ describe( 'shortcode-checkout', () => { expect( $field.val() ).toBe( 'sess-shortcode' ); // Form re-submitted. - expect( submitSpy ).toHaveBeenCalled(); + expect( document.querySelector( 'form.checkout' ).submit ).toHaveBeenCalled(); } ); it( 'allows through on second pass when hidden field exists', () => {