@ricsam/isolate-test-utils 0.1.10 → 0.1.11

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.
Files changed (45) hide show
  1. package/dist/cjs/fetch-context.cjs +66 -0
  2. package/dist/cjs/fetch-context.cjs.map +10 -0
  3. package/dist/cjs/fs-context.cjs +73 -0
  4. package/dist/cjs/fs-context.cjs.map +10 -0
  5. package/dist/cjs/index.cjs +121 -0
  6. package/dist/cjs/index.cjs.map +10 -0
  7. package/{src/mock-fs.ts → dist/cjs/mock-fs.cjs} +63 -97
  8. package/dist/cjs/mock-fs.cjs.map +10 -0
  9. package/dist/cjs/native-input-test.cjs +347 -0
  10. package/dist/cjs/native-input-test.cjs.map +10 -0
  11. package/dist/cjs/package.json +5 -0
  12. package/dist/cjs/runtime-context.cjs +97 -0
  13. package/dist/cjs/runtime-context.cjs.map +10 -0
  14. package/dist/cjs/server.cjs +109 -0
  15. package/dist/cjs/server.cjs.map +10 -0
  16. package/dist/mjs/fetch-context.mjs +23 -0
  17. package/dist/mjs/fetch-context.mjs.map +10 -0
  18. package/dist/mjs/fs-context.mjs +30 -0
  19. package/dist/mjs/fs-context.mjs.map +10 -0
  20. package/dist/mjs/index.mjs +78 -0
  21. package/dist/mjs/index.mjs.map +10 -0
  22. package/dist/mjs/mock-fs.mjs +181 -0
  23. package/dist/mjs/mock-fs.mjs.map +10 -0
  24. package/{src/native-input-test.ts → dist/mjs/native-input-test.mjs} +60 -169
  25. package/dist/mjs/native-input-test.mjs.map +10 -0
  26. package/dist/mjs/package.json +5 -0
  27. package/dist/mjs/runtime-context.mjs +67 -0
  28. package/dist/mjs/runtime-context.mjs.map +10 -0
  29. package/dist/mjs/server.mjs +79 -0
  30. package/dist/mjs/server.mjs.map +10 -0
  31. package/dist/types/fetch-context.d.ts +7 -0
  32. package/dist/types/fs-context.d.ts +30 -0
  33. package/dist/types/index.d.ts +88 -0
  34. package/dist/types/mock-fs.d.ts +59 -0
  35. package/dist/types/native-input-test.d.ts +29 -0
  36. package/dist/types/runtime-context.d.ts +73 -0
  37. package/dist/types/server.d.ts +53 -0
  38. package/package.json +45 -18
  39. package/CHANGELOG.md +0 -119
  40. package/src/fetch-context.ts +0 -33
  41. package/src/fs-context.ts +0 -65
  42. package/src/index.test.ts +0 -472
  43. package/src/index.ts +0 -177
  44. package/src/runtime-context.ts +0 -148
  45. package/src/server.ts +0 -150
@@ -0,0 +1,30 @@
1
+ import type ivm from "isolated-vm";
2
+ import { MockFileSystem } from "./mock-fs.ts";
3
+ export interface FsTestContext {
4
+ isolate: ivm.Isolate;
5
+ context: ivm.Context;
6
+ mockFs: MockFileSystem;
7
+ dispose(): void;
8
+ }
9
+ /**
10
+ * Create a test context with file system APIs set up using a mock file system.
11
+ *
12
+ * @example
13
+ * const ctx = await createFsTestContext();
14
+ *
15
+ * // Set up initial files
16
+ * ctx.mockFs.setFile("/test.txt", "Hello, World!");
17
+ *
18
+ * // Use file system APIs in the isolate
19
+ * const result = await ctx.context.eval(`
20
+ * (async () => {
21
+ * const root = await navigator.storage.getDirectory();
22
+ * const fileHandle = await root.getFileHandle("test.txt");
23
+ * const file = await fileHandle.getFile();
24
+ * return await file.text();
25
+ * })()
26
+ * `, { promise: true });
27
+ *
28
+ * ctx.dispose();
29
+ */
30
+ export declare function createFsTestContext(): Promise<FsTestContext>;
@@ -0,0 +1,88 @@
1
+ import type ivm from "isolated-vm";
2
+ export interface TestContext {
3
+ isolate: ivm.Isolate;
4
+ context: ivm.Context;
5
+ dispose(): void;
6
+ }
7
+ export interface TestResult<T> {
8
+ result: T;
9
+ logs: Array<{
10
+ level: string;
11
+ args: unknown[];
12
+ }>;
13
+ }
14
+ /**
15
+ * Create a basic test context for isolated-vm tests.
16
+ * This creates a bare context without any APIs set up.
17
+ */
18
+ export declare function createTestContext(): Promise<TestContext>;
19
+ /**
20
+ * Create a test context with core APIs set up (Blob, File, URL, streams, etc.)
21
+ */
22
+ export declare function createCoreTestContext(): Promise<TestContext>;
23
+ /**
24
+ * Synchronously evaluate code and return typed result.
25
+ * Use this for simple expressions that don't involve promises.
26
+ *
27
+ * @example
28
+ * const result = evalCode<number>(ctx.context, "1 + 1");
29
+ * // result === 2
30
+ */
31
+ export declare function evalCode<T = unknown>(context: ivm.Context, code: string): T;
32
+ /**
33
+ * Asynchronously evaluate code that may return promises.
34
+ * Automatically wraps code to handle promise resolution.
35
+ *
36
+ * @example
37
+ * const result = await evalCodeAsync<string>(ctx.context, `
38
+ * (async () => {
39
+ * return "hello";
40
+ * })()
41
+ * `);
42
+ */
43
+ export declare function evalCodeAsync<T = unknown>(context: ivm.Context, code: string): Promise<T>;
44
+ /**
45
+ * Evaluate code and return the result as JSON (for complex objects).
46
+ * Useful when you need to extract structured data from the isolate.
47
+ *
48
+ * @example
49
+ * const data = evalCodeJson<{ name: string }>(ctx.context, `
50
+ * JSON.stringify({ name: "test" })
51
+ * `);
52
+ */
53
+ export declare function evalCodeJson<T = unknown>(context: ivm.Context, code: string): T;
54
+ /**
55
+ * Evaluate async code and return the result as JSON (for complex objects).
56
+ *
57
+ * @example
58
+ * const data = await evalCodeJsonAsync<{ status: number }>(ctx.context, `
59
+ * (async () => {
60
+ * const response = await fetch("...");
61
+ * return JSON.stringify({ status: response.status });
62
+ * })()
63
+ * `);
64
+ */
65
+ export declare function evalCodeJsonAsync<T = unknown>(context: ivm.Context, code: string): Promise<T>;
66
+ /**
67
+ * Inject values into the isolate's global scope before running code.
68
+ *
69
+ * @example
70
+ * await injectGlobals(ctx.context, {
71
+ * testInput: "hello",
72
+ * testConfig: { debug: true }
73
+ * });
74
+ * const result = evalCode<string>(ctx.context, "testInput");
75
+ */
76
+ export declare function injectGlobals(context: ivm.Context, values: Record<string, unknown>): Promise<void>;
77
+ export { MockFileSystem } from "./mock-fs.ts";
78
+ export { createFsTestContext } from "./fs-context.ts";
79
+ export type { FsTestContext } from "./fs-context.ts";
80
+ export { createRuntimeTestContext } from "./runtime-context.ts";
81
+ export type { RuntimeTestContext } from "./runtime-context.ts";
82
+ export { startIntegrationServer } from "./server.ts";
83
+ export type { IntegrationServer } from "./server.ts";
84
+ export { runTestCode } from "./native-input-test.ts";
85
+ export type { TestRunner, TestRuntime } from "./native-input-test.ts";
86
+ export { createFetchTestContext } from "./fetch-context.ts";
87
+ export type { FetchTestContext } from "./fetch-context.ts";
88
+ export type { FileSystemHandler } from "@ricsam/isolate-fs";
@@ -0,0 +1,59 @@
1
+ import type { FileSystemHandler } from "@ricsam/isolate-fs";
2
+ /**
3
+ * In-memory file system implementation for testing.
4
+ * Implements the FileSystemHandler interface from @ricsam/isolate-fs.
5
+ */
6
+ export declare class MockFileSystem implements FileSystemHandler {
7
+ files: Map<string, {
8
+ data: Uint8Array;
9
+ lastModified: number;
10
+ type: string;
11
+ }>;
12
+ directories: Set<string>;
13
+ getFileHandle(path: string, options?: {
14
+ create?: boolean;
15
+ }): Promise<void>;
16
+ getDirectoryHandle(path: string, options?: {
17
+ create?: boolean;
18
+ }): Promise<void>;
19
+ removeEntry(path: string, options?: {
20
+ recursive?: boolean;
21
+ }): Promise<void>;
22
+ readDirectory(path: string): Promise<Array<{
23
+ name: string;
24
+ kind: "file" | "directory";
25
+ }>>;
26
+ readFile(path: string): Promise<{
27
+ data: Uint8Array;
28
+ size: number;
29
+ lastModified: number;
30
+ type: string;
31
+ }>;
32
+ writeFile(path: string, data: Uint8Array, position?: number): Promise<void>;
33
+ truncateFile(path: string, size: number): Promise<void>;
34
+ getFileMetadata(path: string): Promise<{
35
+ size: number;
36
+ lastModified: number;
37
+ type: string;
38
+ }>;
39
+ /**
40
+ * Reset the mock file system to its initial state (empty, with only root directory)
41
+ */
42
+ reset(): void;
43
+ /**
44
+ * Convenience method to set a file with string or binary content
45
+ */
46
+ setFile(path: string, content: string | Uint8Array, type?: string): void;
47
+ /**
48
+ * Get file content as Uint8Array, or undefined if not found
49
+ */
50
+ getFile(path: string): Uint8Array | undefined;
51
+ /**
52
+ * Get file content as string, or undefined if not found
53
+ */
54
+ getFileAsString(path: string): string | undefined;
55
+ /**
56
+ * Create a directory (and any necessary parent directories)
57
+ */
58
+ createDirectory(path: string): void;
59
+ }
@@ -0,0 +1,29 @@
1
+ import ivm from "isolated-vm";
2
+ export interface TestRuntime {
3
+ logs: Record<string, unknown>;
4
+ result: unknown;
5
+ }
6
+ export interface TestRunner {
7
+ input(inputs: Record<string, unknown>): TestRuntime;
8
+ }
9
+ /**
10
+ * Run isolate code with native objects as input and capture logs
11
+ *
12
+ * This utility allows testing whether native objects passed INTO the isolate
13
+ * behave like isolate instances. It converts native web API classes (Headers,
14
+ * Request, Response, URL, Blob, File, FormData) to their isolate equivalents
15
+ * before executing the test code.
16
+ *
17
+ * @example
18
+ * const runtime = runTestCode(ctx.context, `
19
+ * const headers = testingInput.headers;
20
+ * log("instanceof", headers instanceof Headers);
21
+ * log("contentType", headers.get("content-type"));
22
+ * `).input({
23
+ * headers: new Headers({ "content-type": "application/json" })
24
+ * });
25
+ *
26
+ * expect(runtime.logs.instanceof).toBe(true);
27
+ * expect(runtime.logs.contentType).toBe("application/json");
28
+ */
29
+ export declare function runTestCode(context: ivm.Context, code: string): TestRunner;
@@ -0,0 +1,73 @@
1
+ import { MockFileSystem } from "./mock-fs.ts";
2
+ export interface MockResponse {
3
+ status?: number;
4
+ body?: string;
5
+ headers?: Record<string, string>;
6
+ }
7
+ export interface RuntimeTestContextOptions {
8
+ /** Enable file system APIs with mock file system */
9
+ fs?: boolean;
10
+ }
11
+ export interface RuntimeTestContext {
12
+ /** Execute code in the runtime (ES module mode, supports top-level await) */
13
+ eval(code: string): Promise<void>;
14
+ /** Clear all pending timers */
15
+ clearTimers(): void;
16
+ /** Dispatch an HTTP request to the serve() handler */
17
+ dispatchRequest(request: Request): Promise<Response>;
18
+ /** Dispose all resources */
19
+ dispose(): Promise<void>;
20
+ /** Captured console.log calls */
21
+ logs: Array<{
22
+ level: string;
23
+ stdout: string;
24
+ }>;
25
+ /** Captured fetch calls */
26
+ fetchCalls: Array<{
27
+ url: string;
28
+ method: string;
29
+ headers: [string, string][];
30
+ }>;
31
+ /** Set the mock response for the next fetch call */
32
+ setMockResponse(response: MockResponse): void;
33
+ /** Mock file system (only available if fs option is true) */
34
+ mockFs: MockFileSystem;
35
+ /**
36
+ * Get a result from the isolate. Call `await setResult(value)` in your eval code
37
+ * to pass a value back to the host.
38
+ */
39
+ getResult<T = unknown>(): T | undefined;
40
+ /** Clear the stored result */
41
+ clearResult(): void;
42
+ }
43
+ /**
44
+ * Create a full runtime test context with all APIs set up.
45
+ * Includes console logging capture, fetch mocking, and optionally file system.
46
+ *
47
+ * @example
48
+ * const ctx = await createRuntimeTestContext({ fs: true });
49
+ *
50
+ * // Set up mock response for fetch
51
+ * ctx.setMockResponse({ status: 200, body: '{"data": "test"}' });
52
+ *
53
+ * // Run code and pass result back via setResult
54
+ * await ctx.eval(`
55
+ * console.log("Starting fetch...");
56
+ * const response = await fetch("https://api.example.com/data");
57
+ * const data = await response.json();
58
+ * console.log("Got data:", data);
59
+ * setResult(data);
60
+ * `);
61
+ *
62
+ * // Get the result
63
+ * console.log(ctx.getResult()); // { data: "test" }
64
+ *
65
+ * // Check logs
66
+ * console.log(ctx.logs); // [{ level: "log", stdout: "Starting fetch..." }, ...]
67
+ *
68
+ * // Check fetch calls
69
+ * console.log(ctx.fetchCalls); // [{ url: "https://api.example.com/data", method: "GET", ... }]
70
+ *
71
+ * await ctx.dispose();
72
+ */
73
+ export declare function createRuntimeTestContext(options?: RuntimeTestContextOptions): Promise<RuntimeTestContext>;
@@ -0,0 +1,53 @@
1
+ export interface MockServerResponse {
2
+ status?: number;
3
+ body?: string;
4
+ headers?: Record<string, string>;
5
+ }
6
+ export interface RecordedRequest {
7
+ method: string;
8
+ path: string;
9
+ headers: Record<string, string>;
10
+ body?: string;
11
+ }
12
+ export interface IntegrationServer {
13
+ /** The base URL of the server (e.g., "http://localhost:3000") */
14
+ url: string;
15
+ /** The port the server is listening on */
16
+ port: number;
17
+ /** Close the server */
18
+ close(): Promise<void>;
19
+ /** Set the response for a specific path */
20
+ setResponse(path: string, response: MockServerResponse): void;
21
+ /** Set a default response for any unmatched path */
22
+ setDefaultResponse(response: MockServerResponse): void;
23
+ /** Get all recorded requests */
24
+ getRequests(): RecordedRequest[];
25
+ /** Clear all recorded requests */
26
+ clearRequests(): void;
27
+ /** Clear all configured responses */
28
+ clearResponses(): void;
29
+ }
30
+ /**
31
+ * Start an HTTP server for integration tests.
32
+ * Useful for testing fetch operations against a real server.
33
+ *
34
+ * @example
35
+ * const server = await startIntegrationServer();
36
+ *
37
+ * server.setResponse("/api/data", {
38
+ * status: 200,
39
+ * body: JSON.stringify({ message: "Hello" }),
40
+ * headers: { "Content-Type": "application/json" }
41
+ * });
42
+ *
43
+ * // In your test
44
+ * const response = await fetch(`${server.url}/api/data`);
45
+ * const data = await response.json();
46
+ *
47
+ * // Check what requests were made
48
+ * const requests = server.getRequests();
49
+ * console.log(requests[0].path); // "/api/data"
50
+ *
51
+ * await server.close();
52
+ */
53
+ export declare function startIntegrationServer(port?: number): Promise<IntegrationServer>;
package/package.json CHANGED
@@ -1,21 +1,23 @@
1
1
  {
2
2
  "name": "@ricsam/isolate-test-utils",
3
- "version": "0.1.10",
4
- "type": "module",
5
- "main": "./src/index.ts",
6
- "types": "./src/index.ts",
3
+ "version": "0.1.11",
4
+ "main": "./dist/cjs/index.cjs",
5
+ "types": "./dist/types/index.d.ts",
7
6
  "exports": {
8
7
  ".": {
9
- "import": "./src/index.ts",
10
- "types": "./src/index.ts"
8
+ "types": "./dist/types/index.d.ts",
9
+ "require": "./dist/cjs/index.cjs",
10
+ "import": "./dist/mjs/index.mjs"
11
11
  },
12
12
  "./fs": {
13
- "import": "./src/fs-context.ts",
14
- "types": "./src/fs-context.ts"
13
+ "types": "./dist/types/fs-context.d.ts",
14
+ "require": "./dist/cjs/fs-context.cjs",
15
+ "import": "./dist/mjs/fs-context.mjs"
15
16
  },
16
17
  "./runtime": {
17
- "import": "./src/runtime-context.ts",
18
- "types": "./src/runtime-context.ts"
18
+ "types": "./dist/types/runtime-context.d.ts",
19
+ "require": "./dist/cjs/runtime-context.cjs",
20
+ "import": "./dist/mjs/runtime-context.mjs"
19
21
  }
20
22
  },
21
23
  "scripts": {
@@ -26,12 +28,6 @@
26
28
  "dependencies": {
27
29
  "isolated-vm": "^6"
28
30
  },
29
- "devDependencies": {
30
- "@ricsam/isolate-fs": "*",
31
- "@ricsam/isolate-runtime": "*",
32
- "@types/node": "^24",
33
- "typescript": "^5"
34
- },
35
31
  "peerDependencies": {
36
32
  "isolated-vm": "^6",
37
33
  "@ricsam/isolate-console": "*",
@@ -50,5 +46,36 @@
50
46
  "@ricsam/isolate-runtime": {
51
47
  "optional": true
52
48
  }
53
- }
54
- }
49
+ },
50
+ "author": "ricsam <oss@ricsam.dev>",
51
+ "license": "MIT",
52
+ "repository": {
53
+ "type": "git",
54
+ "url": "git+https://github.com/ricsam/isolate.git",
55
+ "directory": "packages/test-utils"
56
+ },
57
+ "bugs": {
58
+ "url": "https://github.com/ricsam/isolate/issues"
59
+ },
60
+ "homepage": "https://github.com/ricsam/isolate#readme",
61
+ "keywords": [
62
+ "isolated-vm",
63
+ "sandbox",
64
+ "javascript",
65
+ "runtime",
66
+ "fetch",
67
+ "filesystem",
68
+ "streams",
69
+ "v8",
70
+ "isolate"
71
+ ],
72
+ "description": "Utilities for isolated-vm - run JavaScript in a sandboxed V8 environment with web-standard APIs",
73
+ "module": "./dist/mjs/index.mjs",
74
+ "publishConfig": {
75
+ "access": "public"
76
+ },
77
+ "files": [
78
+ "dist",
79
+ "README.md"
80
+ ]
81
+ }
package/CHANGELOG.md DELETED
@@ -1,119 +0,0 @@
1
- # @ricsam/isolate-test-utils
2
-
3
- ## 0.1.10
4
-
5
- ### Patch Changes
6
-
7
- - new console.log handling
8
- - Updated dependencies
9
- - @ricsam/isolate-console@0.1.10
10
- - @ricsam/isolate-runtime@0.1.11
11
- - @ricsam/isolate-fetch@0.1.11
12
-
13
- ## 0.1.9
14
-
15
- ### Patch Changes
16
-
17
- - target node when building
18
- - Updated dependencies
19
- - @ricsam/isolate-console@0.1.9
20
- - @ricsam/isolate-core@0.1.9
21
- - @ricsam/isolate-fetch@0.1.9
22
- - @ricsam/isolate-fs@0.1.9
23
- - @ricsam/isolate-runtime@0.1.10
24
-
25
- ## 0.1.8
26
-
27
- ### Patch Changes
28
-
29
- - various updates
30
- - Updated dependencies
31
- - @ricsam/isolate-console@0.1.8
32
- - @ricsam/isolate-core@0.1.8
33
- - @ricsam/isolate-fetch@0.1.8
34
- - @ricsam/isolate-fs@0.1.8
35
- - @ricsam/isolate-runtime@0.1.9
36
-
37
- ## 0.1.7
38
-
39
- ### Patch Changes
40
-
41
- - fix bugs
42
- - Updated dependencies
43
- - @ricsam/isolate-fetch@0.1.7
44
- - @ricsam/isolate-core@0.1.7
45
- - @ricsam/isolate-fs@0.1.7
46
- - @ricsam/isolate-console@0.1.7
47
- - @ricsam/isolate-runtime@0.1.8
48
-
49
- ## 0.1.6
50
-
51
- ### Patch Changes
52
-
53
- - new version
54
- - Updated dependencies
55
- - @ricsam/isolate-console@0.1.6
56
- - @ricsam/isolate-core@0.1.6
57
- - @ricsam/isolate-fetch@0.1.6
58
- - @ricsam/isolate-fs@0.1.6
59
- - @ricsam/isolate-runtime@0.1.7
60
-
61
- ## 0.1.5
62
-
63
- ### Patch Changes
64
-
65
- - new API
66
- - Updated dependencies
67
- - @ricsam/isolate-runtime@0.1.5
68
- - @ricsam/isolate-console@0.1.5
69
- - @ricsam/isolate-core@0.1.5
70
- - @ricsam/isolate-fetch@0.1.5
71
- - @ricsam/isolate-fs@0.1.5
72
-
73
- ## 0.1.4
74
-
75
- ### Patch Changes
76
-
77
- - new packages
78
- - Updated dependencies
79
- - @ricsam/isolate-console@0.1.4
80
- - @ricsam/isolate-core@0.1.4
81
- - @ricsam/isolate-fetch@0.1.4
82
- - @ricsam/isolate-fs@0.1.4
83
- - @ricsam/isolate-runtime@0.1.4
84
-
85
- ## 0.1.3
86
-
87
- ### Patch Changes
88
-
89
- - add playwright package
90
- - Updated dependencies
91
- - @ricsam/isolate-console@0.1.3
92
- - @ricsam/isolate-core@0.1.3
93
- - @ricsam/isolate-fetch@0.1.3
94
- - @ricsam/isolate-fs@0.1.3
95
- - @ricsam/isolate-runtime@0.1.3
96
-
97
- ## 0.1.2
98
-
99
- ### Patch Changes
100
-
101
- - new build script
102
- - Updated dependencies
103
- - @ricsam/isolate-console@0.1.2
104
- - @ricsam/isolate-core@0.1.2
105
- - @ricsam/isolate-fetch@0.1.2
106
- - @ricsam/isolate-fs@0.1.2
107
- - @ricsam/isolate-runtime@0.1.2
108
-
109
- ## 0.1.1
110
-
111
- ### Patch Changes
112
-
113
- - initial release
114
- - Updated dependencies
115
- - @ricsam/isolate-console@0.1.1
116
- - @ricsam/isolate-core@0.1.1
117
- - @ricsam/isolate-fetch@0.1.1
118
- - @ricsam/isolate-fs@0.1.1
119
- - @ricsam/isolate-runtime@0.1.1
@@ -1,33 +0,0 @@
1
- import type ivm from "isolated-vm";
2
- import type { TestContext } from "./index.ts";
3
-
4
- export interface FetchTestContext extends TestContext {
5
- // Context with fetch APIs set up
6
- }
7
-
8
- /**
9
- * Create a test context with fetch APIs set up (Headers, Request, Response, FormData, fetch)
10
- */
11
- export async function createFetchTestContext(): Promise<FetchTestContext> {
12
- const ivmModule = await import("isolated-vm");
13
- const { setupFetch, clearAllInstanceState } = await import(
14
- "@ricsam/isolate-fetch"
15
- );
16
-
17
- const isolate = new ivmModule.default.Isolate();
18
- const context = await isolate.createContext();
19
-
20
- clearAllInstanceState();
21
-
22
- const fetchHandle = await setupFetch(context);
23
-
24
- return {
25
- isolate,
26
- context,
27
- dispose() {
28
- fetchHandle.dispose();
29
- context.release();
30
- isolate.dispose();
31
- },
32
- };
33
- }
package/src/fs-context.ts DELETED
@@ -1,65 +0,0 @@
1
- import type ivm from "isolated-vm";
2
- import { MockFileSystem } from "./mock-fs.ts";
3
-
4
- export interface FsTestContext {
5
- isolate: ivm.Isolate;
6
- context: ivm.Context;
7
- mockFs: MockFileSystem;
8
- dispose(): void;
9
- }
10
-
11
- /**
12
- * Create a test context with file system APIs set up using a mock file system.
13
- *
14
- * @example
15
- * const ctx = await createFsTestContext();
16
- *
17
- * // Set up initial files
18
- * ctx.mockFs.setFile("/test.txt", "Hello, World!");
19
- *
20
- * // Use file system APIs in the isolate
21
- * const result = await ctx.context.eval(`
22
- * (async () => {
23
- * const root = await navigator.storage.getDirectory();
24
- * const fileHandle = await root.getFileHandle("test.txt");
25
- * const file = await fileHandle.getFile();
26
- * return await file.text();
27
- * })()
28
- * `, { promise: true });
29
- *
30
- * ctx.dispose();
31
- */
32
- export async function createFsTestContext(): Promise<FsTestContext> {
33
- const ivmModule = await import("isolated-vm");
34
- const { setupCore, clearAllInstanceState } = await import(
35
- "@ricsam/isolate-core"
36
- );
37
- const { setupFs } = await import("@ricsam/isolate-fs");
38
-
39
- const isolate = new ivmModule.default.Isolate();
40
- const context = await isolate.createContext();
41
-
42
- // Clear any previous instance state
43
- clearAllInstanceState();
44
-
45
- // Create mock file system
46
- const mockFs = new MockFileSystem();
47
-
48
- // Setup core APIs (required for Blob, File, streams)
49
- const coreHandle = await setupCore(context);
50
-
51
- // Setup file system APIs with mock handler
52
- const fsHandle = await setupFs(context, { getDirectory: async () => mockFs });
53
-
54
- return {
55
- isolate,
56
- context,
57
- mockFs,
58
- dispose() {
59
- fsHandle.dispose();
60
- coreHandle.dispose();
61
- context.release();
62
- isolate.dispose();
63
- },
64
- };
65
- }