-
Notifications
You must be signed in to change notification settings - Fork 399
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add toBePartiallyChecked matcher (#249)
* feat: add toBePartiallyChecked matcher * refactor: don't check the aria-checked in isValidAriaElement
- Loading branch information
Showing
4 changed files
with
222 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import {render} from './helpers/test-utils' | ||
|
||
describe('.toBePartiallyChecked', () => { | ||
test('handles input checkbox with aria-checked', () => { | ||
const {queryByTestId} = render(` | ||
<input type="checkbox" aria-checked="mixed" data-testid="checkbox-mixed" /> | ||
<input type="checkbox" checked data-testid="checkbox-checked" /> | ||
<input type="checkbox" data-testid="checkbox-unchecked" /> | ||
`) | ||
|
||
expect(queryByTestId('checkbox-mixed')).toBePartiallyChecked() | ||
expect(queryByTestId('checkbox-checked')).not.toBePartiallyChecked() | ||
expect(queryByTestId('checkbox-unchecked')).not.toBePartiallyChecked() | ||
}) | ||
|
||
test('handles input checkbox set as indeterminate', () => { | ||
const {queryByTestId} = render(` | ||
<input type="checkbox" data-testid="checkbox-mixed" /> | ||
<input type="checkbox" checked data-testid="checkbox-checked" /> | ||
<input type="checkbox" data-testid="checkbox-unchecked" /> | ||
`) | ||
|
||
queryByTestId('checkbox-mixed').indeterminate = true | ||
|
||
expect(queryByTestId('checkbox-mixed')).toBePartiallyChecked() | ||
expect(queryByTestId('checkbox-checked')).not.toBePartiallyChecked() | ||
expect(queryByTestId('checkbox-unchecked')).not.toBePartiallyChecked() | ||
}) | ||
|
||
test('handles element with role="checkbox"', () => { | ||
const {queryByTestId} = render(` | ||
<div role="checkbox" aria-checked="mixed" data-testid="aria-checkbox-mixed" /> | ||
<div role="checkbox" aria-checked="true" data-testid="aria-checkbox-checked" /> | ||
<div role="checkbox" aria-checked="false" data-testid="aria-checkbox-unchecked" /> | ||
`) | ||
|
||
expect(queryByTestId('aria-checkbox-mixed')).toBePartiallyChecked() | ||
expect(queryByTestId('aria-checkbox-checked')).not.toBePartiallyChecked() | ||
expect(queryByTestId('aria-checkbox-unchecked')).not.toBePartiallyChecked() | ||
}) | ||
|
||
test('throws when input checkbox is mixed but expected not to be', () => { | ||
const {queryByTestId} = render( | ||
`<input type="checkbox" aria-checked="mixed" data-testid="checkbox-mixed" />`, | ||
) | ||
|
||
expect(() => | ||
expect(queryByTestId('checkbox-mixed')).not.toBePartiallyChecked(), | ||
).toThrowError() | ||
}) | ||
|
||
test('throws when input checkbox is indeterminate but expected not to be', () => { | ||
const {queryByTestId} = render( | ||
`<input type="checkbox" data-testid="checkbox-mixed" />`, | ||
) | ||
|
||
queryByTestId('checkbox-mixed').indeterminate = true | ||
|
||
expect(() => | ||
expect(queryByTestId('input-mixed')).not.toBePartiallyChecked(), | ||
).toThrowError() | ||
}) | ||
|
||
test('throws when input checkbox is not checked but expected to be', () => { | ||
const {queryByTestId} = render( | ||
`<input type="checkbox" data-testid="checkbox-empty" />`, | ||
) | ||
|
||
expect(() => | ||
expect(queryByTestId('checkbox-empty')).toBePartiallyChecked(), | ||
).toThrowError() | ||
}) | ||
|
||
test('throws when element with role="checkbox" is partially checked but expected not to be', () => { | ||
const {queryByTestId} = render( | ||
`<div role="checkbox" aria-checked="mixed" data-testid="aria-checkbox-mixed" />`, | ||
) | ||
|
||
expect(() => | ||
expect(queryByTestId('aria-checkbox-mixed')).not.toBePartiallyChecked(), | ||
).toThrowError() | ||
}) | ||
|
||
test('throws when element with role="checkbox" is checked but expected to be partially checked', () => { | ||
const {queryByTestId} = render( | ||
`<div role="checkbox" aria-checked="true" data-testid="aria-checkbox-checked" />`, | ||
) | ||
|
||
expect(() => | ||
expect(queryByTestId('aria-checkbox-checked')).toBePartiallyChecked(), | ||
).toThrowError() | ||
}) | ||
|
||
test('throws when element with role="checkbox" is not checked but expected to be', () => { | ||
const {queryByTestId} = render( | ||
`<div role="checkbox" aria-checked="false" data-testid="aria-checkbox" />`, | ||
) | ||
|
||
expect(() => | ||
expect(queryByTestId('aria-checkbox')).toBePartiallyChecked(), | ||
).toThrowError() | ||
}) | ||
|
||
test('throws when element with role="checkbox" has an invalid aria-checked attribute', () => { | ||
const {queryByTestId} = render( | ||
`<div role="checkbox" aria-checked="something" data-testid="aria-checkbox-invalid" />`, | ||
) | ||
|
||
expect(() => | ||
expect(queryByTestId('aria-checkbox-invalid')).toBePartiallyChecked(), | ||
).toThrowError() | ||
}) | ||
|
||
test('throws when the element is not a checkbox', () => { | ||
const {queryByTestId} = render(`<select data-testid="select"></select>`) | ||
expect(() => | ||
expect(queryByTestId('select')).toBePartiallyChecked(), | ||
).toThrowError( | ||
'only inputs with type="checkbox" or elements with role="checkbox" and a valid aria-checked attribute can be used with .toBePartiallyChecked(). Use .toHaveValue() instead', | ||
) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import {matcherHint, printReceived} from 'jest-matcher-utils' | ||
import {checkHtmlElement} from './utils' | ||
|
||
export function toBePartiallyChecked(element) { | ||
checkHtmlElement(element, toBePartiallyChecked, this) | ||
|
||
const isValidInput = () => { | ||
return ( | ||
element.tagName.toLowerCase() === 'input' && element.type === 'checkbox' | ||
) | ||
} | ||
|
||
const isValidAriaElement = () => { | ||
return element.getAttribute('role') === 'checkbox' | ||
} | ||
|
||
if (!isValidInput() && !isValidAriaElement()) { | ||
return { | ||
pass: false, | ||
message: () => | ||
'only inputs with type="checkbox" or elements with role="checkbox" and a valid aria-checked attribute can be used with .toBePartiallyChecked(). Use .toHaveValue() instead', | ||
} | ||
} | ||
|
||
const isPartiallyChecked = () => { | ||
const isAriaMixed = element.getAttribute('aria-checked') === 'mixed' | ||
|
||
if (isValidInput()) { | ||
return element.indeterminate || isAriaMixed | ||
} | ||
|
||
return isAriaMixed | ||
} | ||
|
||
return { | ||
pass: isPartiallyChecked(), | ||
message: () => { | ||
const is = isPartiallyChecked() ? 'is' : 'is not' | ||
return [ | ||
matcherHint( | ||
`${this.isNot ? '.not' : ''}.toBePartiallyChecked`, | ||
'element', | ||
'', | ||
), | ||
'', | ||
`Received element ${is} partially checked:`, | ||
` ${printReceived(element.cloneNode(false))}`, | ||
].join('\n') | ||
}, | ||
} | ||
} |