test(FN-4208): complete Step 3 — add failed badge precedence regressions

Fusion-Task-Id: FN-4208
Fusion-Task-Lineage: a195b416-f5c2-402e-939a-5d356a17ceec
This commit is contained in:
Fusion
2026-05-13 04:07:15 -07:00
committed by gsxdsm
parent 30619ed542
commit 3e2d646f2a
2 changed files with 86 additions and 8 deletions

View File

@@ -36,6 +36,27 @@ const mockAddToast = vi.fn();
const TEST_PROJECT_ID = "proj-123";
const scopedStorageKey = (key: string) => scopedKey(key, TEST_PROJECT_ID);
function mountCssForBadgeTests() {
const style = document.createElement("style");
style.textContent = loadAllAppCss();
document.head.appendChild(style);
document.documentElement.style.setProperty("--status-error-bg", "rgb(255, 230, 230)");
document.documentElement.style.setProperty("--color-error-dark", "rgb(200, 0, 0)");
document.documentElement.style.setProperty("--status-in-review-bg", "rgb(230, 255, 230)");
document.documentElement.style.setProperty("--in-review", "rgb(0, 160, 0)");
document.documentElement.style.setProperty("--triage", "rgb(240, 140, 0)");
document.documentElement.style.setProperty("--todo", "rgb(80, 120, 220)");
return () => {
style.remove();
document.documentElement.style.removeProperty("--status-error-bg");
document.documentElement.style.removeProperty("--color-error-dark");
document.documentElement.style.removeProperty("--status-in-review-bg");
document.documentElement.style.removeProperty("--in-review");
document.documentElement.style.removeProperty("--triage");
document.documentElement.style.removeProperty("--todo");
};
}
const createMockTask = (overrides: Partial<Task> = {}): Task => ({
id: "FN-001",
description: "Test task description",
@@ -646,14 +667,37 @@ describe("ListView", () => {
expect(statusBadge.className).toContain("failed");
});
it("keeps failed list badges on error tokens even for in-review tasks", () => {
const css = loadAllAppCss();
const failedRule = css.match(/\.list-status-badge\.failed\s*\{([^}]*)\}/);
const inReviewRuleIndex = css.indexOf(".list-status-badge--in-review");
const failedRuleIndex = css.indexOf(".list-status-badge.failed");
it.each([
{
name: "failed + in-review uses error token color",
classes: "list-status-badge list-status-badge--in-review failed",
expectedClass: "failed",
expectedColor: "var(--color-error-dark)",
disallowedColor: "var(--in-review)",
},
{
name: "stuck + todo uses triage token color",
classes: "list-status-badge list-status-badge--todo stuck",
expectedClass: "stuck",
expectedColor: "var(--triage)",
disallowedColor: "var(--todo)",
},
])("FN-4208 keeps list badge state precedence: $name", ({ classes, expectedClass, expectedColor, disallowedColor }) => {
const cleanupCss = mountCssForBadgeTests();
try {
const badge = document.createElement("span");
badge.className = classes;
badge.textContent = "status";
document.body.appendChild(badge);
expect(failedRule?.[1]).toContain("background: var(--status-error-bg)");
expect(failedRuleIndex).toBeGreaterThan(inReviewRuleIndex);
expect(badge.className).toContain(expectedClass);
expect(getComputedStyle(badge).color).toBe(expectedColor);
expect(getComputedStyle(badge).color).not.toBe(disallowedColor);
badge.remove();
} finally {
cleanupCss();
}
});
it("renders paused tasks with dimmed styling", () => {

View File

@@ -34,7 +34,7 @@ vi.mock("../../api", () => ({
}));
import { uploadAttachment, fetchMission, fetchAgent } from "../../api";
import { loadAllAppCssBaseOnly } from "../../test/cssFixture";
import { loadAllAppCss, loadAllAppCssBaseOnly } from "../../test/cssFixture";
function makeTask(overrides: Partial<Task> = {}): Task {
return {
@@ -51,6 +51,23 @@ function makeTask(overrides: Partial<Task> = {}): Task {
const noop = () => {};
function mountCssForBadgeTests() {
const style = document.createElement("style");
style.textContent = loadAllAppCss();
document.head.appendChild(style);
document.documentElement.style.setProperty("--status-error-bg", "rgb(255, 230, 230)");
document.documentElement.style.setProperty("--color-error-dark", "rgb(200, 0, 0)");
document.documentElement.style.setProperty("--status-in-review-bg", "rgb(230, 255, 230)");
document.documentElement.style.setProperty("--in-review", "rgb(0, 160, 0)");
return () => {
style.remove();
document.documentElement.style.removeProperty("--status-error-bg");
document.documentElement.style.removeProperty("--color-error-dark");
document.documentElement.style.removeProperty("--status-in-review-bg");
document.documentElement.style.removeProperty("--in-review");
};
}
const highFanout = {
totalCount: 7,
activeTodoCount: 3,
@@ -153,6 +170,23 @@ describe("TaskCard", () => {
expect(badge?.className).toContain("pulsing");
});
it("FN-4208 keeps failed in-review TaskCard badge on error colors", () => {
const cleanupCss = mountCssForBadgeTests();
try {
const { container } = render(
<TaskCard task={makeTask({ column: "in-review", status: "failed" as any, error: "boom" })} onOpenDetail={noop} addToast={noop} />,
);
const badge = container.querySelector(".card-status-badge") as HTMLElement;
expect(badge.className).toContain("card-status-badge--in-review");
expect(badge.className).toContain("failed");
expect(getComputedStyle(badge).color).toBe("var(--color-error-dark)");
expect(getComputedStyle(badge).color).not.toBe("var(--in-review)");
} finally {
cleanupCss();
}
});
it("renders the status badge after the card ID in DOM order", () => {
const { container } = render(
<TaskCard