Skip to content

Commit

Permalink
feat: [toBeValid/toBeInvalid] Check aria-invalid on any element (#259)
Browse files Browse the repository at this point in the history
  • Loading branch information
missilev committed Jun 11, 2020
1 parent 159a7a2 commit 14d1630
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 15 deletions.
15 changes: 7 additions & 8 deletions README.md
Expand Up @@ -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)
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -1162,6 +1160,7 @@ Thanks goes to these people ([emoji key][emojis]):

<!-- markdownlint-enable -->
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors][all-contributors] specification.
Expand Down
64 changes: 64 additions & 0 deletions src/__tests__/to-be-invalid.js
Expand Up @@ -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(`
<ol data-testid="valid">
<li data-testid="no-aria-invalid" > </li>
<li data-testid="aria-invalid" aria-invalid> </li>
<li data-testid="aria-invalid-value" aria-invalid="true"> </li>
<li data-testid="aria-invalid-false" aria-invalid="false"> </li>
</ol>
`)

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', () => {
Expand Down Expand Up @@ -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(`
<ol data-testid="valid">
<li data-testid="no-aria-invalid" > </li>
<li data-testid="aria-invalid" aria-invalid> </li>
<li data-testid="aria-invalid-value" aria-invalid="true"> </li>
<li data-testid="aria-invalid-false" aria-invalid="false"> </li>
</ol>
`)

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()
})
})
19 changes: 12 additions & 7 deletions src/to-be-invalid.js
Expand Up @@ -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,
Expand All @@ -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,
Expand Down

0 comments on commit 14d1630

Please sign in to comment.