diff --git a/README.md b/README.md index 22901ce8..b7428b99 100644 --- a/README.md +++ b/README.md @@ -274,10 +274,9 @@ expect( toBeInvalid() ``` -This allows you to check if a form element, or the entire `form`, is currently -invalid. +This allows you to check if an element, is currently invalid. -An `input`, `select`, `textarea`, or `form` element is invalid if it has an +An 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) 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) @@ -359,14 +358,13 @@ expect(getByTestId('supported-role-aria')).toBeRequired() toBeValid() ``` -This allows you to check if the value of a form element, or the entire `form`, -is currently valid. +This allows you to check if the value of an element, is currently valid. -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) +An 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)s 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`. +must also be `true` if it's a form element. #### Examples @@ -1162,6 +1160,7 @@ Thanks goes to these people ([emoji key][emojis]): + This project follows the [all-contributors][all-contributors] specification. diff --git a/src/__tests__/to-be-invalid.js b/src/__tests__/to-be-invalid.js index 9929d53d..66ed8749 100644 --- a/src/__tests__/to-be-invalid.js +++ b/src/__tests__/to-be-invalid.js @@ -80,6 +80,38 @@ describe('.toBeInvalid', () => { expect(() => expect(queryByTestId('valid')).toBeInvalid()).toThrowError() expect(() => expect(invalidFormNode).not.toBeInvalid()).toThrowError() }) + + test('handles any element', () => { + const {queryByTestId} = render(` +
    +
  1. +
  2. +
  3. +
  4. +
+ `) + + expect(queryByTestId('valid')).not.toBeInvalid() + 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() + + // negative test cases wrapped in throwError assertions for coverage. + expect(() => expect(queryByTestId('valid')).toBeInvalid()).toThrowError() + 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() + }) }) describe('.toBeValid', () => { @@ -129,4 +161,36 @@ describe('.toBeValid', () => { expect(() => expect(queryByTestId('valid')).not.toBeValid()).toThrowError() expect(() => expect(invalidFormNode).toBeValid()).toThrowError() }) + + test('handles any element', () => { + const {queryByTestId} = render(` +
    +
  1. +
  2. +
  3. +
  4. +
+ `) + + expect(queryByTestId('valid')).toBeValid() + 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() + + // negative test cases wrapped in throwError assertions for coverage. + expect(() => expect(queryByTestId('valid')).not.toBeValid()).toThrowError() + 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() + }) }) diff --git a/src/to-be-invalid.js b/src/to-be-invalid.js index 388c9f63..cb476827 100644 --- a/src/to-be-invalid.js +++ b/src/to-be-invalid.js @@ -10,15 +10,23 @@ function isElementHavingAriaInvalid(element) { ) } +function isSupportsValidityMethod(element) { + return FORM_TAGS.includes(getTag(element)) +} + function isElementInvalid(element) { - return !element.checkValidity() + const isHaveAriaInvalid = isElementHavingAriaInvalid(element) + if (isSupportsValidityMethod(element)) { + return isHaveAriaInvalid || !element.checkValidity() + } else { + return isHaveAriaInvalid + } } export function toBeInvalid(element) { checkHtmlElement(element, toBeInvalid, this) - const isInvalid = - isElementHavingAriaInvalid(element) || isElementInvalid(element) + const isInvalid = isElementInvalid(element) return { pass: isInvalid, @@ -37,10 +45,7 @@ export function toBeInvalid(element) { export function toBeValid(element) { checkHtmlElement(element, toBeValid, this) - const isValid = - !isElementHavingAriaInvalid(element) && - FORM_TAGS.includes(getTag(element)) && - !isElementInvalid(element) + const isValid = !isElementInvalid(element) return { pass: isValid,