FN-9189: expand dashboard concurrency callback coverage

Expand post-landing QA coverage for dashboard concurrency settings callbacks.

- Exercise unset, configured, and worktree-bound settings across all TUI callback paths.
- Verify pause callbacks use project defaults while the task store is still initializing.
- Extend the dashboard harness with live settings events and a startup barrier.

Files changed:
 .../dashboard-concurrency-settings.test.ts         | 104 ++++++++++++++++++---
 1 file changed, 92 insertions(+), 12 deletions(-)

Fusion-Task-Id: FN-9189

Fusion-Task-Lineage: c373954a-7316-47d2-9821-75e0d34b22d4

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
gsxdsm
2026-08-21 17:15:20 -07:00
parent a010dc42bf
commit 47de350fca

View File

@@ -3,14 +3,21 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
const harness = vi.hoisted(() => {
let settings: Record<string, unknown> = {};
let latestTui: FakeDashboardTui | undefined;
let resolveTuiReady: ((tui: FakeDashboardTui) => void) | undefined;
let tuiReady = new Promise<FakeDashboardTui>((resolve) => { resolveTuiReady = resolve; });
let resolveTaskStoreBarrier: (() => void) | undefined;
let taskStoreBarrier: Promise<void> = Promise.resolve();
class FakeDashboardTui {
settingsPayloads: Array<Record<string, unknown>> = [];
callbackPayloads: Array<Record<string, unknown>> = [];
callbacks: Record<string, unknown> = {};
interactiveData: Record<string, unknown> = {};
boardScopedProjectPath: string | null = null;
constructor() {
latestTui = this;
resolveTuiReady?.(this);
}
start = vi.fn(async () => undefined);
@@ -19,11 +26,14 @@ const harness = vi.hoisted(() => {
setSystemInfo = vi.fn();
setReady = vi.fn();
setTaskStats = vi.fn();
setInteractiveData = vi.fn();
setInteractiveData = vi.fn((data: Record<string, unknown>) => { this.interactiveData = data; });
onBoardScopeChange = vi.fn();
hydrateVitestKillSettings = vi.fn();
log = vi.fn();
setCallbacks = vi.fn((callbacks: Record<string, unknown>) => { this.callbacks = callbacks; });
setCallbacks = vi.fn((callbacks: Record<string, unknown>) => {
this.callbackPayloads.push(callbacks);
this.callbacks = callbacks;
});
setSettings = vi.fn((payload: Record<string, unknown>) => { this.settingsPayloads.push(payload); });
}
@@ -37,6 +47,9 @@ const harness = vi.hoisted(() => {
}
const listeners = new Map<string, Array<(...args: any[]) => void>>();
const emitStoreEvent = (event: string, ...args: unknown[]) => {
for (const listener of listeners.get(event) ?? []) listener(...args);
};
const store: Record<string, any> = {
on: (event: string, listener: (...args: any[]) => void) => {
listeners.set(event, [...(listeners.get(event) ?? []), listener]);
@@ -52,6 +65,9 @@ const harness = vi.hoisted(() => {
getFusionDir: vi.fn(() => "/repo/.fusion"),
getRootDir: vi.fn(() => "/repo"),
getSettings: vi.fn(async () => settings),
updateSettings: vi.fn(async (patch: Record<string, unknown>) => {
settings = { ...settings, ...patch };
}),
getGlobalSettingsStore: vi.fn(() => ({ getSettings: vi.fn(async () => ({})), updateSettings: vi.fn(async () => undefined) })),
getPluginStore: vi.fn(() => ({ init: vi.fn(async () => undefined) })),
healthCheck: vi.fn(async () => ({ ok: true })),
@@ -82,10 +98,25 @@ const harness = vi.hoisted(() => {
store,
getSettings: () => settings,
latestTui: () => latestTui,
waitForTui: () => tuiReady,
emitStoreEvent,
holdTaskStore: () => {
taskStoreBarrier = new Promise<void>((resolve) => { resolveTaskStoreBarrier = resolve; });
},
releaseTaskStore: () => resolveTaskStoreBarrier?.(),
createTaskStore: async () => {
await taskStoreBarrier;
return { taskStore: store, shutdown: vi.fn(async () => undefined) };
},
setSettings: (next: Record<string, unknown>) => { settings = next; },
reset: () => {
resolveTaskStoreBarrier?.();
settings = {};
latestTui = undefined;
resolveTuiReady = undefined;
tuiReady = new Promise<FakeDashboardTui>((resolve) => { resolveTuiReady = resolve; });
taskStoreBarrier = Promise.resolve();
resolveTaskStoreBarrier = undefined;
vi.clearAllMocks();
},
};
@@ -100,11 +131,16 @@ vi.mock("@fusion/core", async (importOriginal) => {
}
return {
...actual,
createTaskStoreForBackend: vi.fn(async () => ({ taskStore: harness.store, shutdown: vi.fn(async () => undefined) })),
createTaskStoreForBackend: vi.fn(() => harness.createTaskStore()),
AutomationStore: NoopStore,
AgentStore: class extends NoopStore { listAgents = vi.fn(async () => []); },
PluginLoader: class { loadAllPlugins = vi.fn(async () => ({ loaded: 0, errors: 0 })); getPluginSkills = vi.fn(() => []); },
MissionStore: NoopStore,
CentralCore: class {
init = vi.fn(async () => undefined);
listProjects = vi.fn(async () => []);
listNodes = vi.fn(async () => []);
},
setHostTaskStore: vi.fn(),
setDiagnosticDbHealthCheck: vi.fn(),
setDiagnosticStoreListenerCheck: vi.fn(),
@@ -138,29 +174,73 @@ vi.mock("../dashboard-startup-chain.js", () => ({
}),
}));
const { DEFAULT_PROJECT_SETTINGS, resolveEffectiveConcurrency, resolveWorktreeCapacityLimit } = await import("@fusion/core");
const { runDashboard } = await import("../dashboard.js");
type SettingsCallbacks = {
onTogglePause: (paused: boolean) => Promise<Record<string, unknown>>;
getSettings: () => Promise<Record<string, unknown>>;
};
function getSettingsCallbacks(tui: InstanceType<typeof harness.FakeDashboardTui>): SettingsCallbacks {
const pauseCallbacks = tui.callbackPayloads.find((callbacks) => "onTogglePause" in callbacks);
return {
onTogglePause: pauseCallbacks?.onTogglePause as SettingsCallbacks["onTogglePause"],
getSettings: tui.interactiveData.getSettings as SettingsCallbacks["getSettings"],
};
}
function expectedConcurrency(settings: Record<string, unknown>): Pick<Record<string, unknown>, "maxConcurrent" | "maxWorktrees"> {
const capacity = resolveEffectiveConcurrency(settings);
return {
maxConcurrent: capacity.maxConcurrent,
maxWorktrees: resolveWorktreeCapacityLimit({ ...settings, worktreeLimitEnabled: true }),
};
}
/**
* FNXC:CapacityModel 2026-08-21-17:43:
* The reported console mismatch was in dashboard startup, not the standalone mapping helper.
* Run the real TTY branch with a controlled live store and capture DashboardTUI.setSettings so
* future callback changes cannot reintroduce private defaults or bypass the shared resolver.
* FNXC:CapacityModel 2026-08-21-23:57:
* Callback-level coverage is required because a correct mapping helper cannot detect a
* runDashboard callback that stops reading live settings and reintroduces private defaults.
*/
describe("dashboard TUI concurrency settings", () => {
beforeEach(() => harness.reset());
it.each([
["unset", {}, { maxConcurrent: 2, maxWorktrees: 4 }],
["configured", { maxConcurrent: 6, maxWorktrees: 9 }, { maxConcurrent: 6, maxWorktrees: 9 }],
["worktree-bound", { maxConcurrent: 8, maxWorktrees: 4, worktreeLimitEnabled: true }, { maxConcurrent: 8, maxWorktrees: 4 }],
])("hydrates %s live settings through runDashboard's TUI setter", async (_state, settings, expected) => {
["unset", {}],
["configured", { maxConcurrent: 6, maxWorktrees: 9 }],
["worktree-bound", { maxConcurrent: 8, maxWorktrees: 4, worktreeLimitEnabled: true }],
] as const)("drives %s live settings through every runDashboard TUI callback", async (_state, settings) => {
harness.setSettings(settings);
const expected = expectedConcurrency(settings);
await runDashboard(0, { noEngine: true, noAuth: true });
await new Promise((resolve) => setImmediate(resolve));
const tui = harness.latestTui();
expect(harness.store.getSettings).toHaveBeenCalled();
expect(tui).toBeDefined();
expect(tui?.setSettings).toHaveBeenCalledWith(expect.objectContaining(expected));
const callbacks = getSettingsCallbacks(tui!);
await expect(callbacks.onTogglePause(true)).resolves.toEqual(expect.objectContaining(expected));
await expect(callbacks.getSettings()).resolves.toEqual(expect.objectContaining(expected));
tui!.setSettings.mockClear();
harness.emitStoreEvent("settings:updated", { settings, previous: {} });
await new Promise((resolve) => setImmediate(resolve));
expect(tui!.setSettings).toHaveBeenCalledWith(expect.objectContaining(expected));
});
it("uses DEFAULT_PROJECT_SETTINGS when onTogglePause runs before a store exists", async () => {
harness.holdTaskStore();
const dashboard = runDashboard(0, { noEngine: true, noAuth: true });
const tui = await harness.waitForTui();
await expect(getSettingsCallbacks(tui).onTogglePause(true)).resolves.toEqual(expect.objectContaining({
maxConcurrent: DEFAULT_PROJECT_SETTINGS.maxConcurrent,
maxWorktrees: DEFAULT_PROJECT_SETTINGS.maxWorktrees,
}));
harness.releaseTaskStore();
await dashboard;
});
});