Skip to content

Commit 79af3b2

Browse files
committed
Unique directories
1 parent b534f09 commit 79af3b2

File tree

1 file changed

+56
-41
lines changed

1 file changed

+56
-41
lines changed

src/tool.vercel.integration.test.ts

Lines changed: 56 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
1+
// Excluded from pnpm test. Use pnpm test:vercel to run these tests.
12
import { Sandbox } from "@vercel/sandbox";
23
import type { ToolExecutionOptions } from "ai";
3-
import {
4-
afterAll,
5-
afterEach,
6-
assert,
7-
beforeAll,
8-
describe,
9-
expect,
10-
it,
11-
} from "vitest";
4+
import { afterAll, assert, beforeAll, describe, expect, it } from "vitest";
125
import { createBashTool } from "./tool.js";
136
import type { CommandResult } from "./types.js";
147

158
// AI SDK tool execute requires (args, options) - we provide test options
169
const opts: ToolExecutionOptions = { toolCallId: "test", messages: [] };
1710

11+
/** Generate a unique test directory to avoid race conditions between tests */
12+
function uniqueDir(): string {
13+
return `/vercel/sandbox/test-${Date.now()}-${Math.random()
14+
.toString(36)
15+
.slice(2, 8)}`;
16+
}
17+
1818
/**
1919
* Integration tests that verify createBashTool works correctly
2020
* with the real @vercel/sandbox environment.
2121
*
2222
* These tests require Vercel OIDC authentication.
2323
* Run with: pnpm test:vercel
2424
*
25-
* Note: createBashTool automatically uses /vercel/sandbox as the default
25+
* Note: createBashTool automatically uses /vercel/sandbox/workspace as the default
2626
* destination when a @vercel/sandbox instance is provided.
2727
*/
2828
describe("createBashTool @vercel/sandbox integration", () => {
@@ -41,19 +41,9 @@ describe("createBashTool @vercel/sandbox integration", () => {
4141
beforeAll(async () => {
4242
console.log("Creating sandbox");
4343
vercelSandbox = await Sandbox.create();
44+
console.log("Sandbox created");
4445
}, 60000);
4546

46-
afterEach(async () => {
47-
if (vercelSandbox) {
48-
const result = await vercelSandbox.runCommand("rm", [
49-
"-rf",
50-
"/vercel/sandbox/workspace",
51-
]);
52-
expect(await result.stderr()).toBe("");
53-
expect(result.exitCode).toBe(0);
54-
}
55-
});
56-
5747
afterAll(async () => {
5848
if (vercelSandbox) {
5949
await vercelSandbox.stop();
@@ -62,15 +52,17 @@ describe("createBashTool @vercel/sandbox integration", () => {
6252

6353
describe("ls command", () => {
6454
it("ls -la lists files with details", async () => {
55+
const dest = uniqueDir();
6556
const { tools } = await createBashTool({
6657
sandbox: vercelSandbox,
58+
destination: dest,
6759
files: testFiles,
6860
});
6961

7062
assert(tools.bash.execute, "bash.execute should be defined");
7163
const result = (await tools.bash.execute(
7264
{ command: "ls -la" },
73-
opts,
65+
opts
7466
)) as CommandResult;
7567

7668
expect(result.exitCode).toBe(0);
@@ -80,15 +72,17 @@ describe("createBashTool @vercel/sandbox integration", () => {
8072
}, 30000);
8173

8274
it("ls lists directory contents", async () => {
75+
const dest = uniqueDir();
8376
const { tools } = await createBashTool({
8477
sandbox: vercelSandbox,
78+
destination: dest,
8579
files: testFiles,
8680
});
8781

8882
assert(tools.bash.execute, "bash.execute should be defined");
8983
const result = (await tools.bash.execute(
9084
{ command: "ls src" },
91-
opts,
85+
opts
9286
)) as CommandResult;
9387

9488
expect(result.exitCode).toBe(0);
@@ -98,15 +92,17 @@ describe("createBashTool @vercel/sandbox integration", () => {
9892

9993
describe("find command", () => {
10094
it("find . -name '*.ts' finds TypeScript files", async () => {
95+
const dest = uniqueDir();
10196
const { tools } = await createBashTool({
10297
sandbox: vercelSandbox,
98+
destination: dest,
10399
files: testFiles,
104100
});
105101

106102
assert(tools.bash.execute, "bash.execute should be defined");
107103
const result = (await tools.bash.execute(
108104
{ command: "find . -name '*.ts'" },
109-
opts,
105+
opts
110106
)) as CommandResult;
111107

112108
expect(result.exitCode).toBe(0);
@@ -117,15 +113,17 @@ describe("createBashTool @vercel/sandbox integration", () => {
117113
}, 30000);
118114

119115
it("find . -name '*.json' finds JSON files", async () => {
116+
const dest = uniqueDir();
120117
const { tools } = await createBashTool({
121118
sandbox: vercelSandbox,
119+
destination: dest,
122120
files: testFiles,
123121
});
124122

125123
assert(tools.bash.execute, "bash.execute should be defined");
126124
const result = (await tools.bash.execute(
127125
{ command: "find . -name '*.json'" },
128-
opts,
126+
opts
129127
)) as CommandResult;
130128

131129
expect(result.exitCode).toBe(0);
@@ -135,15 +133,17 @@ describe("createBashTool @vercel/sandbox integration", () => {
135133

136134
describe("grep command", () => {
137135
it("grep -r 'pattern' . searches file contents", async () => {
136+
const dest = uniqueDir();
138137
const { tools } = await createBashTool({
139138
sandbox: vercelSandbox,
139+
destination: dest,
140140
files: testFiles,
141141
});
142142

143143
assert(tools.bash.execute, "bash.execute should be defined");
144144
const result = (await tools.bash.execute(
145145
{ command: "grep -r 'export' ." },
146-
opts,
146+
opts
147147
)) as CommandResult;
148148

149149
expect(result.stderr).toBe("");
@@ -154,62 +154,69 @@ describe("createBashTool @vercel/sandbox integration", () => {
154154
}, 30000);
155155

156156
it("grep finds specific patterns", async () => {
157+
const dest = uniqueDir();
157158
const { tools } = await createBashTool({
158159
sandbox: vercelSandbox,
160+
destination: dest,
159161
files: testFiles,
160162
});
161163

162164
assert(tools.bash.execute, "bash.execute should be defined");
163165
const result = (await tools.bash.execute(
164166
{ command: "grep -r 'hello' ." },
165-
opts,
167+
opts
166168
)) as CommandResult;
167169

168170
expect(result.exitCode).toBe(0);
169171
expect(result.stdout.trim()).toBe(
170-
'./src/index.ts:export const hello = "world";',
172+
'./src/index.ts:export const hello = "world";'
171173
);
172174
}, 30000);
173175
});
174176

175177
describe("cat command", () => {
176178
it("cat <file> views file contents", async () => {
179+
const dest = uniqueDir();
177180
const { tools } = await createBashTool({
178181
sandbox: vercelSandbox,
182+
destination: dest,
179183
files: testFiles,
180184
});
181185

182186
assert(tools.bash.execute, "bash.execute should be defined");
183187
const result = (await tools.bash.execute(
184188
{ command: "cat src/index.ts" },
185-
opts,
189+
opts
186190
)) as CommandResult;
187191

188192
expect(result.exitCode).toBe(0);
189193
expect(result.stdout).toBe('export const hello = "world";');
190194
}, 30000);
191195

192196
it("cat package.json shows JSON content", async () => {
197+
const dest = uniqueDir();
193198
const { tools } = await createBashTool({
194199
sandbox: vercelSandbox,
200+
destination: dest,
195201
files: testFiles,
196202
});
197203

198204
assert(tools.bash.execute, "bash.execute should be defined");
199205
const result = (await tools.bash.execute(
200206
{ command: "cat package.json" },
201-
opts,
207+
opts
202208
)) as CommandResult;
203209

204210
expect(result.exitCode).toBe(0);
205211
expect(result.stdout).toBe(
206-
'{"name": "test-project", "version": "1.0.0"}',
212+
'{"name": "test-project", "version": "1.0.0"}'
207213
);
208214
}, 30000);
209215
});
210216

211217
describe("working directory", () => {
212-
it("pwd shows correct working directory", async () => {
218+
it("uses /vercel/sandbox/workspace as default destination", async () => {
219+
// This test verifies the default destination behavior - no custom destination
213220
const { tools } = await createBashTool({
214221
sandbox: vercelSandbox,
215222
files: testFiles,
@@ -218,43 +225,45 @@ describe("createBashTool @vercel/sandbox integration", () => {
218225
assert(tools.bash.execute, "bash.execute should be defined");
219226
const result = (await tools.bash.execute(
220227
{ command: "pwd" },
221-
opts,
228+
opts
222229
)) as CommandResult;
223230

224231
expect(result.exitCode).toBe(0);
225232
expect(result.stdout.trim()).toBe("/vercel/sandbox/workspace");
226233
}, 30000);
227234

228235
it("pwd shows custom destination within sandbox", async () => {
229-
const customDest = "/vercel/sandbox/project";
236+
const dest = uniqueDir();
230237
const { tools } = await createBashTool({
231238
sandbox: vercelSandbox,
239+
destination: dest,
232240
files: testFiles,
233-
destination: customDest,
234241
});
235242

236243
assert(tools.bash.execute, "bash.execute should be defined");
237244
const result = (await tools.bash.execute(
238245
{ command: "pwd" },
239-
opts,
246+
opts
240247
)) as CommandResult;
241248

242249
expect(result.exitCode).toBe(0);
243-
expect(result.stdout.trim()).toBe(customDest);
250+
expect(result.stdout.trim()).toBe(dest);
244251
}, 30000);
245252
});
246253

247254
describe("readFile tool", () => {
248255
it("reads file content correctly", async () => {
256+
const dest = uniqueDir();
249257
const { tools } = await createBashTool({
250258
sandbox: vercelSandbox,
259+
destination: dest,
251260
files: testFiles,
252261
});
253262

254263
assert(tools.readFile.execute, "readFile.execute should be defined");
255264
const result = (await tools.readFile.execute(
256-
{ path: "/vercel/sandbox/workspace/src/index.ts" },
257-
opts,
265+
{ path: `${dest}/src/index.ts` },
266+
opts
258267
)) as { content: string };
259268

260269
expect(result.content).toBe('export const hello = "world";');
@@ -263,8 +272,10 @@ describe("createBashTool @vercel/sandbox integration", () => {
263272

264273
describe("writeFile tool", () => {
265274
it("writes file and can be read back", async () => {
275+
const dest = uniqueDir();
266276
const { tools } = await createBashTool({
267277
sandbox: vercelSandbox,
278+
destination: dest,
268279
files: testFiles,
269280
});
270281

@@ -276,12 +287,12 @@ describe("createBashTool @vercel/sandbox integration", () => {
276287
path: "newfile.txt",
277288
content: "Hello, World!",
278289
},
279-
opts,
290+
opts
280291
);
281292

282293
const result = (await tools.bash.execute(
283294
{ command: "cat newfile.txt" },
284-
opts,
295+
opts
285296
)) as CommandResult;
286297

287298
expect(result.stdout).toBe("Hello, World!");
@@ -292,8 +303,10 @@ describe("createBashTool @vercel/sandbox integration", () => {
292303

293304
describe("promptOptions", () => {
294305
it("uses custom toolPrompt when provided", async () => {
306+
const dest = uniqueDir();
295307
const { tools } = await createBashTool({
296308
sandbox: vercelSandbox,
309+
destination: dest,
297310
files: { "data.json": "{}" },
298311
promptOptions: {
299312
toolPrompt: "Custom tools: myTool",
@@ -305,8 +318,10 @@ describe("createBashTool @vercel/sandbox integration", () => {
305318
}, 30000);
306319

307320
it("disables tool hints with empty string toolPrompt", async () => {
321+
const dest = uniqueDir();
308322
const { tools } = await createBashTool({
309323
sandbox: vercelSandbox,
324+
destination: dest,
310325
files: { "data.json": "{}" },
311326
promptOptions: {
312327
toolPrompt: "",

0 commit comments

Comments
 (0)