From 3c1576dacf0186b4694dd7e916f9e3c2b58bc7a1 Mon Sep 17 00:00:00 2001 From: Tom Byers Date: Wed, 4 Sep 2019 10:24:31 +0100 Subject: [PATCH] Add helper for mocking/stubbing form.submit JSDOM doesn't implement the submit method on form elements. It does have a submit method but this just fires a 'not implemented' error. We need to spy on form submissions fired by clicking on the submit button but can't because this event calls the submit method internally so spying on `form.submit` doesn't work. This adds a helper which spies on the internal method that is actually called. When JSDOM implements the submit method properly this should be removed. --- tests/javascripts/support/helpers.js | 2 ++ tests/javascripts/support/helpers/forms.js | 33 ++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 tests/javascripts/support/helpers/forms.js diff --git a/tests/javascripts/support/helpers.js b/tests/javascripts/support/helpers.js index 620bba003..65c7f6a0d 100644 --- a/tests/javascripts/support/helpers.js +++ b/tests/javascripts/support/helpers.js @@ -3,6 +3,7 @@ const domInterfaces = require('./helpers/dom_interfaces.js'); const html = require('./helpers/html.js'); const elements = require('./helpers/elements.js'); const rendering = require('./helpers/rendering.js'); +const forms = require('./helpers/forms.js'); exports.triggerEvent = events.triggerEvent; exports.clickElementWithMouse = events.clickElementWithMouse; @@ -15,3 +16,4 @@ exports.getRadios = html.getRadios; exports.element = elements.element; exports.WindowMock = rendering.WindowMock; exports.ScreenMock = rendering.ScreenMock; +exports.spyOnFormSubmit = forms.spyOnFormSubmit; diff --git a/tests/javascripts/support/helpers/forms.js b/tests/javascripts/support/helpers/forms.js new file mode 100644 index 000000000..415ac0dbe --- /dev/null +++ b/tests/javascripts/support/helpers/forms.js @@ -0,0 +1,33 @@ + +// helper for spying on the submit method on a form element +// JSDOM's implementation of submit just wraps a 'not implemented' error so we need to mock that to track calls to it +// +// * Remove when JSDOM implements submit on its form elements * +// +// elements in JSDOM have a public API and a private implementation API, only used by internal code +// For form elements, these are instances of the following classes: +// - HTMLFormElement +// - HTMLFormElementImpl +// +// form elements link to their implementation instance via a symbol property +// this spies on the submit method of the implementation instance for a form element and mocks it to prevent 'not implemented' errors +function spyOnFormSubmit (jest, form) { + + const formImplementationSymbols = Object.getOwnPropertySymbols(form).filter( + symbol => form[symbol].constructor.name === 'HTMLFormElementImpl' + ); + + if (!formImplementationSymbols.length) { + throw Error("Error mocking form.submit: symbol reference to HTMLFormElementImpl instance not found on form element"); + } + + const HTMLFormElementImpl = form[formImplementationSymbols[0]]; + + const submitSpy = jest.spyOn(HTMLFormElementImpl, 'submit') + + submitSpy.mockImplementation(); + return submitSpy; + +}; + +exports.spyOnFormSubmit = spyOnFormSubmit;