the universal sandbox runtime for agents and humans.
pocketenv.io
sandbox
openclaw
agent
claude-code
vercel-sandbox
deno-sandbox
cloudflare-sandbox
atproto
sprites
daytona
1/**
2 * Shared test helpers for xrpc handler tests.
3 */
4
5/**
6 * Creates a chainable Drizzle-like mock db.
7 *
8 * Every method call returns a new proxy so you can chain any sequence of
9 * `.select().from().where().execute()` etc. Each call to `.execute()`
10 * consumes the next entry from `results` in order.
11 *
12 * Special handling:
13 * • `.transaction(fn)` – invokes `fn` with a fresh chain (same counter)
14 * • `.then` / `.catch` / `.finally` – undefined (prevents accidental
15 * Promise coercion of the chain itself)
16 */
17export function mockDb(...results: unknown[]) {
18 let idx = 0;
19
20 function chain(): any {
21 return new Proxy(
22 {},
23 {
24 get(_t, key: string | symbol) {
25 if (key === "execute") return () => Promise.resolve(results[idx++]);
26 if (key === "transaction")
27 return (fn: (tx: any) => any) => fn(chain());
28 if (
29 key === "then" ||
30 key === "catch" ||
31 key === "finally" ||
32 key === Symbol.toPrimitive ||
33 key === Symbol.iterator
34 )
35 return undefined;
36 return (..._args: any[]) => chain();
37 },
38 },
39 );
40 }
41
42 return chain();
43}
44
45// ---------------------------------------------------------------------------
46// Shared fixtures
47// ---------------------------------------------------------------------------
48
49export const MOCK_SANDBOX = {
50 id: "sb-abc123",
51 name: "test-sandbox",
52 provider: "cloudflare",
53 displayName: "Test Sandbox",
54 description: "A sandbox for testing",
55 topics: ["testing"],
56 base: null as string | null,
57 status: "running",
58 repo: "https://github.com/test/repo",
59 logo: null as string | null,
60 readme: "# Test",
61 installs: 42,
62 uri: "at://did:plc:xyz/io.pocketenv.sandbox/tid1",
63 sandboxId: null as string | null,
64 publicKey: "pk-abc",
65 userId: "user-1",
66 instanceType: null as string | null,
67 vcpus: 2,
68 memory: 4,
69 disk: 10,
70 keepAlive: false,
71 sleepAfter: null as string | null,
72 cid: null as string | null,
73 createdAt: new Date("2024-01-01T00:00:00Z"),
74 startedAt: new Date("2024-01-02T00:00:00Z"),
75 updatedAt: new Date("2024-01-01T00:00:00Z"),
76};
77
78export const MOCK_USER = {
79 id: "user-1",
80 did: "did:plc:testuser",
81 displayName: "Test User",
82 handle: "testuser.bsky.social",
83 avatar: "https://cdn.bsky.app/img/avatar.jpg",
84 createdAt: new Date("2023-01-01T00:00:00Z"),
85 updatedAt: new Date("2023-06-01T00:00:00Z"),
86};
87
88export const MOCK_SECRET = {
89 id: "secret-1",
90 name: "MY_API_KEY",
91 value: "encrypted-value",
92 redacted: true,
93 createdAt: new Date("2024-03-01T00:00:00Z"),
94 updatedAt: new Date("2024-03-01T00:00:00Z"),
95};
96
97// ---------------------------------------------------------------------------
98// Mock server builders
99// ---------------------------------------------------------------------------
100
101/** Builds a minimal server mock and returns the captured handler after registration. */
102export function captureSandboxHandler(
103 method: string,
104 register: (server: any, ctx: any) => void,
105 ctx: any,
106) {
107 let capturedHandler: ((opts: any) => Promise<any>) | null = null;
108 const server = {
109 io: {
110 pocketenv: {
111 sandbox: {
112 [method]: (config: { handler: any }) => {
113 capturedHandler = config.handler;
114 },
115 },
116 },
117 },
118 };
119 register(server, ctx);
120 if (!capturedHandler)
121 throw new Error(`Handler for ${method} was not registered`);
122 return capturedHandler;
123}
124
125export function captureSecretHandler(
126 method: string,
127 register: (server: any, ctx: any) => void,
128 ctx: any,
129) {
130 let capturedHandler: ((opts: any) => Promise<any>) | null = null;
131 const server = {
132 io: {
133 pocketenv: {
134 secret: {
135 [method]: (config: { handler: any }) => {
136 capturedHandler = config.handler;
137 },
138 },
139 },
140 },
141 };
142 register(server, ctx);
143 if (!capturedHandler)
144 throw new Error(`Handler for ${method} was not registered`);
145 return capturedHandler;
146}
147
148// ---------------------------------------------------------------------------
149// Auth mocks
150// ---------------------------------------------------------------------------
151
152export const authWithDid = (did = "did:plc:testuser") => ({
153 credentials: { did },
154 artifacts: false,
155});
156
157export const authNoCredentials = { artifacts: false };