import { expect, test, type Page } from "@playwright/test";
import { assertGitHubJourneyCheck, assertGitHubJourneyTaskDone } from "./github-review-browser.js";
const expected = { repository: "fixture/repo", url: "https://github.com/fixture/repo/runs/123", headSha: "a".repeat(40), score: 2 };
async function openCheck(page: Page, input: { status?: string; score?: number; headSha?: string; unrelatedFailure?: boolean; url?: string } = {}) {
const body = `
Fixture bot / Paperclip Review ${input.status ?? "failed"}
${input.score ?? expected.score}/5
Reviewed commit: ${input.headSha ?? expected.headSha}
Review rationale: failed tests are discussed in the summary.
${input.unrelatedFailure ? '
' : ""}`;
await page.route("https://github.com/**", route => route.fulfill({ contentType: "text/html", body }));
await page.goto(input.url ?? expected.url);
}
test("accepts the visible failed check despite an earlier hidden re-run menu item", async ({ page }) => {
await openCheck(page);
await expect(page.getByText(/failed/i).first()).toBeHidden();
await assertGitHubJourneyCheck(page, expected, 150);
});
test("rejects a successful check even when its narrative and another check say failed", async ({ page }) => {
await openCheck(page, { status: "succeeded", unrelatedFailure: true });
await expect(assertGitHubJourneyCheck(page, expected, 150)).rejects.toThrow();
});
test("rejects the wrong reviewed commit", async ({ page }) => {
await openCheck(page, { headSha: "b".repeat(40) });
await expect(assertGitHubJourneyCheck(page, expected, 150)).rejects.toThrow();
});
test("rejects a different score", async ({ page }) => {
await openCheck(page, { score: 3 });
await expect(assertGitHubJourneyCheck(page, expected, 150)).rejects.toThrow();
});
test("rejects a page for another repository", async ({ page }) => {
await openCheck(page, { url: "https://github.com/foreign/repo/runs/123" });
await expect(assertGitHubJourneyCheck(page, expected, 150)).rejects.toThrow();
});
test("rejects a check reference outside the configured repository", async ({ page }) => {
const url = "https://github.com/foreign/repo/runs/123";
await openCheck(page, { url });
await expect(assertGitHubJourneyCheck(page, { ...expected, url }, 150)).rejects.toThrow();
});
for (const [name, override] of [
["foreign origin", { url: "https://example.com/fixture/repo/runs/123" }],
["embedded credentials", { url: "https://fixture-user:fixture-password@github.com/fixture/repo/runs/123" }],
["query suffix", { url: `${expected.url}?x=1` }],
["hash suffix", { url: `${expected.url}#fragment` }],
["non-numeric run ID", { url: "https://github.com/fixture/repo/runs/abc" }],
["short commit", { headSha: "a".repeat(7) }],
["score below range", { score: 0 }],
["score above range", { score: 6 }],
] as const) {
test(`rejects a malformed check reference: ${name}`, async ({ page }) => {
// These must reject before navigation or DOM inspection.
await expect(assertGitHubJourneyCheck(page, { ...expected, ...override }, 150))
.rejects.toThrow("github_check_reference_mismatch");
});
}
function taskStatus(status: string, hidden = false) {
return `
Status
`;
}
test("accepts visible Done status despite hidden controls and SVG title text", async ({ page }) => {
await page.setContent(`${taskStatus("Done", true)}${taskStatus("Done")}`);
await expect(page.getByText("Done", { exact: true }).first()).toBeHidden();
await assertGitHubJourneyTaskDone(page, 150);
});
test("rejects Done in the narrative when the task is still in progress", async ({ page }) => {
await page.setContent(`Done
${taskStatus("In Progress")}`);
await expect(assertGitHubJourneyTaskDone(page, 150)).rejects.toThrow();
});
test("rejects hidden Done status when the visible status is in progress", async ({ page }) => {
await page.setContent(`${taskStatus("Done", true)}${taskStatus("In Progress")}`);
await expect(assertGitHubJourneyTaskDone(page, 150)).rejects.toThrow();
});
test("rejects a Done picker in an unrelated property", async ({ page }) => {
await page.setContent(taskStatus("Done").replace('data-property-label="Status">Status', 'data-property-label="Assignee">Assignee'));
await expect(assertGitHubJourneyTaskDone(page, 150)).rejects.toThrow();
});