-
Notifications
You must be signed in to change notification settings - Fork 272
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: toHaveAccessibleName matcher (#1509)
* feat: toHaveAccessibleName matcher * feat: toHaveAccessibleName matcher * feat: toHaveAccessibleName matcher * refactor: check logic * chore: fix lint * refactor: tests * chore: test tweaks --------- Co-authored-by: Maciej Jastrzębski <[email protected]>
- Loading branch information
1 parent
b019479
commit 2ada536
Showing
7 changed files
with
214 additions
and
2 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
134 changes: 134 additions & 0 deletions
134
src/matchers/__tests__/to-have-accessible-name.test.tsx
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,134 @@ | ||
import * as React from 'react'; | ||
import { View, Text, TextInput } from 'react-native'; | ||
import { render, screen } from '../..'; | ||
import '../extend-expect'; | ||
|
||
test('toHaveAccessibleName() handles view with "accessibilityLabel" prop', () => { | ||
render(<View testID="view" accessibilityLabel="Test label" />); | ||
const element = screen.getByTestId('view'); | ||
expect(element).toHaveAccessibleName('Test label'); | ||
expect(element).not.toHaveAccessibleName('Other label'); | ||
}); | ||
|
||
test('toHaveAccessibleName() handles view with "aria-label" prop', () => { | ||
render(<View testID="view" aria-label="Test label" />); | ||
const element = screen.getByTestId('view'); | ||
expect(element).toHaveAccessibleName('Test label'); | ||
expect(element).not.toHaveAccessibleName('Other label'); | ||
}); | ||
|
||
test('toHaveAccessibleName() handles view with "accessibilityLabelledBy" prop', async () => { | ||
render( | ||
<View> | ||
<Text nativeID="label">External label</Text> | ||
<TextInput testID="input" accessibilityLabelledBy="label" /> | ||
</View> | ||
); | ||
|
||
const element = screen.getByTestId('input'); | ||
expect(element).toHaveAccessibleName('External label'); | ||
expect(element).not.toHaveAccessibleName('Other label'); | ||
}); | ||
|
||
test('toHaveAccessibleName() handles nested "accessibilityLabelledBy"', async () => { | ||
render( | ||
<> | ||
<View nativeID="label"> | ||
<Text>External label</Text> | ||
</View> | ||
<TextInput testID="input" accessibilityLabelledBy="label" /> | ||
</> | ||
); | ||
|
||
const element = screen.getByTestId('input'); | ||
expect(element).toHaveAccessibleName('External label'); | ||
expect(element).not.toHaveAccessibleName('Other label'); | ||
}); | ||
|
||
test('toHaveAccessibleName() handles view with nested "accessibilityLabelledBy" with no text', async () => { | ||
render( | ||
<> | ||
<View nativeID="label"> | ||
<View /> | ||
</View> | ||
<TextInput testID="text-input" accessibilityLabelledBy="label" /> | ||
</> | ||
); | ||
|
||
const element = screen.getByTestId('text-input'); | ||
expect(element).not.toHaveAccessibleName(); | ||
}); | ||
|
||
test('toHaveAccessibleName() handles view with "aria-labelledby" prop', async () => { | ||
render( | ||
<View> | ||
<Text nativeID="label">External label</Text> | ||
<TextInput testID="input" aria-labelledby="label" /> | ||
</View> | ||
); | ||
|
||
const element = screen.getByTestId('input'); | ||
expect(element).toHaveAccessibleName('External label'); | ||
expect(element).not.toHaveAccessibleName('Other label'); | ||
}); | ||
|
||
test('toHaveAccessibleName() handles view with implicit accessible name', () => { | ||
render(<Text testID="view">Text</Text>); | ||
const element = screen.getByTestId('view'); | ||
expect(element).toHaveAccessibleName('Text'); | ||
expect(element).not.toHaveAccessibleName('Other text'); | ||
}); | ||
|
||
test('toHaveAccessibleName() supports calling without expected name', () => { | ||
render(<View testID="view" accessibilityLabel="Test label" />); | ||
const element = screen.getByTestId('view'); | ||
|
||
expect(element).toHaveAccessibleName(); | ||
expect(() => expect(element).not.toHaveAccessibleName()) | ||
.toThrowErrorMatchingInlineSnapshot(` | ||
"expect(element).not.toHaveAccessibleName() | ||
Expected element not to have accessible name: | ||
undefined | ||
Received: | ||
Test label" | ||
`); | ||
}); | ||
|
||
test('toHaveAccessibleName() handles a view without name when called without expected name', () => { | ||
render(<View testID="view" />); | ||
const element = screen.getByTestId('view'); | ||
|
||
expect(element).not.toHaveAccessibleName(); | ||
expect(() => expect(element).toHaveAccessibleName()) | ||
.toThrowErrorMatchingInlineSnapshot(` | ||
"expect(element).toHaveAccessibleName() | ||
Expected element to have accessible name: | ||
undefined | ||
Received: | ||
" | ||
`); | ||
}); | ||
|
||
it('toHaveAccessibleName() rejects non-host element', () => { | ||
const nonElement = 'This is not a ReactTestInstance'; | ||
|
||
expect(() => expect(nonElement).toHaveAccessibleName()) | ||
.toThrowErrorMatchingInlineSnapshot(` | ||
"expect(received).toHaveAccessibleName() | ||
received value must be a host element. | ||
Received has type: string | ||
Received has value: "This is not a ReactTestInstance"" | ||
`); | ||
|
||
expect(() => expect(nonElement).not.toHaveAccessibleName()) | ||
.toThrowErrorMatchingInlineSnapshot(` | ||
"expect(received).not.toHaveAccessibleName() | ||
received value must be a host element. | ||
Received has type: string | ||
Received has value: "This is not a ReactTestInstance"" | ||
`); | ||
}); |
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
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,53 @@ | ||
import type { ReactTestInstance } from 'react-test-renderer'; | ||
import { matcherHint } from 'jest-matcher-utils'; | ||
import { getAccessibleName } from '../helpers/accessiblity'; | ||
import { TextMatch, TextMatchOptions, matches } from '../matches'; | ||
import { checkHostElement, formatMessage } from './utils'; | ||
|
||
export function toHaveAccessibleName( | ||
this: jest.MatcherContext, | ||
element: ReactTestInstance, | ||
expectedName?: TextMatch, | ||
options?: TextMatchOptions | ||
) { | ||
checkHostElement(element, toHaveAccessibleName, this); | ||
|
||
const receivedName = getAccessibleName(element); | ||
const missingExpectedValue = arguments.length === 1; | ||
|
||
let pass = false; | ||
if (missingExpectedValue) { | ||
pass = receivedName !== ''; | ||
} else { | ||
pass = | ||
expectedName != null | ||
? matches( | ||
expectedName, | ||
receivedName, | ||
options?.normalizer, | ||
options?.exact | ||
) | ||
: false; | ||
} | ||
|
||
return { | ||
pass, | ||
message: () => { | ||
return [ | ||
formatMessage( | ||
matcherHint( | ||
`${this.isNot ? '.not' : ''}.toHaveAccessibleName`, | ||
'element', | ||
'' | ||
), | ||
`Expected element ${ | ||
this.isNot ? 'not to' : 'to' | ||
} have accessible name`, | ||
expectedName, | ||
'Received', | ||
receivedName | ||
), | ||
].join('\n'); | ||
}, | ||
}; | ||
} |
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