hermes-test 0.2.0 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +421 -0
- package/package.json +4 -4
- package/src/harness.ts +4 -0
- package/src/store.ts +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
# hermes-test
|
|
2
|
+
|
|
3
|
+
**26–64x faster than Jest.** A test runner built for React Native and Expo. One esbuild pass, one process, zero Babel — results in under a second.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
1472 tests — 0.84s (cached) | 5s with coverage
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
<img src="docs/demo.gif" alt="hermes-test demo — 1472 tests with coverage in 5s" width="800">
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
> **⚠️ Early release (v0).** hermes-test is battle-tested on a production Expo app (1472 tests, 100% pass rate) but the API may still change.
|
|
14
|
+
>
|
|
15
|
+
> **Recommended approach:** Use `.hermes.test.ts` as your test file suffix. This lets you run hermes-test alongside Jest without overwriting your existing tests. Migrate one file at a time, verify it passes in both runners, then expand. Don't delete your Jest tests until you're confident.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
### The problem
|
|
20
|
+
|
|
21
|
+
Jest in React Native is slow by design. Every test file spawns a worker, runs Babel transforms, resolves `transformIgnorePatterns` for every `node_modules` import, and coordinates results over IPC. For a mid-size Expo app, that's 1-2 minutes per run. With coverage, even longer.
|
|
22
|
+
|
|
23
|
+
On top of that, the configuration tax is real: `transformIgnorePatterns` breaks every time you add a dependency, `jest-expo` mocks silently drift from real APIs, and `moduleNameMapper` requires manual upkeep for every monorepo alias. Developers stop running tests. Tests rot. Coverage drops.
|
|
24
|
+
|
|
25
|
+
### The fix
|
|
26
|
+
|
|
27
|
+
hermes-test replaces the entire Jest pipeline with two things: **esbuild** (one bundle pass, <100ms) and a **Rust CLI** that evaluates it in a single process. No workers, no Babel, no `transformIgnorePatterns`. Native modules are auto-detected and externalized — zero manual configuration needed.
|
|
28
|
+
|
|
29
|
+
Your tests run in Hermes — the same JavaScript engine your app ships with — so you also get engine parity for free. But the real win is speed: results appear before your hand leaves `Cmd+S`.
|
|
30
|
+
|
|
31
|
+
### Benchmarks
|
|
32
|
+
|
|
33
|
+
Production Expo app (Topdanmark, Danish insurance — 259 files, 1472 tests):
|
|
34
|
+
|
|
35
|
+
| | Jest | hermes-test | Speedup |
|
|
36
|
+
|---|---|---|---|
|
|
37
|
+
| Full suite (no coverage) | 54s | **0.84s** cached / 2.5s cold | **64x** / **22x** |
|
|
38
|
+
| Full suite (with coverage) | 128s | **5s** | **26x** |
|
|
39
|
+
| Watch rerun | ~3s | **~300ms** | **10x** |
|
|
40
|
+
|
|
41
|
+
Micro benchmarks (Apple Silicon, no coverage):
|
|
42
|
+
|
|
43
|
+
| Scenario | hermes-test | Jest + @swc/jest | Speedup |
|
|
44
|
+
|----------|-------------|------------------|---------|
|
|
45
|
+
| 10 pure function tests | **16ms** | 714ms | **45x** |
|
|
46
|
+
| 50 hook tests (renderHook + act) | **75ms** | 721ms | **10x** |
|
|
47
|
+
| Trivial cold start | **4.6ms** | 1,486ms | **364x** |
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Quick start
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
bun add -D hermes-test
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
// useCounter.test.ts
|
|
59
|
+
import { test, expect, renderHook, act } from 'hermes-test';
|
|
60
|
+
|
|
61
|
+
test('useCounter increments', () => {
|
|
62
|
+
const { result } = renderHook(() => useCounter(0));
|
|
63
|
+
act(() => result.current.increment());
|
|
64
|
+
expect(result.current.count).toBe(1);
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
hermes-test # run all tests
|
|
70
|
+
hermes-test --watch # watch mode
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## API
|
|
74
|
+
|
|
75
|
+
### Test structure
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
import { test, expect, group, beforeEach, afterEach } from 'hermes-test';
|
|
79
|
+
|
|
80
|
+
group('myFeature', () => {
|
|
81
|
+
beforeEach(() => { /* reset */ });
|
|
82
|
+
|
|
83
|
+
test('does the thing', () => {
|
|
84
|
+
expect(result).toBe(42);
|
|
85
|
+
expect(arr).toEqual([1, 2, 3]);
|
|
86
|
+
expect(str).toContain('hello');
|
|
87
|
+
expect(fn).toThrow('error message');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test.skip('not yet', () => {});
|
|
91
|
+
test.only('focus this', () => {});
|
|
92
|
+
test('slow test', () => { /* ... */ }, { timeout: 10000 });
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Assertions
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
expect(val).toBe(exact) expect(val).toEqual(deep)
|
|
100
|
+
expect(val).toBeTruthy() expect(val).toBeFalsy()
|
|
101
|
+
expect(val).toBeDefined() expect(val).toBeUndefined()
|
|
102
|
+
expect(val).toBeNull() expect(val).toBeGreaterThan(n)
|
|
103
|
+
expect(val).toContain(item) expect(val).toContainEqual(item)
|
|
104
|
+
expect(val).toMatch(/regex/) expect(val).toBeCloseTo(n, precision)
|
|
105
|
+
expect(fn).toThrow('msg') expect(val).not.toBe(other)
|
|
106
|
+
|
|
107
|
+
// Asymmetric matchers
|
|
108
|
+
expect.anything() expect.any(String)
|
|
109
|
+
expect.objectContaining({ key }) expect.arrayContaining([1, 2])
|
|
110
|
+
expect.stringContaining('sub') expect.stringMatching(/pattern/)
|
|
111
|
+
|
|
112
|
+
// Async
|
|
113
|
+
await expect(promise).resolves.toBe(value)
|
|
114
|
+
await expect(promise).rejects.toThrow('msg')
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Spies
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
import { spy, spyOn, clearAllMocks } from 'hermes-test';
|
|
121
|
+
|
|
122
|
+
const fn = spy(() => 'default');
|
|
123
|
+
fn.mockReturnValue('mocked');
|
|
124
|
+
fn.mockReturnValueOnce('first');
|
|
125
|
+
fn.mockImplementation((x) => x * 2);
|
|
126
|
+
fn.mockResolvedValue('async');
|
|
127
|
+
|
|
128
|
+
expect(fn).toHaveBeenCalled();
|
|
129
|
+
expect(fn).toHaveBeenCalledWith('arg1', 'arg2');
|
|
130
|
+
expect(fn).toHaveBeenCalledTimes(3);
|
|
131
|
+
expect(fn.calls[0][0]).toBe('arg1'); // direct access
|
|
132
|
+
|
|
133
|
+
// spyOn — intercept real object methods
|
|
134
|
+
const s = spyOn(storage, 'get');
|
|
135
|
+
s.mockReturnValue('cached');
|
|
136
|
+
s.mockRestore(); // revert to original
|
|
137
|
+
|
|
138
|
+
// Clear all spies at once
|
|
139
|
+
clearAllMocks();
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Module mocking
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
import { mockModule } from 'hermes-test';
|
|
146
|
+
import { useMyHook } from './useMyHook'; // import order doesn't matter
|
|
147
|
+
|
|
148
|
+
mockModule('./useRedux', () => ({
|
|
149
|
+
useAppSelector: (selector) => mockState,
|
|
150
|
+
}));
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Shadow wrappers check mocks at call time — `mockModule` can appear before or after imports.
|
|
154
|
+
|
|
155
|
+
### Hook testing
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
import { renderHook, act, waitFor } from 'hermes-test';
|
|
159
|
+
|
|
160
|
+
const { result, history, renderCount } = renderHook(() => useCounter(0));
|
|
161
|
+
act(() => result.current.increment());
|
|
162
|
+
expect(result.current.count).toBe(1);
|
|
163
|
+
expect(renderCount).toBe(2);
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Fetch mocking (MSW-style)
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
import { mockFetch, mockFetchUse, mockFetchReset, http, HttpResponse } from 'hermes-test';
|
|
170
|
+
|
|
171
|
+
mockFetch(
|
|
172
|
+
http.get('https://api.example.com/data', () => HttpResponse.json({ ok: true })),
|
|
173
|
+
http.post('https://api.example.com/login', () => HttpResponse.json({ token: '...' })),
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
// Per-test override
|
|
177
|
+
mockFetchUse(http.get('https://api.example.com/data', () => HttpResponse.error()));
|
|
178
|
+
|
|
179
|
+
// Cleanup
|
|
180
|
+
mockFetchReset();
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Redux store
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
import { setupApiStore } from 'hermes-test/store';
|
|
187
|
+
|
|
188
|
+
const ctx = setupApiStore([api, cms], { app: rootReducer }, {
|
|
189
|
+
preloadedState: { app: { auth: { session: mockSession } } },
|
|
190
|
+
});
|
|
191
|
+
const { result } = ctx.renderHookWithReduxStore(() => useMyHook());
|
|
192
|
+
ctx.store.dispatch(authActions.logout());
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Fake timers
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
import { useFakeTimers, advanceTimersByTime, useRealTimers } from 'hermes-test';
|
|
199
|
+
|
|
200
|
+
useFakeTimers();
|
|
201
|
+
setTimeout(() => { fired = true }, 1000);
|
|
202
|
+
advanceTimersByTime(1000);
|
|
203
|
+
expect(fired).toBe(true);
|
|
204
|
+
useRealTimers();
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## How it works
|
|
208
|
+
|
|
209
|
+
```
|
|
210
|
+
┌──────────────┐ ┌─────────┐ ┌────────────┐
|
|
211
|
+
│ .test.ts │────▶│ esbuild │────▶│ Hermes │
|
|
212
|
+
│ files │ │ bundle │ │ VM eval │
|
|
213
|
+
└──────────────┘ └─────────┘ └────────────┘
|
|
214
|
+
│ │ │
|
|
215
|
+
mockModule() <100ms bundle native execution
|
|
216
|
+
spy/expect path aliases drainMicrotasks
|
|
217
|
+
renderHook Hermes patches real React tree
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
1. **esbuild** bundles your test + source into a single IIFE (~100ms)
|
|
221
|
+
2. Rust CLI applies **Hermes patches** (class-extends, for-let-of)
|
|
222
|
+
3. **Bytecode compilation** — cached .hbc for instant loading on subsequent runs
|
|
223
|
+
4. **Hermes VM** evaluates the bytecode — same engine as your app
|
|
224
|
+
5. Results printed to terminal — single process, no workers, no IPC
|
|
225
|
+
|
|
226
|
+
### Three-tier cache
|
|
227
|
+
|
|
228
|
+
| Tier | What | Speed |
|
|
229
|
+
|---|---|---|
|
|
230
|
+
| **Bytecode (.hbc)** | Pre-compiled Hermes bytecode | Fastest — skip JS parsing |
|
|
231
|
+
| **Patched JS** | Post-patched esbuild output | Fast — skip bundling + patching |
|
|
232
|
+
| **Fresh bundle** | Full esbuild + patch pipeline | Cold start only |
|
|
233
|
+
|
|
234
|
+
### Auto-detect native externals
|
|
235
|
+
|
|
236
|
+
Native modules are detected automatically by scanning `node_modules` for `ios/`, `android/`, `*.podspec`, and `app.plugin.js`. No manual `externals` config needed for standard React Native packages.
|
|
237
|
+
|
|
238
|
+
### Mock isolation (Shadow Wrappers)
|
|
239
|
+
|
|
240
|
+
When multiple test files mock the same module differently, hermes-test uses **shadow wrappers** — filesystem-based Proxy wrappers that check which test file is running at call time. One bundle, one runtime, per-file mock isolation.
|
|
241
|
+
|
|
242
|
+
## CLI
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
hermes-test # run all test files
|
|
246
|
+
hermes-test src/hooks/ # run tests in a directory
|
|
247
|
+
hermes-test src/hooks/useLogin.test.ts # run a specific file
|
|
248
|
+
hermes-test --watch # watch mode — reruns on file changes
|
|
249
|
+
hermes-test --watch useLogin # watch mode, filtered to matching files
|
|
250
|
+
hermes-test --coverage # run with coverage (lcov + HTML report)
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Configuration
|
|
254
|
+
|
|
255
|
+
### Polyrepo (single package)
|
|
256
|
+
|
|
257
|
+
No config file needed for simple projects. Just run `hermes-test` in your project root.
|
|
258
|
+
|
|
259
|
+
```
|
|
260
|
+
my-app/
|
|
261
|
+
├── src/
|
|
262
|
+
│ └── hooks/
|
|
263
|
+
│ └── useLogin.hermes.test.ts
|
|
264
|
+
├── package.json
|
|
265
|
+
└── tsconfig.json ← path aliases read automatically
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Monorepo
|
|
269
|
+
|
|
270
|
+
Create `hermes-test.config.json` in your app directory. The `root` field tells hermes-test where the monorepo root is (for resolving shared `node_modules`).
|
|
271
|
+
|
|
272
|
+
```
|
|
273
|
+
monorepo/
|
|
274
|
+
├── apps/
|
|
275
|
+
│ └── my-app/
|
|
276
|
+
│ ├── src/
|
|
277
|
+
│ ├── hermes-test.config.json ← config here
|
|
278
|
+
│ ├── package.json
|
|
279
|
+
│ └── tsconfig.json
|
|
280
|
+
├── packages/
|
|
281
|
+
│ └── shared/
|
|
282
|
+
└── node_modules/ ← root points here
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
```json
|
|
286
|
+
{
|
|
287
|
+
"root": "../..",
|
|
288
|
+
"testMatch": ".hermes.test.ts"
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### hermes-test.config.json
|
|
293
|
+
|
|
294
|
+
| Key | Description | Required |
|
|
295
|
+
|-----|-------------|----------|
|
|
296
|
+
| `root` | Monorepo workspace root (for resolving node_modules) | Monorepo only |
|
|
297
|
+
| `testMatch` | Test file suffix (default: `.test.ts`) | No |
|
|
298
|
+
| `externals` | Additional modules to externalize | No (most auto-detected) |
|
|
299
|
+
| `shims` | Built-in or custom module replacements | No |
|
|
300
|
+
| `split` | Enable vendor/group bundle splitting for large suites | No |
|
|
301
|
+
| `coverageThreshold` | Minimum coverage % — fails if below (e.g. `65`) | No |
|
|
302
|
+
|
|
303
|
+
**tsconfig paths** are read automatically — monorepo path aliases just work:
|
|
304
|
+
|
|
305
|
+
```json
|
|
306
|
+
{
|
|
307
|
+
"compilerOptions": {
|
|
308
|
+
"paths": {
|
|
309
|
+
"@app/*": ["./src/*"],
|
|
310
|
+
"@myorg/shared/*": ["../../packages/shared/src/*"]
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
**Native externals** are auto-detected by scanning `node_modules` for `ios/`, `android/`, `*.podspec`, and `app.plugin.js`. Most projects need zero manual `externals`.
|
|
317
|
+
|
|
318
|
+
### Built-in shims
|
|
319
|
+
|
|
320
|
+
hermes-test ships with ready-to-use shims for common React Native ecosystem packages. Use `hermes-test/shims/<name>` in your config — no local shim files needed.
|
|
321
|
+
|
|
322
|
+
| Shim | What it provides |
|
|
323
|
+
|------|-----------------|
|
|
324
|
+
| `hermes-test/shims/react-native` | Platform, StyleSheet, Dimensions, Alert, Linking stubs |
|
|
325
|
+
| `hermes-test/shims/react-i18next` | Identity translation (`t('key')` returns `'key'`) |
|
|
326
|
+
| `hermes-test/shims/async-storage` | In-memory AsyncStorage (getItem, setItem, clear, etc.) |
|
|
327
|
+
| `hermes-test/shims/rtk-query` | RTK Query createApi singleton cache |
|
|
328
|
+
| `hermes-test/shims/react-redux` | Pass-through for react-redux |
|
|
329
|
+
| `hermes-test/shims/reduxjs-toolkit` | Pass-through for @reduxjs/toolkit |
|
|
330
|
+
|
|
331
|
+
Example config with shims:
|
|
332
|
+
|
|
333
|
+
```json
|
|
334
|
+
{
|
|
335
|
+
"root": "../..",
|
|
336
|
+
"testMatch": ".hermes.test.ts",
|
|
337
|
+
"shims": {
|
|
338
|
+
"react-i18next": "hermes-test/shims/react-i18next",
|
|
339
|
+
"@reduxjs/toolkit/query/react": "hermes-test/shims/rtk-query",
|
|
340
|
+
"@react-native-async-storage/async-storage": "hermes-test/shims/async-storage"
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
You can also write custom shims for app-specific native modules:
|
|
346
|
+
|
|
347
|
+
```json
|
|
348
|
+
{
|
|
349
|
+
"shims": {
|
|
350
|
+
"react-native-keychain": "./test/shims/keychain.js"
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
## Coverage
|
|
356
|
+
|
|
357
|
+
```bash
|
|
358
|
+
hermes-test --coverage
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
Generates:
|
|
362
|
+
- **Terminal table** — per-file line + function coverage with color coding
|
|
363
|
+
- **`coverage/lcov.info`** — standard lcov format, works with any lcov tool
|
|
364
|
+
- **`coverage/index.html`** — interactive HTML report with source-level green/red highlighting
|
|
365
|
+
|
|
366
|
+
Coverage uses esbuild source maps for accurate original-file line mapping. Imports, `node_modules`, test files, and monorepo dependencies are automatically excluded — only your source code is measured.
|
|
367
|
+
|
|
368
|
+
### Coverage threshold
|
|
369
|
+
|
|
370
|
+
Add `coverageThreshold` to `hermes-test.config.json` to fail CI when coverage drops:
|
|
371
|
+
|
|
372
|
+
```json
|
|
373
|
+
{
|
|
374
|
+
"coverageThreshold": 65
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
If total statement coverage is below the threshold, hermes-test exits with code 1.
|
|
379
|
+
|
|
380
|
+
## Stack
|
|
381
|
+
|
|
382
|
+
- **Hermes** — the JS engine that ships with React Native and Expo
|
|
383
|
+
- **esbuild** — bundler, 100x faster than Babel/Metro transforms
|
|
384
|
+
- **Rust** — CLI host, native Hermes FFI, bytecode caching
|
|
385
|
+
- **TypeScript** — test harness (spy, expect, renderHook, mockFetch, timers)
|
|
386
|
+
|
|
387
|
+
## Why not Jest?
|
|
388
|
+
|
|
389
|
+
| | Jest + jest-expo | hermes-test |
|
|
390
|
+
|---|-----------------|-------------|
|
|
391
|
+
| Bundling | Babel on every import | esbuild, one pass |
|
|
392
|
+
| Startup | ~700ms per worker | ~5ms total |
|
|
393
|
+
| Native externals | Manual `transformIgnorePatterns` | Auto-detected |
|
|
394
|
+
| Config needed | `transformIgnorePatterns`, `moduleNameMapper`, mocks | Zero for most projects |
|
|
395
|
+
| Watch rerun | ~2-3s | ~300ms |
|
|
396
|
+
| 1472 tests (no coverage) | 54s | **0.84s** |
|
|
397
|
+
| 1472 tests (with coverage) | 128s | **5s** |
|
|
398
|
+
| Coverage | Built-in (v8/Istanbul) | `--coverage` with source maps, HTML report, threshold |
|
|
399
|
+
| Engine | Node | Hermes (same as your app) |
|
|
400
|
+
|
|
401
|
+
## Platform support
|
|
402
|
+
|
|
403
|
+
| Platform | Status |
|
|
404
|
+
|----------|--------|
|
|
405
|
+
| macOS (Apple Silicon) | Supported |
|
|
406
|
+
| Linux (x64) | Supported |
|
|
407
|
+
| macOS (Intel x64) | Planned |
|
|
408
|
+
| Windows | Not planned |
|
|
409
|
+
|
|
410
|
+
## Roadmap
|
|
411
|
+
|
|
412
|
+
- [x] **Coverage reporting** — source map-based instrumentation, lcov + HTML report, threshold enforcement
|
|
413
|
+
- [ ] **macOS Intel (x64)** — cross-compile or dedicated CI runner
|
|
414
|
+
- [ ] **Component rendering** — `render(<Component />)` with query API (`getByText`, `getByTestId`, `fireEvent`)
|
|
415
|
+
- [ ] **Jest compatibility shim** — `jest.fn()` → `spy()`, `jest.mock()` → `mockModule()`, enables reuse of library `__mocks__/` files
|
|
416
|
+
- [ ] **Library mock support** — auto-load mocks from expo-router, react-native-reanimated, zustand, etc.
|
|
417
|
+
- [ ] **`setupFiles` config** — load setup files before tests (like Jest's `setupFilesAfterFramework`)
|
|
418
|
+
|
|
419
|
+
## License
|
|
420
|
+
|
|
421
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hermes-test",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "147x faster than Jest. Test runner for React Native and Expo that runs in Hermes.",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
"react": ">=18"
|
|
51
51
|
},
|
|
52
52
|
"optionalDependencies": {
|
|
53
|
-
"@hermes-test/darwin-arm64": "0.2.
|
|
54
|
-
"@hermes-test/darwin-x64": "0.2.
|
|
55
|
-
"@hermes-test/linux-x64": "0.2.
|
|
53
|
+
"@hermes-test/darwin-arm64": "0.2.3",
|
|
54
|
+
"@hermes-test/darwin-x64": "0.2.3",
|
|
55
|
+
"@hermes-test/linux-x64": "0.2.3"
|
|
56
56
|
},
|
|
57
57
|
"files": [
|
|
58
58
|
"src/",
|
package/src/harness.ts
CHANGED
|
@@ -340,6 +340,10 @@ function resetRegistry(): void {
|
|
|
340
340
|
beforeAllHooks.length = 0;
|
|
341
341
|
afterAllHooks.length = 0;
|
|
342
342
|
currentGroup = undefined;
|
|
343
|
+
// Clear mock and spy state for clean watch reruns
|
|
344
|
+
clearAllMocks();
|
|
345
|
+
if ((globalThis as any).__HT_file_mocks) (globalThis as any).__HT_file_mocks = {};
|
|
346
|
+
resetMockModulePatches();
|
|
343
347
|
}
|
|
344
348
|
|
|
345
349
|
// Expose to the global scope for the harness entry
|
package/src/store.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// withStore: quick identity-reducer store for any state shape
|
|
5
5
|
// withAppReducer: real app reducer with patchState + real actions
|
|
6
6
|
|
|
7
|
+
// @ts-nocheck
|
|
7
8
|
import React from 'react';
|
|
8
9
|
import { Provider } from 'react-redux';
|
|
9
10
|
import { configureStore } from '@reduxjs/toolkit';
|