fabro/apps/fabro-web/app/routes/run-files.test.ts
2026-05-09 15:33:19 -04:00

182 lines
5.2 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import {
deepLinkToastMessage,
emptyTransitionToastMessage,
extractRequestId,
normalizeRunFileScope,
} from "./run-files";
import {
buildRunCommitOptions,
fabroGeneratedCommitStage,
} from "./run-files/commit-options";
function buildRunFilesPayload({
files = [],
degraded = false,
}: {
files?: string[];
degraded?: boolean;
}) {
return {
data: files.map((name, index) => ({
change_kind: "modified",
old_file: { name, contents: degraded ? null : `old ${index}` },
new_file: { name, contents: degraded ? null : `new ${index}` },
...(degraded ? { unified_patch: `diff --git a/${name} b/${name}` } : {}),
})),
meta: {
degraded,
total_changed: files.length,
source: "sandbox",
scope: "committed",
stats: { additions: 0, deletions: 0 },
truncated: false,
},
} as any;
}
describe("extractRequestId", () => {
test("reads `request_id` from the top level of the error body", () => {
expect(extractRequestId({ request_id: "abc-123" })).toBe("abc-123");
});
test("reads `request_id` from errors[0] under the uniform envelope", () => {
expect(
extractRequestId({
errors: [
{ status: "500", title: "Internal", request_id: "evt_42" },
],
}),
).toBe("evt_42");
});
test("parses `Request ID: xyz` out of errors[0].detail", () => {
expect(
extractRequestId({
errors: [
{
status: "500",
title: "Internal Server Error",
detail: "Run files failed. Request ID: req_999 on shard 2.",
},
],
}),
).toBe("req_999");
});
test("returns null for bodies without any request_id", () => {
expect(extractRequestId(null)).toBe(null);
expect(extractRequestId(undefined)).toBe(null);
expect(extractRequestId("not an object")).toBe(null);
expect(extractRequestId({ errors: [] })).toBe(null);
expect(extractRequestId({ errors: [{ detail: "no id in here" }] })).toBe(
null,
);
});
test("handles request_id values with hyphens and underscores", () => {
expect(
extractRequestId({
errors: [
{ detail: "Something failed. request_id: RX-1A_2B-3C4D" },
],
}),
).toBe("RX-1A_2B-3C4D");
});
});
describe("emptyTransitionToastMessage", () => {
test("returns the no-changes toast when a populated diff becomes empty", () => {
expect(emptyTransitionToastMessage(3, 0)).toBe("No changes in this run.");
});
test("returns null when the diff was already empty", () => {
expect(emptyTransitionToastMessage(0, 0)).toBeNull();
expect(emptyTransitionToastMessage(null, 0)).toBeNull();
expect(emptyTransitionToastMessage(2, 1)).toBeNull();
});
});
describe("normalizeRunFileScope", () => {
test("defaults missing or invalid values to committed", () => {
expect(normalizeRunFileScope(null)).toBe("committed");
expect(normalizeRunFileScope("dirty")).toBe("committed");
});
test("accepts supported scope values", () => {
expect(normalizeRunFileScope("committed")).toBe("committed");
expect(normalizeRunFileScope("uncommitted")).toBe("uncommitted");
expect(normalizeRunFileScope("all")).toBe("all");
});
});
describe("buildRunCommitOptions", () => {
test("shortens Fabro-generated subjects to stage visits", () => {
const commits = [
{
sha: "a".repeat(40),
short_sha: "aaaaaaa",
subject: "fabro(run_1): implement (succeeded)",
parents: [{ sha: "1".repeat(40), short_sha: "1111111" }],
},
{
sha: "b".repeat(40),
short_sha: "bbbbbbb",
subject: "fabro(run_1): implement (succeeded)",
parents: [{ sha: "a".repeat(40), short_sha: "aaaaaaa" }],
},
];
expect(buildRunCommitOptions(commits).map((commit) => commit.label)).toEqual([
"implement@1",
"implement@2",
]);
});
test("leaves externally generated commit subjects intact", () => {
const [option] = buildRunCommitOptions([
{
sha: "a".repeat(40),
short_sha: "aaaaaaa",
subject: "Fix README typo",
parents: [{ sha: "1".repeat(40), short_sha: "1111111" }],
},
]);
expect(fabroGeneratedCommitStage("Fix README typo")).toBeNull();
expect(option.label).toBe("Fix README typo");
});
});
describe("deepLinkToastMessage", () => {
test("returns the missing-file message when the requested file is absent", () => {
expect(
deepLinkToastMessage(
"src/missing.ts",
buildRunFilesPayload({ files: ["src/present.ts"] }),
),
).toBe("File src/missing.ts is not in this run.");
});
test("returns null when the deep-linked file exists", () => {
expect(
deepLinkToastMessage(
"src/present.ts",
buildRunFilesPayload({ files: ["src/present.ts"] }),
),
).toBeNull();
});
test("returns null for degraded file-shaped payloads when the file exists", () => {
expect(
deepLinkToastMessage(
"src/present.ts",
buildRunFilesPayload({
degraded: true,
files: ["src/present.ts"],
}),
),
).toBeNull();
});
});