Skip to content

Commit cd2d93d

Browse files
authored
feat: refactor plugin internals and stabilize isolation:none (#8)
* feat: optimize react testing runtime and add prettier * fix: update test scripts * chore: removed unused var and function * Refactor plugin internals and harden isolation-none flow * format: fix * format: fix
1 parent 2f6f32c commit cd2d93d

27 files changed

Lines changed: 864 additions & 506 deletions

CHANGELOG.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,15 @@
22

33
## [1.1.0](https://github.com/Lojhan/poku-react-testing/compare/v1.0.1...v1.1.0) (2026-03-31)
44

5-
65
### Features
76

8-
* optimize react testing runtime and add prettier ([#6](https://github.com/Lojhan/poku-react-testing/issues/6)) ([424194b](https://github.com/Lojhan/poku-react-testing/commit/424194b2c5bdc5f8c3d3c7a41bc91b50d51dd38c))
7+
- optimize react testing runtime and add prettier ([#6](https://github.com/Lojhan/poku-react-testing/issues/6)) ([424194b](https://github.com/Lojhan/poku-react-testing/commit/424194b2c5bdc5f8c3d3c7a41bc91b50d51dd38c))
98

109
## [1.0.1](https://github.com/Lojhan/poku-react-testing/compare/v1.0.0...v1.0.1) (2026-03-31)
1110

12-
1311
### Bug Fixes
1412

15-
* add repository metadata required for npm provenance ([#4](https://github.com/Lojhan/poku-react-testing/issues/4)) ([f20b16a](https://github.com/Lojhan/poku-react-testing/commit/f20b16a9ab72bb957743c7739a926d0bfb851f68))
13+
- add repository metadata required for npm provenance ([#4](https://github.com/Lojhan/poku-react-testing/issues/4)) ([f20b16a](https://github.com/Lojhan/poku-react-testing/commit/f20b16a9ab72bb957743c7739a926d0bfb851f68))
1614

1715
## 1.0.0 (2026-03-31)
1816

benchmark/REPORT.md

Lines changed: 52 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,49 @@
11
# React Testing Framework Benchmark Report
22

3-
> Generated: Tue, 31 Mar 2026 21:00:50 GMT
3+
> Generated: Wed, 01 Apr 2026 12:41:50 GMT
44
55
## Environment
66

7-
| Property | Value |
8-
|---|---|
9-
| Node.js | v22.5.1 |
10-
| Platform | darwin 25.4.0 |
11-
| CPU | Apple M3 Pro |
12-
| CPU Cores | 12 |
13-
| Total RAM | 18.0 GB |
14-
| Runs/scenario | 7 (trim ±1) |
7+
| Property | Value |
8+
| ------------- | ------------- |
9+
| Node.js | v22.5.1 |
10+
| Platform | darwin 25.4.0 |
11+
| CPU | Apple M3 Pro |
12+
| CPU Cores | 12 |
13+
| Total RAM | 18.0 GB |
14+
| Runs/scenario | 7 (trim ±1) |
1515

1616
## Scenarios
1717

1818
Each scenario runs the **same 9 React tests** across 5 test files:
1919

20-
| Test File | Tests |
21-
|---|---|
22-
| 'counter.test.jsx' | 1 — stateful counter, event interaction |
23-
| 'hooks.test.jsx' | 2 — custom hook harness + `renderHook` |
24-
| 'lifecycle.test.jsx' | 2 — `rerender`, `unmount` + effect cleanup |
25-
| 'context.test.jsx' | 1 — `createContext` + wrapper injection |
26-
| 'concurrency.test.jsx' | 2 — React 19 `use()` + `useTransition` |
20+
| Test File | Tests |
21+
| ---------------------- | ------------------------------------------ |
22+
| 'counter.test.jsx' | 1 — stateful counter, event interaction |
23+
| 'hooks.test.jsx' | 2 — custom hook harness + `renderHook` |
24+
| 'lifecycle.test.jsx' | 2 — `rerender`, `unmount` + effect cleanup |
25+
| 'context.test.jsx' | 1 — `createContext` + wrapper injection |
26+
| 'concurrency.test.jsx' | 2 — React 19 `use()` + `useTransition` |
2727

2828
### Frameworks under test
2929

30-
| Combination | DOM layer | Assertion style |
31-
|---|---|---|
32-
| poku + poku-react-testing | happy-dom | `assert.strictEqual` |
33-
| poku + poku-react-testing | jsdom | `assert.strictEqual` |
34-
| jest 29 + @testing-library/react | jsdom (jest-environment-jsdom) | `expect().toBe()` |
35-
| vitest 3 + @testing-library/react | jsdom | `expect().toBe()` |
36-
| vitest 3 + @testing-library/react | happy-dom | `expect().toBe()` |
30+
| Combination | DOM layer | Assertion style |
31+
| --------------------------------- | ------------------------------ | -------------------- |
32+
| poku + poku-react-testing | happy-dom | `assert.strictEqual` |
33+
| poku + poku-react-testing | jsdom | `assert.strictEqual` |
34+
| jest 29 + @testing-library/react | jsdom (jest-environment-jsdom) | `expect().toBe()` |
35+
| vitest 3 + @testing-library/react | jsdom | `expect().toBe()` |
36+
| vitest 3 + @testing-library/react | happy-dom | `expect().toBe()` |
3737

3838
## Results
3939

4040
| Scenario | Mean | Min | Max | Stdev | Peak RSS | vs poku+happy-dom |
41-
|--------------------|--------|--------|--------|--------|----------|-------------------|
42-
| poku + happy-dom | 1.073s | 0.996s | 1.230s | 0.085s | 163.3 MB | *(baseline)* |
43-
| poku + jsdom | 1.060s | 1.007s | 1.177s | 0.060s | 163.4 MB | -1% |
44-
| jest + jsdom | 0.859s | 0.779s | 0.929s | 0.050s | 206.2 MB | -20% |
45-
| vitest + jsdom | 0.964s | 0.950s | 0.987s | 0.017s | 148.0 MB | -10% |
46-
| vitest + happy-dom | 0.838s | 0.812s | 0.864s | 0.021s | 116.3 MB | -22% |
41+
| ------------------ | ------ | ------ | ------ | ------ | -------- | ----------------- |
42+
| poku + happy-dom | 0.560s | 0.515s | 0.600s | 0.033s | 154.3 MB | _(baseline)_ |
43+
| poku + jsdom | 0.444s | 0.429s | 0.451s | 0.008s | 157.1 MB | -21% |
44+
| jest + jsdom | 1.040s | 0.975s | 1.135s | 0.056s | 203.4 MB | +86% |
45+
| vitest + jsdom | 1.193s | 1.129s | 1.269s | 0.057s | 152.3 MB | +113% |
46+
| vitest + happy-dom | 1.041s | 0.990s | 1.126s | 0.047s | 117.1 MB | +86% |
4747

4848
> **Wall-clock time** is measured with `performance.now()` around the child-process spawn.
4949
> **Peak RSS** is captured via `/usr/bin/time -l` on macOS (bytes → MB).
@@ -53,44 +53,44 @@ Each scenario runs the **same 9 React tests** across 5 test files:
5353

5454
### Overall ranking (mean wall-clock time)
5555

56-
1. **vitest + happy-dom** — 0.838s
57-
2. **jest + jsdom** — 0.859s
58-
3. **vitest + jsdom**0.964s
59-
4. **poku + jsdom** — 1.060s
60-
5. **poku + happy-dom** — 1.073s
56+
1. **poku + jsdom** — 0.444s
57+
2. **poku + happy-dom** — 0.560s
58+
3. **jest + jsdom**1.040s
59+
4. **vitest + happy-dom** — 1.041s
60+
5. **vitest + jsdom** — 1.193s
6161

6262
### Speed comparison
6363

64-
- poku+happy-dom vs jest+jsdom: jest is **-20% faster**
65-
- poku+happy-dom vs vitest+jsdom: vitest is **-10% faster**
66-
- jest+jsdom vs vitest+jsdom: vitest is **12% slower** than jest
64+
- poku+happy-dom vs jest+jsdom: jest is **86% slower**
65+
- poku+happy-dom vs vitest+jsdom: vitest is **113% slower**
66+
- jest+jsdom vs vitest+jsdom: vitest is **15% slower** than jest
6767

6868
### DOM adapter impact
6969

70-
- **poku**: happy-dom vs jsdom — jsdom is **-1% faster**
70+
- **poku**: happy-dom vs jsdom — jsdom is **-21% faster**
7171
- **vitest**: happy-dom vs jsdom — jsdom is **15% slower**
7272

7373
### Memory footprint
7474

75-
- **vitest + happy-dom**: 116.3 MB peak RSS
76-
- **vitest + jsdom**: 148.0 MB peak RSS
77-
- **poku + happy-dom**: 163.3 MB peak RSS
78-
- **poku + jsdom**: 163.4 MB peak RSS
79-
- **jest + jsdom**: 206.2 MB peak RSS
75+
- **vitest + happy-dom**: 117.1 MB peak RSS
76+
- **vitest + jsdom**: 152.3 MB peak RSS
77+
- **poku + happy-dom**: 154.3 MB peak RSS
78+
- **poku + jsdom**: 157.1 MB peak RSS
79+
- **jest + jsdom**: 203.4 MB peak RSS
8080

8181
### Consistency (lower stdev = more predictable)
8282

83-
- **vitest + jsdom**: σ = 0.017s
84-
- **vitest + happy-dom**: σ = 0.021s
85-
- **jest + jsdom**: σ = 0.050s
86-
- **poku + jsdom**: σ = 0.060s
87-
- **poku + happy-dom**: σ = 0.085s
83+
- **poku + jsdom**: σ = 0.008s
84+
- **poku + happy-dom**: σ = 0.033s
85+
- **vitest + happy-dom**: σ = 0.047s
86+
- **jest + jsdom**: σ = 0.056s
87+
- **vitest + jsdom**: σ = 0.057s
8888

8989
## Key findings
9090

91-
- **Fastest**: vitest + happy-dom — 0.838s mean
92-
- **Slowest**: poku + happy-dom — 1.073s mean
93-
- **Speed spread**: 28% difference between fastest and slowest
91+
- **Fastest**: poku + jsdom — 0.444s mean
92+
- **Slowest**: vitest + jsdom — 1.193s mean
93+
- **Speed spread**: 169% difference between fastest and slowest
9494

9595
### Interpretation
9696

@@ -100,6 +100,7 @@ processes with minimal bootstrap — means cold-start overhead is proportional t
100100
files, not to the framework's own initialization.
101101

102102
**jest** carries the heaviest startup cost due to:
103+
103104
1. Babel transformation of every TSX file on first run (no persistent cache in this benchmark)
104105
2. 'jest-worker' process pool initialisation
105106
3. JSDOM environment setup per test file

benchmark/package-lock.json

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

benchmark/poku.config.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import { defineConfig } from 'poku';
22
import { reactTestingPlugin } from 'poku-react-testing/plugin';
33

4-
const configuredDom = process.env.POKU_REACT_TEST_DOM;
5-
const dom = configuredDom === 'jsdom' ? 'jsdom' : 'happy-dom';
4+
const dom = process.env.POKU_REACT_TEST_DOM;
5+
if (!dom) {
6+
throw new Error('POKU_REACT_TEST_DOM environment variable is not set');
7+
}
68

79
export default defineConfig({
810
plugins: [reactTestingPlugin({ dom })],
11+
isolation: 'none',
912
});

benchmark/results.json

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"timestamp": "2026-03-31T21:00:50.386Z",
2+
"timestamp": "2026-04-01T12:41:50.774Z",
33
"system": {
44
"nodeVersion": "v22.5.1",
55
"platform": "darwin 25.4.0",
@@ -14,68 +14,68 @@
1414
"results": [
1515
{
1616
"label": "poku + happy-dom",
17-
"mean": 1073.1924668,
18-
"min": 995.5031250000002,
19-
"max": 1229.6369170000003,
20-
"stddev": 84.66710558647982,
21-
"meanRss": 171232460.8,
22-
"meanUserCpu": 4396,
23-
"meanSysCpu": 1584,
17+
"mean": 559.9537916000002,
18+
"min": 515.060708,
19+
"max": 599.9880840000001,
20+
"stddev": 33.06234198220535,
21+
"meanRss": 161808384,
22+
"meanUserCpu": 672,
23+
"meanSysCpu": 202,
2424
"runs": 7,
2525
"validRuns": 7,
2626
"failures": 0
2727
},
2828
{
2929
"label": "poku + jsdom",
30-
"mean": 1060.1384749999997,
31-
"min": 1007.1474579999995,
32-
"max": 1176.5342500000006,
33-
"stddev": 60.012456221527664,
34-
"meanRss": 171294720,
35-
"meanUserCpu": 3228,
36-
"meanSysCpu": 1440,
30+
"mean": 443.6319584000001,
31+
"min": 428.5047089999998,
32+
"max": 450.59829100000024,
33+
"stddev": 7.9857833050707905,
34+
"meanRss": 164767334.4,
35+
"meanUserCpu": 432,
36+
"meanSysCpu": 92,
3737
"runs": 7,
3838
"validRuns": 7,
3939
"failures": 0
4040
},
4141
{
4242
"label": "jest + jsdom",
43-
"mean": 858.7310334000001,
44-
"min": 778.734042,
45-
"max": 929.1150420000013,
46-
"stddev": 50.38267849622563,
47-
"meanRss": 216186880,
48-
"meanUserCpu": 778,
49-
"meanSysCpu": 176,
43+
"mean": 1040.1169332000002,
44+
"min": 975.1540420000001,
45+
"max": 1134.9154159999998,
46+
"stddev": 56.06532298235639,
47+
"meanRss": 213300019.2,
48+
"meanUserCpu": 936,
49+
"meanSysCpu": 228,
5050
"runs": 7,
5151
"validRuns": 7,
5252
"failures": 0
5353
},
5454
{
5555
"label": "vitest + jsdom",
56-
"mean": 964.3196584000004,
57-
"min": 949.5501660000009,
58-
"max": 986.9945420000004,
59-
"stddev": 16.60550682561403,
60-
"meanRss": 155179417.6,
61-
"meanUserCpu": 3336,
62-
"meanSysCpu": 1102,
56+
"mean": 1192.7835997999996,
57+
"min": 1129.2755830000006,
58+
"max": 1268.7202919999982,
59+
"stddev": 56.83080807294834,
60+
"meanRss": 159652249.6,
61+
"meanUserCpu": 3798,
62+
"meanSysCpu": 1380,
6363
"runs": 7,
6464
"validRuns": 7,
6565
"failures": 0
6666
},
6767
{
6868
"label": "vitest + happy-dom",
69-
"mean": 837.8697498000001,
70-
"min": 812.1916249999995,
71-
"max": 864.1250409999993,
72-
"stddev": 20.924101623413893,
73-
"meanRss": 121916620.8,
74-
"meanUserCpu": 2942,
75-
"meanSysCpu": 1006,
69+
"mean": 1041.3667920000007,
70+
"min": 990.0950420000008,
71+
"max": 1126.3293750000012,
72+
"stddev": 47.26983715919258,
73+
"meanRss": 122814464,
74+
"meanUserCpu": 3346,
75+
"meanSysCpu": 1156,
7676
"runs": 7,
7777
"validRuns": 7,
7878
"failures": 0
7979
}
8080
]
81-
}
81+
}

benchmark/tests/poku/concurrency.test.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const ResourceView = ({ resource }) => {
99
return <h2>{value}</h2>;
1010
};
1111

12-
test('renders a resolved use() resource under Suspense', () => {
12+
test('renders a resolved use() resource under Suspense', async () => {
1313
const value = 'Loaded from use() resource';
1414
const resolvedResource = {
1515
status: 'fulfilled',
@@ -30,7 +30,7 @@ test('renders a resolved use() resource under Suspense', () => {
3030
);
3131
});
3232

33-
await test('runs urgent and transition update pipeline', async () => {
33+
test('runs urgent and transition update pipeline', async () => {
3434
const TransitionPipeline = () => {
3535
const [urgentState, setUrgentState] = useState('idle');
3636
const [deferredState, setDeferredState] = useState('idle');

benchmark/tests/poku/context.test.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const ThemeLabel = () => {
1111
return <p>Theme: {theme}</p>;
1212
};
1313

14-
test('injects context values via wrapper', () => {
14+
test('injects context values via wrapper', async () => {
1515
const ThemeWrapper = ({ children }) => (
1616
<ThemeContext.Provider value='dark'>{children}</ThemeContext.Provider>
1717
);

benchmark/tests/poku/counter.test.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const Counter = ({ initialCount = 0 }) => {
1717
);
1818
};
1919

20-
test('renders and updates a React component', () => {
20+
test('renders and updates a React component', async () => {
2121
render(<Counter initialCount={1} />);
2222

2323
assert.strictEqual(

benchmark/tests/poku/hooks.test.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const HookHarness = () => {
3232
);
3333
};
3434

35-
test('tests custom hooks through a component harness', () => {
35+
test('tests custom hooks through a component harness', async () => {
3636
render(<HookHarness />);
3737

3838
assert.strictEqual(
@@ -46,7 +46,7 @@ test('tests custom hooks through a component harness', () => {
4646
);
4747
});
4848

49-
test('tests hook logic directly with renderHook', () => {
49+
test('tests hook logic directly with renderHook', async () => {
5050
const { result } = renderHook(({ initial }) => useToggle(initial), {
5151
initialProps: { initial: true },
5252
});

0 commit comments

Comments
 (0)