-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: toHaveAccessibilityValue() matcher (#127)
- Loading branch information
1 parent
f050c41
commit eeb35d1
Showing
4 changed files
with
197 additions
and
6 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,24 @@ | ||
import type { AccessibilityState, ImageStyle, StyleProp, TextStyle, ViewStyle } from 'react-native'; | ||
import type { ReactTestInstance } from 'react-test-renderer'; | ||
import type { AccessibilityValueMatcher } from './src/to-have-accessibility-value'; | ||
|
||
declare global { | ||
namespace jest { | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
interface Matchers<R, T> { | ||
toBeDisabled(): R; | ||
toContainElement(element: ReactTestInstance | null): R; | ||
toBeEmptyElement(): R; | ||
toHaveProp(attr: string, value?: unknown): R; | ||
toHaveTextContent(text: string | RegExp, options?: { normalizeWhitespace: boolean }): R; | ||
toBeEnabled(): R; | ||
toBeVisible(): R; | ||
toContainElement(element: ReactTestInstance | null): R; | ||
toHaveTextContent(text: string | RegExp, options?: { normalizeWhitespace: boolean }): R; | ||
toHaveProp(attr: string, value?: unknown): R; | ||
toHaveStyle(style: StyleProp<ViewStyle | TextStyle | ImageStyle>): R; | ||
toHaveAccessibilityState(state: AccessibilityState): R; | ||
toHaveAccessibilityValue(state: AccessibilityValueMatcher): R; | ||
|
||
/** @deprecated This function has been renamed to `toBeEmptyElement`. */ | ||
toBeEmpty(): R; | ||
toBeVisible(): R; | ||
|
||
toHaveAccessibilityState(state: AccessibilityState): R; | ||
} | ||
} | ||
} |
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,137 @@ | ||
import * as React from 'react'; | ||
import { View } from 'react-native'; | ||
import { render } from '@testing-library/react-native'; | ||
|
||
test('.toHaveAccessibilityValue to handle min, max, now', () => { | ||
const { getByTestId } = render( | ||
<View> | ||
<View testID="min" accessibilityValue={{ min: 1 }} /> | ||
<View testID="max" accessibilityValue={{ max: 10 }} /> | ||
<View testID="now" accessibilityValue={{ now: 5 }} /> | ||
<View testID="min-max" accessibilityValue={{ min: 2, max: 5 }} /> | ||
<View testID="min-now" accessibilityValue={{ min: 2, now: 3 }} /> | ||
<View testID="max-now" accessibilityValue={{ max: 5, now: 4 }} /> | ||
<View testID="min-max-now" accessibilityValue={{ min: 2, max: 5, now: 3 }} /> | ||
</View>, | ||
); | ||
|
||
expect(getByTestId('min')).toHaveAccessibilityValue({ min: 1 }); | ||
expect(getByTestId('min')).not.toHaveAccessibilityValue({ min: 2 }); | ||
expect(() => expect(getByTestId('min')).toHaveAccessibilityValue({ min: 2 })) | ||
.toThrowErrorMatchingInlineSnapshot(` | ||
"expect(element).toHaveAccessibilityValue({"min": 2}) | ||
Expected the element to have accessibility value: | ||
{"min": 2} | ||
Received element with accessibility value: | ||
{"min": 1}" | ||
`); | ||
|
||
expect(getByTestId('max')).toHaveAccessibilityValue({ max: 10 }); | ||
expect(getByTestId('max')).not.toHaveAccessibilityValue({ max: 5 }); | ||
expect(() => expect(getByTestId('max')).toHaveAccessibilityValue({ max: 5 })) | ||
.toThrowErrorMatchingInlineSnapshot(` | ||
"expect(element).toHaveAccessibilityValue({"max": 5}) | ||
Expected the element to have accessibility value: | ||
{"max": 5} | ||
Received element with accessibility value: | ||
{"max": 10}" | ||
`); | ||
|
||
expect(getByTestId('now')).toHaveAccessibilityValue({ now: 5 }); | ||
expect(getByTestId('now')).not.toHaveAccessibilityValue({ now: 3 }); | ||
expect(() => expect(getByTestId('now')).toHaveAccessibilityValue({ now: 3 })) | ||
.toThrowErrorMatchingInlineSnapshot(` | ||
"expect(element).toHaveAccessibilityValue({"now": 3}) | ||
Expected the element to have accessibility value: | ||
{"now": 3} | ||
Received element with accessibility value: | ||
{"now": 5}" | ||
`); | ||
|
||
expect(getByTestId('min-max')).toHaveAccessibilityValue({ min: 2, max: 5 }); | ||
expect(getByTestId('min-max')).not.toHaveAccessibilityValue({ min: 3, max: 5 }); | ||
expect(getByTestId('min-max')).not.toHaveAccessibilityValue({ min: 2, max: 4 }); | ||
expect(getByTestId('min-max')).not.toHaveAccessibilityValue({ min: 3, max: 4 }); | ||
|
||
expect(getByTestId('min-now')).toHaveAccessibilityValue({ min: 2, now: 3 }); | ||
expect(getByTestId('min-now')).not.toHaveAccessibilityValue({ min: 1, now: 3 }); | ||
expect(getByTestId('min-now')).not.toHaveAccessibilityValue({ min: 2, now: 4 }); | ||
expect(getByTestId('min-now')).not.toHaveAccessibilityValue({ min: 0, now: 4 }); | ||
|
||
expect(getByTestId('max-now')).toHaveAccessibilityValue({ max: 5, now: 4 }); | ||
expect(getByTestId('max-now')).not.toHaveAccessibilityValue({ max: 6, now: 4 }); | ||
expect(getByTestId('max-now')).not.toHaveAccessibilityValue({ max: 5, now: 3 }); | ||
expect(getByTestId('max-now')).not.toHaveAccessibilityValue({ max: 6, now: 3 }); | ||
|
||
expect(getByTestId('min-max-now')).toHaveAccessibilityValue({ min: 2, max: 5, now: 3 }); | ||
expect(getByTestId('min-max-now')).not.toHaveAccessibilityValue({ min: 1, max: 5, now: 3 }); | ||
expect(getByTestId('min-max-now')).not.toHaveAccessibilityValue({ min: 2, max: 6, now: 3 }); | ||
expect(getByTestId('min-max-now')).not.toHaveAccessibilityValue({ min: 2, max: 5, now: 4 }); | ||
}); | ||
|
||
test('.toHaveAccessibilityValue to handle string text', () => { | ||
const { getByTestId } = render( | ||
<View> | ||
<View testID="text" accessibilityValue={{ text: 'Hello world!' }} /> | ||
<View testID="text-now" accessibilityValue={{ text: 'Hello world!', now: 5 }} /> | ||
</View>, | ||
); | ||
|
||
expect(getByTestId('text')).toHaveAccessibilityValue({ text: 'Hello world!' }); | ||
expect(getByTestId('text')).not.toHaveAccessibilityValue({ text: 'Hello other!' }); | ||
expect(() => expect(getByTestId('text')).toHaveAccessibilityValue({ text: 'Hello other!' })) | ||
.toThrowErrorMatchingInlineSnapshot(` | ||
"expect(element).toHaveAccessibilityValue({"text": "Hello other!"}) | ||
Expected the element to have accessibility value: | ||
{"text": "Hello other!"} | ||
Received element with accessibility value: | ||
{"text": "Hello world!"}" | ||
`); | ||
}); | ||
|
||
test('.toHaveAccessibilityValue to handle regex text', () => { | ||
const { getByTestId } = render( | ||
<View> | ||
<View testID="text" accessibilityValue={{ text: 'Hello world!' }} /> | ||
<View testID="text-now" accessibilityValue={{ text: 'Hello world!', now: 5 }} /> | ||
</View>, | ||
); | ||
|
||
expect(getByTestId('text')).toHaveAccessibilityValue({ text: /hello/i }); | ||
expect(getByTestId('text')).not.toHaveAccessibilityValue({ text: /other/i }); | ||
expect(() => expect(getByTestId('text')).toHaveAccessibilityValue({ text: /other/i })) | ||
.toThrowErrorMatchingInlineSnapshot(` | ||
"expect(element).toHaveAccessibilityValue({"text": /other/i}) | ||
Expected the element to have accessibility value: | ||
{"text": /other/i} | ||
Received element with accessibility value: | ||
{"text": "Hello world!"}" | ||
`); | ||
|
||
expect(getByTestId('text-now')).toHaveAccessibilityValue({ text: /hello/i, now: 5 }); | ||
expect(getByTestId('text-now')).not.toHaveAccessibilityValue({ text: /hello/i, now: 3 }); | ||
expect(getByTestId('text-now')).not.toHaveAccessibilityValue({ text: /other/i, now: 5 }); | ||
expect(() => expect(getByTestId('text-now')).toHaveAccessibilityValue({ text: /hello/i, now: 3 })) | ||
.toThrowErrorMatchingInlineSnapshot(` | ||
"expect(element).toHaveAccessibilityValue({"now": 3, "text": /hello/i}) | ||
Expected the element to have accessibility value: | ||
{"now": 3, "text": /hello/i} | ||
Received element with accessibility value: | ||
{"now": 5, "text": "Hello world!"}" | ||
`); | ||
expect(() => expect(getByTestId('text-now')).toHaveAccessibilityValue({ text: /other/i, now: 5 })) | ||
.toThrowErrorMatchingInlineSnapshot(` | ||
"expect(element).toHaveAccessibilityValue({"now": 5, "text": /other/i}) | ||
Expected the element to have accessibility value: | ||
{"now": 5, "text": /other/i} | ||
Received element with accessibility value: | ||
{"now": 5, "text": "Hello world!"}" | ||
`); | ||
}); |
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 type { AccessibilityValue } from 'react-native'; | ||
import type { ReactTestInstance } from 'react-test-renderer'; | ||
import { matcherHint, stringify } from 'jest-matcher-utils'; | ||
import { checkReactElement, getMessage, matches } from './utils'; | ||
|
||
export interface AccessibilityValueMatcher { | ||
min?: number; | ||
max?: number; | ||
now?: number; | ||
text?: string | RegExp; | ||
} | ||
|
||
export function toHaveAccessibilityValue( | ||
this: jest.MatcherContext, | ||
element: ReactTestInstance, | ||
expectedValue: AccessibilityValueMatcher, | ||
) { | ||
checkReactElement(element, toHaveAccessibilityValue, this); | ||
|
||
const value = element.props.accessibilityValue; | ||
|
||
return { | ||
pass: matchAccessibilityValue(value, expectedValue), | ||
message: () => { | ||
const matcher = matcherHint( | ||
`${this.isNot ? '.not' : ''}.toHaveAccessibilityValue`, | ||
'element', | ||
stringify(expectedValue), | ||
); | ||
return getMessage( | ||
matcher, | ||
`Expected the element ${this.isNot ? 'not to' : 'to'} have accessibility value`, | ||
stringify(expectedValue), | ||
'Received element with accessibility value', | ||
stringify(value), | ||
); | ||
}, | ||
}; | ||
} | ||
|
||
function matchAccessibilityValue( | ||
value: AccessibilityValue, | ||
matcher: AccessibilityValueMatcher, | ||
): boolean { | ||
return ( | ||
(matcher.min === undefined || matcher.min === value.min) && | ||
(matcher.max === undefined || matcher.max === value.max) && | ||
(matcher.now === undefined || matcher.now === value.now) && | ||
(matcher.text === undefined || matches(value.text ?? '', matcher.text)) | ||
); | ||
} |