From e72cd0254f8839abb939f4f49961c59006c6989d Mon Sep 17 00:00:00 2001 From: Winston Date: Mon, 8 Jul 2024 10:51:46 -0700 Subject: [PATCH 1/2] Test for hidden value workarounds for checkbox inputs so they can send "false" --- src/__tests__/to-have-form-values.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/__tests__/to-have-form-values.js b/src/__tests__/to-have-form-values.js index 18b99d98..fa206a11 100644 --- a/src/__tests__/to-have-form-values.js +++ b/src/__tests__/to-have-form-values.js @@ -189,6 +189,19 @@ describe('.toHaveFormValues', () => { }).toThrowError(/must be of the same type/) }) + it('allows a checkbox and a hidden input which is a common workaround so forms can send "false" for a checkbox', () => { + const {container} = render(` +
+ + +
+ `) + const form = container.querySelector('form') + expect(() => { + expect(form).toHaveFormValues({ "sample-checkbox": 1}) + }).not.toThrowError() + }) + it('detects multiple elements with the same type and name', () => { const {container} = render(`
From b8338008db8bb2c57c282e276f4ea5ca569a7f4e Mon Sep 17 00:00:00 2001 From: Winston Date: Mon, 8 Jul 2024 11:43:12 -0700 Subject: [PATCH 2/2] Add logic for this special case, and updated docs. Co-authored-by: Caroline Tan --- README.md | 5 ++++- src/__tests__/to-have-form-values.js | 8 +++++--- src/to-have-form-values.js | 15 ++++++++++++--- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 3e9796af..b310d272 100644 --- a/README.md +++ b/README.md @@ -850,8 +850,11 @@ of all cases covered: unchecked. - if there's more than one checkbox with the same `name` attribute, they are all treated collectively as a single form control, which returns the value - as an **array** containing all the values of the selected checkboxes in the + as an **array** containing all the values of the checkboxes in the collection. + - a hidden input with same name before the checkbox is allowed which is a + common workaround to allow browsers to send `false` for unchecked + checkboxes. - `` elements are all grouped by the `name` attribute, and such a group treated as a single form control. This form control returns the value as a **string** corresponding to the `value` attribute of the selected diff --git a/src/__tests__/to-have-form-values.js b/src/__tests__/to-have-form-values.js index fa206a11..2bdc9581 100644 --- a/src/__tests__/to-have-form-values.js +++ b/src/__tests__/to-have-form-values.js @@ -192,13 +192,15 @@ describe('.toHaveFormValues', () => { it('allows a checkbox and a hidden input which is a common workaround so forms can send "false" for a checkbox', () => { const {container} = render(` - - + + `) const form = container.querySelector('form') expect(() => { - expect(form).toHaveFormValues({ "sample-checkbox": 1}) + expect(form).toHaveFormValues({ + 'checkbox-with-hidden-false': ['0', '1'], + }) }).not.toThrowError() }) diff --git a/src/to-have-form-values.js b/src/to-have-form-values.js index cd479d68..5bcc82de 100644 --- a/src/to-have-form-values.js +++ b/src/to-have-form-values.js @@ -11,9 +11,18 @@ import { function getMultiElementValue(elements) { const types = [...new Set(elements.map(element => element.type))] if (types.length !== 1) { - throw new Error( - 'Multiple form elements with the same name must be of the same type', - ) + if ( + types.length === 2 && + types[0] === 'hidden' && + types[1] === 'checkbox' + ) { + // Allow the special case where there's a 'checkbox' input, and a matching 'hidden' input + // before it, which works around browser forms so a 'false' value is submitted. + } else { + throw new Error( + 'Multiple form elements with the same name must be of the same type', + ) + } } switch (types[0]) { case 'radio': {