test(FN-000): resolve dashboard test noise

This commit is contained in:
Aron Prins
2026-05-05 22:25:29 +02:00
parent 55d8e87cc4
commit f85b124125
15 changed files with 113 additions and 298 deletions

View File

@@ -171,11 +171,22 @@ describe("PR checks workflow (.github/workflows/pr-checks.yml)", () => {
it("uses the same deterministic test sharding command as manual CI", () => {
expect(workflow.jobs?.lint).toBeDefined();
expect(workflow.jobs?.typecheck).toBeDefined();
expect(workflow.jobs?.build).toBeDefined();
expect(workflow.jobs?.["test-shards"]).toBeDefined();
expect(workflow.jobs?.["test-shards"]?.strategy?.matrix?.shard).toEqual([1, 2, 3]);
expect(content).toContain("pnpm test:ci:shard --shard ${{ matrix.shard }} --total 3");
expect(content).not.toContain("run: pnpm test\n");
});
it("keeps build coverage as an explicit PR gate", () => {
const buildSteps = workflow.jobs?.build?.steps ?? [];
expect(buildSteps.some((step: any) => step.name === "Build" && step.run === "pnpm build")).toBe(true);
});
it("does not spend PR action minutes on a pre-test workspace build", () => {
const testSteps = workflow.jobs?.["test-shards"]?.steps ?? [];
expect(testSteps.some((step: any) => step.name === "Build" || step.run === "pnpm build")).toBe(false);
});
});
describe("Version & Release workflow (.github/workflows/version.yml)", () => {

View File

@@ -38,6 +38,24 @@ const fsPromises = requireFromHere("node:fs/promises") as FsPromisesModule;
const childProcess = requireFromHere("node:child_process") as ChildProcessModule;
const { mkdtempSync, mkdirSync, rmSync, realpathSync, existsSync } = fs;
function installWarningFilter(): void {
const warningState = globalThis as typeof globalThis & { __fusionTestWarningFilterInstalled?: boolean };
if (warningState.__fusionTestWarningFilterInstalled) return;
warningState.__fusionTestWarningFilterInstalled = true;
const originalEmitWarning = process.emitWarning.bind(process);
process.emitWarning = ((warning: string | Error, ...args: unknown[]) => {
const warningText = warning instanceof Error ? warning.message : warning;
const warningType = typeof args[0] === "string" ? args[0] : undefined;
if (warningType === "ExperimentalWarning" && warningText.includes("SQLite is an experimental feature")) {
return;
}
return originalEmitWarning(warning as string, ...(args as Parameters<typeof process.emitWarning> extends [any, ...infer Rest] ? Rest : never));
}) as typeof process.emitWarning;
}
installWarningFilter();
const TEST_HOME_PREFIX = "fn-test-home-";
const DEFAULT_TEST_SUBPROCESS_TIMEOUT_MS = Math.max(
1_000,

View File

@@ -25,12 +25,6 @@ function hasClass(cls: string): boolean {
return new RegExp(`${escaped}(?=[\\s,{:.#>+~])`).test(stylesContent);
}
function extractSection(startMarker: string, endMarker: string): string {
const start = stylesContent.indexOf(startMarker);
const end = stylesContent.indexOf(endMarker, start + startMarker.length);
return start >= 0 && end >= 0 ? stylesContent.slice(start, end) : "";
}
describe("Agent CSS classes", () => {
// Verify agent state CSS variables are defined in the global stylesheet
it("should define --state-* CSS variables", () => {
@@ -48,109 +42,6 @@ describe("Agent CSS classes", () => {
expect(stylesContent).toContain("--state-error-border:");
});
// Verify BEM button modifier classes exist
it("should define BEM button modifier classes", () => {
expect(hasClass(".btn--sm")).toBe(true);
expect(hasClass(".btn--primary")).toBe(true);
expect(hasClass(".btn--danger")).toBe(true);
expect(hasClass(".btn--warning")).toBe(true);
expect(hasClass(".btn--compact")).toBe(true);
});
// Verify badge base class
it("should define .badge base class", () => {
expect(hasClass(".badge")).toBe(true);
});
// Verify AgentMetricsBar classes
it("should define AgentMetricsBar CSS classes", () => {
expect(hasClass(".agent-metrics-bar")).toBe(true);
expect(hasClass(".agent-metric-card")).toBe(true);
expect(hasClass(".agent-metric-card--active")).toBe(true);
expect(hasClass(".agent-metric-card--tasks")).toBe(true);
expect(hasClass(".agent-metric-card--success")).toBe(true);
expect(hasClass(".agent-metric-card--runs")).toBe(true);
expect(hasClass(".agent-metric-info")).toBe(true);
expect(hasClass(".agent-metric-value")).toBe(true);
expect(hasClass(".agent-metric-label")).toBe(true);
});
// Verify AgentsView classes
it("should define AgentsView CSS classes", () => {
expect(hasClass(".agents-view")).toBe(true);
expect(hasClass(".agents-view-header")).toBe(true);
expect(hasClass(".agents-view-title")).toBe(true);
expect(hasClass(".agents-view-controls")).toBe(true);
expect(hasClass(".agents-view-primary-actions")).toBe(true);
expect(hasClass(".agents-view-content")).toBe(true);
expect(hasClass(".agents-overview-bar")).toBe(true);
expect(hasClass(".agents-overview-bar__toggle")).toBe(true);
expect(hasClass(".agents-overview-bar__content")).toBe(true);
expect(hasClass(".agent-controls-trigger")).toBe(true);
expect(hasClass(".agent-controls-trigger--active")).toBe(true);
expect(hasClass(".agent-controls-panel")).toBe(true);
expect(hasClass(".agent-controls")).toBe(true);
expect(hasClass(".agent-controls-filters")).toBe(true);
expect(hasClass(".agent-state-filter")).toBe(true);
expect(hasClass(".agent-state-filter-select")).toBe(true);
expect(hasClass(".agent-system-filter")).toBe(true);
expect(hasClass(".agent-controls-actions")).toBe(true);
expect(hasClass(".agent-global-controls")).toBe(true);
expect(hasClass(".agent-org-chart-shell")).toBe(true);
expect(hasClass(".agent-org-chart-controls")).toBe(true);
expect(hasClass(".agent-org-chart-viewport")).toBe(true);
expect(hasClass(".agent-org-chart-canvas")).toBe(true);
expect(hasClass(".agent-org-chart-canvas--zoom-75")).toBe(true);
expect(hasClass(".agent-org-chart-canvas--zoom-100")).toBe(true);
expect(hasClass(".agent-org-chart-canvas--zoom-125")).toBe(true);
expect(hasClass(".agent-org-chart-canvas--zoom-150")).toBe(true);
expect(hasClass(".agent-org-chart--vertical")).toBe(true);
expect(hasClass(".agent-board")).toBe(true);
expect(hasClass(".agent-board-card")).toBe(true);
expect(hasClass(".agent-board-card--idle")).toBe(true);
expect(hasClass(".agent-board-card--active")).toBe(true);
expect(hasClass(".agent-board-card--running")).toBe(true);
expect(hasClass(".agent-board-card--paused")).toBe(true);
expect(hasClass(".agent-board-card--error")).toBe(true);
expect(hasClass(".agent-board-header")).toBe(true);
expect(hasClass(".agent-board-icon")).toBe(true);
expect(hasClass(".agent-board-badge")).toBe(true);
expect(hasClass(".agent-badge--idle")).toBe(true);
expect(hasClass(".agent-badge--active")).toBe(true);
expect(hasClass(".agent-badge--running")).toBe(true);
expect(hasClass(".agent-badge--paused")).toBe(true);
expect(hasClass(".agent-badge--error")).toBe(true);
expect(hasClass(".agent-board-health")).toBe(true);
expect(hasClass(".agent-board-name")).toBe(true);
expect(hasClass(".agent-board-id")).toBe(true);
expect(hasClass(".agent-board-clickable")).toBe(true);
expect(hasClass(".agent-board-actions")).toBe(true);
expect(hasClass(".agent-list")).toBe(true);
expect(hasClass(".agent-card")).toBe(true);
expect(hasClass(".agent-card--idle")).toBe(true);
expect(hasClass(".agent-card--active")).toBe(true);
expect(hasClass(".agent-card--running")).toBe(true);
expect(hasClass(".agent-card--paused")).toBe(true);
expect(hasClass(".agent-card--error")).toBe(true);
expect(hasClass(".agent-card-header")).toBe(true);
expect(hasClass(".agent-card-body")).toBe(true);
expect(hasClass(".agent-card-actions")).toBe(true);
expect(hasClass(".agent-info")).toBe(true);
expect(hasClass(".agent-info--clickable")).toBe(true);
expect(hasClass(".agent-icon")).toBe(true);
expect(hasClass(".agent-icon--clickable")).toBe(true);
expect(hasClass(".agent-meta")).toBe(true);
expect(hasClass(".agent-name")).toBe(true);
expect(hasClass(".agent-id")).toBe(true);
expect(hasClass(".agent-badges")).toBe(true);
expect(hasClass(".agent-card-chevron")).toBe(true);
expect(hasClass(".agent-task")).toBe(true);
expect(hasClass(".agent-heartbeat")).toBe(true);
expect(hasClass(".agent-role-select")).toBe(true);
expect(hasClass(".agent-empty")).toBe(true);
expect(hasClass(".spin")).toBe(true);
});
it("keeps split layout as the scroll-constrained pane container", () => {
const splitLayout = extractRuleBlock(".agents-split-layout");
expect(splitLayout).toContain("flex: 1");
@@ -218,7 +109,6 @@ describe("Agent CSS classes", () => {
expect(orgChartSection).not.toMatch(/1\.5rem|0\.75rem|0\.72rem|0\.78rem|0\.65rem|120ms\s+ease|10px/);
});
// Verify AgentDetailView classes
it("encodes compact mobile agent detail header layout contracts", () => {
const css = fs.readFileSync(path.join(__dirname, "../components/AgentDetailView.css"), "utf-8");
const mobileStart = css.indexOf("@media (max-width: 768px)");
@@ -232,117 +122,6 @@ describe("Agent CSS classes", () => {
expect(mobileCss).toContain(".agent-detail-mobile-icon-control .agent-detail-control-label {");
});
it("should define AgentDetailView CSS classes", () => {
expect(hasClass(".agent-detail-overlay")).toBe(true);
expect(hasClass(".agent-detail-modal")).toBe(true);
expect(hasClass(".agent-detail-loading")).toBe(true);
expect(hasClass(".agent-detail-header")).toBe(true);
expect(hasClass(".agent-detail-title")).toBe(true);
expect(hasClass(".agent-detail-icon")).toBe(true);
expect(hasClass(".agent-detail-info")).toBe(true);
expect(hasClass(".agent-detail-badges")).toBe(true);
expect(hasClass(".agent-detail-actions")).toBe(true);
// Redesigned compact header structure
expect(hasClass(".agent-detail-identity")).toBe(true);
expect(hasClass(".agent-detail-inline-back")).toBe(true);
expect(hasClass(".agent-detail-controls")).toBe(true);
expect(hasClass(".agent-detail-utility-actions")).toBe(true);
expect(hasClass(".agent-detail-tabs")).toBe(true);
expect(hasClass(".agent-detail-tab")).toBe(true);
expect(hasClass(".agent-detail-content")).toBe(true);
expect(hasClass(".agent-detail-footer")).toBe(true);
expect(hasClass(".agent-detail-id")).toBe(true);
expect(hasClass(".dashboard-tab")).toBe(true);
expect(hasClass(".dashboard-section")).toBe(true);
expect(hasClass(".info-grid")).toBe(true);
expect(hasClass(".info-item")).toBe(true);
expect(hasClass(".info-label")).toBe(true);
expect(hasClass(".info-value")).toBe(true);
expect(hasClass(".inline-badge")).toBe(true);
expect(hasClass(".stats-grid")).toBe(true);
expect(hasClass(".stat-card")).toBe(true);
expect(hasClass(".stat-value")).toBe(true);
expect(hasClass(".stat-label")).toBe(true);
expect(hasClass(".current-task")).toBe(true);
expect(hasClass(".task-badge")).toBe(true);
expect(hasClass(".metadata-json")).toBe(true);
expect(hasClass(".logs-tab")).toBe(true);
expect(hasClass(".logs-header")).toBe(true);
expect(hasClass(".logs-count")).toBe(true);
expect(hasClass(".streaming-indicator")).toBe(true);
expect(hasClass(".streaming-dot")).toBe(true);
expect(hasClass(".logs-empty")).toBe(true);
expect(hasClass(".runs-tab")).toBe(true);
expect(hasClass(".runs-empty")).toBe(true);
expect(hasClass(".run-card")).toBe(true);
expect(hasClass(".run-card--active")).toBe(true);
expect(hasClass(".run-header")).toBe(true);
expect(hasClass(".run-live-indicator")).toBe(true);
expect(hasClass(".live-dot")).toBe(true);
expect(hasClass(".run-id")).toBe(true);
expect(hasClass(".run-status")).toBe(true);
expect(hasClass(".run-details")).toBe(true);
expect(hasClass(".config-tab")).toBe(true);
expect(hasClass(".config-section")).toBe(true);
expect(hasClass(".config-description")).toBe(true);
expect(hasClass(".config-fields")).toBe(true);
expect(hasClass(".config-field")).toBe(true);
expect(hasClass(".config-hint")).toBe(true);
expect(hasClass(".config-error")).toBe(true);
expect(hasClass(".config-actions")).toBe(true);
expect(hasClass(".config-saved-indicator")).toBe(true);
expect(hasClass(".input--error")).toBe(true);
});
it("should define AgentReflectionsTab and ratings CSS classes", () => {
expect(hasClass(".reflections-tab")).toBe(true);
expect(hasClass(".reflections-header")).toBe(true);
expect(hasClass(".reflections-stats-grid")).toBe(true);
expect(hasClass(".reflections-stat-card")).toBe(true);
expect(hasClass(".reflections-no-data")).toBe(true);
expect(hasClass(".reflections-loading-indicator")).toBe(true);
expect(hasClass(".reflections-ratings-section")).toBe(true);
expect(hasClass(".reflections-list")).toBe(true);
expect(hasClass(".reflection-cards")).toBe(true);
expect(hasClass(".reflection-card")).toBe(true);
expect(hasClass(".reflection-card--expanded")).toBe(true);
expect(hasClass(".reflection-card-header")).toBe(true);
expect(hasClass(".reflection-trigger-badge")).toBe(true);
expect(hasClass(".reflection-summary")).toBe(true);
expect(hasClass(".reflection-details")).toBe(true);
expect(hasClass(".reflection-empty")).toBe(true);
expect(hasClass(".rating-summary-card")).toBe(true);
expect(hasClass(".rating-score-display")).toBe(true);
expect(hasClass(".rating-average")).toBe(true);
expect(hasClass(".rating-stats")).toBe(true);
expect(hasClass(".rating-count")).toBe(true);
expect(hasClass(".rating-trend-badge")).toBe(true);
expect(hasClass(".trend-improving")).toBe(true);
expect(hasClass(".trend-declining")).toBe(true);
expect(hasClass(".trend-stable")).toBe(true);
expect(hasClass(".trend-insufficient")).toBe(true);
expect(hasClass(".category-breakdown")).toBe(true);
expect(hasClass(".category-item")).toBe(true);
expect(hasClass(".category-name")).toBe(true);
expect(hasClass(".category-score")).toBe(true);
expect(hasClass(".add-rating-form")).toBe(true);
expect(hasClass(".add-rating-category-select")).toBe(true);
expect(hasClass(".add-rating-comment-input")).toBe(true);
expect(hasClass(".star-selector")).toBe(true);
expect(hasClass(".star-btn")).toBe(true);
expect(hasClass(".rating-stars")).toBe(true);
expect(hasClass(".star-filled")).toBe(true);
expect(hasClass(".star-empty")).toBe(true);
expect(hasClass(".rating-history")).toBe(true);
expect(hasClass(".rating-history-item")).toBe(true);
expect(hasClass(".rating-item-header")).toBe(true);
expect(hasClass(".rating-category-badge")).toBe(true);
expect(hasClass(".rating-time")).toBe(true);
expect(hasClass(".rating-delete-btn")).toBe(true);
expect(hasClass(".rating-comment")).toBe(true);
});
it("should apply accessible focus/hover styles for merged evaluation cards and actions", () => {
expect(stylesContent).toContain(".star-btn:focus-visible");
expect(extractRuleBlock(".star-btn:focus-visible")).toContain("box-shadow: var(--focus-ring-strong)");
@@ -358,49 +137,6 @@ describe("Agent CSS classes", () => {
expect(stylesContent).toContain("flex-wrap: wrap");
});
// Verify ActiveAgentsPanel classes
it("should define ActiveAgentsPanel CSS classes", () => {
expect(hasClass(".active-agents-panel")).toBe(true);
expect(hasClass(".active-agents-panel-header")).toBe(true);
expect(hasClass(".active-agents-grid")).toBe(true);
expect(hasClass(".live-agent-card")).toBe(true);
expect(hasClass(".live-agent-card-header")).toBe(true);
expect(hasClass(".live-agent-card-name")).toBe(true);
expect(hasClass(".status-dot")).toBe(true);
expect(hasClass(".live-agent-task")).toBe(true);
expect(hasClass(".live-agent-card-transcript")).toBe(true);
expect(hasClass(".live-agent-card-empty")).toBe(true);
expect(hasClass(".live-agent-card-line")).toBe(true);
expect(hasClass(".live-agent-card-footer")).toBe(true);
expect(hasClass(".live-agent-streaming-dot")).toBe(true);
});
// Verify NewAgentDialog classes
it("should define NewAgentDialog CSS classes", () => {
expect(hasClass(".agent-dialog-overlay")).toBe(true);
expect(hasClass(".agent-dialog")).toBe(true);
expect(hasClass(".agent-dialog-header")).toBe(true);
expect(hasClass(".agent-dialog-header-title")).toBe(true);
expect(hasClass(".agent-dialog-body")).toBe(true);
expect(hasClass(".agent-dialog-footer")).toBe(true);
expect(hasClass(".agent-dialog-steps")).toBe(true);
expect(hasClass(".agent-dialog-step")).toBe(true);
expect(hasClass(".agent-dialog-field")).toBe(true);
expect(hasClass(".agent-role-grid")).toBe(true);
expect(hasClass(".agent-role-option")).toBe(true);
expect(hasClass(".agent-role-option-icon")).toBe(true);
expect(hasClass(".agent-role-option-label")).toBe(true);
expect(hasClass(".agent-dialog-summary")).toBe(true);
expect(hasClass(".agent-dialog-summary-row")).toBe(true);
expect(hasClass(".agent-dialog-summary-row-label")).toBe(true);
expect(hasClass(".agent-dialog-summary-row-value")).toBe(true);
expect(hasClass(".agent-dialog-required")).toBe(true);
expect(hasClass(".agent-dialog-optional")).toBe(true);
expect(hasClass(".agent-dialog-error")).toBe(true);
expect(hasClass(".agent-dialog-info")).toBe(true);
expect(hasClass(".agent-dialog-loading")).toBe(true);
});
it("should give role option buttons a tokenized focus-visible state", () => {
expect(stylesContent).toContain(".agent-role-option:focus-visible");
const roleFocusBlock = extractRuleBlock(".agent-role-option:focus-visible");
@@ -408,10 +144,7 @@ describe("Agent CSS classes", () => {
expect(roleFocusBlock).toContain("box-shadow: var(--focus-ring-strong)");
});
it("should define shared AgentEmptyState component primitives", () => {
expect(hasClass(".agent-empty-state__icon")).toBe(true);
expect(hasClass(".agent-empty-state__title")).toBe(true);
expect(hasClass(".agent-empty-state__description")).toBe(true);
it("should keep the create-agent empty-state action copy", () => {
expect(agentEmptyStateContent).toContain("Create Agent");
});

View File

@@ -6,6 +6,7 @@ const COMPONENTS_DIR = join(APP_DIR, "components");
let cached: string | null = null;
let stylesCached: string | null = null;
let baseOnlyCached: string | null = null;
export function loadStylesCss(): string {
if (stylesCached !== null) return stylesCached;
@@ -40,6 +41,7 @@ export function loadAllAppCss(): string {
* against @media overrides that happen to come earlier in the source order.
*/
export function loadAllAppCssBaseOnly(): string {
if (baseOnlyCached !== null) return baseOnlyCached;
const src = loadAllAppCss();
// Walk and excise any top-level @<rule> { ... } block (e.g. @media, @supports)
let out = "";
@@ -60,5 +62,6 @@ export function loadAllAppCssBaseOnly(): string {
}
out += src[i++];
}
return out;
baseOnlyCached = out;
return baseOnlyCached;
}

View File

@@ -37,6 +37,8 @@
"dev": "pnpm build && pnpm typecheck && pnpm dev:serve",
"dev:serve": "vite dev",
"test": "vitest run --silent=passed-only --reporter=dot --exclude '**/build-output.test.ts'",
"test:app": "vitest run --project dashboard-app --silent=passed-only --reporter=dot --exclude '**/build-output.test.ts'",
"test:api": "vitest run --project dashboard-api --silent=passed-only --reporter=dot",
"test:browser-smoke": "node scripts/browser-layout-smoke.mjs",
"test:build": "vitest run --silent=passed-only --reporter=dot app/__tests__/build-output.test.ts",
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.app.json"

View File

@@ -42,7 +42,7 @@ describe("Session files endpoint", () => {
mkdirSync(testWorktree, { recursive: true });
// Initialize git repo
execSync("git init", { cwd: testWorktree });
execSync("git init --initial-branch=main", { cwd: testWorktree });
execSync("git config user.email test@test.com", { cwd: testWorktree });
execSync("git config user.name Test", { cwd: testWorktree });

View File

@@ -716,7 +716,7 @@ describe("POST /api/projects route handler", () => {
const cloneDestination = join(tempRoot, "cloned-project");
try {
execFileSync("git", ["init", "--bare", bareRepo]);
execFileSync("git", ["init", "--bare", "--initial-branch=main", bareRepo]);
const res = await request(
app,

View File

@@ -307,8 +307,8 @@ function getSharedGitTestRepo(): GitTestRepo {
const repoDir = join(root, "repo");
mkdirSync(repoDir, { recursive: true });
execFileSync("git", ["init", "--bare", remoteDir], { stdio: "pipe" });
execFileSync("git", ["init", repoDir], { stdio: "pipe" });
execFileSync("git", ["init", "--bare", "--initial-branch=main", remoteDir], { stdio: "pipe" });
execFileSync("git", ["init", "--initial-branch=main", repoDir], { stdio: "pipe" });
execFileSync("git", ["-C", repoDir, "config", "user.email", "kb-tests@example.com"], { stdio: "pipe" });
execFileSync("git", ["-C", repoDir, "config", "user.name", "KB Tests"], { stdio: "pipe" });
writeFileSync(join(repoDir, "README.md"), "# Test Repo\n");
@@ -1485,4 +1485,3 @@ describe("Workspace File Routes", () => {
});
});
});

View File

@@ -307,8 +307,8 @@ function getSharedGitTestRepo(): GitTestRepo {
const repoDir = join(root, "repo");
mkdirSync(repoDir, { recursive: true });
execFileSync("git", ["init", "--bare", remoteDir], { stdio: "pipe" });
execFileSync("git", ["init", repoDir], { stdio: "pipe" });
execFileSync("git", ["init", "--bare", "--initial-branch=main", remoteDir], { stdio: "pipe" });
execFileSync("git", ["init", "--initial-branch=main", repoDir], { stdio: "pipe" });
execFileSync("git", ["-C", repoDir, "config", "user.email", "kb-tests@example.com"], { stdio: "pipe" });
execFileSync("git", ["-C", repoDir, "config", "user.name", "KB Tests"], { stdio: "pipe" });
writeFileSync(join(repoDir, "README.md"), "# Test Repo\n");
@@ -2029,4 +2029,3 @@ describe("GET /tasks/:id/file-diffs", () => {
// --- Git Management route tests ---
// These are integration tests that run against the actual git repository

View File

@@ -694,8 +694,8 @@ function getSharedGitTestRepo(): GitTestRepo {
const repoDir = join(root, "repo");
mkdirSync(repoDir, { recursive: true });
execFileSync("git", ["init", "--bare", remoteDir], { stdio: "pipe" });
execFileSync("git", ["init", repoDir], { stdio: "pipe" });
execFileSync("git", ["init", "--bare", "--initial-branch=main", remoteDir], { stdio: "pipe" });
execFileSync("git", ["init", "--initial-branch=main", repoDir], { stdio: "pipe" });
execFileSync("git", ["-C", repoDir, "config", "user.email", "kb-tests@example.com"], { stdio: "pipe" });
execFileSync("git", ["-C", repoDir, "config", "user.name", "KB Tests"], { stdio: "pipe" });
writeFileSync(join(repoDir, "README.md"), "# Test Repo\n");
@@ -720,4 +720,3 @@ afterAll(() => {
afterEach(() => {
resetDiagnosticsSink();
});

View File

@@ -36,20 +36,7 @@ export default defineConfig({
},
},
test: {
// `app/**` is React UI — needs jsdom + CSS. `src/**` is the Express
// backend, mostly Node-only logic; running it in node env trims jsdom
// env+CSS-include cost. The handful of src tests that genuinely need DOM
// opt-in via `// @vitest-environment jsdom`.
environment: "node",
environmentMatchGlobs: [
["app/**", "jsdom"],
],
// Process CSS imports only for jsdom-based tests that assert on
// getComputedStyle. Node-env tests under src/** don't need CSS rules and
// skipping the transform there cuts a large slice of total wall time.
css: { include: [/app\//] },
globals: true,
include: ["app/**/*.test.{ts,tsx}", "src/**/*.test.{ts,tsx}"],
setupFiles: [
resolve(__dirname, "../core/src/__test-utils__/vitest-setup.ts"),
"./vitest.setup.ts",
@@ -66,6 +53,28 @@ export default defineConfig({
// 5s default under workspace-concurrent runs.
testTimeout: 15_000,
hookTimeout: 15_000,
projects: [
{
extends: true,
test: {
name: "dashboard-app",
environment: "jsdom",
include: ["app/**/*.test.{ts,tsx}"],
// Process CSS imports only for jsdom tests that assert on
// getComputedStyle. Node API tests do not need CSS transforms.
css: { include: [/app\//] },
},
},
{
extends: true,
test: {
name: "dashboard-api",
environment: "node",
include: ["src/**/*.test.{ts,tsx}"],
css: { include: [] },
},
},
],
coverage: {
enabled: false,
reporter: ["text", "html", "json"],

View File

@@ -12,6 +12,7 @@ const clearDaemonAuthEnv = () => {
clearDaemonAuthEnv();
const noisyOutputMarkers = [
"ExperimentalWarning: SQLite is an experimental feature",
"Subagent result watcher failed",
"pi-async-subagent-results",
"[pi] createFnAgent called",