Skip to content

Commit 896a0f1

Browse files
IM.codesclaude
andcommitted
Add web e2e test for session override-global checkbox
The browser-level path for "user ticks Override global on this session" was not exercised by any existing test. The new case mocks fetchSupervisorDefaults with a non-empty global customInstructions, enables supervised mode, types session-level instructions, asserts the merged preview renders, clicks the override checkbox, asserts the preview disappears, and verifies the resulting patchSession payload carries customInstructionsOverride=true plus the globalCustomInstructions cache mirror, while leaving the user-defaults endpoint untouched. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent d735e8f commit 896a0f1

1 file changed

Lines changed: 80 additions & 0 deletions

File tree

web/test/components/SessionSettingsDialog.test.tsx

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,86 @@ describe('SessionSettingsDialog supervision', () => {
213213
expect(screen.getByText('summaryMeta:supervision_decision_v1')).toBeDefined();
214214
});
215215

216+
it('persists customInstructionsOverride=true when user checks the override checkbox, and drops the global cache for that session', async () => {
217+
// Simulate a user who already has global custom instructions saved.
218+
fetchSupervisorDefaultsMock.mockResolvedValue({
219+
backend: 'codex-sdk',
220+
model: CODEX_MODEL_IDS[0],
221+
timeoutMs: 12_000,
222+
promptVersion: 'supervision_decision_v1',
223+
customInstructions: 'GLOBAL: always prefer tests',
224+
});
225+
226+
render(
227+
<SessionSettingsDialog
228+
serverId="srv-1"
229+
sessionName="deck_proj_brain"
230+
label="Brain"
231+
description="desc"
232+
cwd="/proj"
233+
type="codex-sdk"
234+
transportConfig={null}
235+
onClose={vi.fn()}
236+
onSaved={vi.fn()}
237+
/>,
238+
);
239+
240+
// Wait for the async fetchSupervisorDefaults to resolve and the global
241+
// textarea to pre-populate. Both the "merged preview" gate and the
242+
// `globalCustomInstructions` cache-mirror field depend on this.
243+
await waitFor(() => {
244+
expect(fetchSupervisorDefaultsMock).toHaveBeenCalled();
245+
});
246+
247+
// Turn on supervised mode and the session body must become editable.
248+
fireEvent.change(screen.getAllByRole('combobox')[3]!, { target: { value: 'supervised' } });
249+
fireEvent.change(screen.getAllByRole('combobox')[4]!, { target: { value: 'codex-sdk' } });
250+
fireEvent.change(screen.getAllByRole('combobox')[5]!, { target: { value: CODEX_MODEL_IDS[0] } });
251+
252+
// Session-level custom instructions — different text so we can confirm
253+
// the session layer vs global layer are kept distinct in the payload.
254+
fireEvent.input(screen.getByPlaceholderText('customInstructionsPlaceholder'), {
255+
target: { value: 'SESSION: block commits on failing tests' },
256+
});
257+
258+
// The override checkbox must be present and initially unchecked.
259+
const overrideCheckbox = screen.getByLabelText(/customInstructionsOverrideLabel/i) as HTMLInputElement;
260+
expect(overrideCheckbox.checked).toBe(false);
261+
262+
// With override=false AND both layers non-empty, the merged preview is
263+
// shown — this proves the UI reads both layers.
264+
expect(screen.getByTestId('supervision-merged-preview')).toBeDefined();
265+
266+
// Check override → session replaces global for this session.
267+
fireEvent.click(overrideCheckbox);
268+
expect(overrideCheckbox.checked).toBe(true);
269+
270+
// Preview must hide when override is active (no ambiguity to preview).
271+
expect(screen.queryByTestId('supervision-merged-preview')).toBeNull();
272+
273+
fireEvent.click(screen.getByRole('button', { name: /save/i }));
274+
275+
await waitFor(() => {
276+
expect(patchSessionMock).toHaveBeenCalledWith('srv-1', 'deck_proj_brain', expect.objectContaining({
277+
transportConfig: expect.objectContaining({
278+
supervision: expect.objectContaining({
279+
mode: 'supervised',
280+
customInstructions: 'SESSION: block commits on failing tests',
281+
customInstructionsOverride: true,
282+
// Cache mirror of the current global value is still written to the
283+
// snapshot so the daemon can re-read it next time override flips
284+
// back to false without needing another defaults fetch.
285+
globalCustomInstructions: 'GLOBAL: always prefer tests',
286+
}),
287+
}),
288+
}));
289+
});
290+
291+
// User did not edit the global region → defaults endpoint must not be
292+
// hit. This proves the save-split handles override-only changes cleanly.
293+
expect(saveSupervisorDefaultsMock).not.toHaveBeenCalled();
294+
});
295+
216296
it('persists custom supervision instructions in the session snapshot', async () => {
217297
render(
218298
<SessionSettingsDialog

0 commit comments

Comments
 (0)