@ricsam/isolate-test-utils 0.1.9 → 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 (46) hide show
  1. package/README.md +2 -2
  2. package/dist/cjs/fetch-context.cjs +66 -0
  3. package/dist/cjs/fetch-context.cjs.map +10 -0
  4. package/dist/cjs/fs-context.cjs +73 -0
  5. package/dist/cjs/fs-context.cjs.map +10 -0
  6. package/dist/cjs/index.cjs +121 -0
  7. package/dist/cjs/index.cjs.map +10 -0
  8. package/{src/mock-fs.ts → dist/cjs/mock-fs.cjs} +63 -97
  9. package/dist/cjs/mock-fs.cjs.map +10 -0
  10. package/dist/cjs/native-input-test.cjs +347 -0
  11. package/dist/cjs/native-input-test.cjs.map +10 -0
  12. package/dist/cjs/package.json +5 -0
  13. package/dist/cjs/runtime-context.cjs +97 -0
  14. package/dist/cjs/runtime-context.cjs.map +10 -0
  15. package/dist/cjs/server.cjs +109 -0
  16. package/dist/cjs/server.cjs.map +10 -0
  17. package/dist/mjs/fetch-context.mjs +23 -0
  18. package/dist/mjs/fetch-context.mjs.map +10 -0
  19. package/dist/mjs/fs-context.mjs +30 -0
  20. package/dist/mjs/fs-context.mjs.map +10 -0
  21. package/dist/mjs/index.mjs +78 -0
  22. package/dist/mjs/index.mjs.map +10 -0
  23. package/dist/mjs/mock-fs.mjs +181 -0
  24. package/dist/mjs/mock-fs.mjs.map +10 -0
  25. package/{src/native-input-test.ts → dist/mjs/native-input-test.mjs} +60 -169
  26. package/dist/mjs/native-input-test.mjs.map +10 -0
  27. package/dist/mjs/package.json +5 -0
  28. package/dist/mjs/runtime-context.mjs +67 -0
  29. package/dist/mjs/runtime-context.mjs.map +10 -0
  30. package/dist/mjs/server.mjs +79 -0
  31. package/dist/mjs/server.mjs.map +10 -0
  32. package/dist/types/fetch-context.d.ts +7 -0
  33. package/dist/types/fs-context.d.ts +30 -0
  34. package/dist/types/index.d.ts +88 -0
  35. package/dist/types/mock-fs.d.ts +59 -0
  36. package/dist/types/native-input-test.d.ts +29 -0
  37. package/dist/types/runtime-context.d.ts +73 -0
  38. package/dist/types/server.d.ts +53 -0
  39. package/package.json +45 -18
  40. package/CHANGELOG.md +0 -109
  41. package/src/fetch-context.ts +0 -33
  42. package/src/fs-context.ts +0 -65
  43. package/src/index.test.ts +0 -472
  44. package/src/index.ts +0 -177
  45. package/src/runtime-context.ts +0 -148
  46. 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.9",
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,109 +0,0 @@
1
- # @ricsam/isolate-test-utils
2
-
3
- ## 0.1.9
4
-
5
- ### Patch Changes
6
-
7
- - target node when building
8
- - Updated dependencies
9
- - @ricsam/isolate-console@0.1.9
10
- - @ricsam/isolate-core@0.1.9
11
- - @ricsam/isolate-fetch@0.1.9
12
- - @ricsam/isolate-fs@0.1.9
13
- - @ricsam/isolate-runtime@0.1.10
14
-
15
- ## 0.1.8
16
-
17
- ### Patch Changes
18
-
19
- - various updates
20
- - Updated dependencies
21
- - @ricsam/isolate-console@0.1.8
22
- - @ricsam/isolate-core@0.1.8
23
- - @ricsam/isolate-fetch@0.1.8
24
- - @ricsam/isolate-fs@0.1.8
25
- - @ricsam/isolate-runtime@0.1.9
26
-
27
- ## 0.1.7
28
-
29
- ### Patch Changes
30
-
31
- - fix bugs
32
- - Updated dependencies
33
- - @ricsam/isolate-fetch@0.1.7
34
- - @ricsam/isolate-core@0.1.7
35
- - @ricsam/isolate-fs@0.1.7
36
- - @ricsam/isolate-console@0.1.7
37
- - @ricsam/isolate-runtime@0.1.8
38
-
39
- ## 0.1.6
40
-
41
- ### Patch Changes
42
-
43
- - new version
44
- - Updated dependencies
45
- - @ricsam/isolate-console@0.1.6
46
- - @ricsam/isolate-core@0.1.6
47
- - @ricsam/isolate-fetch@0.1.6
48
- - @ricsam/isolate-fs@0.1.6
49
- - @ricsam/isolate-runtime@0.1.7
50
-
51
- ## 0.1.5
52
-
53
- ### Patch Changes
54
-
55
- - new API
56
- - Updated dependencies
57
- - @ricsam/isolate-runtime@0.1.5
58
- - @ricsam/isolate-console@0.1.5
59
- - @ricsam/isolate-core@0.1.5
60
- - @ricsam/isolate-fetch@0.1.5
61
- - @ricsam/isolate-fs@0.1.5
62
-
63
- ## 0.1.4
64
-
65
- ### Patch Changes
66
-
67
- - new packages
68
- - Updated dependencies
69
- - @ricsam/isolate-console@0.1.4
70
- - @ricsam/isolate-core@0.1.4
71
- - @ricsam/isolate-fetch@0.1.4
72
- - @ricsam/isolate-fs@0.1.4
73
- - @ricsam/isolate-runtime@0.1.4
74
-
75
- ## 0.1.3
76
-
77
- ### Patch Changes
78
-
79
- - add playwright package
80
- - Updated dependencies
81
- - @ricsam/isolate-console@0.1.3
82
- - @ricsam/isolate-core@0.1.3
83
- - @ricsam/isolate-fetch@0.1.3
84
- - @ricsam/isolate-fs@0.1.3
85
- - @ricsam/isolate-runtime@0.1.3
86
-
87
- ## 0.1.2
88
-
89
- ### Patch Changes
90
-
91
- - new build script
92
- - Updated dependencies
93
- - @ricsam/isolate-console@0.1.2
94
- - @ricsam/isolate-core@0.1.2
95
- - @ricsam/isolate-fetch@0.1.2
96
- - @ricsam/isolate-fs@0.1.2
97
- - @ricsam/isolate-runtime@0.1.2
98
-
99
- ## 0.1.1
100
-
101
- ### Patch Changes
102
-
103
- - initial release
104
- - Updated dependencies
105
- - @ricsam/isolate-console@0.1.1
106
- - @ricsam/isolate-core@0.1.1
107
- - @ricsam/isolate-fetch@0.1.1
108
- - @ricsam/isolate-fs@0.1.1
109
- - @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
- }