Skip to content

Commit 35f7a46

Browse files
committed
🤖 tests: add Settings Modes story for Chromatic
Change-Id: I8d55fb7ca4c3173706e390846b77416f7540af59 Signed-off-by: Thomas Kosiewski <tk@coder.com>
1 parent 66ab016 commit 35f7a46

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

.storybook/mocks/orpc.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ import {
2121
type SubagentAiDefaults,
2222
type TaskSettings,
2323
} from "@/common/types/tasks";
24+
import {
25+
normalizeModeAiDefaults,
26+
type ModeAiDefaults,
27+
} from "@/common/types/modeAiDefaults";
2428
import { createAsyncMessageQueue } from "@/common/utils/asyncMessageQueue";
2529
import { isWorkspaceArchived } from "@/common/utils/archive";
2630

@@ -57,6 +61,8 @@ export interface MockORPCClientOptions {
5761
workspaces?: FrontendWorkspaceMetadata[];
5862
/** Initial task settings for config.getConfig (e.g., Settings → Tasks section) */
5963
taskSettings?: Partial<TaskSettings>;
64+
/** Initial mode AI defaults for config.getConfig (e.g., Settings → Modes section) */
65+
modeAiDefaults?: ModeAiDefaults;
6066
/** Initial per-subagent AI defaults for config.getConfig (e.g., Settings → Tasks section) */
6167
subagentAiDefaults?: SubagentAiDefaults;
6268
/** Per-workspace chat callback. Return messages to emit, or use the callback for streaming. */
@@ -140,6 +146,7 @@ export function createMockORPCClient(options: MockORPCClientOptions = {}): APICl
140146
mcpOverrides = new Map(),
141147
mcpTestResults = new Map(),
142148
taskSettings: initialTaskSettings,
149+
modeAiDefaults: initialModeAiDefaults,
143150
subagentAiDefaults: initialSubagentAiDefaults,
144151
} = options;
145152

@@ -158,6 +165,7 @@ export function createMockORPCClient(options: MockORPCClientOptions = {}): APICl
158165
};
159166

160167
const workspaceMap = new Map(workspaces.map((w) => [w.id, w]));
168+
let modeAiDefaults = normalizeModeAiDefaults(initialModeAiDefaults ?? {});
161169
let taskSettings = normalizeTaskSettings(initialTaskSettings ?? DEFAULT_TASK_SETTINGS);
162170
let subagentAiDefaults = normalizeSubagentAiDefaults(initialSubagentAiDefaults ?? {});
163171

@@ -193,14 +201,18 @@ export function createMockORPCClient(options: MockORPCClientOptions = {}): APICl
193201
setSshHost: async () => undefined,
194202
},
195203
config: {
196-
getConfig: async () => ({ taskSettings, subagentAiDefaults }),
204+
getConfig: async () => ({ taskSettings, subagentAiDefaults, modeAiDefaults }),
197205
saveConfig: async (input: { taskSettings: unknown; subagentAiDefaults?: unknown }) => {
198206
taskSettings = normalizeTaskSettings(input.taskSettings);
199207
if (input.subagentAiDefaults !== undefined) {
200208
subagentAiDefaults = normalizeSubagentAiDefaults(input.subagentAiDefaults);
201209
}
202210
return undefined;
203211
},
212+
updateModeAiDefaults: async (input: { modeAiDefaults: unknown }) => {
213+
modeAiDefaults = normalizeModeAiDefaults(input.modeAiDefaults);
214+
return undefined;
215+
},
204216
},
205217
providers: {
206218
list: async () => providersList,

src/browser/stories/App.settings.stories.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
*
44
* Shows different sections and states of the Settings modal:
55
* - General (theme toggle)
6+
* - Agents (task parallelism / nesting)
67
* - Providers (API key configuration)
78
* - Models (custom model management)
9+
* - Modes (per-mode default model / reasoning)
810
* - Experiments
911
*
1012
* NOTE: Projects/MCP stories live in App.mcp.stories.tsx
@@ -19,6 +21,7 @@ import { selectWorkspace } from "./storyHelpers";
1921
import { createMockORPCClient } from "../../../.storybook/mocks/orpc";
2022
import { within, userEvent, waitFor } from "@storybook/test";
2123
import { getExperimentKey, EXPERIMENT_IDS } from "@/common/constants/experiments";
24+
import type { ModeAiDefaults } from "@/common/types/modeAiDefaults";
2225
import type { TaskSettings } from "@/common/types/tasks";
2326

2427
export default {
@@ -34,6 +37,7 @@ export default {
3437
function setupSettingsStory(options: {
3538
providersConfig?: Record<string, { apiKeySet: boolean; baseUrl?: string; models?: string[] }>;
3639
providersList?: string[];
40+
modeAiDefaults?: ModeAiDefaults;
3741
taskSettings?: Partial<TaskSettings>;
3842
/** Pre-set experiment states in localStorage before render */
3943
experiments?: Partial<Record<string, boolean>>;
@@ -54,6 +58,7 @@ function setupSettingsStory(options: {
5458
projects: groupWorkspacesByProject(workspaces),
5559
workspaces,
5660
providersConfig: options.providersConfig ?? {},
61+
modeAiDefaults: options.modeAiDefaults,
5762
providersList: options.providersList ?? ["anthropic", "openai", "xai"],
5863
taskSettings: options.taskSettings,
5964
});
@@ -229,6 +234,35 @@ export const ModelsConfigured: AppStory = {
229234
},
230235
};
231236

237+
/** Modes section - global default model/reasoning per mode */
238+
export const Modes: AppStory = {
239+
render: () => (
240+
<AppWithMocks
241+
setup={() =>
242+
setupSettingsStory({
243+
modeAiDefaults: {
244+
plan: { modelString: "anthropic:claude-sonnet-4-5", thinkingLevel: "medium" },
245+
exec: { modelString: "openai:gpt-5.2", thinkingLevel: "xhigh" },
246+
compact: { modelString: "openai:gpt-5.2-pro", thinkingLevel: "high" },
247+
},
248+
})
249+
}
250+
/>
251+
),
252+
play: async ({ canvasElement }: { canvasElement: HTMLElement }) => {
253+
await openSettingsToSection(canvasElement, "modes");
254+
255+
const body = within(canvasElement.ownerDocument.body);
256+
const dialog = await body.findByRole("dialog");
257+
const modal = within(dialog);
258+
259+
await modal.findByText(/Mode Defaults/i);
260+
await modal.findByText(/^Plan$/i);
261+
await modal.findByText(/^Exec$/i);
262+
await modal.findByText(/^Compact$/i);
263+
},
264+
};
265+
232266
/** Experiments section - shows available experiments */
233267
export const Experiments: AppStory = {
234268
render: () => <AppWithMocks setup={() => setupSettingsStory({})} />,

0 commit comments

Comments
 (0)