Skip to content

Commit 1240b85

Browse files
committed
jest matchers
1 parent 39222fa commit 1240b85

File tree

2 files changed

+108
-4
lines changed

2 files changed

+108
-4
lines changed

website/docs/13.x/docs/guides/llm-guidelines.mdx

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,63 @@ Actionable guidelines for writing tests with React Native Testing Library (RNTL)
1414

1515
## Assertions
1616

17-
- **Use RNTL matchers**: `toBeOnTheScreen()`, `toBeDisabled()`, `toHaveTextContent()`, `toHaveAccessibleName()`
18-
- **Don't assert on props directly** - use semantic matchers instead
17+
- **Use RNTL matchers** - prefer semantic matchers over prop assertions
1918
- **Combine queries with matchers**: `expect(screen.getByText('Hello')).toBeOnTheScreen()`
2019
- **No redundant null checks** - `getBy*` already throws if not found
2120

21+
## Jest Matchers Reference
22+
23+
| Matcher | Description |
24+
|---------|-------------|
25+
| `toBeOnTheScreen()` | Element is present in the element tree |
26+
| `toBeVisible()` | Element is visible (checks style, `aria-hidden`, `accessibilityElementsHidden`, ancestors) |
27+
| `toBeEmptyElement()` | Element has no children or text content |
28+
| `toContainElement(element)` | Element contains another element |
29+
| `toBeEnabled()` | Element is not disabled (checks `aria-disabled`, `accessibilityState`, ancestors) |
30+
| `toBeDisabled()` | Element has `aria-disabled` or `accessibilityState={{ disabled: true }}` (checks ancestors) |
31+
| `toBeBusy()` | Element has `aria-busy` or `accessibilityState={{ busy: true }}` |
32+
| `toBeChecked()` | Element has `aria-checked` or `accessibilityState={{ checked: true }}` |
33+
| `toBePartiallyChecked()` | Element has `aria-checked="mixed"` or `accessibilityState={{ checked: 'mixed' }}` |
34+
| `toBeSelected()` | Element has `aria-selected` or `accessibilityState={{ selected: true }}` |
35+
| `toBeExpanded()` | Element has `aria-expanded` or `accessibilityState={{ expanded: true }}` |
36+
| `toBeCollapsed()` | Element has `aria-expanded={false}` or `accessibilityState={{ expanded: false }}` |
37+
| `toHaveTextContent(text)` | Element has matching text content |
38+
| `toHaveDisplayValue(value)` | TextInput has matching display value |
39+
| `toHaveAccessibleName(name?)` | Element has matching `aria-label`, `accessibilityLabel`, or text content |
40+
| `toHaveAccessibilityValue(value)` | Element has matching `aria-value*` or `accessibilityValue` |
41+
| `toHaveStyle(style)` | Element has matching style |
42+
| `toHaveProp(name, value?)` | Element has prop (use semantic matchers when possible) |
43+
44+
## User Interactions
45+
46+
**Prefer `userEvent`** over `fireEvent` for realistic user interaction simulation. `userEvent` triggers the complete event sequence that real users would produce.
47+
48+
### userEvent (Preferred, Async)
49+
50+
```tsx
51+
const user = userEvent.setup();
52+
```
53+
54+
| Method | Description |
55+
|--------|-------------|
56+
| `await user.press(element)` | Press an element (triggers `pressIn`, `pressOut`, `press`) |
57+
| `await user.longPress(element, options?)` | Long press with optional `{ duration }` |
58+
| `await user.type(element, text, options?)` | Type into TextInput (triggers `focus`, `keyPress`, `change`, `changeText` per char) |
59+
| `await user.clear(element)` | Clear TextInput (select all + backspace) |
60+
| `await user.paste(element, text)` | Paste text into TextInput |
61+
| `await user.scrollTo(element, options)` | Scroll a ScrollView with `{ y }` or `{ x }` offset |
62+
63+
### fireEvent (Low-level, Sync in v13)
64+
65+
Use only when `userEvent` doesn't support the event or when you need direct control.
66+
67+
| Method | Description |
68+
|--------|-------------|
69+
| `fireEvent(element, eventName, ...data)` | Fire any event by name |
70+
| `fireEvent.press(element)` | Fire `onPress` only (no `pressIn`/`pressOut`) |
71+
| `fireEvent.changeText(element, text)` | Fire `onChangeText` directly |
72+
| `fireEvent.scroll(element, eventData)` | Fire `onScroll` with event data |
73+
2274
## Sync vs Async APIs (v13)
2375

2476
- **`render()`, `fireEvent.*`, `renderHook()` are synchronous** - no `await` needed

website/docs/14.x/docs/guides/llm-guidelines.mdx

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,63 @@ Actionable guidelines for writing tests with React Native Testing Library (RNTL)
1414

1515
## Assertions
1616

17-
- **Use RNTL matchers**: `toBeOnTheScreen()`, `toBeDisabled()`, `toHaveTextContent()`, `toHaveAccessibleName()`
18-
- **Don't assert on props directly** - use semantic matchers instead
17+
- **Use RNTL matchers** - prefer semantic matchers over prop assertions
1918
- **Combine queries with matchers**: `expect(screen.getByText('Hello')).toBeOnTheScreen()`
2019
- **No redundant null checks** - `getBy*` already throws if not found
2120

21+
## Jest Matchers Reference
22+
23+
| Matcher | Description |
24+
|---------|-------------|
25+
| `toBeOnTheScreen()` | Element is present in the element tree |
26+
| `toBeVisible()` | Element is visible (checks style, `aria-hidden`, `accessibilityElementsHidden`, ancestors) |
27+
| `toBeEmptyElement()` | Element has no children or text content |
28+
| `toContainElement(element)` | Element contains another element |
29+
| `toBeEnabled()` | Element is not disabled (checks `aria-disabled`, `accessibilityState`, ancestors) |
30+
| `toBeDisabled()` | Element has `aria-disabled` or `accessibilityState={{ disabled: true }}` (checks ancestors) |
31+
| `toBeBusy()` | Element has `aria-busy` or `accessibilityState={{ busy: true }}` |
32+
| `toBeChecked()` | Element has `aria-checked` or `accessibilityState={{ checked: true }}` |
33+
| `toBePartiallyChecked()` | Element has `aria-checked="mixed"` or `accessibilityState={{ checked: 'mixed' }}` |
34+
| `toBeSelected()` | Element has `aria-selected` or `accessibilityState={{ selected: true }}` |
35+
| `toBeExpanded()` | Element has `aria-expanded` or `accessibilityState={{ expanded: true }}` |
36+
| `toBeCollapsed()` | Element has `aria-expanded={false}` or `accessibilityState={{ expanded: false }}` |
37+
| `toHaveTextContent(text)` | Element has matching text content |
38+
| `toHaveDisplayValue(value)` | TextInput has matching display value |
39+
| `toHaveAccessibleName(name?)` | Element has matching `aria-label`, `accessibilityLabel`, or text content |
40+
| `toHaveAccessibilityValue(value)` | Element has matching `aria-value*` or `accessibilityValue` |
41+
| `toHaveStyle(style)` | Element has matching style |
42+
| `toHaveProp(name, value?)` | Element has prop (use semantic matchers when possible) |
43+
44+
## User Interactions
45+
46+
**Prefer `userEvent`** over `fireEvent` for realistic user interaction simulation. `userEvent` triggers the complete event sequence that real users would produce.
47+
48+
### userEvent (Preferred)
49+
50+
```tsx
51+
const user = userEvent.setup();
52+
```
53+
54+
| Method | Description |
55+
|--------|-------------|
56+
| `user.press(element)` | Press an element (triggers `pressIn`, `pressOut`, `press`) |
57+
| `user.longPress(element, options?)` | Long press with optional `{ duration }` |
58+
| `user.type(element, text, options?)` | Type into TextInput (triggers `focus`, `keyPress`, `change`, `changeText` per char) |
59+
| `user.clear(element)` | Clear TextInput (select all + backspace) |
60+
| `user.paste(element, text)` | Paste text into TextInput |
61+
| `user.scrollTo(element, options)` | Scroll a ScrollView with `{ y }` or `{ x }` offset |
62+
63+
### fireEvent (Low-level)
64+
65+
Use only when `userEvent` doesn't support the event or when you need direct control.
66+
67+
| Method | Description |
68+
|--------|-------------|
69+
| `fireEvent(element, eventName, ...data)` | Fire any event by name |
70+
| `fireEvent.press(element)` | Fire `onPress` only (no `pressIn`/`pressOut`) |
71+
| `fireEvent.changeText(element, text)` | Fire `onChangeText` directly |
72+
| `fireEvent.scroll(element, eventData)` | Fire `onScroll` with event data |
73+
2274
## Async/Await (v14)
2375

2476
- **Always `await`**: `render()`, `fireEvent.*`, `renderHook()`, `userEvent.*`

0 commit comments

Comments
 (0)