Skip to content

Commit 5d0fe00

Browse files
committed
🤖 tests: add Settings Modes story for Chromatic
Change-Id: I8d55fb7ca4c3173706e390846b77416f7540af59 Signed-off-by: Thomas Kosiewski <tk@coder.com>
1 parent 0f4796f commit 5d0fe00

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
@@ -20,6 +20,10 @@ import {
2020
type SubagentAiDefaults,
2121
type TaskSettings,
2222
} from "@/common/types/tasks";
23+
import {
24+
normalizeModeAiDefaults,
25+
type ModeAiDefaults,
26+
} from "@/common/types/modeAiDefaults";
2327
import { createAsyncMessageQueue } from "@/common/utils/asyncMessageQueue";
2428
import { isWorkspaceArchived } from "@/common/utils/archive";
2529

@@ -56,6 +60,8 @@ export interface MockORPCClientOptions {
5660
workspaces?: FrontendWorkspaceMetadata[];
5761
/** Initial task settings for config.getConfig (e.g., Settings → Tasks section) */
5862
taskSettings?: Partial<TaskSettings>;
63+
/** Initial mode AI defaults for config.getConfig (e.g., Settings → Modes section) */
64+
modeAiDefaults?: ModeAiDefaults;
5965
/** Initial per-subagent AI defaults for config.getConfig (e.g., Settings → Tasks section) */
6066
subagentAiDefaults?: SubagentAiDefaults;
6167
/** Per-workspace chat callback. Return messages to emit, or use the callback for streaming. */
@@ -136,6 +142,7 @@ export function createMockORPCClient(options: MockORPCClientOptions = {}): APICl
136142
mcpOverrides = new Map(),
137143
mcpTestResults = new Map(),
138144
taskSettings: initialTaskSettings,
145+
modeAiDefaults: initialModeAiDefaults,
139146
subagentAiDefaults: initialSubagentAiDefaults,
140147
} = options;
141148

@@ -154,6 +161,7 @@ export function createMockORPCClient(options: MockORPCClientOptions = {}): APICl
154161
};
155162

156163
const workspaceMap = new Map(workspaces.map((w) => [w.id, w]));
164+
let modeAiDefaults = normalizeModeAiDefaults(initialModeAiDefaults ?? {});
157165
let taskSettings = normalizeTaskSettings(initialTaskSettings ?? DEFAULT_TASK_SETTINGS);
158166
let subagentAiDefaults = normalizeSubagentAiDefaults(initialSubagentAiDefaults ?? {});
159167

@@ -189,14 +197,18 @@ export function createMockORPCClient(options: MockORPCClientOptions = {}): APICl
189197
setSshHost: async () => undefined,
190198
},
191199
config: {
192-
getConfig: async () => ({ taskSettings, subagentAiDefaults }),
200+
getConfig: async () => ({ taskSettings, subagentAiDefaults, modeAiDefaults }),
193201
saveConfig: async (input: { taskSettings: unknown; subagentAiDefaults?: unknown }) => {
194202
taskSettings = normalizeTaskSettings(input.taskSettings);
195203
if (input.subagentAiDefaults !== undefined) {
196204
subagentAiDefaults = normalizeSubagentAiDefaults(input.subagentAiDefaults);
197205
}
198206
return undefined;
199207
},
208+
updateModeAiDefaults: async (input: { modeAiDefaults: unknown }) => {
209+
modeAiDefaults = normalizeModeAiDefaults(input.modeAiDefaults);
210+
return undefined;
211+
},
200212
},
201213
providers: {
202214
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)