Skip to content

Commit

Permalink
feat: Add toBeEnabled matcher (#78)
Browse files Browse the repository at this point in the history
  • Loading branch information
lourenci authored and gnapse committed Feb 10, 2019
1 parent dd310ee commit 02c340d
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 6 deletions.
4 changes: 3 additions & 1 deletion .all-contributorsrc
Expand Up @@ -196,7 +196,9 @@
"profile": "https://blog.lourenci.com/",
"contributions": [
"bug",
"doc"
"doc",
"code",
"test"
]
},
{
Expand Down
19 changes: 16 additions & 3 deletions README.md
Expand Up @@ -46,6 +46,7 @@ to maintain.
- [Usage](#usage)
- [Custom matchers](#custom-matchers)
- [`toBeDisabled`](#tobedisabled)
- [`toBeEnabled`](#tobeenabled)
- [`toBeEmpty`](#tobeempty)
- [`toBeInTheDocument`](#tobeinthedocument)
- [`toBeVisible`](#tobevisible)
Expand Down Expand Up @@ -144,6 +145,18 @@ expect(getByText(container, 'link')).not.toBeDisabled()

<hr />

### `toBeEnabled`

```typescript
toBeEnabled()
```

This allows you to check whether an element is not disabled from the user's perspective.

It works like `not.toBeDisabled()`. Use this matcher to avoid double negation in your tests.

<hr />

### `toBeEmpty`

```typescript
Expand Down Expand Up @@ -733,10 +746,10 @@ Thanks goes to these people ([emoji key][emojis]):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore -->
| [<img src="https://avatars.githubusercontent.com/u/1500684?v=3" width="100px;" alt="Kent C. Dodds"/><br /><sub><b>Kent C. Dodds</b></sub>](https://kentcdodds.com)<br />[💻](https://github.com/gnapse/jest-dom/commits?author=kentcdodds "Code") [📖](https://github.com/gnapse/jest-dom/commits?author=kentcdodds "Documentation") [🚇](#infra-kentcdodds "Infrastructure (Hosting, Build-Tools, etc)") [⚠️](https://github.com/gnapse/jest-dom/commits?author=kentcdodds "Tests") | [<img src="https://avatars1.githubusercontent.com/u/2430381?v=4" width="100px;" alt="Ryan Castner"/><br /><sub><b>Ryan Castner</b></sub>](http://audiolion.github.io)<br />[📖](https://github.com/gnapse/jest-dom/commits?author=audiolion "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/8008023?v=4" width="100px;" alt="Daniel Sandiego"/><br /><sub><b>Daniel Sandiego</b></sub>](https://www.dnlsandiego.com)<br />[💻](https://github.com/gnapse/jest-dom/commits?author=dnlsandiego "Code") | [<img src="https://avatars2.githubusercontent.com/u/12592677?v=4" width="100px;" alt="Paweł Mikołajczyk"/><br /><sub><b>Paweł Mikołajczyk</b></sub>](https://github.com/Miklet)<br />[💻](https://github.com/gnapse/jest-dom/commits?author=Miklet "Code") | [<img src="https://avatars3.githubusercontent.com/u/464978?v=4" width="100px;" alt="Alejandro Ñáñez Ortiz"/><br /><sub><b>Alejandro Ñáñez Ortiz</b></sub>](http://co.linkedin.com/in/alejandronanez/)<br />[📖](https://github.com/gnapse/jest-dom/commits?author=alejandronanez "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/1402095?v=4" width="100px;" alt="Matt Parrish"/><br /><sub><b>Matt Parrish</b></sub>](https://github.com/pbomb)<br />[🐛](https://github.com/gnapse/jest-dom/issues?q=author%3Apbomb "Bug reports") [💻](https://github.com/gnapse/jest-dom/commits?author=pbomb "Code") [📖](https://github.com/gnapse/jest-dom/commits?author=pbomb "Documentation") [⚠️](https://github.com/gnapse/jest-dom/commits?author=pbomb "Tests") | [<img src="https://avatars1.githubusercontent.com/u/1288694?v=4" width="100px;" alt="Justin Hall"/><br /><sub><b>Justin Hall</b></sub>](https://github.com/wKovacs64)<br />[📦](#platform-wKovacs64 "Packaging/porting to new platform") |
| [<img src="https://avatars.githubusercontent.com/u/1500684?v=3" width="100px;"/><br /><sub><b>Kent C. Dodds</b></sub>](https://kentcdodds.com)<br />[💻](https://github.com/gnapse/jest-dom/commits?author=kentcdodds "Code") [📖](https://github.com/gnapse/jest-dom/commits?author=kentcdodds "Documentation") [🚇](#infra-kentcdodds "Infrastructure (Hosting, Build-Tools, etc)") [⚠️](https://github.com/gnapse/jest-dom/commits?author=kentcdodds "Tests") | [<img src="https://avatars1.githubusercontent.com/u/2430381?v=4" width="100px;"/><br /><sub><b>Ryan Castner</b></sub>](http://audiolion.github.io)<br />[📖](https://github.com/gnapse/jest-dom/commits?author=audiolion "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/8008023?v=4" width="100px;"/><br /><sub><b>Daniel Sandiego</b></sub>](https://www.dnlsandiego.com)<br />[💻](https://github.com/gnapse/jest-dom/commits?author=dnlsandiego "Code") | [<img src="https://avatars2.githubusercontent.com/u/12592677?v=4" width="100px;"/><br /><sub><b>Paweł Mikołajczyk</b></sub>](https://github.com/Miklet)<br />[💻](https://github.com/gnapse/jest-dom/commits?author=Miklet "Code") | [<img src="https://avatars3.githubusercontent.com/u/464978?v=4" width="100px;"/><br /><sub><b>Alejandro Ñáñez Ortiz</b></sub>](http://co.linkedin.com/in/alejandronanez/)<br />[📖](https://github.com/gnapse/jest-dom/commits?author=alejandronanez "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/1402095?v=4" width="100px;"/><br /><sub><b>Matt Parrish</b></sub>](https://github.com/pbomb)<br />[🐛](https://github.com/gnapse/jest-dom/issues?q=author%3Apbomb "Bug reports") [💻](https://github.com/gnapse/jest-dom/commits?author=pbomb "Code") [📖](https://github.com/gnapse/jest-dom/commits?author=pbomb "Documentation") [⚠️](https://github.com/gnapse/jest-dom/commits?author=pbomb "Tests") | [<img src="https://avatars1.githubusercontent.com/u/1288694?v=4" width="100px;"/><br /><sub><b>Justin Hall</b></sub>](https://github.com/wKovacs64)<br />[📦](#platform-wKovacs64 "Packaging/porting to new platform") |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| [<img src="https://avatars1.githubusercontent.com/u/1241511?s=460&v=4" width="100px;" alt="Anto Aravinth"/><br /><sub><b>Anto Aravinth</b></sub>](https://github.com/antoaravinth)<br />[💻](https://github.com/gnapse/jest-dom/commits?author=antoaravinth "Code") [⚠️](https://github.com/gnapse/jest-dom/commits?author=antoaravinth "Tests") [📖](https://github.com/gnapse/jest-dom/commits?author=antoaravinth "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/3462296?v=4" width="100px;" alt="Jonah Moses"/><br /><sub><b>Jonah Moses</b></sub>](https://github.com/JonahMoses)<br />[📖](https://github.com/gnapse/jest-dom/commits?author=JonahMoses "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/4002543?v=4" width="100px;" alt="Łukasz Gandecki"/><br /><sub><b>Łukasz Gandecki</b></sub>](http://team.thebrain.pro)<br />[💻](https://github.com/gnapse/jest-dom/commits?author=lgandecki "Code") [⚠️](https://github.com/gnapse/jest-dom/commits?author=lgandecki "Tests") [📖](https://github.com/gnapse/jest-dom/commits?author=lgandecki "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/498274?v=4" width="100px;" alt="Ivan Babak"/><br /><sub><b>Ivan Babak</b></sub>](https://sompylasar.github.io)<br />[🐛](https://github.com/gnapse/jest-dom/issues?q=author%3Asompylasar "Bug reports") [🤔](#ideas-sompylasar "Ideas, Planning, & Feedback") | [<img src="https://avatars3.githubusercontent.com/u/4439618?v=4" width="100px;" alt="Jesse Day"/><br /><sub><b>Jesse Day</b></sub>](https://github.com/jday3)<br />[💻](https://github.com/gnapse/jest-dom/commits?author=jday3 "Code") | [<img src="https://avatars0.githubusercontent.com/u/15199?v=4" width="100px;" alt="Ernesto García"/><br /><sub><b>Ernesto García</b></sub>](http://gnapse.github.io)<br />[💻](https://github.com/gnapse/jest-dom/commits?author=gnapse "Code") [📖](https://github.com/gnapse/jest-dom/commits?author=gnapse "Documentation") [⚠️](https://github.com/gnapse/jest-dom/commits?author=gnapse "Tests") | [<img src="https://avatars0.githubusercontent.com/u/79312?v=4" width="100px;" alt="Mark Volkmann"/><br /><sub><b>Mark Volkmann</b></sub>](http://ociweb.com/mark/)<br />[🐛](https://github.com/gnapse/jest-dom/issues?q=author%3Amvolkmann "Bug reports") [💻](https://github.com/gnapse/jest-dom/commits?author=mvolkmann "Code") |
| [<img src="https://avatars1.githubusercontent.com/u/1659099?v=4" width="100px;" alt="smacpherson64"/><br /><sub><b>smacpherson64</b></sub>](https://github.com/smacpherson64)<br />[💻](https://github.com/gnapse/jest-dom/commits?author=smacpherson64 "Code") [📖](https://github.com/gnapse/jest-dom/commits?author=smacpherson64 "Documentation") [⚠️](https://github.com/gnapse/jest-dom/commits?author=smacpherson64 "Tests") | [<img src="https://avatars2.githubusercontent.com/u/132233?v=4" width="100px;" alt="John Gozde"/><br /><sub><b>John Gozde</b></sub>](https://github.com/jgoz)<br />[🐛](https://github.com/gnapse/jest-dom/issues?q=author%3Ajgoz "Bug reports") [💻](https://github.com/gnapse/jest-dom/commits?author=jgoz "Code") | [<img src="https://avatars2.githubusercontent.com/u/7830590?v=4" width="100px;" alt="Iwona"/><br /><sub><b>Iwona</b></sub>](https://github.com/callada)<br />[💻](https://github.com/gnapse/jest-dom/commits?author=callada "Code") [📖](https://github.com/gnapse/jest-dom/commits?author=callada "Documentation") [⚠️](https://github.com/gnapse/jest-dom/commits?author=callada "Tests") | [<img src="https://avatars0.githubusercontent.com/u/840609?v=4" width="100px;" alt="Lewis"/><br /><sub><b>Lewis</b></sub>](https://github.com/6ewis)<br />[💻](https://github.com/gnapse/jest-dom/commits?author=6ewis "Code") | [<img src="https://avatars3.githubusercontent.com/u/2339362?v=4" width="100px;" alt="Leandro Lourenci"/><br /><sub><b>Leandro Lourenci</b></sub>](https://blog.lourenci.com/)<br />[🐛](https://github.com/gnapse/jest-dom/issues?q=author%3Alourenci "Bug reports") [📖](https://github.com/gnapse/jest-dom/commits?author=lourenci "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/626420?v=4" width="100px;" alt="Shukhrat Mukimov"/><br /><sub><b>Shukhrat Mukimov</b></sub>](https://github.com/mufasa71)<br />[🐛](https://github.com/gnapse/jest-dom/issues?q=author%3Amufasa71 "Bug reports") |
| [<img src="https://avatars1.githubusercontent.com/u/1241511?s=460&v=4" width="100px;"/><br /><sub><b>Anto Aravinth</b></sub>](https://github.com/antoaravinth)<br />[💻](https://github.com/gnapse/jest-dom/commits?author=antoaravinth "Code") [⚠️](https://github.com/gnapse/jest-dom/commits?author=antoaravinth "Tests") [📖](https://github.com/gnapse/jest-dom/commits?author=antoaravinth "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/3462296?v=4" width="100px;"/><br /><sub><b>Jonah Moses</b></sub>](https://github.com/JonahMoses)<br />[📖](https://github.com/gnapse/jest-dom/commits?author=JonahMoses "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/4002543?v=4" width="100px;"/><br /><sub><b>Łukasz Gandecki</b></sub>](http://team.thebrain.pro)<br />[💻](https://github.com/gnapse/jest-dom/commits?author=lgandecki "Code") [⚠️](https://github.com/gnapse/jest-dom/commits?author=lgandecki "Tests") [📖](https://github.com/gnapse/jest-dom/commits?author=lgandecki "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/498274?v=4" width="100px;"/><br /><sub><b>Ivan Babak</b></sub>](https://sompylasar.github.io)<br />[🐛](https://github.com/gnapse/jest-dom/issues?q=author%3Asompylasar "Bug reports") [🤔](#ideas-sompylasar "Ideas, Planning, & Feedback") | [<img src="https://avatars3.githubusercontent.com/u/4439618?v=4" width="100px;"/><br /><sub><b>Jesse Day</b></sub>](https://github.com/jday3)<br />[💻](https://github.com/gnapse/jest-dom/commits?author=jday3 "Code") | [<img src="https://avatars0.githubusercontent.com/u/15199?v=4" width="100px;"/><br /><sub><b>Ernesto García</b></sub>](http://gnapse.github.io)<br />[💻](https://github.com/gnapse/jest-dom/commits?author=gnapse "Code") [📖](https://github.com/gnapse/jest-dom/commits?author=gnapse "Documentation") [⚠️](https://github.com/gnapse/jest-dom/commits?author=gnapse "Tests") | [<img src="https://avatars0.githubusercontent.com/u/79312?v=4" width="100px;"/><br /><sub><b>Mark Volkmann</b></sub>](http://ociweb.com/mark/)<br />[🐛](https://github.com/gnapse/jest-dom/issues?q=author%3Amvolkmann "Bug reports") [💻](https://github.com/gnapse/jest-dom/commits?author=mvolkmann "Code") |
| [<img src="https://avatars1.githubusercontent.com/u/1659099?v=4" width="100px;"/><br /><sub><b>smacpherson64</b></sub>](https://github.com/smacpherson64)<br />[💻](https://github.com/gnapse/jest-dom/commits?author=smacpherson64 "Code") [📖](https://github.com/gnapse/jest-dom/commits?author=smacpherson64 "Documentation") [⚠️](https://github.com/gnapse/jest-dom/commits?author=smacpherson64 "Tests") | [<img src="https://avatars2.githubusercontent.com/u/132233?v=4" width="100px;"/><br /><sub><b>John Gozde</b></sub>](https://github.com/jgoz)<br />[🐛](https://github.com/gnapse/jest-dom/issues?q=author%3Ajgoz "Bug reports") [💻](https://github.com/gnapse/jest-dom/commits?author=jgoz "Code") | [<img src="https://avatars2.githubusercontent.com/u/7830590?v=4" width="100px;"/><br /><sub><b>Iwona</b></sub>](https://github.com/callada)<br />[💻](https://github.com/gnapse/jest-dom/commits?author=callada "Code") [📖](https://github.com/gnapse/jest-dom/commits?author=callada "Documentation") [⚠️](https://github.com/gnapse/jest-dom/commits?author=callada "Tests") | [<img src="https://avatars0.githubusercontent.com/u/840609?v=4" width="100px;"/><br /><sub><b>Lewis</b></sub>](https://github.com/6ewis)<br />[💻](https://github.com/gnapse/jest-dom/commits?author=6ewis "Code") | [<img src="https://avatars3.githubusercontent.com/u/2339362?v=4" width="100px;"/><br /><sub><b>Leandro Lourenci</b></sub>](https://blog.lourenci.com/)<br />[🐛](https://github.com/gnapse/jest-dom/issues?q=author%3Alourenci "Bug reports") [📖](https://github.com/gnapse/jest-dom/commits?author=lourenci "Documentation") [💻](https://github.com/gnapse/jest-dom/commits?author=lourenci "Code") [⚠️](https://github.com/gnapse/jest-dom/commits?author=lourenci "Tests") | [<img src="https://avatars1.githubusercontent.com/u/626420?v=4" width="100px;"/><br /><sub><b>Shukhrat Mukimov</b></sub>](https://github.com/mufasa71)<br />[🐛](https://github.com/gnapse/jest-dom/issues?q=author%3Amufasa71 "Bug reports") |
<!-- ALL-CONTRIBUTORS-LIST:END -->
Expand Down
128 changes: 128 additions & 0 deletions src/__tests__/to-be-disabled.js
Expand Up @@ -103,3 +103,131 @@ test('.toBeDisabled fieldset>legend', () => {

expect(queryByTestId('outer-fieldset-element')).toBeDisabled()
})

test('.toBeEnabled', () => {
const {queryByTestId} = render(`
<div>
<button disabled={true} data-testid="button-element">x</button>
<textarea disabled={true} data-testid="textarea-element"></textarea>
<input type="checkbox" disabled={true} data-testid="input-element" />
<fieldset disabled={true} data-testid="fieldset-element">
<button data-testid="fieldset-child-element">x</button>
</fieldset>
<div disabled={true} data-testid="div-element">
<button data-testid="div-child-element">x</button>
</div>
<fieldset disabled={true}>
<div>
<button data-testid="nested-form-element">x</button>
<select data-testid="deep-select-element">
<optgroup data-testid="deep-optgroup-element">
<option data-testid="deep-option-element">x</option>
</optgroup>
</select>
</div>
</fieldset>
<a href="http://github.com" disabled={true} data-testid="a-element">x</a>
</div>
`)

expect(() => {
expect(queryByTestId('button-element')).toBeEnabled()
}).toThrowError()
expect(queryByTestId('button-element')).not.toBeEnabled()
expect(() => {
expect(queryByTestId('textarea-element')).toBeEnabled()
}).toThrowError()
expect(() => {
expect(queryByTestId('input-element')).toBeEnabled()
}).toThrowError()

expect(() => {
expect(queryByTestId('fieldset-element')).toBeEnabled()
}).toThrowError()
expect(() => {
expect(queryByTestId('fieldset-child-element')).toBeEnabled()
}).toThrowError()

expect(queryByTestId('div-element')).toBeEnabled()
expect(queryByTestId('div-child-element')).toBeEnabled()

expect(() => {
expect(queryByTestId('nested-form-element')).toBeEnabled()
}).toThrowError()
expect(() => {
expect(queryByTestId('deep-select-element')).toBeEnabled()
}).toThrowError()
expect(() => {
expect(queryByTestId('deep-optgroup-element')).toBeEnabled()
}).toThrowError()
expect(() => {
expect(queryByTestId('deep-option-element')).toBeEnabled()
}).toThrowError()

expect(queryByTestId('a-element')).toBeEnabled()
expect(() =>
expect(queryByTestId('a-element')).not.toBeEnabled(),
).toThrowError()
})

test('.toBeEnabled fieldset>legend', () => {
const {queryByTestId} = render(`
<div>
<fieldset disabled={true}>
<button data-testid="inherited-element">x</button>
</fieldset>
<fieldset disabled={true}>
<legend>
<button data-testid="inside-legend-element">x</button>
</legend>
</fieldset>
<fieldset disabled={true}>
<legend>
<div>
<button data-testid="nested-inside-legend-element">x</button>
</div>
</legend>
</fieldset>
<fieldset disabled={true}>
<div></div>
<legend>
<button data-testid="first-legend-element">x</button>
</legend>
<legend>
<button data-testid="second-legend-element">x</button>
</legend>
</fieldset>
<fieldset disabled={true}>
<fieldset>
<legend>
<button data-testid="outer-fieldset-element">x</button>
</legend>
</fieldset>
</fieldset>
</div>
`)

expect(() => {
expect(queryByTestId('inherited-element')).toBeEnabled()
}).toThrowError()
expect(queryByTestId('inside-legend-element')).toBeEnabled()
expect(queryByTestId('nested-inside-legend-element')).toBeEnabled()

expect(queryByTestId('first-legend-element')).toBeEnabled()
expect(() => {
expect(queryByTestId('second-legend-element')).toBeEnabled()
}).toThrowError()

expect(() => {
expect(queryByTestId('outer-fieldset-element')).toBeEnabled()
}).toThrowError()
})
3 changes: 2 additions & 1 deletion src/index.js
Expand Up @@ -10,7 +10,7 @@ import {toHaveStyle} from './to-have-style'
import {toHaveFocus} from './to-have-focus'
import {toHaveFormValues} from './to-have-form-values'
import {toBeVisible} from './to-be-visible'
import {toBeDisabled} from './to-be-disabled'
import {toBeDisabled, toBeEnabled} from './to-be-disabled'

export {
toBeInTheDOM,
Expand All @@ -26,4 +26,5 @@ export {
toHaveFormValues,
toBeVisible,
toBeDisabled,
toBeEnabled,
}
21 changes: 20 additions & 1 deletion src/to-be-disabled.js
Expand Up @@ -20,7 +20,7 @@ function getTag(element) {
* According to specification:
* If <fieldset> is disabled, the form controls that are its descendants,
* except descendants of its first optional <legend> element, are disabled
*
*
* https://html.spec.whatwg.org/multipage/form-elements.html#concept-fieldset-disabled
*
* This method tests whether element is first legend child of fieldset parent
Expand Down Expand Up @@ -71,3 +71,22 @@ export function toBeDisabled(element) {
},
}
}

export function toBeEnabled(element) {
checkHtmlElement(element, toBeEnabled, this)

const isEnabled = !(isElementDisabled(element) || isAncestorDisabled(element))

return {
pass: isEnabled,
message: () => {
const is = isEnabled ? 'is' : 'is not'
return [
matcherHint(`${this.isNot ? '.not' : ''}.toBeEnabled`, 'element', ''),
'',
`Received element ${is} enabled:`,
` ${printReceived(element.cloneNode(false))}`,
].join('\n')
},
}
}

0 comments on commit 02c340d

Please sign in to comment.