diff --git a/lib/sandbox/__tests__/createSandboxHandler.test.ts b/lib/sandbox/__tests__/createSandboxHandler.test.ts index c48b0cb5..269163eb 100644 --- a/lib/sandbox/__tests__/createSandboxHandler.test.ts +++ b/lib/sandbox/__tests__/createSandboxHandler.test.ts @@ -96,6 +96,56 @@ describe("createSandboxHandler", () => { }); }); + it("forwards `branch` (existing branch) to the source as branch when isNewBranch is false", async () => { + vi.mocked(validateCreateSandboxBody).mockResolvedValueOnce({ + body: { + repoUrl: "https://github.com/o/r", + sessionId: "sess-1", + branch: "develop", + isNewBranch: false, + }, + auth: { accountId: ACCOUNT_ID, orgId: null, authToken: "k" }, + }); + + await createSandboxHandler(makeReq()); + + const args = vi.mocked(connectSandbox).mock.calls[0]?.[0] as { + state: { source?: { repo: string; branch?: string; newBranch?: string } }; + }; + expect(args.state.source).toMatchObject({ repo: "https://github.com/o/r", branch: "develop" }); + expect(args.state.source?.newBranch).toBeUndefined(); + }); + + it("forwards `branch` to the source as newBranch when isNewBranch is true", async () => { + vi.mocked(validateCreateSandboxBody).mockResolvedValueOnce({ + body: { + repoUrl: "https://github.com/o/r", + sessionId: "sess-1", + branch: "xy/abcd1234", + isNewBranch: true, + }, + auth: { accountId: ACCOUNT_ID, orgId: null, authToken: "k" }, + }); + + await createSandboxHandler(makeReq()); + + const args = vi.mocked(connectSandbox).mock.calls[0]?.[0] as { + state: { source?: { repo: string; branch?: string; newBranch?: string } }; + }; + expect(args.state.source?.newBranch).toBe("xy/abcd1234"); + expect(args.state.source?.branch).toBeUndefined(); + }); + + it("omits both branch and newBranch when neither is provided (current default)", async () => { + await createSandboxHandler(makeReq()); + + const args = vi.mocked(connectSandbox).mock.calls[0]?.[0] as { + state: { source?: { repo: string; branch?: string; newBranch?: string } }; + }; + expect(args.state.source?.branch).toBeUndefined(); + expect(args.state.source?.newBranch).toBeUndefined(); + }); + it("short-circuits with the validator's response on validation failure", async () => { const fail = NextResponse.json({ status: "error", error: "bad" }, { status: 400 }); vi.mocked(validateCreateSandboxBody).mockResolvedValueOnce(fail); diff --git a/lib/sandbox/__tests__/validateCreateSandboxBody.test.ts b/lib/sandbox/__tests__/validateCreateSandboxBody.test.ts index e3894f2e..37f18b3a 100644 --- a/lib/sandbox/__tests__/validateCreateSandboxBody.test.ts +++ b/lib/sandbox/__tests__/validateCreateSandboxBody.test.ts @@ -102,16 +102,31 @@ describe("validateCreateSandboxBody", () => { expect(result.body.sessionId).toBe("sess-1"); }); - it("strips an unknown branch input from the validated body", async () => { + it("preserves `branch` and `isNewBranch` on the validated body", async () => { const result = await validateCreateSandboxBody( makeReq({ repoUrl: "https://github.com/o/r", branch: "feat/x", + isNewBranch: true, }), ); expect(result).not.toBeInstanceOf(NextResponse); if (result instanceof NextResponse) return; - expect((result.body as Record).branch).toBeUndefined(); + expect(result.body.branch).toBe("feat/x"); + expect(result.body.isNewBranch).toBe(true); + }); + + it("rejects a non-boolean isNewBranch", async () => { + const result = await validateCreateSandboxBody( + makeReq({ + repoUrl: "https://github.com/o/r", + isNewBranch: "yes", + }), + ); + + expect(result).toBeInstanceOf(NextResponse); + if (!(result instanceof NextResponse)) return; + expect(result.status).toBe(400); }); }); diff --git a/lib/sandbox/createSandboxHandler.ts b/lib/sandbox/createSandboxHandler.ts index 83922877..bb405cc6 100644 --- a/lib/sandbox/createSandboxHandler.ts +++ b/lib/sandbox/createSandboxHandler.ts @@ -101,7 +101,17 @@ export async function createSandboxHandler(request: NextRequest): Promise;