diff --git a/open-sse/services/__tests__/tierResolver.test.ts b/open-sse/services/__tests__/tierResolver.test.ts
index 7f2ce7a9f8..62ad4f1867 100644
--- a/open-sse/services/__tests__/tierResolver.test.ts
+++ b/open-sse/services/__tests__/tierResolver.test.ts
@@ -197,7 +197,7 @@ describe("TierResolver", () => {
{ provider: "openai", model: "gpt-4o" },
{ provider: "openai", model: "gpt-4o" },
]);
- // Observable effect of the cache: the duplicate resolves to the same tier and only
+// Observable effect of the cache: the duplicate resolves to the same tier and only
// ONE entry is memoized (getTierStats counts cache entries, not classify calls).
expect(results).toHaveLength(2);
expect(results[0].tier).toBe(results[1].tier);
diff --git a/tests/unit/AutoComboCatalog.test.tsx b/tests/unit/AutoComboCatalog.test.tsx
index 64aabf8971..f4162130ae 100644
--- a/tests/unit/AutoComboCatalog.test.tsx
+++ b/tests/unit/AutoComboCatalog.test.tsx
@@ -26,7 +26,7 @@ function makeContainer(): HTMLElement {
return container;
}
-describe("AutoComboCatalog", () => {
+describe("AutoComboCatalog", { timeout: 15_000 }, () => {
beforeEach(() => {
(
globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }
diff --git a/tests/unit/agent-skills-page.test.tsx b/tests/unit/agent-skills-page.test.tsx
index bae548fe9c..b315e71806 100644
--- a/tests/unit/agent-skills-page.test.tsx
+++ b/tests/unit/agent-skills-page.test.tsx
@@ -8,7 +8,12 @@ import type { AgentSkill, SkillCoverage } from "../../src/lib/agentSkills/types"
// ── i18n stub ────────────────────────────────────────────────────────────────
vi.mock("next-intl", () => ({
- useTranslations: () => (key: string) => key,
+ useLocale: () => "en",
+ useTranslations: () => {
+ const t = (key: string) => key;
+ t.has = () => false;
+ return t;
+ },
}));
// ── next/link stub ───────────────────────────────────────────────────────────
@@ -30,7 +35,10 @@ vi.mock("next/link", () => ({
// ── next/dynamic stub — renders placeholder immediately ───────────────────────
vi.mock("next/dynamic", () => ({
- default: (loader: () => Promise<{ default: React.ComponentType<{ children: string }> }>, _opts?: unknown) => {
+ default: (
+ loader: () => Promise<{ default: React.ComponentType<{ children: string }> }>,
+ _opts?: unknown
+ ) => {
// Return a synchronous stub that renders children as plain text.
return function DynamicStub({ children }: { children: string }) {
return
{children}
;
@@ -49,7 +57,8 @@ function makeSkill(overrides: Partial = {}): AgentSkill {
area: "providers",
icon: "hub",
endpoints: ["POST /api/providers", "GET /api/providers"],
- rawUrl: "https://raw.githubusercontent.com/diegosouzapw/OmniRoute/refs/heads/main/skills/omni-providers/SKILL.md",
+ rawUrl:
+ "https://raw.githubusercontent.com/diegosouzapw/OmniRoute/refs/heads/main/skills/omni-providers/SKILL.md",
githubUrl: "https://github.com/diegosouzapw/OmniRoute/blob/main/skills/omni-providers/SKILL.md",
...overrides,
};
@@ -63,7 +72,7 @@ function make42Skills(): AgentSkill[] {
id: `omni-skill-${i}`,
name: `API Skill ${i}`,
category: "api",
- }),
+ })
);
}
for (let i = 0; i < 20; i++) {
@@ -74,7 +83,7 @@ function make42Skills(): AgentSkill[] {
category: "cli",
endpoints: undefined,
cliCommands: [`skill${i} run`, `skill${i} status`],
- }),
+ })
);
}
return skills;
@@ -96,7 +105,11 @@ const PARTIAL_COVERAGE: SkillCoverage = {
// ── Fetch mock factory ───────────────────────────────────────────────────────
-function mockFetch(skills: AgentSkill[], coverage: SkillCoverage, rawMarkdown = "# Test Skill\nContent here.") {
+function mockFetch(
+ skills: AgentSkill[],
+ coverage: SkillCoverage,
+ rawMarkdown = "# Test Skill\nContent here."
+) {
return vi.fn(async (url: string | Request) => {
const urlStr = typeof url === "string" ? url : url.toString();
if (urlStr === "/api/agent-skills") {
@@ -128,7 +141,9 @@ function makeContainer(): HTMLElement {
}
beforeEach(() => {
- (globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
+ (
+ globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }
+ ).IS_REACT_ACT_ENVIRONMENT = true;
// Mock clipboard
Object.defineProperty(navigator, "clipboard", {
value: { writeText: vi.fn().mockResolvedValue(undefined) },
@@ -165,9 +180,8 @@ describe("AgentSkillsPageClient", () => {
const skills = make42Skills();
vi.stubGlobal("fetch", mockFetch(skills, FULL_COVERAGE));
- const { AgentSkillsPageClient } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient"
- );
+ const { AgentSkillsPageClient } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient");
const container = makeContainer();
root = createRoot(container);
await act(async () => {
@@ -181,9 +195,8 @@ describe("AgentSkillsPageClient", () => {
it("renders SkillsConceptCard variant=agent at the top", async () => {
vi.stubGlobal("fetch", mockFetch(make42Skills(), FULL_COVERAGE));
- const { AgentSkillsPageClient } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient"
- );
+ const { AgentSkillsPageClient } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient");
const container = makeContainer();
root = createRoot(container);
await act(async () => {
@@ -198,16 +211,17 @@ describe("AgentSkillsPageClient", () => {
const skills = make42Skills();
vi.stubGlobal("fetch", mockFetch(skills, FULL_COVERAGE));
- const { AgentSkillsPageClient } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient"
- );
+ const { AgentSkillsPageClient } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient");
const container = makeContainer();
root = createRoot(container);
await act(async () => {
root?.render();
});
- const filterApiBtn = container.querySelector("[data-testid='filter-api']") as HTMLButtonElement | null;
+ const filterApiBtn = container.querySelector(
+ "[data-testid='filter-api']"
+ ) as HTMLButtonElement | null;
expect(filterApiBtn).not.toBeNull();
await act(async () => {
@@ -222,16 +236,17 @@ describe("AgentSkillsPageClient", () => {
const skills = make42Skills();
vi.stubGlobal("fetch", mockFetch(skills, FULL_COVERAGE));
- const { AgentSkillsPageClient } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient"
- );
+ const { AgentSkillsPageClient } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient");
const container = makeContainer();
root = createRoot(container);
await act(async () => {
root?.render();
});
- const filterCliBtn = container.querySelector("[data-testid='filter-cli']") as HTMLButtonElement | null;
+ const filterCliBtn = container.querySelector(
+ "[data-testid='filter-cli']"
+ ) as HTMLButtonElement | null;
await act(async () => {
filterCliBtn?.click();
});
@@ -246,16 +261,17 @@ describe("AgentSkillsPageClient", () => {
const fetchMock = mockFetch(skills, FULL_COVERAGE, "# omni-skill-0 doc");
vi.stubGlobal("fetch", fetchMock);
- const { AgentSkillsPageClient } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient"
- );
+ const { AgentSkillsPageClient } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient");
const container = makeContainer();
root = createRoot(container);
await act(async () => {
root?.render();
});
- const firstCard = container.querySelector("[data-testid='skill-card-omni-skill-0']") as HTMLElement | null;
+ const firstCard = container.querySelector(
+ "[data-testid='skill-card-omni-skill-0']"
+ ) as HTMLElement | null;
expect(firstCard).not.toBeNull();
await act(async () => {
@@ -264,7 +280,7 @@ describe("AgentSkillsPageClient", () => {
// Before debounce fires — raw fetch should NOT have been made yet
const rawFetchCallsBefore = (fetchMock as ReturnType).mock.calls.filter(
- ([url]: [string]) => typeof url === "string" && url.includes("/raw"),
+ ([url]: [string]) => typeof url === "string" && url.includes("/raw")
);
expect(rawFetchCallsBefore.length).toBe(0);
@@ -275,7 +291,7 @@ describe("AgentSkillsPageClient", () => {
// Now the raw fetch should have been triggered
const rawFetchCallsAfter = (fetchMock as ReturnType).mock.calls.filter(
- ([url]: [string]) => typeof url === "string" && url.includes("/raw"),
+ ([url]: [string]) => typeof url === "string" && url.includes("/raw")
);
expect(rawFetchCallsAfter.length).toBeGreaterThan(0);
@@ -285,9 +301,8 @@ describe("AgentSkillsPageClient", () => {
it("preview pane shows empty state when no card is selected", async () => {
vi.stubGlobal("fetch", mockFetch(make42Skills(), FULL_COVERAGE));
- const { AgentSkillsPageClient } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient"
- );
+ const { AgentSkillsPageClient } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient");
const container = makeContainer();
root = createRoot(container);
await act(async () => {
@@ -301,9 +316,8 @@ describe("AgentSkillsPageClient", () => {
it("CoverageBar is rendered with 100% = green bars when coverage is full", async () => {
vi.stubGlobal("fetch", mockFetch(make42Skills(), FULL_COVERAGE));
- const { AgentSkillsPageClient } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient"
- );
+ const { AgentSkillsPageClient } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient");
const container = makeContainer();
root = createRoot(container);
await act(async () => {
@@ -328,9 +342,8 @@ describe("AgentSkillsPageClient", () => {
it("generate button is hidden when coverage is 100%", async () => {
vi.stubGlobal("fetch", mockFetch(make42Skills(), FULL_COVERAGE));
- const { AgentSkillsPageClient } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient"
- );
+ const { AgentSkillsPageClient } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient");
const container = makeContainer();
root = createRoot(container);
await act(async () => {
@@ -344,9 +357,8 @@ describe("AgentSkillsPageClient", () => {
it("generate button is visible when coverage is partial", async () => {
vi.stubGlobal("fetch", mockFetch(make42Skills(), PARTIAL_COVERAGE));
- const { AgentSkillsPageClient } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient"
- );
+ const { AgentSkillsPageClient } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient");
const container = makeContainer();
root = createRoot(container);
await act(async () => {
@@ -361,16 +373,17 @@ describe("AgentSkillsPageClient", () => {
const skills = make42Skills();
vi.stubGlobal("fetch", mockFetch(skills, FULL_COVERAGE));
- const { AgentSkillsPageClient } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient"
- );
+ const { AgentSkillsPageClient } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient");
const container = makeContainer();
root = createRoot(container);
await act(async () => {
root?.render();
});
- const searchInput = container.querySelector("[data-testid='search-input']") as HTMLInputElement | null;
+ const searchInput = container.querySelector(
+ "[data-testid='search-input']"
+ ) as HTMLInputElement | null;
expect(searchInput).not.toBeNull();
await act(async () => {
@@ -380,7 +393,7 @@ describe("AgentSkillsPageClient", () => {
// React uses onChange
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
window.HTMLInputElement.prototype,
- "value",
+ "value"
)?.set;
nativeInputValueSetter?.call(searchInput, "API Skill 0");
searchInput.dispatchEvent(new Event("change", { bubbles: true }));
@@ -396,9 +409,8 @@ describe("AgentSkillsPageClient", () => {
it("MCP and A2A links bar is present", async () => {
vi.stubGlobal("fetch", mockFetch(make42Skills(), FULL_COVERAGE));
- const { AgentSkillsPageClient } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient"
- );
+ const { AgentSkillsPageClient } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/AgentSkillsPageClient");
const container = makeContainer();
root = createRoot(container);
await act(async () => {
@@ -414,9 +426,8 @@ describe("AgentSkillsPageClient", () => {
describe("CoverageBar", () => {
it("renders two progressbars with correct aria attributes", async () => {
- const { CoverageBar } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/components/CoverageBar"
- );
+ const { CoverageBar } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/components/CoverageBar");
const container = makeContainer();
const localRoot = createRoot(container);
await act(async () => {
@@ -438,9 +449,8 @@ describe("CoverageBar", () => {
});
it("applies red color class when coverage is below 75%", async () => {
- const { CoverageBar } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/components/CoverageBar"
- );
+ const { CoverageBar } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/components/CoverageBar");
const lowCoverage: SkillCoverage = {
api: { have: 5, total: 22 },
cli: { have: 0, total: 20 },
@@ -462,9 +472,8 @@ describe("CoverageBar", () => {
});
it("applies amber color class when coverage is between 75% and 100%", async () => {
- const { CoverageBar } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/components/CoverageBar"
- );
+ const { CoverageBar } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/components/CoverageBar");
const partialCoverage: SkillCoverage = {
api: { have: 18, total: 22 }, // ~81.8% = amber
cli: { have: 15, total: 20 }, // 75% = amber
@@ -490,9 +499,8 @@ describe("CoverageBar", () => {
describe("SkillCard", () => {
it("renders skill name and description", async () => {
- const { SkillCard } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/components/SkillCard"
- );
+ const { SkillCard } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/components/SkillCard");
const skill = makeSkill({ name: "Providers", description: "Manage connections" });
const container = makeContainer();
const localRoot = createRoot(container);
@@ -507,9 +515,8 @@ describe("SkillCard", () => {
});
it("has role=button and aria-pressed=false when not selected", async () => {
- const { SkillCard } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/components/SkillCard"
- );
+ const { SkillCard } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/components/SkillCard");
const container = makeContainer();
const localRoot = createRoot(container);
await act(async () => {
@@ -524,9 +531,8 @@ describe("SkillCard", () => {
});
it("has aria-pressed=true when selected", async () => {
- const { SkillCard } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/components/SkillCard"
- );
+ const { SkillCard } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/components/SkillCard");
const container = makeContainer();
const localRoot = createRoot(container);
await act(async () => {
@@ -540,9 +546,8 @@ describe("SkillCard", () => {
});
it("calls onClick when clicked", async () => {
- const { SkillCard } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/components/SkillCard"
- );
+ const { SkillCard } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/components/SkillCard");
const handleClick = vi.fn();
const container = makeContainer();
const localRoot = createRoot(container);
@@ -558,9 +563,8 @@ describe("SkillCard", () => {
});
it("shows first 2 endpoints as chips for API skill", async () => {
- const { SkillCard } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/components/SkillCard"
- );
+ const { SkillCard } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/components/SkillCard");
const skill = makeSkill({
endpoints: ["POST /api/providers", "GET /api/providers", "DELETE /api/providers/:id"],
});
@@ -583,15 +587,12 @@ describe("SkillCard", () => {
describe("SkillPreviewPane", () => {
it("renders empty state when skillId is null", async () => {
- const { SkillPreviewPane } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/components/SkillPreviewPane"
- );
+ const { SkillPreviewPane } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/components/SkillPreviewPane");
const container = makeContainer();
const localRoot = createRoot(container);
await act(async () => {
- localRoot.render(
- ,
- );
+ localRoot.render();
});
const empty = container.querySelector("[data-testid='skill-preview-empty']");
@@ -602,9 +603,8 @@ describe("SkillPreviewPane", () => {
});
it("renders markdown when skillId and markdown are provided", async () => {
- const { SkillPreviewPane } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/components/SkillPreviewPane"
- );
+ const { SkillPreviewPane } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/components/SkillPreviewPane");
const container = makeContainer();
const localRoot = createRoot(container);
await act(async () => {
@@ -613,7 +613,7 @@ describe("SkillPreviewPane", () => {
skillId="omni-providers"
markdown="# Providers\nContent here."
loading={false}
- />,
+ />
);
});
@@ -625,15 +625,12 @@ describe("SkillPreviewPane", () => {
});
it("shows error state when skillId provided but markdown is empty string", async () => {
- const { SkillPreviewPane } = await import(
- "../../src/app/(dashboard)/dashboard/agent-skills/components/SkillPreviewPane"
- );
+ const { SkillPreviewPane } =
+ await import("../../src/app/(dashboard)/dashboard/agent-skills/components/SkillPreviewPane");
const container = makeContainer();
const localRoot = createRoot(container);
await act(async () => {
- localRoot.render(
- ,
- );
+ localRoot.render();
});
// markdown is "" (falsy) — should show error state
diff --git a/tests/unit/dashboard/batch/concept-cards.test.tsx b/tests/unit/dashboard/batch/concept-cards.test.tsx
index e543b75dc5..5bc2a716d5 100644
--- a/tests/unit/dashboard/batch/concept-cards.test.tsx
+++ b/tests/unit/dashboard/batch/concept-cards.test.tsx
@@ -20,14 +20,23 @@ vi.mock("next-intl", () => ({
useTranslations: () => (key: string) => key,
}));
+const storage = new Map();
+Object.defineProperty(globalThis, "localStorage", {
+ configurable: true,
+ value: {
+ clear: () => storage.clear(),
+ getItem: (key: string) => storage.get(key) ?? null,
+ removeItem: (key: string) => storage.delete(key),
+ setItem: (key: string, value: string) => storage.set(key, value),
+ },
+});
+
// ── Import components after mocks ─────────────────────────────────────────────
-const { default: BatchConceptCard } = await import(
- "../../../../src/app/(dashboard)/dashboard/batch/components/BatchConceptCard"
-);
-const { default: FilesConceptCard } = await import(
- "../../../../src/app/(dashboard)/dashboard/batch/components/FilesConceptCard"
-);
+const { default: BatchConceptCard } =
+ await import("../../../../src/app/(dashboard)/dashboard/batch/components/BatchConceptCard");
+const { default: FilesConceptCard } =
+ await import("../../../../src/app/(dashboard)/dashboard/batch/components/FilesConceptCard");
// ── Helpers ───────────────────────────────────────────────────────────────────
diff --git a/tests/unit/dashboard/batch/list-regression.test.tsx b/tests/unit/dashboard/batch/list-regression.test.tsx
index 333a715e77..7fcdd6a118 100644
--- a/tests/unit/dashboard/batch/list-regression.test.tsx
+++ b/tests/unit/dashboard/batch/list-regression.test.tsx
@@ -22,7 +22,12 @@ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
// ── Mocks ─────────────────────────────────────────────────────────────────────
vi.mock("next-intl", () => ({
- useTranslations: () => (key: string) => key,
+ useLocale: () => "en",
+ useTranslations: () => {
+ const t = (key: string) => key;
+ t.has = () => false;
+ return t;
+ },
}));
vi.mock("next/link", () => ({
@@ -33,17 +38,20 @@ vi.mock("next/link", () => ({
// Mock retryFailed (used by BatchRowActions → useBatchActions)
vi.mock("@/lib/batches/retryFailed", () => ({
- buildRetryPlan: vi.fn(() => ({ retriableLines: 0, newJsonl: "", failedCustomIds: [], skippedLines: 0 })),
+ buildRetryPlan: vi.fn(() => ({
+ retriableLines: 0,
+ newJsonl: "",
+ failedCustomIds: [],
+ skippedLines: 0,
+ })),
}));
// ── Import components after mocks ─────────────────────────────────────────────
-const { default: BatchListTab } = await import(
- "../../../../src/app/(dashboard)/dashboard/batch/BatchListTab"
-);
-const { default: FilesListTab } = await import(
- "../../../../src/app/(dashboard)/dashboard/batch/FilesListTab"
-);
+const { default: BatchListTab } =
+ await import("../../../../src/app/(dashboard)/dashboard/batch/BatchListTab");
+const { default: FilesListTab } =
+ await import("../../../../src/app/(dashboard)/dashboard/batch/FilesListTab");
// ── Helpers ───────────────────────────────────────────────────────────────────
@@ -56,21 +64,23 @@ function makeDiv() {
}
// Batch record factory
-function makeBatch(overrides: Partial<{
- id: string;
- status: string;
- endpoint: string;
- model: string;
- requestCountsTotal: number;
- requestCountsCompleted: number;
- requestCountsFailed: number;
- outputFileId: string | null;
- errorFileId: string | null;
- expiresAt: number | null;
- inputFileId: string;
- completionWindow: string;
- createdAt: number;
-}> = {}) {
+function makeBatch(
+ overrides: Partial<{
+ id: string;
+ status: string;
+ endpoint: string;
+ model: string;
+ requestCountsTotal: number;
+ requestCountsCompleted: number;
+ requestCountsFailed: number;
+ outputFileId: string | null;
+ errorFileId: string | null;
+ expiresAt: number | null;
+ inputFileId: string;
+ completionWindow: string;
+ createdAt: number;
+ }> = {}
+) {
return {
id: overrides.id ?? "batch-001",
endpoint: overrides.endpoint ?? "/v1/chat/completions",
@@ -99,14 +109,16 @@ function makeBatch(overrides: Partial<{
}
// File record factory
-function makeFile(overrides: Partial<{
- id: string;
- filename: string;
- bytes: number;
- purpose: string;
- createdAt: number;
- expiresAt: number | null;
-}> = {}) {
+function makeFile(
+ overrides: Partial<{
+ id: string;
+ filename: string;
+ bytes: number;
+ purpose: string;
+ createdAt: number;
+ expiresAt: number | null;
+ }> = {}
+) {
return {
id: overrides.id ?? "file-001",
filename: overrides.filename ?? "batch-input.jsonl",
@@ -131,7 +143,10 @@ function render(jsx: React.ReactElement) {
// ── Lifecycle ─────────────────────────────────────────────────────────────────
beforeEach(() => {
- vi.stubGlobal("fetch", vi.fn().mockResolvedValue({ ok: true, json: async () => ({}), text: async () => "" }));
+ vi.stubGlobal(
+ "fetch",
+ vi.fn().mockResolvedValue({ ok: true, json: async () => ({}), text: async () => "" })
+ );
vi.stubGlobal("confirm", vi.fn().mockReturnValue(false)); // don't confirm dialogs
});
@@ -163,9 +178,7 @@ describe("BatchListTab — rendering", () => {
it("2. 'Remove completed' button appears when there are completed batches", () => {
const batches = [makeBatch({ id: "batch-completed", status: "completed" })];
- const el = render(
-
- );
+ const el = render();
// button text contains "Remove completed"
const btn = Array.from(el.querySelectorAll("button")).find((b) =>
b.textContent?.includes("batchListRemoveCompleted")
@@ -205,9 +218,7 @@ describe("BatchListTab — rendering", () => {
makeBatch({ id: "batch-completed", status: "completed" }),
makeBatch({ id: "batch-in-progress", status: "in_progress" }),
];
- const el = render(
-
- );
+ const el = render();
// Both visible initially
expect(el.textContent).toContain("batch-completed");
@@ -231,9 +242,7 @@ describe("BatchListTab — rendering", () => {
makeBatch({ id: "batch-unique-aaa", status: "completed" }),
makeBatch({ id: "batch-unique-bbb", status: "completed" }),
];
- const el = render(
-
- );
+ const el = render();
// Search input exists and accepts text
const input = el.querySelector("input[type='text']") as HTMLInputElement;
@@ -245,27 +254,21 @@ describe("BatchListTab — rendering", () => {
});
it("6. shows loading spinner when loading=true and no batches", () => {
- const el = render(
-
- );
+ const el = render();
// Loading state renders a spinner (animate-spin class)
const spinner = el.querySelector(".animate-spin");
expect(spinner).not.toBeNull();
});
it("7. shows empty state when no batches and not loading", () => {
- const el = render(
-
- );
+ const el = render();
// Should show some empty-state indicator (no spinner)
expect(el.querySelector(".animate-spin")).toBeNull();
});
it("8. sanitization: rendered content contains no stack traces or file paths", () => {
const batches = [makeBatch({ id: "batch-safe", status: "completed" })];
- const el = render(
-
- );
+ const el = render();
const text = el.textContent ?? "";
expect(text).not.toMatch(/\/home\//);
expect(text).not.toMatch(/at \//);
@@ -283,9 +286,7 @@ describe("BatchListTab — rendering", () => {
requestCountsFailed: 10,
}),
];
- const el = render(
-
- );
+ const el = render();
// The i18n key is rendered literally in tests (mock useTranslations returns key)
expect(el.textContent).toContain("batchListProgressPartial");
});
@@ -300,21 +301,21 @@ describe("BatchListTab — rendering", () => {
requestCountsFailed: 0,
}),
];
- const el = render(
-
- );
+ const el = render();
expect(el.textContent).toContain("-50%");
});
it("18. Provider column derives provider from model id (A-1)", () => {
const batches = [
makeBatch({ id: "batch-openai", model: "gpt-4o", status: "completed" }),
- makeBatch({ id: "batch-anthropic", model: "claude-3-5-sonnet-20241022", status: "completed" }),
+ makeBatch({
+ id: "batch-anthropic",
+ model: "claude-3-5-sonnet-20241022",
+ status: "completed",
+ }),
makeBatch({ id: "batch-gemini", model: "gemini-1.5-flash", status: "completed" }),
];
- const el = render(
-
- );
+ const el = render();
const text = el.textContent ?? "";
expect(text).toContain("OpenAI");
expect(text).toContain("Anthropic");
@@ -327,9 +328,7 @@ describe("BatchListTab — rendering", () => {
makeBatch({ id: "b-o1", model: "o1-preview", status: "completed" }),
makeBatch({ id: "b-o3", model: "o3-mini", status: "completed" }),
];
- const el = render(
-
- );
+ const el = render();
const text = el.textContent ?? "";
// All three are OpenAI families — the column should print "OpenAI" three times.
const occurrences = (text.match(/OpenAI/g) ?? []).length;
@@ -338,13 +337,15 @@ describe("BatchListTab — rendering", () => {
it("20. Provider derivation routes unknown / null model through i18n keys (R2)", () => {
const batches = [
- makeBatch({ id: "b-unknown-model", model: "weird-model-name-not-recognized", status: "completed" }),
+ makeBatch({
+ id: "b-unknown-model",
+ model: "weird-model-name-not-recognized",
+ status: "completed",
+ }),
// makeBatch's default model is gpt-4o; explicitly null-ish models below
makeBatch({ id: "b-null-model", model: "", status: "completed" }),
];
- const el = render(
-
- );
+ const el = render();
const text = el.textContent ?? "";
// i18n mock returns the key literal — proves we route through t() and
// didn't leave hardcoded "Other" / "—" English strings in the cell.
@@ -362,9 +363,7 @@ describe("FilesListTab — rendering", () => {
makeFile({ id: "file-bbb", filename: "output-bbb.jsonl", purpose: "batch-output" }),
makeFile({ id: "file-ccc", filename: "fine-tune-ccc.jsonl", purpose: "fine-tune" }),
];
- const el = render(
-
- );
+ const el = render();
expect(el.textContent).toContain("input-aaa.jsonl");
expect(el.textContent).toContain("output-bbb.jsonl");
expect(el.textContent).toContain("fine-tune-ccc.jsonl");
@@ -375,9 +374,7 @@ describe("FilesListTab — rendering", () => {
makeFile({ id: "file-batch", filename: "batch-input.jsonl", purpose: "batch" }),
makeFile({ id: "file-fine", filename: "fine-tune.jsonl", purpose: "fine-tune" }),
];
- const el = render(
-
- );
+ const el = render();
expect(el.textContent).toContain("batch-input.jsonl");
expect(el.textContent).toContain("fine-tune.jsonl");
@@ -399,9 +396,7 @@ describe("FilesListTab — rendering", () => {
makeFile({ id: "file-alpha", filename: "alpha-batch.jsonl", purpose: "batch" }),
makeFile({ id: "file-beta", filename: "beta-batch.jsonl", purpose: "batch" }),
];
- const el = render(
-
- );
+ const el = render();
// Search input exists
const input = el.querySelector("input[type='text']") as HTMLInputElement;
@@ -413,9 +408,7 @@ describe("FilesListTab — rendering", () => {
});
it("12. 'used by' column header is visible (i18n key)", () => {
- const el = render(
-
- );
+ const el = render();
// filesListUsedByColumn key is rendered in the header
expect(el.textContent).toContain("filesListUsedByColumn");
});
@@ -433,9 +426,7 @@ describe("FilesListTab — rendering", () => {
model: "gpt-4o",
},
];
- const el = render(
-
- );
+ const el = render();
// Truncated id prefix (12 chars) appears inline
expect(el.textContent).toContain("batch-using-");
// Role label is rendered next to the id (G-AUD1 — plan §4 "b1 (input)")
@@ -447,9 +438,7 @@ describe("FilesListTab — rendering", () => {
});
it("14. loading state shows spinner", () => {
- const el = render(
-
- );
+ const el = render();
const spinner = el.querySelector(".animate-spin");
expect(spinner).not.toBeNull();
});
diff --git a/tests/unit/omni-skills-page.test.tsx b/tests/unit/omni-skills-page.test.tsx
index 0b584985df..ffc2d53eeb 100644
--- a/tests/unit/omni-skills-page.test.tsx
+++ b/tests/unit/omni-skills-page.test.tsx
@@ -4,11 +4,10 @@
* split, file structure, source patterns, and exported symbols without DOM rendering.
*
* Run:
- * node --import tsx/esm --test tests/unit/omni-skills-page.test.tsx
+ * vitest run tests/unit/omni-skills-page.test.tsx
*/
-import { describe, it } from "node:test";
-import assert from "node:assert/strict";
+import { describe, expect, it } from "vitest";
import { existsSync, readFileSync } from "node:fs";
import { resolve, join } from "node:path";
@@ -20,11 +19,13 @@ const base = resolve(join(cwd, "src/app/(dashboard)/dashboard/omni-skills"));
describe("File structure — omni-skills directory", () => {
it("old /dashboard/skills directory does not exist", () => {
const oldPath = resolve(join(cwd, "src/app/(dashboard)/dashboard/skills"));
- assert.ok(!existsSync(oldPath), `Old skills/ directory must be absent (found at ${oldPath})`);
+ expect(existsSync(oldPath), `Old skills/ directory must be absent (found at ${oldPath})`).toBe(
+ false
+ );
});
it("new /dashboard/omni-skills directory exists", () => {
- assert.ok(existsSync(base), `omni-skills/ directory must exist at ${base}`);
+ expect(existsSync(base), `omni-skills/ directory must exist at ${base}`).toBe(true);
});
const expectedFiles = [
@@ -40,9 +41,8 @@ describe("File structure — omni-skills directory", () => {
for (const file of expectedFiles) {
it(`file exists: omni-skills/${file}`, () => {
- assert.ok(
- existsSync(resolve(join(base, file))),
- `Expected omni-skills/${file} to exist`
+ expect(existsSync(resolve(join(base, file))), `Expected omni-skills/${file} to exist`).toBe(
+ true
);
});
}
@@ -54,21 +54,24 @@ describe("page.tsx — server component", () => {
const src = readFileSync(resolve(join(base, "page.tsx")), "utf-8");
it("is a server component (no 'use client' directive)", () => {
- assert.ok(
+ expect(
!src.includes('"use client"') && !src.includes("'use client'"),
"page.tsx must not have 'use client'"
- );
+ ).toBe(true);
});
it("imports and renders OmniSkillsPageClient", () => {
- assert.ok(src.includes("OmniSkillsPageClient"), "page.tsx must reference OmniSkillsPageClient");
+ expect(
+ src.includes("OmniSkillsPageClient"),
+ "page.tsx must reference OmniSkillsPageClient"
+ ).toBe(true);
});
it("has a default export named Page", () => {
- assert.ok(
+ expect(
src.includes("export default function Page"),
"page.tsx must have 'export default function Page'"
- );
+ ).toBe(true);
});
});
@@ -78,48 +81,50 @@ describe("OmniSkillsPageClient.tsx", () => {
const src = readFileSync(resolve(join(base, "OmniSkillsPageClient.tsx")), "utf-8");
it("starts with 'use client'", () => {
- assert.ok(src.startsWith('"use client"'), "OmniSkillsPageClient must start with 'use client'");
+ expect(
+ src.startsWith('"use client"'),
+ "OmniSkillsPageClient must start with 'use client'"
+ ).toBe(true);
});
it("has all 4 tab IDs", () => {
for (const tabId of ["skills", "executions", "sandbox", "marketplace"]) {
- assert.ok(
+ expect(
src.includes(`id: "${tabId}"`),
`OmniSkillsPageClient must have tab id="${tabId}"`
- );
+ ).toBe(true);
}
});
it("renders SkillsConceptCard with variant='omni'", () => {
- assert.ok(
+ expect(
src.includes('variant="omni"'),
- "OmniSkillsPageClient must render "
- );
+ 'OmniSkillsPageClient must render '
+ ).toBe(true);
});
it("imports SkillsConceptCard from shared components", () => {
- assert.ok(
+ expect(
src.includes("SkillsConceptCard"),
"OmniSkillsPageClient must import SkillsConceptCard"
- );
+ ).toBe(true);
});
it("has selectedSkillId state", () => {
- assert.ok(
+ expect(
src.includes("selectedSkillId"),
"OmniSkillsPageClient must maintain selectedSkillId state"
- );
+ ).toBe(true);
});
it("wires OmniSkillsList with inspector props", () => {
- assert.ok(
- src.includes("OmniSkillsList"),
- "OmniSkillsPageClient must render OmniSkillsList"
+ expect(src.includes("OmniSkillsList"), "OmniSkillsPageClient must render OmniSkillsList").toBe(
+ true
);
- assert.ok(
+ expect(
src.includes("onSelectSkill"),
"OmniSkillsPageClient must pass onSelectSkill to OmniSkillsList"
- );
+ ).toBe(true);
});
it("renders all 4 tab components", () => {
@@ -129,12 +134,12 @@ describe("OmniSkillsPageClient.tsx", () => {
"OmniSandboxTab",
"OmniMarketplaceTab",
]) {
- assert.ok(src.includes(component), `OmniSkillsPageClient must render <${component}>`);
+ expect(src.includes(component), `OmniSkillsPageClient must render <${component}>`).toBe(true);
}
});
it("has install modal with hardcoded 'X' close button (preserved behavior)", () => {
- assert.ok(src.includes("showInstallModal"), "must preserve showInstallModal state");
+ expect(src.includes("showInstallModal"), "must preserve showInstallModal state").toBe(true);
});
});
@@ -144,31 +149,31 @@ describe("OmniSkillCard.tsx", () => {
const src = readFileSync(resolve(join(base, "components/OmniSkillCard.tsx")), "utf-8");
it("starts with 'use client'", () => {
- assert.ok(src.startsWith('"use client"'), "must be a client component");
+ expect(src.startsWith('"use client"'), "must be a client component").toBe(true);
});
it("accepts skill, selected, onClick props", () => {
- assert.ok(src.includes("OmniSkillCardProps"), "must define OmniSkillCardProps");
- assert.ok(src.includes("selected:"), "must have selected prop");
- assert.ok(src.includes("onClick:"), "must have onClick prop");
+ expect(src.includes("OmniSkillCardProps"), "must define OmniSkillCardProps").toBe(true);
+ expect(src.includes("selected:"), "must have selected prop").toBe(true);
+ expect(src.includes("onClick:"), "must have onClick prop").toBe(true);
});
it("has role='button' for accessibility", () => {
- assert.ok(src.includes('role="button"'), "must have role='button' for accessibility");
+ expect(src.includes('role="button"'), "must have role='button' for accessibility").toBe(true);
});
it("exports OmniSkillCard", () => {
- assert.ok(
+ expect(
src.includes("export function OmniSkillCard") || src.includes("export { OmniSkillCard }"),
"must export OmniSkillCard"
- );
+ ).toBe(true);
});
it("exports OmniSkill interface", () => {
- assert.ok(
+ expect(
src.includes("export interface OmniSkill"),
"must export OmniSkill interface for other components"
- );
+ ).toBe(true);
});
});
@@ -178,44 +183,42 @@ describe("SkillInspectorPane.tsx", () => {
const src = readFileSync(resolve(join(base, "components/SkillInspectorPane.tsx")), "utf-8");
it("starts with 'use client'", () => {
- assert.ok(src.startsWith('"use client"'), "must be a client component");
+ expect(src.startsWith('"use client"'), "must be a client component").toBe(true);
});
it("has all 4 sub-tab IDs", () => {
for (const tabId of ["schema", "handler", "executions", "sandbox"]) {
- assert.ok(
- src.includes(`"${tabId}"`),
- `SkillInspectorPane must include sub-tab "${tabId}"`
+ expect(src.includes(`"${tabId}"`), `SkillInspectorPane must include sub-tab "${tabId}"`).toBe(
+ true
);
}
});
it("has empty state text when no skill selected", () => {
- assert.ok(
- src.includes("Selecione uma skill"),
- "must have empty state message"
- );
+ expect(
+ src.includes("selectSkillToInspect"),
+ "must have empty state message (i18n key selectSkillToInspect)"
+ ).toBe(true);
});
it("fetches /api/skills/[id] for skill detail", () => {
- assert.ok(
+ expect(
src.includes("/api/skills/${selectedSkillId}") ||
src.includes("`/api/skills/${selectedSkillId}`"),
"must fetch /api/skills/${selectedSkillId} for detail"
- );
+ ).toBe(true);
});
it("fetches /api/skills/executions for the executions tab", () => {
- assert.ok(
- src.includes("api/skills/executions?skillId=") ||
- src.includes("api/skills/executions"),
+ expect(
+ src.includes("api/skills/executions?skillId=") || src.includes("api/skills/executions"),
"must fetch executions for the selected skill"
- );
+ ).toBe(true);
});
it("has ON / AUTO / OFF / Uninstall buttons", () => {
- assert.ok(src.includes("onSetMode"), "must call onSetMode for mode buttons");
- assert.ok(src.includes("onUninstall"), "must call onUninstall");
+ expect(src.includes("onSetMode"), "must call onSetMode for mode buttons").toBe(true);
+ expect(src.includes("onUninstall"), "must call onUninstall").toBe(true);
});
});
@@ -225,19 +228,21 @@ describe("OmniSkillsList.tsx", () => {
const src = readFileSync(resolve(join(base, "components/OmniSkillsList.tsx")), "utf-8");
it("uses grid-cols-12 split layout", () => {
- assert.ok(src.includes("grid-cols-12"), "must use 12-column grid for split layout");
+ expect(src.includes("grid-cols-12"), "must use 12-column grid for split layout").toBe(true);
});
it("renders OmniSkillCard for each skill", () => {
- assert.ok(src.includes("OmniSkillCard"), "must render OmniSkillCard per skill");
+ expect(src.includes("OmniSkillCard"), "must render OmniSkillCard per skill").toBe(true);
});
it("renders SkillInspectorPane on the right", () => {
- assert.ok(src.includes("SkillInspectorPane"), "must include SkillInspectorPane in right col");
+ expect(src.includes("SkillInspectorPane"), "must include SkillInspectorPane in right col").toBe(
+ true
+ );
});
it("has onSelectSkill prop to control inspector state", () => {
- assert.ok(src.includes("onSelectSkill"), "must accept onSelectSkill prop");
+ expect(src.includes("onSelectSkill"), "must accept onSelectSkill prop").toBe(true);
});
});
@@ -247,18 +252,18 @@ describe("OmniExecutionsTab.tsx", () => {
const src = readFileSync(resolve(join(base, "components/OmniExecutionsTab.tsx")), "utf-8");
it("starts with 'use client'", () => {
- assert.ok(src.startsWith('"use client"'), "must be a client component");
+ expect(src.startsWith('"use client"'), "must be a client component").toBe(true);
});
it("renders a table with skill/status/duration/time columns", () => {
- assert.ok(src.includes("{t(\"skill\")}"), "must have skill column");
- assert.ok(src.includes("{t(\"status\")}"), "must have status column");
- assert.ok(src.includes("{t(\"duration\")}"), "must have duration column");
+ expect(src.includes('{t("skill")}'), "must have skill column").toBe(true);
+ expect(src.includes('{t("status")}'), "must have status column").toBe(true);
+ expect(src.includes('{t("duration")}'), "must have duration column").toBe(true);
});
it("has pagination buttons", () => {
- assert.ok(src.includes("onPagePrev"), "must accept onPagePrev handler");
- assert.ok(src.includes("onPageNext"), "must accept onPageNext handler");
+ expect(src.includes("onPagePrev"), "must accept onPagePrev handler").toBe(true);
+ expect(src.includes("onPageNext"), "must accept onPageNext handler").toBe(true);
});
});
@@ -268,13 +273,13 @@ describe("OmniSandboxTab.tsx", () => {
const src = readFileSync(resolve(join(base, "components/OmniSandboxTab.tsx")), "utf-8");
it("starts with 'use client'", () => {
- assert.ok(src.startsWith('"use client"'), "must be a client component");
+ expect(src.startsWith('"use client"'), "must be a client component").toBe(true);
});
it("shows sandbox config values", () => {
- assert.ok(src.includes("100ms"), "must show 100ms CPU limit");
- assert.ok(src.includes("256MB"), "must show 256MB memory limit");
- assert.ok(src.includes("30s"), "must show 30s timeout");
+ expect(src.includes("100ms"), "must show 100ms CPU limit").toBe(true);
+ expect(src.includes("256MB"), "must show 256MB memory limit").toBe(true);
+ expect(src.includes("30s"), "must show 30s timeout").toBe(true);
});
});
@@ -284,42 +289,41 @@ describe("OmniMarketplaceTab.tsx", () => {
const src = readFileSync(resolve(join(base, "components/OmniMarketplaceTab.tsx")), "utf-8");
it("starts with 'use client'", () => {
- assert.ok(src.startsWith('"use client"'), "must be a client component");
+ expect(src.startsWith('"use client"'), "must be a client component").toBe(true);
});
it("has marketplace search logic", () => {
- assert.ok(
+ expect(
src.includes("/api/skills/marketplace"),
"must call /api/skills/marketplace endpoint"
- );
+ ).toBe(true);
});
it("has skills.sh search logic", () => {
- assert.ok(src.includes("/api/skills/skillssh"), "must call /api/skills/skillssh endpoint");
+ expect(src.includes("/api/skills/skillssh"), "must call /api/skills/skillssh endpoint").toBe(
+ true
+ );
});
it("accepts skillsProvider and onRefreshSkills props", () => {
- assert.ok(src.includes("skillsProvider"), "must accept skillsProvider prop");
- assert.ok(src.includes("onRefreshSkills"), "must accept onRefreshSkills prop");
+ expect(src.includes("skillsProvider"), "must accept skillsProvider prop").toBe(true);
+ expect(src.includes("onRefreshSkills"), "must accept onRefreshSkills prop").toBe(true);
});
});
// ─── E2E test update ──────────────────────────────────────────────────────────
describe("E2E spec path", () => {
- const src = readFileSync(
- resolve(join(cwd, "tests/e2e/skills-marketplace.spec.ts")),
- "utf-8"
- );
+ const src = readFileSync(resolve(join(cwd, "tests/e2e/skills-marketplace.spec.ts")), "utf-8");
it("uses /dashboard/omni-skills (not /dashboard/skills)", () => {
- assert.ok(
+ expect(
src.includes("/dashboard/omni-skills"),
"E2E spec must navigate to /dashboard/omni-skills"
- );
- assert.ok(
+ ).toBe(true);
+ expect(
!src.includes('"/dashboard/skills"') && !src.includes("'/dashboard/skills'"),
"E2E spec must not have the old /dashboard/skills path in gotoDashboardRoute call"
- );
+ ).toBe(true);
});
});
diff --git a/tests/unit/shared/components/AutoRoutingBanner.test.tsx b/tests/unit/shared/components/AutoRoutingBanner.test.tsx
deleted file mode 100644
index 4d0d32d04f..0000000000
--- a/tests/unit/shared/components/AutoRoutingBanner.test.tsx
+++ /dev/null
@@ -1,116 +0,0 @@
-// @vitest-environment jsdom
-import React from "react";
-import { act } from "react";
-import { createRoot } from "react-dom/client";
-import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
-
-const cleanupCallbacks: Array<() => void> = [];
-
-function createTestStorage(): Storage {
- const entries = new Map();
- return {
- get length() {
- return entries.size;
- },
- clear: () => entries.clear(),
- getItem: (key) => entries.get(key) ?? null,
- key: (index) => Array.from(entries.keys())[index] ?? null,
- removeItem: (key) => {
- entries.delete(key);
- },
- setItem: (key, value) => {
- entries.set(key, value);
- },
- };
-}
-
-function makeContainer(): HTMLElement {
- const container = document.createElement("div");
- document.body.appendChild(container);
- cleanupCallbacks.push(() => {
- container.remove();
- });
- return container;
-}
-
-describe("AutoRoutingBanner", () => {
- beforeEach(() => {
- (
- globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }
- ).IS_REACT_ACT_ENVIRONMENT = true;
- vi.stubGlobal("localStorage", createTestStorage());
- localStorage.clear();
- });
-
- afterEach(() => {
- while (cleanupCallbacks.length > 0) {
- cleanupCallbacks.pop()?.();
- }
- document.body.innerHTML = "";
- localStorage.clear();
- vi.unstubAllGlobals();
- });
-
- it("renders banner on first mount", async () => {
- const { default: AutoRoutingBanner } = await import("@/shared/components/AutoRoutingBanner");
- const container = makeContainer();
- const root = createRoot(container);
- await act(async () => {
- root.render();
- });
- expect(container.querySelector('[role="banner"]')).toBeTruthy();
- expect(container.textContent).toContain("Auto-Routing Active");
- });
-
- it("includes link to Combos page", async () => {
- const { default: AutoRoutingBanner } = await import("@/shared/components/AutoRoutingBanner");
- const container = makeContainer();
- const root = createRoot(container);
- await act(async () => {
- root.render();
- });
- const link = container.querySelector('a[href="/dashboard/combos"]');
- expect(link).toBeTruthy();
- });
-
- it("can be dismissed by clicking close button", async () => {
- const { default: AutoRoutingBanner } = await import("@/shared/components/AutoRoutingBanner");
- const container = makeContainer();
- const root = createRoot(container);
- await act(async () => {
- root.render();
- });
- expect(container.querySelector('[role="banner"]')).toBeTruthy();
- const closeButton = container.querySelector('button[aria-label="Dismiss auto-routing banner"]');
- expect(closeButton).toBeTruthy();
- await act(async () => {
- closeButton?.click();
- });
- expect(container.querySelector('[role="banner"]')).toBeFalsy();
- });
-
- it("persists dismissal to localStorage", async () => {
- const { default: AutoRoutingBanner } = await import("@/shared/components/AutoRoutingBanner");
- const container = makeContainer();
- const root = createRoot(container);
- await act(async () => {
- root.render();
- });
- const closeButton = container.querySelector('button[aria-label="Dismiss auto-routing banner"]');
- await act(async () => {
- closeButton?.click();
- });
- expect(localStorage.getItem("auto-routing-banner-dismissed")).toBe("true");
- });
-
- it("remains hidden after dismissal on remount", async () => {
- localStorage.setItem("auto-routing-banner-dismissed", "true");
- const { default: AutoRoutingBanner } = await import("@/shared/components/AutoRoutingBanner");
- const container = makeContainer();
- const root = createRoot(container);
- await act(async () => {
- root.render();
- });
- expect(container.querySelector('[role="banner"]')).toBeFalsy();
- });
-});
diff --git a/tests/unit/translator-friendly-compression.test.tsx b/tests/unit/translator-friendly-compression.test.tsx
index 517a7e79f2..502448c3af 100644
--- a/tests/unit/translator-friendly-compression.test.tsx
+++ b/tests/unit/translator-friendly-compression.test.tsx
@@ -21,7 +21,12 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
// ---------------------------------------------------------------------------
vi.mock("next-intl", () => ({
- useTranslations: () => (key: string) => key,
+ useTranslations: () => {
+ const t = (key: string) => key;
+ t.has = () => true;
+ return t;
+ },
+ useLocale: () => "en",
}));
// Stub shared components
@@ -91,11 +96,10 @@ async function renderComponent(
forceOpen?: boolean;
inputContent?: string;
onOpenChange?: (open: boolean) => void;
- } = {},
+ } = {}
) {
- const { default: CompressionPreviewAccordion } = await import(
- "@/app/(dashboard)/dashboard/translator/components/advanced/CompressionPreviewAccordion"
- );
+ const { default: CompressionPreviewAccordion } =
+ await import("@/app/(dashboard)/dashboard/translator/components/advanced/CompressionPreviewAccordion");
const container = makeContainer();
const root = createRoot(container);
await act(async () => {
@@ -106,9 +110,7 @@ async function renderComponent(
/** Click the accordion toggle button to open/close it. */
async function clickToggle(container: HTMLElement) {
- const btn = container.querySelector(
- "button[aria-expanded]",
- ) as HTMLButtonElement | null;
+ const btn = container.querySelector("button[aria-expanded]") as HTMLButtonElement | null;
expect(btn).toBeTruthy();
await act(async () => {
btn?.click();
@@ -137,9 +139,8 @@ afterEach(() => {
describe("CompressionPreviewAccordion — export", () => {
it("exports a default function component", async () => {
- const mod = await import(
- "@/app/(dashboard)/dashboard/translator/components/advanced/CompressionPreviewAccordion"
- );
+ const mod =
+ await import("@/app/(dashboard)/dashboard/translator/components/advanced/CompressionPreviewAccordion");
expect(typeof mod.default).toBe("function");
});
});
@@ -345,7 +346,7 @@ describe("CompressionPreviewAccordion — Preview fetch", () => {
expect.objectContaining({
method: "POST",
headers: expect.objectContaining({ "Content-Type": "application/json" }),
- }),
+ })
);
// Verify body has correct shape
@@ -534,7 +535,7 @@ describe("CompressionPreviewAccordion — error path (Hard Rule #12)", () => {
it("error message does NOT contain stack-trace lines (at /path/...)", async () => {
const stackError = new Error(
- "Something went wrong\n at /home/user/app/src/file.ts:42:13\n at Object. /home/user/app/tests/test.ts:10:5",
+ "Something went wrong\n at /home/user/app/src/file.ts:42:13\n at Object. /home/user/app/tests/test.ts:10:5"
);
const fetchMock = vi.fn().mockRejectedValue(stackError);
vi.stubGlobal("fetch", fetchMock);
@@ -578,7 +579,7 @@ describe("CompressionPreviewAccordion — error path (Hard Rule #12)", () => {
const errorEl = container.querySelector("[role='alert']");
expect(errorEl).toBeTruthy();
- expect(errorEl?.textContent).toContain("Preview failed");
+ expect(errorEl?.textContent).toContain("compressionPreviewFailed");
vi.unstubAllGlobals();
});
diff --git a/tests/unit/translator-friendly-concept-card.test.tsx b/tests/unit/translator-friendly-concept-card.test.tsx
index fea085dffa..ae1d3d8d7f 100644
--- a/tests/unit/translator-friendly-concept-card.test.tsx
+++ b/tests/unit/translator-friendly-concept-card.test.tsx
@@ -6,18 +6,21 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
// Minimal i18n stub — returns the key so tests can assert on fallback rendering
vi.mock("next-intl", () => ({
- useTranslations: () => (key: string) => key,
+ useLocale: () => "en",
+ useTranslations: () => {
+ const t = (key: string) => key;
+ t.has = () => false;
+ return t;
+ },
}));
// Minimal shared component stubs — Card wraps children, Tooltip passes through
vi.mock("@/shared/components", () => ({
- Card: ({
- children,
- className,
- }: {
- children: React.ReactNode;
- className?: string;
- }) => {children}
,
+ Card: ({ children, className }: { children: React.ReactNode; className?: string }) => (
+
+ {children}
+
+ ),
}));
vi.mock("@/shared/components/Tooltip", () => ({
@@ -50,16 +53,14 @@ describe("TranslatorConceptCard", () => {
});
it("exports a default function component", { timeout: 30000 }, async () => {
- const mod = await import(
- "@/app/(dashboard)/dashboard/translator/components/TranslatorConceptCard"
- );
+ const mod =
+ await import("@/app/(dashboard)/dashboard/translator/components/TranslatorConceptCard");
expect(typeof mod.default).toBe("function");
});
it("renders the card with info icon and headline", async () => {
- const { default: TranslatorConceptCard } = await import(
- "@/app/(dashboard)/dashboard/translator/components/TranslatorConceptCard"
- );
+ const { default: TranslatorConceptCard } =
+ await import("@/app/(dashboard)/dashboard/translator/components/TranslatorConceptCard");
const container = makeContainer();
const root = createRoot(container);
await act(async () => {
@@ -74,9 +75,8 @@ describe("TranslatorConceptCard", () => {
});
it("renders the flow diagram with 4 FlowNode elements (app, source, hub, target)", async () => {
- const { default: TranslatorConceptCard } = await import(
- "@/app/(dashboard)/dashboard/translator/components/TranslatorConceptCard"
- );
+ const { default: TranslatorConceptCard } =
+ await import("@/app/(dashboard)/dashboard/translator/components/TranslatorConceptCard");
const container = makeContainer();
const root = createRoot(container);
await act(async () => {
@@ -92,9 +92,8 @@ describe("TranslatorConceptCard", () => {
});
it("renders the diagram with arrow_forward separators", async () => {
- const { default: TranslatorConceptCard } = await import(
- "@/app/(dashboard)/dashboard/translator/components/TranslatorConceptCard"
- );
+ const { default: TranslatorConceptCard } =
+ await import("@/app/(dashboard)/dashboard/translator/components/TranslatorConceptCard");
const container = makeContainer();
const root = createRoot(container);
await act(async () => {
@@ -107,16 +106,15 @@ describe("TranslatorConceptCard", () => {
});
it("toggle button starts collapsed (aria-expanded=false)", async () => {
- const { default: TranslatorConceptCard } = await import(
- "@/app/(dashboard)/dashboard/translator/components/TranslatorConceptCard"
- );
+ const { default: TranslatorConceptCard } =
+ await import("@/app/(dashboard)/dashboard/translator/components/TranslatorConceptCard");
const container = makeContainer();
const root = createRoot(container);
await act(async () => {
root.render();
});
const toggleBtn = container.querySelector(
- "button[aria-controls='translator-concept-how-it-works']",
+ "button[aria-controls='translator-concept-how-it-works']"
);
expect(toggleBtn).toBeTruthy();
expect(toggleBtn?.getAttribute("aria-expanded")).toBe("false");
@@ -125,16 +123,15 @@ describe("TranslatorConceptCard", () => {
});
it("toggle expands 'Como funciona' section and sets aria-expanded=true", async () => {
- const { default: TranslatorConceptCard } = await import(
- "@/app/(dashboard)/dashboard/translator/components/TranslatorConceptCard"
- );
+ const { default: TranslatorConceptCard } =
+ await import("@/app/(dashboard)/dashboard/translator/components/TranslatorConceptCard");
const container = makeContainer();
const root = createRoot(container);
await act(async () => {
root.render();
});
const toggleBtn = container.querySelector(
- "button[aria-controls='translator-concept-how-it-works']",
+ "button[aria-controls='translator-concept-how-it-works']"
) as HTMLButtonElement | null;
expect(toggleBtn).toBeTruthy();
@@ -149,16 +146,15 @@ describe("TranslatorConceptCard", () => {
});
it("toggle collapses section on second click and restores aria-expanded=false", async () => {
- const { default: TranslatorConceptCard } = await import(
- "@/app/(dashboard)/dashboard/translator/components/TranslatorConceptCard"
- );
+ const { default: TranslatorConceptCard } =
+ await import("@/app/(dashboard)/dashboard/translator/components/TranslatorConceptCard");
const container = makeContainer();
const root = createRoot(container);
await act(async () => {
root.render();
});
const toggleBtn = container.querySelector(
- "button[aria-controls='translator-concept-how-it-works']",
+ "button[aria-controls='translator-concept-how-it-works']"
) as HTMLButtonElement | null;
// Expand
@@ -176,9 +172,8 @@ describe("TranslatorConceptCard", () => {
});
it("toggle button icon changes between expand_more and expand_less", async () => {
- const { default: TranslatorConceptCard } = await import(
- "@/app/(dashboard)/dashboard/translator/components/TranslatorConceptCard"
- );
+ const { default: TranslatorConceptCard } =
+ await import("@/app/(dashboard)/dashboard/translator/components/TranslatorConceptCard");
const container = makeContainer();
const root = createRoot(container);
await act(async () => {
@@ -186,7 +181,7 @@ describe("TranslatorConceptCard", () => {
});
const toggleBtn = container.querySelector(
- "button[aria-controls='translator-concept-how-it-works']",
+ "button[aria-controls='translator-concept-how-it-works']"
) as HTMLButtonElement | null;
// Initially collapsed: should show expand_more
@@ -221,16 +216,14 @@ describe("TranslateFlowDiagram", () => {
});
it("exports a default function component", async () => {
- const mod = await import(
- "@/app/(dashboard)/dashboard/translator/components/TranslateFlowDiagram"
- );
+ const mod =
+ await import("@/app/(dashboard)/dashboard/translator/components/TranslateFlowDiagram");
expect(typeof mod.default).toBe("function");
});
it("renders all 4 flow node icons (app, source, hub, target)", async () => {
- const { default: TranslateFlowDiagram } = await import(
- "@/app/(dashboard)/dashboard/translator/components/TranslateFlowDiagram"
- );
+ const { default: TranslateFlowDiagram } =
+ await import("@/app/(dashboard)/dashboard/translator/components/TranslateFlowDiagram");
const container = makeContainer();
const root = createRoot(container);
await act(async () => {
@@ -246,9 +239,8 @@ describe("TranslateFlowDiagram", () => {
});
it("renders exactly 3 arrow_forward separators between 4 nodes", async () => {
- const { default: TranslateFlowDiagram } = await import(
- "@/app/(dashboard)/dashboard/translator/components/TranslateFlowDiagram"
- );
+ const { default: TranslateFlowDiagram } =
+ await import("@/app/(dashboard)/dashboard/translator/components/TranslateFlowDiagram");
const container = makeContainer();
const root = createRoot(container);
await act(async () => {
@@ -260,9 +252,8 @@ describe("TranslateFlowDiagram", () => {
});
it("renders a responsive grid container", async () => {
- const { default: TranslateFlowDiagram } = await import(
- "@/app/(dashboard)/dashboard/translator/components/TranslateFlowDiagram"
- );
+ const { default: TranslateFlowDiagram } =
+ await import("@/app/(dashboard)/dashboard/translator/components/TranslateFlowDiagram");
const container = makeContainer();
const root = createRoot(container);
await act(async () => {
@@ -276,9 +267,8 @@ describe("TranslateFlowDiagram", () => {
});
it("i18n fallback: renders labels using fallback strings when translations return keys", async () => {
- const { default: TranslateFlowDiagram } = await import(
- "@/app/(dashboard)/dashboard/translator/components/TranslateFlowDiagram"
- );
+ const { default: TranslateFlowDiagram } =
+ await import("@/app/(dashboard)/dashboard/translator/components/TranslateFlowDiagram");
const container = makeContainer();
const root = createRoot(container);
await act(async () => {
@@ -287,13 +277,13 @@ describe("TranslateFlowDiagram", () => {
// When mock returns key, tr() detects key === translation and uses fallback
// The fallback text should appear in the DOM
const text = container.textContent ?? "";
- expect(text).toContain("Sua app");
+ expect(text).toContain("Your app");
expect(text).toContain("ex: SDK Anthropic");
- expect(text).toContain("Formato origem");
+ expect(text).toContain("Source format");
expect(text).toContain("claude");
// 4th node: OpenAI hub
expect(text).toContain("OpenAI (hub)");
- expect(text).toContain("Provider destino");
+ expect(text).toContain("Target provider");
expect(text).toContain("Gemini");
});
});
diff --git a/tests/unit/translator-friendly-monitor-tab.test.tsx b/tests/unit/translator-friendly-monitor-tab.test.tsx
index 1eb1d30285..7b023e5476 100644
--- a/tests/unit/translator-friendly-monitor-tab.test.tsx
+++ b/tests/unit/translator-friendly-monitor-tab.test.tsx
@@ -6,7 +6,12 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
// ── i18n stub — returns fallback key so we can assert on translateOrFallback ──
vi.mock("next-intl", () => ({
- useTranslations: () => (key: string) => key,
+ useLocale: () => "en",
+ useTranslations: () => {
+ const t = (key: string) => key;
+ t.has = () => false;
+ return t;
+ },
}));
// ── Shared component stubs ────────────────────────────────────────────────────
@@ -58,16 +63,13 @@ vi.mock("@/shared/components", () => ({
}));
// ── FORMAT_META stub ──────────────────────────────────────────────────────────
-vi.mock(
- "@/app/(dashboard)/dashboard/translator/exampleTemplates",
- () => ({
- FORMAT_META: {
- openai: { label: "OpenAI", color: "green" },
- claude: { label: "Claude", color: "orange" },
- gemini: { label: "Gemini", color: "blue" },
- },
- }),
-);
+vi.mock("@/app/(dashboard)/dashboard/translator/exampleTemplates", () => ({
+ FORMAT_META: {
+ openai: { label: "OpenAI", color: "green" },
+ claude: { label: "Claude", color: "orange" },
+ gemini: { label: "Gemini", color: "blue" },
+ },
+}));
// ── fetch mock helpers ────────────────────────────────────────────────────────
function mockFetchEmpty() {
@@ -76,7 +78,7 @@ function mockFetchEmpty() {
vi.fn().mockResolvedValue({
ok: true,
json: async () => ({ success: true, events: [] }),
- }),
+ })
);
}
@@ -90,14 +92,14 @@ function mockFetchWithEvents(
targetFormat?: string;
status?: string;
latency?: number;
- }>,
+ }>
) {
vi.stubGlobal(
"fetch",
vi.fn().mockResolvedValue({
ok: true,
json: async () => ({ success: true, events }),
- }),
+ })
);
}
@@ -120,7 +122,7 @@ function makeContainer(): HTMLElement {
*/
async function mountAndFlushInitialFetch(
component: React.ReactElement,
- container: HTMLElement,
+ container: HTMLElement
): Promise> {
const root = createRoot(container);
await act(async () => {
@@ -137,8 +139,9 @@ async function mountAndFlushInitialFetch(
describe("MonitorTab", () => {
beforeEach(() => {
vi.useFakeTimers();
- (globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT =
- true;
+ (
+ globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }
+ ).IS_REACT_ACT_ENVIRONMENT = true;
});
afterEach(() => {
@@ -152,17 +155,14 @@ describe("MonitorTab", () => {
// ── 1. Smoke render ──────────────────────────────────────────────────────────
it("exports a default function component", async () => {
- const mod = await import(
- "@/app/(dashboard)/dashboard/translator/components/MonitorTab"
- );
+ const mod = await import("@/app/(dashboard)/dashboard/translator/components/MonitorTab");
expect(typeof mod.default).toBe("function");
});
it("renders the origin hint header (monitorOriginHint) always visible", async () => {
mockFetchEmpty();
- const { default: MonitorTab } = await import(
- "@/app/(dashboard)/dashboard/translator/components/MonitorTab"
- );
+ const { default: MonitorTab } =
+ await import("@/app/(dashboard)/dashboard/translator/components/MonitorTab");
const container = makeContainer();
await mountAndFlushInitialFetch(, container);
@@ -176,9 +176,8 @@ describe("MonitorTab", () => {
it("renders 6 StatCards with correct icons", async () => {
mockFetchEmpty();
- const { default: MonitorTab } = await import(
- "@/app/(dashboard)/dashboard/translator/components/MonitorTab"
- );
+ const { default: MonitorTab } =
+ await import("@/app/(dashboard)/dashboard/translator/components/MonitorTab");
const container = makeContainer();
await mountAndFlushInitialFetch(, container);
@@ -196,9 +195,8 @@ describe("MonitorTab", () => {
// ── 2. Empty state ───────────────────────────────────────────────────────────
it("shows empty state when events array is empty", async () => {
mockFetchEmpty();
- const { default: MonitorTab } = await import(
- "@/app/(dashboard)/dashboard/translator/components/MonitorTab"
- );
+ const { default: MonitorTab } =
+ await import("@/app/(dashboard)/dashboard/translator/components/MonitorTab");
const container = makeContainer();
await mountAndFlushInitialFetch(, container);
@@ -210,30 +208,30 @@ describe("MonitorTab", () => {
it("empty state shows CTA description text from monitorEmptyCta", async () => {
mockFetchEmpty();
- const { default: MonitorTab } = await import(
- "@/app/(dashboard)/dashboard/translator/components/MonitorTab"
- );
+ const { default: MonitorTab } =
+ await import("@/app/(dashboard)/dashboard/translator/components/MonitorTab");
const container = makeContainer();
await mountAndFlushInitialFetch(, container);
// When t() mock returns key, translateOrFallback detects key === translation and uses hardcoded fallback
const emptyDescription = container.querySelector("[data-testid='empty-description']");
- expect(emptyDescription?.textContent).toContain("Volte para a aba Translate");
+ expect(emptyDescription?.textContent).toContain("Go back to the Translate tab");
});
- it("empty state 'Ir para Translate' button calls onGoToTranslate callback", async () => {
+ it("empty state 'Go to Translate' button calls onGoToTranslate callback", async () => {
mockFetchEmpty();
- const { default: MonitorTab } = await import(
- "@/app/(dashboard)/dashboard/translator/components/MonitorTab"
- );
+ const { default: MonitorTab } =
+ await import("@/app/(dashboard)/dashboard/translator/components/MonitorTab");
const container = makeContainer();
const onGoToTranslate = vi.fn();
await mountAndFlushInitialFetch(, container);
- const actionBtn = container.querySelector("[data-testid='empty-action']") as HTMLButtonElement | null;
+ const actionBtn = container.querySelector(
+ "[data-testid='empty-action']"
+ ) as HTMLButtonElement | null;
expect(actionBtn).toBeTruthy();
// Label comes from monitorOpenTranslateButton fallback
- expect(actionBtn?.textContent).toContain("Ir para Translate");
+ expect(actionBtn?.textContent).toContain("Go to Translate");
await act(async () => {
actionBtn?.click();
@@ -243,9 +241,8 @@ describe("MonitorTab", () => {
it("empty state action button is not rendered when onGoToTranslate is not provided", async () => {
mockFetchEmpty();
- const { default: MonitorTab } = await import(
- "@/app/(dashboard)/dashboard/translator/components/MonitorTab"
- );
+ const { default: MonitorTab } =
+ await import("@/app/(dashboard)/dashboard/translator/components/MonitorTab");
const container = makeContainer();
await mountAndFlushInitialFetch(, container);
@@ -280,9 +277,8 @@ describe("MonitorTab", () => {
];
mockFetchWithEvents(sampleEvents);
- const { default: MonitorTab } = await import(
- "@/app/(dashboard)/dashboard/translator/components/MonitorTab"
- );
+ const { default: MonitorTab } =
+ await import("@/app/(dashboard)/dashboard/translator/components/MonitorTab");
const container = makeContainer();
await mountAndFlushInitialFetch(, container);
@@ -309,9 +305,8 @@ describe("MonitorTab", () => {
];
mockFetchWithEvents(sampleEvents);
- const { default: MonitorTab } = await import(
- "@/app/(dashboard)/dashboard/translator/components/MonitorTab"
- );
+ const { default: MonitorTab } =
+ await import("@/app/(dashboard)/dashboard/translator/components/MonitorTab");
const container = makeContainer();
await mountAndFlushInitialFetch(, container);
@@ -324,9 +319,8 @@ describe("MonitorTab", () => {
const sampleEvents = [{ id: "x", status: "success" }];
mockFetchWithEvents(sampleEvents);
- const { default: MonitorTab } = await import(
- "@/app/(dashboard)/dashboard/translator/components/MonitorTab"
- );
+ const { default: MonitorTab } =
+ await import("@/app/(dashboard)/dashboard/translator/components/MonitorTab");
const container = makeContainer();
await mountAndFlushInitialFetch(, container);
@@ -343,14 +337,13 @@ describe("MonitorTab", () => {
// ── 4. Auto-refresh toggle ───────────────────────────────────────────────────
it("toggle auto-refresh button is present with aria-label and shows live state text", async () => {
mockFetchEmpty();
- const { default: MonitorTab } = await import(
- "@/app/(dashboard)/dashboard/translator/components/MonitorTab"
- );
+ const { default: MonitorTab } =
+ await import("@/app/(dashboard)/dashboard/translator/components/MonitorTab");
const container = makeContainer();
await mountAndFlushInitialFetch(, container);
const toggleBtn = container.querySelector(
- "[data-testid='auto-refresh-toggle']",
+ "[data-testid='auto-refresh-toggle']"
) as HTMLButtonElement | null;
expect(toggleBtn).toBeTruthy();
@@ -362,14 +355,13 @@ describe("MonitorTab", () => {
it("clicking toggle changes button text from live to paused", async () => {
mockFetchEmpty();
- const { default: MonitorTab } = await import(
- "@/app/(dashboard)/dashboard/translator/components/MonitorTab"
- );
+ const { default: MonitorTab } =
+ await import("@/app/(dashboard)/dashboard/translator/components/MonitorTab");
const container = makeContainer();
await mountAndFlushInitialFetch(, container);
const toggleBtn = container.querySelector(
- "[data-testid='auto-refresh-toggle']",
+ "[data-testid='auto-refresh-toggle']"
) as HTMLButtonElement | null;
expect(toggleBtn).toBeTruthy();
@@ -389,9 +381,8 @@ describe("MonitorTab", () => {
});
vi.stubGlobal("fetch", fetchMock);
- const { default: MonitorTab } = await import(
- "@/app/(dashboard)/dashboard/translator/components/MonitorTab"
- );
+ const { default: MonitorTab } =
+ await import("@/app/(dashboard)/dashboard/translator/components/MonitorTab");
const container = makeContainer();
await mountAndFlushInitialFetch(, container);
@@ -412,15 +403,14 @@ describe("MonitorTab", () => {
});
vi.stubGlobal("fetch", fetchMock);
- const { default: MonitorTab } = await import(
- "@/app/(dashboard)/dashboard/translator/components/MonitorTab"
- );
+ const { default: MonitorTab } =
+ await import("@/app/(dashboard)/dashboard/translator/components/MonitorTab");
const container = makeContainer();
await mountAndFlushInitialFetch(, container);
// Pause auto-refresh
const toggleBtn = container.querySelector(
- "[data-testid='auto-refresh-toggle']",
+ "[data-testid='auto-refresh-toggle']"
) as HTMLButtonElement | null;
await act(async () => {
toggleBtn?.click();
@@ -452,14 +442,13 @@ describe("MonitorTab", () => {
it("fetch error does not leak stack traces into the DOM", async () => {
vi.stubGlobal(
"fetch",
- vi.fn().mockRejectedValue(
- new Error("Network Error\n at fetch (/some/internal/path.ts:42:10)"),
- ),
+ vi
+ .fn()
+ .mockRejectedValue(new Error("Network Error\n at fetch (/some/internal/path.ts:42:10)"))
);
- const { default: MonitorTab } = await import(
- "@/app/(dashboard)/dashboard/translator/components/MonitorTab"
- );
+ const { default: MonitorTab } =
+ await import("@/app/(dashboard)/dashboard/translator/components/MonitorTab");
const container = makeContainer();
// Don't use mountAndFlushInitialFetch here — we want to let the rejection settle
const root = createRoot(container);
diff --git a/vitest.config.ts b/vitest.config.ts
index f6ecedc017..d602eecb71 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -105,6 +105,7 @@ export default defineConfig({
"tests/unit/ui/combos-page-smoke.test.tsx", // #8618 — pre-existing failure; remove this exclusion when fixed
"tests/unit/ui/evals-tab-smoke.test.tsx", // #8618 — pre-existing failure; remove this exclusion when fixed
],
+
coverage: {
reportsDirectory: "coverage",
},