1import { CallbackRegistry } from "../module-runner/module-runner.worker.ts";
2import { describe, expect, test, vi } from "vitest";
3
4vi.mock("cloudflare:workers", () => ({
5 DurableObject: class {},
6}));
7
8describe("module runner callback registry", () => {
9 test("hands the result back and forgets the entry", async () => {
10 const registry = new CallbackRegistry();
11 const namespace = { default: "module" };
12 const result = await registry.run(
13 (id) => registry.execute(id),
14 async () => namespace,
15 );
16 expect(result).toBe(namespace);
17 expect(registry.size).toBe(0);
18 });
19
20 test("forgets the entry when the callback fails", async () => {
21 const registry = new CallbackRegistry();
22 await expect(
23 registry.run(
24 (id) => registry.execute(id),
25 async () => {
26 throw new Error("evaluation failed");
27 },
28 ),
29 ).rejects.toThrow("evaluation failed");
30 expect(registry.size).toBe(0);
31 });
32
33 test("forgets the entry when the callback never runs", async () => {
34 const registry = new CallbackRegistry();
35 await expect(
36 registry.run(
37 async () => {
38 throw new Error("rpc failed");
39 },
40 async () => "unreached",
41 ),
42 ).rejects.toThrow("rpc failed");
43 expect(registry.size).toBe(0);
44 });
45
46 test("keeps concurrent callbacks apart", async () => {
47 const registry = new CallbackRegistry();
48 const results = await Promise.all(
49 [1, 2, 3].map((value) =>
50 registry.run(
51 (id) => registry.execute(id),
52 async () => value * 10,
53 ),
54 ),
55 );
56 expect(results).toEqual([10, 20, 30]);
57 expect(registry.size).toBe(0);
58 });
59
60 test("rejects an unknown id", async () => {
61 const registry = new CallbackRegistry();
62 await expect(registry.execute(42)).rejects.toThrow(
63 "No pending callback with id 42",
64 );
65 });
66});