import assert from "node:assert/strict"; import { describe, test } from "vitest"; /** * Tests for the boot route's null-project path. * * When no SF_WEB_PROJECT_CWD is set and no ?project param is present, * the boot route returns a canned "no project" payload so the frontend * can show the project picker. These tests verify the shape and values * of that payload without requiring bridge/subprocess. * * See: web/app/api/boot/route.ts — null-project early return branch. */ /** Mirrors the null-project payload returned by the boot route. */ function makeNullProjectPayload() { return { project: null, workspace: null, auto: null, onboarding: { locked: false }, onboardingNeeded: false, resumableSessions: [], bridge: null, projectDetection: null, }; } /** * Mirrors resolveProjectCwd URL-parsing logic from bridge-service.ts. * Returns the ?project query param value, or null if absent/malformed. */ function resolveProjectFromUrl(requestUrl: string): string | null { try { const url = new URL(requestUrl); const projectParam = url.searchParams.get("project"); if (projectParam) return decodeURIComponent(projectParam); } catch { // Malformed URL — fall through } return null; } describe("boot route — null-project payload shape", () => { test("nullProjectPayload_always_hasNullTopLevelFields", () => { const payload = makeNullProjectPayload(); assert.equal(payload.project, null); assert.equal(payload.workspace, null); assert.equal(payload.auto, null); assert.equal(payload.bridge, null); assert.equal(payload.projectDetection, null); }); test("nullProjectPayload_always_hasOnboardingNotLocked", () => { const payload = makeNullProjectPayload(); assert.deepEqual(payload.onboarding, { locked: false }); }); test("nullProjectPayload_always_hasOnboardingNeededFalse", () => { const payload = makeNullProjectPayload(); assert.equal(payload.onboardingNeeded, false); }); test("nullProjectPayload_always_hasEmptyResumableSessions", () => { const payload = makeNullProjectPayload(); assert.deepEqual(payload.resumableSessions, []); }); }); describe("boot route — resolveProjectCwd URL parsing", () => { test("resolveProjectFromUrl_whenProjectParamPresent_returnsDecodedValue", () => { const result = resolveProjectFromUrl( "http://localhost:3000/api/boot?project=%2Fhome%2Fuser%2Fproject", ); assert.equal(result, "/home/user/project"); }); test("resolveProjectFromUrl_whenNoProjectParam_returnsNull", () => { const result = resolveProjectFromUrl("http://localhost:3000/api/boot"); assert.equal(result, null); }); test("resolveProjectFromUrl_whenProjectParamIsEmpty_returnsNull", () => { // Empty ?project= param → searchParams.get returns "" → falsy → null const result = resolveProjectFromUrl( "http://localhost:3000/api/boot?project=", ); assert.equal(result, null); }); test("resolveProjectFromUrl_whenUrlIsMalformed_returnsNull", () => { const result = resolveProjectFromUrl("not-a-valid-url"); assert.equal(result, null); }); test("resolveProjectFromUrl_whenProjectParamHasSpaces_returnsDecodedPath", () => { const result = resolveProjectFromUrl( "http://localhost:3000/api/boot?project=%2Fhome%2Fmy%20project", ); assert.equal(result, "/home/my project"); }); });