feat(FN-5204): add test mode activation across settings, engine, and dashboard
- Add core settings schema/types support for testMode with model-resolution override handling - Enforce engine session lane overrides in test mode with targeted helper coverage - Add dashboard settings toggle plus persistent test-mode banner and related component tests - Update settings documentation and parity/roundtrip tests for the new test mode behavior
This commit is contained in:
committed by
gsxdsm
parent
fbf7e2cb4d
commit
9c2b61eec6
@@ -0,0 +1,87 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { render, screen, waitFor } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { SettingsModal } from "../SettingsModal";
|
||||
|
||||
const mockFetchSettings = vi.fn();
|
||||
const mockFetchSettingsByScope = vi.fn();
|
||||
|
||||
vi.mock("../../api", async (importOriginal) => {
|
||||
const { createDashboardApiMock } = await import("../../test/mockApi");
|
||||
return createDashboardApiMock(() => importOriginal<typeof import("../../api")>(), {
|
||||
fetchSettings: (...args: unknown[]) => mockFetchSettings(...args),
|
||||
fetchSettingsByScope: (...args: unknown[]) => mockFetchSettingsByScope(...args),
|
||||
});
|
||||
});
|
||||
|
||||
vi.mock("../../hooks/useMemoryBackendStatus", () => ({
|
||||
useMemoryBackendStatus: () => ({ status: null, capabilities: null, loading: false, error: null, refresh: vi.fn() }),
|
||||
}));
|
||||
vi.mock("../../hooks/useViewportMode", () => ({ useViewportMode: () => "desktop" }));
|
||||
vi.mock("../../hooks/useMobileKeyboard", () => ({
|
||||
useMobileKeyboard: () => ({ keyboardOverlap: 0, viewportHeight: null, viewportOffsetTop: 0, keyboardOpen: false }),
|
||||
}));
|
||||
vi.mock("../../hooks/useMobileScrollLock", () => ({ useMobileScrollLock: vi.fn() }));
|
||||
vi.mock("../../hooks/useConfirm", () => ({ useConfirm: () => ({ confirm: vi.fn() }) }));
|
||||
vi.mock("../../hooks/useWorkspaceFileBrowser", () => ({
|
||||
useWorkspaceFileBrowser: () => ({ entries: [], currentPath: ".", setPath: vi.fn(), loading: false, error: null, refresh: vi.fn() }),
|
||||
}));
|
||||
vi.mock("../../hooks/useWorktrunkInstallStatus", () => ({
|
||||
useWorktrunkInstallStatus: () => ({ status: "idle", requestInstall: vi.fn() }),
|
||||
}));
|
||||
|
||||
function buildSettings(testMode: boolean) {
|
||||
return {
|
||||
autoMerge: true,
|
||||
testMode,
|
||||
maxConcurrent: 2,
|
||||
maxTriageConcurrent: 2,
|
||||
maxWorktrees: 4,
|
||||
pollIntervalMs: 15000,
|
||||
heartbeatMultiplier: 1,
|
||||
groupOverlappingFiles: true,
|
||||
overlapIgnorePaths: [],
|
||||
mergeStrategy: "direct",
|
||||
mergeIntegrationWorktree: "reuse-task-worktree",
|
||||
recycleWorktrees: false,
|
||||
executorAllowSiblingBranchRename: false,
|
||||
worktreeNaming: "random",
|
||||
worktreesDir: "",
|
||||
worktrunk: { enabled: false, binaryPath: "", onFailure: "fail" },
|
||||
includeTaskIdInCommit: true,
|
||||
ntfyEnabled: false,
|
||||
failureNotificationMode: "sticky-only",
|
||||
failureNotificationDelayMs: 30000,
|
||||
webhookEnabled: false,
|
||||
experimentalFeatures: {},
|
||||
};
|
||||
}
|
||||
|
||||
describe("SettingsModal testMode toggle", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
const merged = buildSettings(true);
|
||||
mockFetchSettings.mockResolvedValue(merged);
|
||||
mockFetchSettingsByScope.mockResolvedValue({ global: {}, project: { testMode: true } });
|
||||
});
|
||||
|
||||
it("renders merge test mode toggle with initial checked state", async () => {
|
||||
render(<SettingsModal onClose={() => {}} addToast={() => {}} initialSection="merge" />);
|
||||
|
||||
const toggle = await screen.findByLabelText("Enable test mode");
|
||||
expect(toggle).toBeChecked();
|
||||
});
|
||||
|
||||
it("flips checkbox state when clicked", async () => {
|
||||
render(<SettingsModal onClose={() => {}} addToast={() => {}} initialSection="merge" />);
|
||||
|
||||
const toggle = await screen.findByLabelText("Enable test mode");
|
||||
expect(toggle).toBeChecked();
|
||||
|
||||
await userEvent.click(toggle);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(toggle).not.toBeChecked();
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user