Skip to content

Commit d5f1086

Browse files
authored
chore: add skills (#84)
1 parent 93c3e1f commit d5f1086

File tree

5 files changed

+357
-1
lines changed

5 files changed

+357
-1
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
---
2+
name: react-native-harness
3+
description: Write and debug React Native Harness tests for app code. Use when the user asks to create or fix tests that import from react-native-harness, mock modules, spy on functions, render React Native components on-device, use setupFiles or setupFilesAfterEnv, or add optional UI tests with @react-native-harness/ui.
4+
---
5+
6+
# React Native Harness
7+
8+
React Native Harness tests use Jest-style APIs but run in the app or browser environment instead of plain Node.
9+
10+
## Test File Conventions
11+
12+
- Use `.harness.[jt]s` or `.harness.[jt]sx` test files.
13+
- Import test APIs from `react-native-harness`.
14+
- Put tests inside `describe(...)` blocks.
15+
- Use `@react-native-harness/ui` only when the test needs queries, interactions, or screenshots.
16+
17+
## Default Test Shape
18+
19+
```ts
20+
import { describe, test, expect } from 'react-native-harness';
21+
22+
describe('Feature name', () => {
23+
test('does something', () => {
24+
expect(true).toBe(true);
25+
});
26+
});
27+
```
28+
29+
Prefer these public APIs when writing tests:
30+
31+
- Test structure: `describe`, `test`, `it`, `beforeEach`, `afterEach`, `beforeAll`, `afterAll`
32+
- Focus and pending helpers: `test.skip`, `test.only`, `test.todo`, `describe.skip`, `describe.only`
33+
- Assertions: `expect`
34+
- Mocking and spying: `fn`, `spyOn`, `clearAllMocks`, `resetAllMocks`, `restoreAllMocks`
35+
- Module mocking: `mock`, `requireActual`, `unmock`, `resetModules`
36+
- Async polling: `waitFor`, `waitUntil`
37+
38+
Test functions may be async. If a test returns a promise, Harness waits for it; if that promise rejects, the test fails.
39+
40+
## Mocking And Spying
41+
42+
Use `fn()` for standalone mock functions and `spyOn()` for existing methods.
43+
44+
- `expect` follows Vitest's API.
45+
- `expect.soft(...)` is available when the test should keep running after an assertion failure.
46+
- `clearAllMocks()` clears call history but keeps implementations.
47+
- `resetAllMocks()` clears call history and resets mock implementations.
48+
- `restoreAllMocks()` restores spied methods to their original implementations.
49+
50+
Typical cleanup:
51+
52+
```ts
53+
import { afterEach, clearAllMocks } from 'react-native-harness';
54+
55+
afterEach(() => {
56+
clearAllMocks();
57+
});
58+
```
59+
60+
## Module Mocking
61+
62+
Use module mocking when the test must replace an entire module or specific exports.
63+
64+
- `mock(moduleId, factory)` registers a lazy mock factory.
65+
- `requireActual(moduleId)` is the safe path for partial mocks.
66+
- `unmock(moduleId)` removes a mock for one module.
67+
- `resetModules()` clears module mocks and module cache state.
68+
69+
Recommended pattern:
70+
71+
```ts
72+
import {
73+
afterEach,
74+
describe,
75+
expect,
76+
mock,
77+
requireActual,
78+
resetModules,
79+
test,
80+
} from 'react-native-harness';
81+
82+
afterEach(() => {
83+
resetModules();
84+
});
85+
86+
describe('partial mock', () => {
87+
test('overrides one export but keeps the rest', () => {
88+
mock('react-native', () => {
89+
const actual = requireActual('react-native');
90+
const proto = Object.getPrototypeOf(actual);
91+
const descriptors = Object.getOwnPropertyDescriptors(actual);
92+
const mocked = Object.create(proto, descriptors);
93+
94+
Object.defineProperty(mocked, 'Platform', {
95+
get() {
96+
return {
97+
...actual.Platform,
98+
OS: 'mockOS',
99+
};
100+
},
101+
});
102+
103+
return mocked;
104+
});
105+
106+
const rn = require('react-native');
107+
expect(rn.Platform.OS).toBe('mockOS');
108+
});
109+
});
110+
```
111+
112+
- Always clean up module mocks with `resetModules()` in `afterEach` when tests mock modules.
113+
- Use `requireActual()` for partial mocks so unrelated exports stay real.
114+
- For `react-native`, preserve property descriptors when partially mocking to avoid triggering lazy getters too early.
115+
- Remember that module factories are evaluated when the module is first required.
116+
117+
## Async Behavior
118+
119+
Use:
120+
121+
- `waitFor(...)` when the callback should eventually succeed or stop throwing
122+
- `waitUntil(...)` when the callback should eventually return a truthy value
123+
124+
Both support timeout control. Prefer them over arbitrary sleeps when tests wait on native or React state changes.
125+
126+
## UI Testing
127+
128+
UI testing is opt-in and uses `render(...)` from `react-native-harness` together with `@react-native-harness/ui`.
129+
130+
Use `render(...)` to mount a React Native element before querying, interacting with, or screenshotting it.
131+
132+
- `render(...)` is async
133+
- `rerender(...)` is async
134+
- `unmount()` is optional because cleanup happens automatically after each test
135+
- `wrapper` is the right tool for providers and shared context
136+
- Rendered UI appears as an overlay in the real environment, not as an in-memory tree
137+
- Only one rendered component can be visible at a time
138+
139+
Use it when the task requires:
140+
141+
- `render(...)` or `rerender(...)`
142+
- `screen.findByTestId(...)`
143+
- `screen.findAllByTestId(...)`
144+
- `screen.queryByTestId(...)`
145+
- `screen.queryAllByTestId(...)`
146+
- `screen.findByAccessibilityLabel(...)`
147+
- `screen.findAllByAccessibilityLabel(...)`
148+
- `screen.queryByAccessibilityLabel(...)`
149+
- `screen.queryAllByAccessibilityLabel(...)`
150+
- `userEvent.press(...)`
151+
- `userEvent.type(...)`
152+
- screenshots with `screen.screenshot()`
153+
- element screenshots with `screen.screenshot(element)`
154+
- image assertions with `toMatchImageSnapshot(...)`
155+
156+
- Keep imports split correctly: core APIs from `react-native-harness`, UI APIs from `@react-native-harness/ui`.
157+
- Mention that `@react-native-harness/ui` requires installation, and native apps must be rebuilt after adding it.
158+
- `toMatchImageSnapshot(...)` needs a unique snapshot `name`.
159+
- If screenshotting elements that extend beyond screen bounds, call out `disableViewFlattening: true` in `rn-harness.config.mjs`.
160+
- On web, UI interactions and screenshots run through the web runner's Playwright-backed browser environment.
161+
162+
## Setup Files
163+
164+
Harness follows two setup phases configured in `jest.harness.config.mjs`:
165+
166+
- `setupFiles`: runs before the test framework is initialized. Use for early polyfills and globals. Do not use `describe`, `test`, `expect`, or hooks here.
167+
- `setupFilesAfterEnv`: runs after the test framework is ready. Use for global mocks, hooks, and matcher setup.
168+
169+
Recommended uses:
170+
171+
- Early environment shims in `setupFiles`
172+
- Global `afterEach`, `clearAllMocks`, `resetModules`, and shared mocks in `setupFilesAfterEnv`
173+
174+
## CLI And Execution Constraints
175+
176+
- Harness wraps the Jest CLI.
177+
- Tests execute on one configured runner at a time.
178+
- Execution is serial for stability.
179+
- `--harnessRunner <name>` selects the runner.
180+
- Standard Jest flags like `--watch`, `--coverage`, and `--testNamePattern` are still relevant.
181+
- Do not recommend unsupported Jest environment overrides or snapshot-update workflows for native image snapshots.
182+
183+
For install, runner setup, and config files, read [references/installation.md](references/installation.md).
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# Installation And Setup
2+
3+
Use this reference only when the task involves installing, configuring, or running React Native Harness.
4+
5+
## Install
6+
7+
Install the main package:
8+
9+
```bash
10+
npm install --save-dev react-native-harness
11+
```
12+
13+
Most projects should also install the platform packages they plan to run:
14+
15+
- `@react-native-harness/platform-android`
16+
- `@react-native-harness/platform-apple`
17+
- `@react-native-harness/platform-web`
18+
19+
If the user wants UI queries, interactions, or screenshots, also install:
20+
21+
- `@react-native-harness/ui`
22+
23+
For iOS and Android, adding `@react-native-harness/ui` requires rebuilding the app because it includes debug-only native code.
24+
25+
## Recommended Bootstrap
26+
27+
Prefer the setup wizard first:
28+
29+
```bash
30+
npx react-native-harness@latest init
31+
```
32+
33+
The wizard can generate:
34+
35+
- `rn-harness.config.mjs`
36+
- `jest.harness.config.mjs`
37+
- platform package setup
38+
39+
## Minimal Config Expectations
40+
41+
`rn-harness.config.mjs` should define:
42+
43+
- `entryPoint`
44+
- `appRegistryComponentName`
45+
- `runners`
46+
- optional `defaultRunner`
47+
48+
Typical runner guidance:
49+
50+
- Android: configure `androidPlatform(...)` with `androidEmulator(...)` or `physicalAndroidDevice(...)`
51+
- iOS: configure `applePlatform(...)` with `appleSimulator(...)` or `applePhysicalDevice(...)`
52+
- Web: configure `webPlatform(...)` with a browser helper like `chromium(...)`
53+
54+
`jest.harness.config.mjs` should normally use:
55+
56+
```js
57+
export default {
58+
preset: 'react-native-harness',
59+
};
60+
```
61+
62+
Common additions:
63+
64+
- `testMatch` for `**/*.harness.[jt]s?(x)`
65+
- `setupFiles`
66+
- `setupFilesAfterEnv`
67+
68+
## Writing Tests
69+
70+
Author tests in files like:
71+
72+
- `feature.harness.ts`
73+
- `feature.harness.tsx`
74+
75+
Import public test APIs from `react-native-harness`.
76+
77+
## Running Tests
78+
79+
Run one runner at a time:
80+
81+
```bash
82+
npx react-native-harness --harnessRunner android
83+
npx react-native-harness --harnessRunner ios
84+
npx react-native-harness --harnessRunner web
85+
```
86+
87+
Helpful supported Jest-style flags include:
88+
89+
- `--watch`
90+
- `--coverage`
91+
- `--testNamePattern`
92+
93+
If `defaultRunner` is configured in `rn-harness.config.mjs`, the runner flag can be omitted.
94+
95+
## Environment Notes
96+
97+
- Harness runs tests in the app or browser environment, not plain Node.
98+
- The app must already be built and installed for native runners.
99+
- Web tests require the target web app dev server to be running.
100+
- Harness can reset the environment between test files by restarting the app when configured with the default isolation behavior.
101+
102+
## Setup Files Guidance
103+
104+
Use `setupFiles` for early polyfills and globals.
105+
106+
Use `setupFilesAfterEnv` for:
107+
108+
- `afterEach(...)`
109+
- `clearAllMocks()`
110+
- `resetModules()`
111+
- shared Harness mocks
112+
113+
## UI Testing Notes
114+
115+
Use `@react-native-harness/ui` for:
116+
117+
- `screen`
118+
- `userEvent`
119+
- screenshot testing
120+
121+
If screenshots need content outside normal screen bounds, mention `disableViewFlattening: true` in `rn-harness.config.mjs`.

website/src/docs/getting-started/_meta.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@
1919
"name": "quick-start",
2020
"label": "Quick Start"
2121
},
22+
{
23+
"type": "file",
24+
"name": "agent-skills",
25+
"label": "Agent Skills"
26+
},
2227
{
2328
"type": "file",
2429
"name": "configuration",
@@ -29,4 +34,4 @@
2934
"name": "prior-art",
3035
"label": "Prior Art"
3136
}
32-
]
37+
]
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { PackageManagerTabs } from '@theme';
2+
3+
# Agent Skills
4+
5+
If you use Codex or another coding agent that supports the Vercel `skills` CLI, you can install the `react-native-harness` skill so the agent can author Harness tests more effectively.
6+
7+
The skill gives the agent the expected React Native Harness workflow for writing tests, using module mocks, working with `render(...)`, and using the optional `@react-native-harness/ui` package correctly.
8+
9+
The skill complements the `react-native-harness` package, it does not replace it. Your project still needs `react-native-harness` installed because the agent is ultimately writing and running real Harness tests in your app.
10+
11+
## Install with the Vercel `skills` CLI
12+
13+
Install the skill from this repository using the repo URL and the skill name:
14+
15+
<PackageManagerTabs
16+
command={{
17+
npm: 'npx skills add https://github.com/callstackincubator/react-native-harness --skill react-native-harness',
18+
yarn: 'yarn dlx skills add https://github.com/callstackincubator/react-native-harness --skill react-native-harness',
19+
pnpm: 'pnpm dlx skills add https://github.com/callstackincubator/react-native-harness --skill react-native-harness',
20+
bun: 'bunx skills add https://github.com/callstackincubator/react-native-harness --skill react-native-harness',
21+
}}
22+
/>
23+
24+
By default, the `skills` CLI installs project-local skills for the agents it supports in your project.
25+
26+
To install it globally for all projects instead, use:
27+
28+
<PackageManagerTabs
29+
command={{
30+
npm: 'npx skills add https://github.com/callstackincubator/react-native-harness --skill react-native-harness --global',
31+
yarn: 'yarn dlx skills add https://github.com/callstackincubator/react-native-harness --skill react-native-harness --global',
32+
pnpm: 'pnpm dlx skills add https://github.com/callstackincubator/react-native-harness --skill react-native-harness --global',
33+
bun: 'bunx skills add https://github.com/callstackincubator/react-native-harness --skill react-native-harness --global',
34+
}}
35+
/>
36+
37+
After installation, ask your agent to use `react-native-harness` whenever it needs to write or debug Harness tests.
38+
39+
## Next Steps
40+
41+
- Go back to [Quick Start](/docs/getting-started/quick-start).
42+
- Read the [Configuration](/docs/getting-started/configuration) guide.
43+
- Browse the [API](/docs/api/defining-tests) docs for the public testing surface.

website/src/docs/getting-started/quick-start.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ Install React Native Harness as a development dependency:
1616

1717
<PackageManagerTabs command="install react-native-harness" />
1818

19+
## Using Coding Agents
20+
21+
If you use Codex or another coding agent that supports the Vercel `skills` CLI, install the [React Native Harness skill](/docs/getting-started/agent-skills) so the agent can write Harness tests more effectively.
22+
1923
## Configuration
2024

2125
The easiest way to get started is with our interactive setup wizard! It will guide you through the configuration process and handle most of the setup automatically.

0 commit comments

Comments
 (0)