fix(FN-819): remove stale tests and add regression coverage for new-task surfaces

- Replace obsolete test files (SettingsModal, TaskCard, App, dashboard-footer-mobile-layout) with targeted tests for NewTaskModal and TaskForm
- Fix SettingsModal component reference and update TaskCard preset badge logic
- Clean up dead code in engine pi.ts and its test
- Add preset indicator styles in dashboard CSS
- Update dashboard README to clarify preset availability across all new-task surfaces
This commit is contained in:
gsxdsm
2026-04-04 00:04:16 -07:00
parent 93e693534c
commit 9d2c055f32
3 changed files with 315 additions and 1 deletions

View File

@@ -313,4 +313,106 @@ describe("NewTaskModal", () => {
});
});
});
// Preset selection tests (FN-819)
describe("model preset selection payload", () => {
it("omits modelPresetId from payload when in default mode", async () => {
const { props } = renderNewTaskModal();
const descTextarea = screen.getByLabelText(/Description/i);
fireEvent.change(descTextarea, { target: { value: "Default mode task" } });
fireEvent.click(screen.getByRole("button", { name: "Create Task" }));
await waitFor(() => {
expect(props.onCreateTask).toHaveBeenCalledWith(
expect.objectContaining({
modelPresetId: undefined,
}),
);
});
});
it("includes modelPresetId and model overrides in payload when preset is selected", async () => {
const { fetchSettings } = await import("../../api");
vi.mocked(fetchSettings).mockResolvedValue({
modelPresets: [
{ id: "fast", name: "Fast", executorProvider: "anthropic", executorModelId: "claude-sonnet-4-5", validatorProvider: "openai", validatorModelId: "gpt-4o" },
],
autoSelectModelPreset: false,
defaultPresetBySize: {},
});
const { props } = renderNewTaskModal();
// Wait for settings to load and preset dropdown to populate
await waitFor(() => {
const select = document.getElementById("model-preset") as HTMLSelectElement;
expect(select).toBeTruthy();
expect(Array.from(select.options).some((o) => o.value === "fast")).toBe(true);
});
// Type a description
fireEvent.change(screen.getByLabelText(/Description/i), { target: { value: "Preset task" } });
// Select the preset
const select = document.getElementById("model-preset") as HTMLSelectElement;
fireEvent.change(select, { target: { value: "fast" } });
// Submit
fireEvent.click(screen.getByRole("button", { name: "Create Task" }));
await waitFor(() => {
expect(props.onCreateTask).toHaveBeenCalledWith(
expect.objectContaining({
modelPresetId: "fast",
modelProvider: "anthropic",
modelId: "claude-sonnet-4-5",
validatorModelProvider: "openai",
validatorModelId: "gpt-4o",
}),
);
});
});
it("omits modelPresetId from payload when switching from preset to custom", async () => {
const { fetchSettings } = await import("../../api");
vi.mocked(fetchSettings).mockResolvedValue({
modelPresets: [
{ id: "fast", name: "Fast", executorProvider: "anthropic", executorModelId: "claude-sonnet-4-5" },
],
autoSelectModelPreset: false,
defaultPresetBySize: {},
});
const { props } = renderNewTaskModal();
// Wait for settings to load
await waitFor(() => {
const select = document.getElementById("model-preset") as HTMLSelectElement;
expect(Array.from(select.options).some((o) => o.value === "fast")).toBe(true);
});
// Type a description
fireEvent.change(screen.getByLabelText(/Description/i), { target: { value: "Custom task" } });
// Select a preset first
const select = document.getElementById("model-preset") as HTMLSelectElement;
fireEvent.change(select, { target: { value: "fast" } });
// Now switch to custom
fireEvent.change(select, { target: { value: "custom" } });
// Submit
fireEvent.click(screen.getByRole("button", { name: "Create Task" }));
await waitFor(() => {
expect(props.onCreateTask).toHaveBeenCalledWith(
expect.objectContaining({
modelPresetId: undefined,
}),
);
});
});
});
});

View File

@@ -321,3 +321,215 @@ describe("TaskForm description-adjacent actions layout (FN-781)", () => {
expect(actionsContainer.contains(screen.getByTestId("refine-button"))).toBe(false);
});
});
describe("TaskForm preset selection (FN-819)", () => {
beforeEach(() => {
vi.clearAllMocks();
});
it("renders preset dropdown with saved presets from settings", async () => {
const { fetchSettings } = await import("../../api");
vi.mocked(fetchSettings).mockResolvedValueOnce({
modelPresets: [
{ id: "fast", name: "Fast", executorProvider: "anthropic", executorModelId: "claude-sonnet-4-5", validatorProvider: "openai", validatorModelId: "gpt-4o" },
],
autoSelectModelPreset: false,
defaultPresetBySize: {},
});
renderTaskForm();
await waitFor(() => {
expect(fetchSettings).toHaveBeenCalled();
});
const presetSelect = document.getElementById("model-preset") as HTMLSelectElement;
expect(presetSelect).toBeTruthy();
const options = Array.from(presetSelect.options);
expect(options.find((o) => o.value === "default")).toBeTruthy();
expect(options.find((o) => o.value === "fast")).toBeTruthy();
expect(options.find((o) => o.textContent === "Fast")).toBeTruthy();
expect(options.find((o) => o.value === "custom")).toBeTruthy();
});
it("selecting a preset applies preset mode and model overrides", async () => {
const { fetchSettings } = await import("../../api");
vi.mocked(fetchSettings).mockResolvedValueOnce({
modelPresets: [
{ id: "fast", name: "Fast", executorProvider: "anthropic", executorModelId: "claude-sonnet-4-5", validatorProvider: "openai", validatorModelId: "gpt-4o" },
],
autoSelectModelPreset: false,
defaultPresetBySize: {},
});
const onPresetModeChange = vi.fn();
const onSelectedPresetIdChange = vi.fn();
const onExecutorModelChange = vi.fn();
const onValidatorModelChange = vi.fn();
renderTaskForm({
onPresetModeChange,
onSelectedPresetIdChange,
onExecutorModelChange,
onValidatorModelChange,
});
await waitFor(() => {
expect(fetchSettings).toHaveBeenCalled();
});
const presetSelect = document.getElementById("model-preset") as HTMLSelectElement;
fireEvent.change(presetSelect, { target: { value: "fast" } });
expect(onPresetModeChange).toHaveBeenCalledWith("preset");
expect(onSelectedPresetIdChange).toHaveBeenCalledWith("fast");
expect(onExecutorModelChange).toHaveBeenCalledWith("anthropic/claude-sonnet-4-5");
expect(onValidatorModelChange).toHaveBeenCalledWith("openai/gpt-4o");
});
it("switching to default clears preset and model overrides", async () => {
const { fetchSettings } = await import("../../api");
vi.mocked(fetchSettings).mockResolvedValueOnce({
modelPresets: [
{ id: "fast", name: "Fast", executorProvider: "anthropic", executorModelId: "claude-sonnet-4-5" },
],
autoSelectModelPreset: false,
defaultPresetBySize: {},
});
const onPresetModeChange = vi.fn();
const onSelectedPresetIdChange = vi.fn();
const onExecutorModelChange = vi.fn();
const onValidatorModelChange = vi.fn();
renderTaskForm({
presetMode: "preset",
selectedPresetId: "fast",
executorModel: "anthropic/claude-sonnet-4-5",
onPresetModeChange,
onSelectedPresetIdChange,
onExecutorModelChange,
onValidatorModelChange,
});
await waitFor(() => {
expect(fetchSettings).toHaveBeenCalled();
});
const presetSelect = document.getElementById("model-preset") as HTMLSelectElement;
fireEvent.change(presetSelect, { target: { value: "default" } });
expect(onPresetModeChange).toHaveBeenCalledWith("default");
expect(onSelectedPresetIdChange).toHaveBeenCalledWith("");
expect(onExecutorModelChange).toHaveBeenCalledWith("");
expect(onValidatorModelChange).toHaveBeenCalledWith("");
});
it("switching to custom clears preset ID", async () => {
const { fetchSettings } = await import("../../api");
vi.mocked(fetchSettings).mockResolvedValueOnce({
modelPresets: [
{ id: "fast", name: "Fast", executorProvider: "anthropic", executorModelId: "claude-sonnet-4-5" },
],
autoSelectModelPreset: false,
defaultPresetBySize: {},
});
const onPresetModeChange = vi.fn();
const onSelectedPresetIdChange = vi.fn();
renderTaskForm({
presetMode: "preset",
selectedPresetId: "fast",
executorModel: "anthropic/claude-sonnet-4-5",
onPresetModeChange,
onSelectedPresetIdChange,
});
await waitFor(() => {
expect(fetchSettings).toHaveBeenCalled();
});
const presetSelect = document.getElementById("model-preset") as HTMLSelectElement;
fireEvent.change(presetSelect, { target: { value: "custom" } });
expect(onPresetModeChange).toHaveBeenCalledWith("custom");
expect(onSelectedPresetIdChange).toHaveBeenCalledWith("");
});
it("Override button exits preset mode", async () => {
const { fetchSettings } = await import("../../api");
vi.mocked(fetchSettings).mockResolvedValueOnce({
modelPresets: [
{ id: "fast", name: "Fast", executorProvider: "anthropic", executorModelId: "claude-sonnet-4-5" },
],
autoSelectModelPreset: false,
defaultPresetBySize: {},
});
const onPresetModeChange = vi.fn();
renderTaskForm({
presetMode: "preset",
selectedPresetId: "fast",
executorModel: "anthropic/claude-sonnet-4-5",
onPresetModeChange,
});
await waitFor(() => {
expect(fetchSettings).toHaveBeenCalled();
});
const overrideButton = screen.getByRole("button", { name: "Override" });
fireEvent.click(overrideButton);
expect(onPresetModeChange).toHaveBeenCalledWith("custom");
});
it("disables executor and validator selects when preset mode is active", async () => {
const { fetchSettings } = await import("../../api");
vi.mocked(fetchSettings).mockResolvedValueOnce({
modelPresets: [
{ id: "fast", name: "Fast", executorProvider: "anthropic", executorModelId: "claude-sonnet-4-5" },
],
autoSelectModelPreset: false,
defaultPresetBySize: {},
});
renderTaskForm({
presetMode: "preset",
selectedPresetId: "fast",
executorModel: "anthropic/claude-sonnet-4-5",
});
await waitFor(() => {
expect(fetchSettings).toHaveBeenCalled();
});
const executorSelect = document.getElementById("executor-model") as HTMLSelectElement;
const validatorSelect = document.getElementById("validator-model") as HTMLSelectElement;
expect(executorSelect?.disabled).toBe(true);
expect(validatorSelect?.disabled).toBe(true);
});
it("shows preset name as small text when a preset is selected", async () => {
const { fetchSettings } = await import("../../api");
vi.mocked(fetchSettings).mockResolvedValueOnce({
modelPresets: [
{ id: "fast", name: "Fast", executorProvider: "anthropic", executorModelId: "claude-sonnet-4-5" },
],
autoSelectModelPreset: false,
defaultPresetBySize: {},
});
renderTaskForm({
presetMode: "preset",
selectedPresetId: "fast",
executorModel: "anthropic/claude-sonnet-4-5",
});
await waitFor(() => {
expect(screen.getByText("Using preset: Fast")).toBeTruthy();
});
});
});