103 lines
3.2 KiB
TypeScript
103 lines
3.2 KiB
TypeScript
|
|
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");
|
||
|
|
});
|
||
|
|
});
|