Files
fusion/packages/dashboard/vitest.config.ts
gsxdsm d22b8cc60a FN-7232: dismiss task detail on mobile swipe-back
Mobile task details now participate in history navigation so native swipe-back dismisses or unwinds the detail modal.

- Push a navigation entry whenever task detail opens through the app-level modal path.
- Restore the previous task detail snapshot when backing out of nested detail opens before closing the modal.
- Add mobile swipe-back coverage for board, list, dock, nested, and explicit close surfaces.
- Include a patch changeset for the published Fusion CLI package.

Files changed:
 .changeset/fn-7232-swipe-back-task-detail.md       |   7 +
 packages/dashboard/app/App.tsx                     |   5 +-
 packages/dashboard/app/components/AppModals.tsx    |  26 +-
 .../__tests__/TaskDetail.swipe-back.test.tsx       | 572 +++++++++++++++++++++
 packages/dashboard/vitest.config.ts                |   1 +
 5 files changed, 605 insertions(+), 6 deletions(-)

Fusion-Task-Id: FN-7232

Fusion-Task-Lineage: 0291d01c-2008-490c-b0d1-0f0641fbd18c

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-06-29 14:34:44 -07:00

686 lines
32 KiB
TypeScript

import { defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { computeMaxWorkers } from "../core/src/__test-utils__/vitest-workers";
const maxWorkers = computeMaxWorkers({ defaultCap: 3 });
/*
FNXC:DashboardTests 2026-06-17-17:02:
Dashboard tests must be insulated from release-oriented shells that export NODE_ENV=production. Force test mode before Vitest resolves React and Testing Library so jsdom projects keep React.act and do not fail after slow browser-environment startup.
*/
process.env.NODE_ENV = "test";
// Curated-gate skip-list (plan U2 / R7). Files listed here run in NO project on
// purpose (pre-existing failures discovered when the curated-gate hole was
// closed). The skip-list is the single source of truth shared with
// scripts/check-test-inventory.mjs's --dashboard-curated guard. Express the
// dashboard-relative globs so the backfill projects can exclude them.
const curatedSkipList: { entries: { file: string; reason: string }[] } = JSON.parse(
readFileSync(resolve(__dirname, "../../scripts/lib/dashboard-curated-skiplist.json"), "utf8"),
);
const skipListDashboardGlobs = curatedSkipList.entries
.map((entry) => entry.file.replace(/^packages\/dashboard\//, ""))
.filter((file) => file.length > 0);
const qualityAppFoundationApiTests = [
// API-client regressions are numerous but lightweight; keep them in their
// own shard so the jsdom heap can reset before broader UI/layout coverage.
"app/__tests__/api-*.test.ts",
"app/api/**/*.test.ts",
];
const qualityAppFoundationUiTests = [
// Top-level UI, auth, shell, mobile layout, and styling regressions.
// Keep these as explicit file paths: this shard completes reliably when the
// worker starts from a concrete file list instead of the broad glob.
"app/__tests__/AgentMentionPopup.css.test.ts",
"app/__tests__/App.boot-gate.test.tsx",
"app/__tests__/App.shell-onboarding.test.tsx",
"app/__tests__/ShellContext.test.tsx",
"app/__tests__/activity-feed-theme-styling.test.ts",
"app/__tests__/activity-log-mobile-layout.test.ts",
"app/__tests__/agent-css-classes.test.ts",
"app/__tests__/agent-runs-ui.test.ts",
"app/__tests__/animation-duration-tokens.css.test.ts",
"app/__tests__/auth.test.ts",
"app/__tests__/board-mobile-corner-rendering.test.ts",
"app/__tests__/board-tablet-overflow.test.ts",
"app/__tests__/browser-layout-smoke-fixture.test.ts",
"app/__tests__/chat-tool-calls-mobile-layout.test.ts",
"app/__tests__/column-fixed-width.test.ts",
"app/__tests__/component-css-no-raw-rgba.test.ts",
"app/__tests__/dashboard-component-color-tokenization.test.ts",
"app/__tests__/dashboard-css-token-validity.css.test.ts",
"app/__tests__/dashboard-footer-mobile-layout.test.ts",
"app/__tests__/detail-body-mobile-overflow.test.ts",
"app/__tests__/dev-server-layout-css.test.ts",
"app/__tests__/executor-status-bar-theme.test.ts",
"app/__tests__/footer-safe-layout.test.ts",
"app/__tests__/git-manager-theme-styling.test.ts",
"app/__tests__/index-html-theme-link.test.ts",
"app/__tests__/insight-model-selector.test.tsx",
"app/__tests__/lazy-loaded-views-docs.test.ts",
"app/__tests__/mission-planning-modals-mobile.test.ts",
"app/__tests__/mobile-bottom-bars-keyboard-layout.test.ts",
"app/__tests__/mobile-bottom-space-layout.test.ts",
"app/__tests__/mobile-feature-access-regression.test.tsx",
"app/__tests__/mobile-header-controls.test.ts",
"app/__tests__/mobile-input-font-size.test.ts",
"app/__tests__/mobile-nav-bar-css.test.ts",
"app/__tests__/mobile-planning-input-font-size.test.ts",
"app/__tests__/mobile-scripts.test.ts",
"app/__tests__/mobile-scroll-snap.test.ts",
"app/__tests__/no-legacy-public.test.ts",
"app/__tests__/onboarding-overlay-layering.test.ts",
"app/__tests__/pwa.test.ts",
"app/__tests__/quick-chat-mobile-keyboard-layout.test.ts",
"app/__tests__/quick-chat-session-dropdown.test.ts",
"app/__tests__/quick-chat-tool-calls-mobile-layout.test.ts",
"app/__tests__/quick-entry-expanded-height.test.tsx",
"app/__tests__/settings-mobile-wrap.test.ts",
"app/__tests__/setup-wizard-modal-layout.test.ts",
"app/__tests__/shell-host.test.ts",
"app/__tests__/shell-native.test.ts",
"app/__tests__/spinner-animation.css.test.ts",
"app/__tests__/sse-bus.test.ts",
"app/__tests__/status-colors-theme.test.ts",
"app/__tests__/swUpdate.test.ts",
"app/__tests__/tablet-header-controls.test.tsx",
"app/__tests__/task-detail-modal-tablet-width.test.ts",
"app/__tests__/terminal-input.test.ts",
"app/__tests__/terminal-mobile-header-row.test.ts",
"app/__tests__/terminal-mobile-keyboard-layout.test.ts",
"app/__tests__/text-token-canonicalization.test.ts",
"app/__tests__/versionCheck.test.ts",
"app/__tests__/viewport-compensation-keyboard.test.ts",
];
const qualityAppHooksAndUtilsTests = [
// Hooks and utilities are fast, user-visible state/formatting behavior.
"app/context/**/*.test.tsx",
"app/hooks/__tests__/{useAgents,useAgentLogs,useAgentLogs.resume-instrumentation,useAppSettings,useAuthOnboarding,useConfirm,useCurrentProject,useNodes,useNodes.resume-instrumentation,useNodeSettingsSync,useProjects,useProjects.resume-instrumentation,useMeshState.resume-instrumentation,useManagedDockerNodes.resume-instrumentation,usePrChecksStream.resume-instrumentation,useDevServerLogs.resume-instrumentation,useResearch.resume-instrumentation,useBackgroundSessions.resume-instrumentation,useQuickChat,useTasks,useTasks.resume-instrumentation,useChatRooms,useTerminalSessions,useTheme,useToast,useUsageData,useViewportMode,useViewState,useMergeAdvanceNotice}.test.{ts,tsx}",
"app/utils/**/*.test.{ts,tsx}",
];
const qualityAppComponentTests = [
"ActiveAgentsPanel",
"ActivityLogModal",
"AgentMentionPopup",
"AgentMetricsBar",
"AgentOnboardingModal",
"AgentReflectionsTab",
"AgentTokenStatsPanel",
"App",
"AuthTokenRecoveryDialog",
"Board",
"Board.canDropTask",
"auto-merge-toggle-blank.mobile",
"auto-merge-toggle-blank.mobile-integration",
"board-mobile",
"board-mobile-view-switch",
"BranchGroupCard",
"ChatView.autosize",
"ChatView.chat-input-autosize",
"ChatView.default-model-icon",
"ChatView.draft",
"ChatView.hash-mention",
"ChatView.rooms",
"ChatView.scroll-to-top",
"ChatView.swipe-back",
"Column",
"ConfirmDialog",
"ConversationHistory",
"DataBoundary",
"DashboardLoader",
"DevServerView.mobile",
"DirectoryPicker",
"DuplicateWarningModal",
"ErrorBoundary",
"ExecutorStatusBar",
"FileBrowser",
"FileEditor",
"GitHubBadge",
"GroupTaskModal",
"InlineCreateCard",
"Lane",
"LoginInstructions",
"MemoryView",
"MergeAdvanceNotice",
"MessageComposer",
"MessageComposer.autosize",
"MobileNavBar",
"NewTaskModal",
"NewTaskModal.shared-cache",
"NodeCard",
"NodeHealthDot",
"NodeStatusIndicator",
"PlanningModeModal.autosize",
"PluginManager.registry",
"PrChecksList",
"PrCreateModal",
"PrCreateModal.layout",
"ProjectCard",
"ProjectHealthBadge",
"ProjectSelector",
"ProviderIcon",
"PrPanel",
"PrPanel.merge",
"PrPanel.reviews",
"QuickChatFAB",
"QuickChatFAB.shared-cache",
"ReliabilityView",
"ResearchView",
"RightDock",
"SecretsView",
"SecretsView.mobile",
"SettingsModal.testMode",
"SettingsModal.worktrunk",
"StashConflictModal",
"StashRecoveryView",
"TaskCard",
"TaskCard.badge-height",
"TaskCard.badge-wrap",
"TaskCard.footer-wrap",
"TaskChangesTab",
"TaskComments",
"TaskDetail.swipe-back",
"TaskDetailModal",
"TaskDetailModal.allow-resurrection",
"TaskDetailModal.create-pr-e2e",
"TaskDetailModal.custom-fields",
"TaskDetailModal.inline-editing-and-integrations",
"TestModeBanner",
"TaskDetailModal.create-pr-integration",
"TaskDetailModal.github-tracking-header",
"TaskDetailModal.github-tracking-stale",
"TaskDocumentsTab",
"TaskFieldsSection",
"TaskReviewTab",
"TaskForm",
"TaskIdIntegrityBanner",
"TrackingRepoSelect",
"WorkflowFieldsPanel",
"WorkflowSettingsPanel",
"WorkflowNodeEditor",
"WorkflowResultsTab",
"WorkflowSelector",
"workflow-flow-mapping",
"WorktrunkInstallApprovalDetails",
] as const;
// FNXC:DashboardTests 2026-06-25-10:10: SettingsModal stays isolated in its own
// project, but the 231-test suite is now 4 sibling files sharing
// SettingsModal.test-harness so the settings project parallelizes them across
// workers instead of one ~61s sequential file (FN-5048 feedback-loop velocity).
const isolatedQualityAppComponentTests = ["App"] as const;
const batchedQualityAppComponentTests = qualityAppComponentTests.filter(
(testName) => !isolatedQualityAppComponentTests.includes(testName),
);
const batchedQualityAppSplitIndex = Math.ceil(batchedQualityAppComponentTests.length / 2);
const batchedQualityAppComponentTestsA = batchedQualityAppComponentTests.slice(0, batchedQualityAppSplitIndex);
const batchedQualityAppComponentTestsB = batchedQualityAppComponentTests.slice(batchedQualityAppSplitIndex);
function buildComponentQualityInclude(testNames: readonly string[]): string[] {
return testNames.map((testName) => `app/components/__tests__/${testName}.test.{ts,tsx}`);
}
const qualityAppTests = [
...qualityAppFoundationApiTests,
...qualityAppFoundationUiTests,
...qualityAppHooksAndUtilsTests,
...buildComponentQualityInclude(qualityAppComponentTests),
];
const qualityAppFoundationApiShardTests = [...qualityAppFoundationApiTests];
const qualityAppFoundationUiShardTests = [...qualityAppFoundationUiTests];
const qualityAppFoundationHooksAndUtilsTests = [...qualityAppHooksAndUtilsTests];
const qualityAppComponentBatchATests = buildComponentQualityInclude(batchedQualityAppComponentTestsA);
const qualityAppComponentBatchBTests = buildComponentQualityInclude(batchedQualityAppComponentTestsB);
const qualityAppAppOnlyTests = ["app/components/__tests__/App.test.tsx"];
/*
FNXC:DashboardTests 2026-06-25-16:30:
ChatView keeps its own isolated `dashboard-app-quality-chat` project, but the 231-test
ChatView.test.tsx is now 3 sibling files sharing ChatView.test-harness so the chat project
parallelizes them across workers instead of one ~24s sequential file (FN-5048 feedback-loop
velocity). Mirror the SettingsModal split: these 3 files live ONLY here (not in
qualityAppComponentTests), so they must be spread into backfillAppExclude too — otherwise
the broad `app/**` backfill glob re-collects them and they run in BOTH projects.
*/
const qualityAppChatOnlyTests = [
"app/components/__tests__/ChatView.core.test.tsx",
"app/components/__tests__/ChatView.sessions-rooms.test.tsx",
"app/components/__tests__/ChatView.mobile.test.tsx",
// FNXC:DashboardTests 2026-06-29-14:14: Task-detail chat typography regressions must run in the same chat quality lane as the required FN-7240 targeted command, so CSS-content assertions cannot fall through to broad backfill only.
"app/components/__tests__/TaskChatTab.test.tsx",
];
const qualityAppSettingsOnlyTests = [
"app/components/__tests__/SettingsModal.general.test.tsx",
"app/components/__tests__/SettingsModal.models-auth.test.tsx",
"app/components/__tests__/SettingsModal.scheduling-merge.test.tsx",
"app/components/__tests__/SettingsModal.remote-notifications.test.tsx",
];
/*
FNXC:DashboardTestQuarantine 2026-06-14-17:01:
FN-6454 applied the quarantine deletion ratchet to every dashboard test quarantined on 2026-06-14.
Keep this list empty until a new flaky dashboard test is quarantined with a matching ledger entry.
FNXC:DashboardTestQuarantine 2026-06-16-21:31:
FN-6514 rescued QuickEntryBox before the 2026-06-30 deletion deadline by restoring its mutated jsdom viewport, visibility, and object-URL globals in file teardown.
Keep it out of this exclude list so the broad app backfill lane exercises its aria-expanded regression coverage without quarantine drift.
FNXC:DashboardTestQuarantine 2026-06-16-19:21:
FN-6496 merge verification observed github-tracking-hook fail during the changed-test backfill shard with temp-directory cleanup ENOTEMPTY, then pass on isolated rerun.
Quarantine the cleanup-flaky file under the deletion ratchet rather than changing production or test timing outside the chat-streaming scope.
FNXC:DashboardTestQuarantine 2026-06-17-16:12:
FN-6593 deletes github-tracking-hook under the ratchet because the temp-cleanup ENOTEMPTY flake did not have a non-appeasement root-cause fix in this follow-up.
Keep the ledger entry and exclude removed together; git history remains the archive for this dropped GitHub tracking hook coverage.
FNXC:DashboardTestQuarantine 2026-06-18-06:12:
FN-6633 workspace verification observed unrelated QuickEntryBox focus and chat-routes SSE lifecycle flakes after the targeted chat prompt regression suite passed.
Quarantine the files under the deletion ratchet so this prompt-only chat guidance change does not appease flaky timing/focus behavior.
FNXC:DashboardTestQuarantine 2026-06-18-09:02:
FN-6642 rescued QuickEntryBox after the single-file and full app-backfill lanes passed with the exclude removed.
Keep QuickEntryBox out of this list so focus-restoration coverage remains active instead of deleting useful user-facing behavior coverage.
FNXC:DashboardTestQuarantine 2026-06-18-09:07:
FN-6642 rescued chat-routes by fixing the shared engine mock to return an iterable chat-task-document tool list during broad API lanes.
Keep chat-routes out of this list so SSE lifecycle coverage remains active and the ledger/config stay in lockstep.
FNXC:DashboardTestQuarantine 2026-06-19-03:22:
FN-6690 workspace verification observed session-cross-tab fail only during the broad dashboard API backfill shard with temp-directory cleanup ENOTEMPTY, then pass on isolated rerun.
Quarantine the cleanup-flaky file under the deletion ratchet rather than changing timing or session-locking behavior outside the lazy-view CSS chunk scope.
FNXC:DashboardTestQuarantine 2026-06-19-05:20:
FN-6697 workspace verification observed the QuickEntryBox post-submit focus restoration test fail only in the broad dashboard app backfill shard, then pass on targeted rerun.
Quarantine the focus-timing flake under the deletion ratchet instead of changing unrelated terminal shortcut behavior or appeasing the test.
FNXC:DashboardTestQuarantine 2026-06-19-08:17:
FN-6726 workspace verification observed the WorkflowNodeEditor duplicate-merge-seam template conflict test fail only in the broad components-b shard, then pass on targeted rerun.
Quarantine the concurrency-sensitive workflow editor file under the deletion ratchet instead of changing unrelated template insertion behavior or appeasing the test.
FNXC:DashboardTestQuarantine 2026-06-19-18:12:
FN-6744 rescued WorkflowNodeEditor before the 2026-07-03 deletion deadline by deriving duplicate-fragment seam conflicts from the active workflow IR plus React Flow nodes.
Keep it out of this exclude list so desktop and mobile template guards continue proving duplicate merge seams surface an inline alert with no insertion under components-b shard load.
FNXC:DashboardTestQuarantine 2026-06-19-15:40:
FN-6742 rescued session-cross-tab before the 2026-07-03 deletion ratchet by reproducing ENOTEMPTY in dashboard-api-quality-backfill and fixing the test-owned route/close-callback teardown seam.
Keep it out of this exclude list so loaded API shards keep exercising cross-tab locking, beacon release, stale-lock expiry, SSE summaries, and stale-session cleanup.
FNXC:DashboardTestQuarantine 2026-06-19-16:50:
FN-6743 rescued QuickEntryBox's third quarantine cycle by replacing the ref-gated post-submit focus effect with a resolved-submit focus trigger and broadening desktop/mobile submit coverage.
Keep QuickEntryBox out of this list so the dashboard app lanes exercise Enter, Save, duplicate-confirmed creation, mobile non-focus, and failure-preserves-draft focus invariants.
FNXC:DashboardTestQuarantine 2026-06-21-06:50:
FN-6722 workspace verification observed dev-server-process time out only in the broad dashboard API backfill shard while the isolated file passed immediately. Quarantine the process/timer race under the deletion ratchet instead of widening waits or changing unrelated Command Center behavior.
FNXC:DashboardTestQuarantine 2026-06-21-12:42:
FN-6860 rescued dev-server-process by settling stdout detection and fallback-probe lifecycle work before stop/close/failure teardown, then removed its ledger/config quarantine entry. The same loaded API shard also confirmed FN-6742's session-cross-tab rescue still holds, so its stale ledger-only entry was removed to restore lockstep.
FNXC:DashboardTestQuarantine 2026-06-22-18:05:
FN-6937 verified that FN-6860's claimed session-cross-tab ledger removal had not landed: the file was active because this exclude list was empty, but `test-quarantine.json` still carried the stale 2026-06-19 row. The repeated loaded `dashboard-api-quality-backfill` runs and lock-holder mutation proof confirmed FN-6742's rescue still holds, so remove the orphaned ledger row and keep this list empty to restore ledger↔config lockstep.
*/
/*
FNXC:DashboardTestQuarantine 2026-06-26-13:16:
FN-7068 rescued DevServerView.mobile before the deletion deadline by realigning its mobile CSS assertion to the split preview-header and launcher-copy rules in DevServerView.css. Keep this quarantine list empty until a new flaky dashboard file is added with a matching ledger entry.
*/
const quarantinedDashboardTests: string[] = [];
const qualityApiTests = [
// Critical HTTP/server behavior: auth, task/project/settings mutation,
// git/GitHub, agents, nodes, chat/files, realtime, and isolation guards.
/*
FNXC:DashboardTests 2026-06-19-22:14:
FN-6753 observed routes-auth timing out only under the broad API backfill shard, while five loaded local shard runs did not expose a concrete probe-spy or teardown root cause.
Keep this auth-critical suite in the curated API shard so its assertions remain active without running inside the contended broad backfill glob.
*/
"src/__tests__/{api-error,auth-middleware,auth-middleware-integration,chat-attachment-routes,chat-manager,chat-routes,file-service,github,github-webhooks,initialize,planning-flow-diagnostics-guardrail,pr-routes-auto-merge,pr-routes.contract,project-routes,project-store-resolver,register-git-github.pr-options-preflight-metadata,register-git-github.pr-resolve-conflicts,remote-access-routes,remote-auth,routes-agent-budget,routes-agent-keys,routes-agent-permissions,routes-agent-ratings,routes-agent-runs,routes-agent-soul-memory,routes-agents,routes-auth,routes-automation,routes-branch-groups,routes-git,routes-github,routes-merge-advance-push-origin,routes-nodes,routes-nodes-sync-contract,routes-planning,routes-plugin-registry,routes-secrets-sync,routes-settings,routes-task-commit-associations,routes-tasks,routes-tasks-deterministic-dedup,routes-tasks-duplicate-check,routes-tasks-explicit-duplicate-marker,server,server-static-assets,server-webhook,server.events,setup-routes,sse,sse-buffer,test-isolation-guard,update-check-route,websocket,recover-branch-binding-route}.test.ts",
"src/__tests__/dashboard-test-config-guard.test.ts",
"src/routes/__tests__/{custom-provider-routes,custom-providers,register-docker-node-routes,register-diagnostics-routes,stash-recovery-routes}.test.ts",
"scripts/__tests__/{run-quality-tests,run-vitest-with-heap}.test.ts",
];
// Backfill projects (plan U2 / R7). Historically the curated quality lanes
// enumerated their files by hand, so any app/ or src/ test file that nobody
// added to a curated list ran in NO project — not locally, not in CI. The
// backfill projects close that hole structurally: they include the broad
// globs and EXCLUDE only (a) files already executed by a curated lane and
// (b) the explicit skip-list. A brand-new test file therefore lands in
// backfill automatically; it can never silently fall through again.
const backfillAppExclude = [
...qualityAppTests,
/*
FNXC:DashboardTests 2026-06-25-10:40:
The SettingsModal split removed the bare "SettingsModal" entry from
qualityAppComponentTests, which is what previously excluded the curated
settings file from the broad app backfill (via qualityAppTests). The 4 split
files live only in qualityAppSettingsOnlyTests, so spread them here too —
otherwise the backfill `app/**` glob re-collects them and they run in BOTH the
settings project and backfill, doubling their wall-time instead of halving it.
*/
...qualityAppSettingsOnlyTests,
// FNXC:DashboardTests 2026-06-25-16:30: same rationale as the settings split above —
// the 3 ChatView split files live only in qualityAppChatOnlyTests, so exclude them from
// the broad app backfill to avoid double-collection.
...qualityAppChatOnlyTests,
...skipListDashboardGlobs.filter((file) => file.startsWith("app/")),
"app/__tests__/build-output.test.ts",
];
const qualityAppBackfillTests = ["app/**/*.test.{ts,tsx}"];
const backfillApiExclude = [
...qualityApiTests,
...skipListDashboardGlobs.filter((file) => file.startsWith("src/")),
];
const qualityApiBackfillTests = ["src/**/*.test.{ts,tsx}"];
// The broad `dashboard-app` / `dashboard-api` lanes fully duplicate the curated
// shards + backfill projects, which already partition app/ and src/ exactly
// once. They exist ONLY as the explicit deep escape hatches
// (`test:deep`/`test:app`/`test:api`/`test:build`). In the DEFAULT no-`--project`
// run — e.g. `vitest run --changed` from `pnpm test` — letting their globs match
// re-executes every test a second time (and, with the now-removed umbrella, a
// third). Gate their includes on FUSION_DASHBOARD_DEEP so the default run uses
// the curated partition once; the deep scripts set the flag to opt back in.
const deepLaneEnabled = process.env.FUSION_DASHBOARD_DEEP === "1";
const deepAppInclude = deepLaneEnabled ? ["app/**/*.test.{ts,tsx}"] : [];
const deepApiInclude = deepLaneEnabled ? ["src/**/*.test.{ts,tsx}"] : [];
// Footgun guard: with the deep lanes gated off, selecting one explicitly
// (`vitest run --project dashboard-app`) matches zero files and exits green in
// milliseconds — a silent no-op that reads as a passing run. Warn loudly so a
// manual invocation isn't mistaken for coverage. Exact token match avoids firing
// on the curated `dashboard-app-*` shard projects. The deep scripts set
// FUSION_DASHBOARD_DEEP=1, so this never fires through the intended entry points.
if (!deepLaneEnabled) {
const selectedProjects = process.argv.flatMap((arg, index) =>
arg === "--project"
? [process.argv[index + 1]]
: arg.startsWith("--project=")
? [arg.slice("--project=".length)]
: [],
);
if (selectedProjects.some((name) => name === "dashboard-app" || name === "dashboard-api")) {
console.warn(
"[dashboard/vitest] --project dashboard-app/dashboard-api selected without FUSION_DASHBOARD_DEEP=1: " +
"these deep lanes are empty by default and will match zero test files. " +
"Use the test:app / test:api / test:deep / test:build scripts, which set the flag.",
);
}
}
export const dashboardQualityProjectGlobs = {
"dashboard-app-quality-foundation-api": {
include: qualityAppFoundationApiShardTests,
exclude: quarantinedDashboardTests,
},
"dashboard-app-quality-foundation-ui": {
include: qualityAppFoundationUiShardTests,
exclude: quarantinedDashboardTests,
},
"dashboard-app-quality-foundation-hooks-utils": {
include: qualityAppFoundationHooksAndUtilsTests,
exclude: quarantinedDashboardTests,
},
"dashboard-app-quality-components-a": {
include: qualityAppComponentBatchATests,
exclude: quarantinedDashboardTests,
},
"dashboard-app-quality-components-b": {
include: qualityAppComponentBatchBTests,
exclude: quarantinedDashboardTests,
},
"dashboard-app-quality-app": {
include: qualityAppAppOnlyTests,
exclude: quarantinedDashboardTests,
},
"dashboard-app-quality-chat": {
include: qualityAppChatOnlyTests,
exclude: quarantinedDashboardTests,
},
"dashboard-app-quality-settings": {
include: qualityAppSettingsOnlyTests,
exclude: quarantinedDashboardTests,
},
"dashboard-api-quality": {
include: qualityApiTests,
exclude: quarantinedDashboardTests,
},
"dashboard-app-quality-backfill": {
include: qualityAppBackfillTests,
exclude: [...backfillAppExclude, ...quarantinedDashboardTests],
},
"dashboard-api-quality-backfill": {
include: qualityApiBackfillTests,
exclude: [...backfillApiExclude, ...quarantinedDashboardTests],
},
} as const;
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
"@fusion/core": resolve(__dirname, "../core/src/index.ts"),
"@fusion/engine": resolve(__dirname, "../engine/src/index.ts"),
"@fusion/plugin-sdk": resolve(__dirname, "../plugin-sdk/src/index.ts"),
"@fusion/test-utils": resolve(__dirname, "../core/src/__test-utils__/workspace.ts"),
"@fusion/dashboard/app/components/TaskCard": resolve(__dirname, "app/components/TaskCard.tsx"),
"@fusion/dashboard/app/components/ViewHeader": resolve(__dirname, "app/components/ViewHeader.tsx"),
"@fusion/dashboard/app/plugins/types": resolve(__dirname, "app/plugins/types.ts"),
"@fusion/dashboard/app/utils/projectStorage": resolve(__dirname, "app/utils/projectStorage.ts"),
"@fusion/dashboard/app/utils/taskStuck": resolve(__dirname, "app/utils/taskStuck.ts"),
"@fusion-plugin-examples/droid-runtime/probe": resolve(
__dirname,
"../../plugins/fusion-plugin-droid-runtime/src/probe.ts",
),
"@fusion-plugin-examples/droid-runtime": resolve(
__dirname,
"../../plugins/fusion-plugin-droid-runtime/src/index.ts",
),
"@fusion-plugin-examples/hermes-runtime": resolve(
__dirname,
"../../plugins/fusion-plugin-hermes-runtime/src/index.ts",
),
"@fusion-plugin-examples/openclaw-runtime": resolve(
__dirname,
"../../plugins/fusion-plugin-openclaw-runtime/src/index.ts",
),
"@fusion-plugin-examples/paperclip-runtime": resolve(
__dirname,
"../../plugins/fusion-plugin-paperclip-runtime/src/index.ts",
),
"@fusion-plugin-examples/dependency-graph/dashboard-view": resolve(
__dirname,
"../../plugins/fusion-plugin-dependency-graph/src/dashboard-view.tsx",
),
"@fusion-plugin-examples/dependency-graph": resolve(
__dirname,
"../../plugins/fusion-plugin-dependency-graph/src/index.ts",
),
"@fusion-plugin-examples/compound-engineering/dashboard-view": resolve(
__dirname,
"../../plugins/fusion-plugin-compound-engineering/src/dashboard-view.tsx",
),
"@fusion-plugin-examples/compound-engineering": resolve(
__dirname,
"../../plugins/fusion-plugin-compound-engineering/src/index.ts",
),
},
},
test: {
globals: true,
setupFiles: [
resolve(__dirname, "../core/src/__test-utils__/vitest-setup.ts"),
"./vitest.setup.ts",
],
globalSetup: [resolve(__dirname, "../core/src/__test-utils__/vitest-teardown.ts")],
// Threads share a V8 heap so they're much lighter than forks for jsdom +
// React suites; forks duplicated the entire renderer per worker (~500MB).
pool: "threads",
maxWorkers,
minWorkers: 1,
fileParallelism: true,
isolate: true,
exclude: quarantinedDashboardTests,
// Dashboard route and integration-heavy suites can exceed the Vitest
// 5s default under workspace-concurrent runs.
testTimeout: 15_000,
hookTimeout: 15_000,
projects: [
// NOTE: the former `dashboard-app-quality` umbrella project was removed —
// it re-ran the exact union of the eight curated shards below (a 3rd copy
// of every curated app test in the default no-`--project` run). The shards
// partition `qualityAppTests` exactly; `dashboardQualityProjectGlobs` and
// scripts/lib/test-inventory-spec.json never referenced the umbrella.
{
extends: true,
test: {
name: "dashboard-app-quality-foundation-api",
environment: "jsdom",
include: qualityAppFoundationApiShardTests,
exclude: quarantinedDashboardTests,
css: { include: [/app\//] },
},
},
{
extends: true,
test: {
name: "dashboard-app-quality-foundation-ui",
environment: "jsdom",
include: qualityAppFoundationUiShardTests,
exclude: quarantinedDashboardTests,
css: { include: [/app\//] },
},
},
{
extends: true,
test: {
name: "dashboard-app-quality-foundation-hooks-utils",
environment: "jsdom",
include: qualityAppFoundationHooksAndUtilsTests,
exclude: quarantinedDashboardTests,
css: { include: [/app\//] },
},
},
{
extends: true,
test: {
name: "dashboard-app-quality-components-a",
environment: "jsdom",
include: qualityAppComponentBatchATests,
exclude: quarantinedDashboardTests,
css: { include: [/app\//] },
},
},
{
extends: true,
test: {
name: "dashboard-app-quality-components-b",
environment: "jsdom",
include: qualityAppComponentBatchBTests,
exclude: quarantinedDashboardTests,
css: { include: [/app\//] },
},
},
{
extends: true,
test: {
name: "dashboard-app-quality-app",
environment: "jsdom",
include: qualityAppAppOnlyTests,
exclude: quarantinedDashboardTests,
css: { include: [/app\//] },
},
},
{
extends: true,
test: {
name: "dashboard-app-quality-chat",
environment: "jsdom",
include: qualityAppChatOnlyTests,
exclude: quarantinedDashboardTests,
css: { include: [/app\//] },
},
},
{
extends: true,
test: {
name: "dashboard-app-quality-settings",
environment: "jsdom",
include: qualityAppSettingsOnlyTests,
exclude: quarantinedDashboardTests,
css: { include: [/app\//] },
},
},
{
extends: true,
test: {
name: "dashboard-api-quality",
environment: "node",
include: qualityApiTests,
exclude: quarantinedDashboardTests,
css: { include: [] },
},
},
{
extends: true,
test: {
name: "dashboard-app-quality-backfill",
environment: "jsdom",
include: qualityAppBackfillTests,
exclude: [...backfillAppExclude, ...quarantinedDashboardTests],
css: { include: [/app\//] },
},
},
{
extends: true,
test: {
name: "dashboard-api-quality-backfill",
environment: "node",
include: qualityApiBackfillTests,
exclude: [...backfillApiExclude, ...quarantinedDashboardTests],
css: { include: [] },
},
},
{
extends: true,
test: {
name: "dashboard-app",
environment: "jsdom",
// Empty unless FUSION_DASHBOARD_DEEP=1 (deep escape hatch). Keeps this
// broad lane out of the default run so it doesn't duplicate the
// curated shards + backfill, while remaining selectable via --project.
include: deepAppInclude,
exclude: quarantinedDashboardTests,
// 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",
// Empty unless FUSION_DASHBOARD_DEEP=1 (deep escape hatch); see the
// dashboard-app note above.
include: deepApiInclude,
exclude: quarantinedDashboardTests,
css: { include: [] },
},
},
],
coverage: {
enabled: false,
reporter: ["text", "html", "json"],
reportsDirectory: "./coverage",
include: ["app/**/*.{ts,tsx}", "src/**/*.{ts,tsx}"],
exclude: ["**/*.test.{ts,tsx}", "**/*.d.ts", "dist/**"],
},
},
});