@ricsam/isolate-test-environment 0.1.3 → 0.1.6

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 CHANGED
@@ -2,18 +2,67 @@
2
2
 
3
3
  Test primitives for running tests in sandboxed V8. Provides a Jest/Vitest-compatible API.
4
4
 
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm add @ricsam/isolate-test-environment
9
+ ```
10
+
11
+ ## Usage with isolate-runtime (Recommended)
12
+
13
+ The easiest way to use this package is through `@ricsam/isolate-runtime`:
14
+
15
+ ```typescript
16
+ import { createRuntime } from "@ricsam/isolate-runtime";
17
+
18
+ const runtime = await createRuntime({
19
+ testEnvironment: {
20
+ onEvent: (event) => {
21
+ // Receive lifecycle events during test execution
22
+ if (event.type === "testEnd") {
23
+ const icon = event.test.status === "pass" ? "✓" : "✗";
24
+ console.log(`${icon} ${event.test.fullName}`);
25
+ }
26
+ },
27
+ },
28
+ });
29
+
30
+ await runtime.eval(`
31
+ describe("math", () => {
32
+ it("adds numbers", () => {
33
+ expect(1 + 1).toBe(2);
34
+ });
35
+ it.todo("subtract numbers");
36
+ });
37
+ `);
38
+
39
+ const results = await runtime.testEnvironment.runTests();
40
+ console.log(`${results.passed}/${results.total} passed, ${results.todo} todo`);
41
+
42
+ // Check if tests exist before running
43
+ if (runtime.testEnvironment.hasTests()) {
44
+ console.log(`Found ${runtime.testEnvironment.getTestCount()} tests`);
45
+ }
46
+ ```
47
+
48
+ ## Low-level Usage (Direct ivm)
49
+
50
+ For advanced use cases with direct isolated-vm access:
51
+
5
52
  ```typescript
6
53
  import { setupTestEnvironment, runTests } from "@ricsam/isolate-test-environment";
7
54
 
8
55
  const handle = await setupTestEnvironment(context);
9
56
  ```
10
57
 
11
- **Injected Globals:**
58
+ ## Injected Globals
59
+
12
60
  - `describe`, `it`, `test` (with `.skip`, `.only`, `.todo` modifiers)
13
61
  - `beforeAll`, `afterAll`, `beforeEach`, `afterEach`
14
62
  - `expect` with matchers and `.not` modifier
15
63
 
16
- **Expect Matchers:**
64
+ ## Expect Matchers
65
+
17
66
  - `toBe(expected)` - Strict equality (`===`)
18
67
  - `toEqual(expected)` - Deep equality
19
68
  - `toStrictEqual(expected)` - Strict deep equality (includes prototype checks)
@@ -26,7 +75,7 @@ const handle = await setupTestEnvironment(context);
26
75
  - `toMatch(pattern)` - String/regex match
27
76
  - `toHaveProperty(path, value?)` - Object property check
28
77
 
29
- **Usage in Isolate:**
78
+ ## Usage in Isolate
30
79
 
31
80
  ```javascript
32
81
  describe("Math operations", () => {
@@ -57,35 +106,107 @@ expect(1).not.toBe(2);
57
106
  expect([1, 2]).not.toContain(3);
58
107
  ```
59
108
 
60
- **Running tests from host:**
109
+ ## Running Tests from Host
61
110
 
62
111
  ```typescript
63
- import { setupTestEnvironment, runTests } from "@ricsam/isolate-test-environment";
64
-
65
- // Setup test environment
66
- const handle = await setupTestEnvironment(context);
112
+ import { setupTestEnvironment, runTests, hasTests, getTestCount } from "@ricsam/isolate-test-environment";
113
+
114
+ // Setup test environment with optional event callback
115
+ const handle = await setupTestEnvironment(context, {
116
+ onEvent: (event) => {
117
+ switch (event.type) {
118
+ case "runStart":
119
+ console.log(`Running ${event.testCount} tests in ${event.suiteCount} suites`);
120
+ break;
121
+ case "testEnd":
122
+ console.log(`${event.test.status}: ${event.test.fullName}`);
123
+ break;
124
+ }
125
+ },
126
+ });
67
127
 
68
128
  // Load test code
69
129
  await context.eval(userProvidedTestCode, { promise: true });
70
130
 
131
+ // Check if any tests were registered
132
+ if (hasTests(context)) {
133
+ console.log(`Found ${getTestCount(context)} tests`);
134
+ }
135
+
71
136
  // Run all registered tests
72
137
  const results = await runTests(context);
73
138
  console.log(`${results.passed}/${results.total} passed`);
74
139
 
75
- // Results structure:
76
- // {
77
- // passed: number,
78
- // failed: number,
79
- // skipped: number,
80
- // total: number,
81
- // results: Array<{
82
- // name: string,
83
- // passed: boolean,
84
- // error?: string,
85
- // duration: number,
86
- // skipped?: boolean
87
- // }>
88
- // }
89
-
90
140
  handle.dispose();
91
- ```
141
+ ```
142
+
143
+ ## Types
144
+
145
+ ### RunResults
146
+
147
+ ```typescript
148
+ interface RunResults {
149
+ passed: number;
150
+ failed: number;
151
+ skipped: number;
152
+ todo: number;
153
+ total: number;
154
+ duration: number;
155
+ success: boolean; // true if no failures
156
+ suites: SuiteResult[]; // suite-level results
157
+ tests: TestResult[]; // individual test results
158
+ }
159
+ ```
160
+
161
+ ### TestResult
162
+
163
+ ```typescript
164
+ interface TestResult {
165
+ name: string;
166
+ suitePath: string[]; // suite ancestry
167
+ fullName: string; // "suite > nested > test name"
168
+ status: "pass" | "fail" | "skip" | "todo";
169
+ duration: number;
170
+ error?: TestError;
171
+ }
172
+
173
+ interface TestError {
174
+ message: string;
175
+ stack?: string;
176
+ expected?: unknown; // for assertion failures
177
+ actual?: unknown;
178
+ matcherName?: string; // e.g., "toBe", "toEqual"
179
+ }
180
+ ```
181
+
182
+ ### SuiteResult
183
+
184
+ ```typescript
185
+ interface SuiteResult {
186
+ name: string;
187
+ path: string[]; // ancestry path
188
+ fullName: string; // "outer > inner"
189
+ depth: number; // nesting level (0 for root)
190
+ passed: number;
191
+ failed: number;
192
+ skipped: number;
193
+ todo: number;
194
+ duration: number;
195
+ }
196
+ ```
197
+
198
+ ### TestEvent
199
+
200
+ ```typescript
201
+ type TestEvent =
202
+ | { type: "runStart"; testCount: number; suiteCount: number }
203
+ | { type: "suiteStart"; suite: SuiteInfo }
204
+ | { type: "suiteEnd"; suite: SuiteResult }
205
+ | { type: "testStart"; test: TestInfo }
206
+ | { type: "testEnd"; test: TestResult }
207
+ | { type: "runEnd"; results: RunResults };
208
+ ```
209
+
210
+ ## License
211
+
212
+ MIT