diff --git a/README.md b/README.md index 5523a2f5..5770ccff 100644 --- a/README.md +++ b/README.md @@ -260,13 +260,14 @@ expect( toBeInvalid() ``` -This allows you to check if an form element is currently invalid. +This allows you to check if a form element, or the entire `form`, is currently +invalid. -An element is invalid if it is having an +An `input`, `select`, `textarea`, or `form` element is invalid if it has an [`aria-invalid` attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-invalid_attribute) -or if the result of +with no value or a value of `"true"`, or if the result of [`checkValidity()`](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation) -are false. +is `false`. #### Examples @@ -275,6 +276,14 @@ are false. + +
+ +
+ +
+ +
``` ##### Using document.querySelector @@ -284,6 +293,9 @@ expect(queryByTestId('no-aria-invalid')).not.toBeInvalid() expect(queryByTestId('aria-invalid')).toBeInvalid() expect(queryByTestId('aria-invalid-value')).toBeInvalid() expect(queryByTestId('aria-invalid-false')).not.toBeInvalid() + +expect(queryByTestId('valid-form')).not.toBeInvalid() +expect(queryByTestId('invalid-form')).toBeInvalid() ``` ##### Using DOM Testing Library @@ -293,6 +305,9 @@ expect(getByTestId(container, 'no-aria-invalid')).not.toBeInvalid() expect(getByTestId(container, 'aria-invalid')).toBeInvalid() expect(getByTestId(container, 'aria-invalid-value')).toBeInvalid() expect(getByTestId(container, 'aria-invalid-false')).not.toBeInvalid() + +expect(getByTestId(container, 'valid-form')).not.toBeInvalid() +expect(getByTestId(container, 'invalid-form')).toBeInvalid() ```
@@ -372,12 +387,14 @@ expect(getByTestId(container, 'supported-role-aria')).toBeRequired() toBeValid() ``` -This allows you to check if the value of a form element is currently valid. +This allows you to check if the value of a form element, or the entire `form`, +is currently valid. -An element is valid if it is not having an +An `input`, `select`, `textarea`, or `form` element is valid if it has no [`aria-invalid` attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-invalid_attribute) -or having `false` as a value and returning `true` when calling -[`checkValidity()`](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation). +or an attribute value of `"false"`. The result of +[`checkValidity()`](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation) +must also be `true`. #### Examples @@ -386,6 +403,14 @@ or having `false` as a value and returning `true` when calling + +
+ +
+ +
+ +
``` ##### Using document.querySelector @@ -395,6 +420,9 @@ expect(queryByTestId('no-aria-invalid')).toBeValid() expect(queryByTestId('aria-invalid')).not.toBeValid() expect(queryByTestId('aria-invalid-value')).not.toBeValid() expect(queryByTestId('aria-invalid-false')).toBeValid() + +expect(queryByTestId('valid-form')).toBeValid() +expect(queryByTestId('invalid-form')).not.toBeValid() ``` ##### Using DOM Testing Library @@ -404,6 +432,9 @@ expect(getByTestId(container, 'no-aria-invalid')).toBeValid() expect(getByTestId(container, 'aria-invalid')).not.toBeValid() expect(getByTestId(container, 'aria-invalid-value')).not.toBeValid() expect(getByTestId(container, 'aria-invalid-false')).toBeValid() + +expect(getByTestId(container, 'valid-form')).toBeValid() +expect(getByTestId(container, 'invalid-form')).not.toBeValid() ```
diff --git a/src/__tests__/to-be-invalid.js b/src/__tests__/to-be-invalid.js index c1ad59ef..9929d53d 100644 --- a/src/__tests__/to-be-invalid.js +++ b/src/__tests__/to-be-invalid.js @@ -19,74 +19,114 @@ import {render} from './helpers/test-utils' * @link https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation * @link https://github.com/jsdom/jsdom */ -function getDOMInput(htmlString) { - const dom = new JSDOM(htmlString) - - return dom.window.document.querySelector('input') +function getDOMElement(htmlString, selector) { + return new JSDOM(htmlString).window.document.querySelector(selector) } -const invalidInputNode = getDOMInput( - ``, -) - -test('.toBeInvalid', () => { - const {queryByTestId} = render(` -
- - - - -
- `) - - expect(queryByTestId('no-aria-invalid')).not.toBeInvalid() - expect(queryByTestId('aria-invalid')).toBeInvalid() - expect(queryByTestId('aria-invalid-value')).toBeInvalid() - expect(queryByTestId('aria-invalid-false')).not.toBeInvalid() - expect(invalidInputNode).toBeInvalid() - - // negative test cases wrapped in throwError assertions for coverage. - expect(() => - expect(queryByTestId('no-aria-invalid')).toBeInvalid(), - ).toThrowError() - expect(() => - expect(queryByTestId('aria-invalid')).not.toBeInvalid(), - ).toThrowError() - expect(() => - expect(queryByTestId('aria-invalid-value')).not.toBeInvalid(), - ).toThrowError() - expect(() => - expect(queryByTestId('aria-invalid-false')).toBeInvalid(), - ).toThrowError() - expect(() => expect(invalidInputNode).not.toBeInvalid()).toThrowError() +// A required field without a value is invalid +const invalidInputHtml = `` + +const invalidInputNode = getDOMElement(invalidInputHtml, 'input') + +// A form is invalid if it contains an invalid input +const invalidFormHtml = `
${invalidInputHtml}
` + +const invalidFormNode = getDOMElement(invalidFormHtml, 'form') + +describe('.toBeInvalid', () => { + test('handles ', () => { + const {queryByTestId} = render(` +
+ + + + +
+ `) + + expect(queryByTestId('no-aria-invalid')).not.toBeInvalid() + expect(queryByTestId('aria-invalid')).toBeInvalid() + expect(queryByTestId('aria-invalid-value')).toBeInvalid() + expect(queryByTestId('aria-invalid-false')).not.toBeInvalid() + expect(invalidInputNode).toBeInvalid() + + // negative test cases wrapped in throwError assertions for coverage. + expect(() => + expect(queryByTestId('no-aria-invalid')).toBeInvalid(), + ).toThrowError() + expect(() => + expect(queryByTestId('aria-invalid')).not.toBeInvalid(), + ).toThrowError() + expect(() => + expect(queryByTestId('aria-invalid-value')).not.toBeInvalid(), + ).toThrowError() + expect(() => + expect(queryByTestId('aria-invalid-false')).toBeInvalid(), + ).toThrowError() + expect(() => expect(invalidInputNode).not.toBeInvalid()).toThrowError() + }) + + test('handles
', () => { + const {queryByTestId} = render(` + + +
+ `) + + expect(queryByTestId('valid')).not.toBeInvalid() + expect(invalidFormNode).toBeInvalid() + + // negative test cases wrapped in throwError assertions for coverage. + expect(() => expect(queryByTestId('valid')).toBeInvalid()).toThrowError() + expect(() => expect(invalidFormNode).not.toBeInvalid()).toThrowError() + }) }) -test('.toBeValid', () => { - const {queryByTestId} = render(` -
- - - - -
- `) - - expect(queryByTestId('no-aria-invalid')).toBeValid() - expect(queryByTestId('aria-invalid')).not.toBeValid() - expect(queryByTestId('aria-invalid-value')).not.toBeValid() - expect(queryByTestId('aria-invalid-false')).toBeValid() - expect(invalidInputNode).not.toBeValid() - - // negative test cases wrapped in throwError assertions for coverage. - expect(() => - expect(queryByTestId('no-aria-invalid')).not.toBeValid(), - ).toThrowError() - expect(() => expect(queryByTestId('aria-invalid')).toBeValid()).toThrowError() - expect(() => - expect(queryByTestId('aria-invalid-value')).toBeValid(), - ).toThrowError() - expect(() => - expect(queryByTestId('aria-invalid-false')).not.toBeValid(), - ).toThrowError() - expect(() => expect(invalidInputNode).toBeValid()).toThrowError() +describe('.toBeValid', () => { + test('handles ', () => { + const {queryByTestId} = render(` +
+ + + + +
+ `) + + expect(queryByTestId('no-aria-invalid')).toBeValid() + expect(queryByTestId('aria-invalid')).not.toBeValid() + expect(queryByTestId('aria-invalid-value')).not.toBeValid() + expect(queryByTestId('aria-invalid-false')).toBeValid() + expect(invalidInputNode).not.toBeValid() + + // negative test cases wrapped in throwError assertions for coverage. + expect(() => + expect(queryByTestId('no-aria-invalid')).not.toBeValid(), + ).toThrowError() + expect(() => + expect(queryByTestId('aria-invalid')).toBeValid(), + ).toThrowError() + expect(() => + expect(queryByTestId('aria-invalid-value')).toBeValid(), + ).toThrowError() + expect(() => + expect(queryByTestId('aria-invalid-false')).not.toBeValid(), + ).toThrowError() + expect(() => expect(invalidInputNode).toBeValid()).toThrowError() + }) + + test('handles
', () => { + const {queryByTestId} = render(` + + +
+ `) + + expect(queryByTestId('valid')).toBeValid() + expect(invalidFormNode).not.toBeValid() + + // negative test cases wrapped in throwError assertions for coverage. + expect(() => expect(queryByTestId('valid')).not.toBeValid()).toThrowError() + expect(() => expect(invalidFormNode).toBeValid()).toThrowError() + }) }) diff --git a/src/to-be-invalid.js b/src/to-be-invalid.js index 6096e737..ab1d6ad1 100644 --- a/src/to-be-invalid.js +++ b/src/to-be-invalid.js @@ -1,7 +1,7 @@ import {matcherHint, printReceived} from 'jest-matcher-utils' import {checkHtmlElement, getTag} from './utils' -const FORM_TAGS = ['input', 'select', 'textarea'] +const FORM_TAGS = ['form', 'input', 'select', 'textarea'] function isElementHavingAriaInvalid(element) { return (