diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 4fb5754..f07e2dc 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -240,9 +240,10 @@ return; } - // Ctrl+C - Interrupt (only when processing) + // Ctrl+C - Interrupt (only when processing AND no text is selected) if (event.ctrlKey && event.key === "c") { - if (get(isClaudeProcessing)) { + const hasSelection = Boolean(window.getSelection()?.toString()); + if (get(isClaudeProcessing) && !hasSelection) { event.preventDefault(); handleInterrupt(); return; diff --git a/src/routes/page.test.ts b/src/routes/page.test.ts new file mode 100644 index 0000000..e96f2ee --- /dev/null +++ b/src/routes/page.test.ts @@ -0,0 +1,38 @@ +/** + * +page.svelte keyboard shortcut tests + * + * Tests the pure decision logic for the Ctrl+C keyboard shortcut handler. + * The handler should only intercept Ctrl+C (to send an interrupt signal) when: + * - Claude is currently processing a request, AND + * - No text is currently selected (so normal copy behaviour is preserved) + * + * Manual testing checklist: + * - [ ] Ctrl+C with text selected copies the text (browser default) + * - [ ] Ctrl+C with no text selected and Claude processing sends an interrupt + * - [ ] Ctrl+C with no text selected and Claude idle does nothing special + */ + +import { describe, it, expect } from "vitest"; + +// Mirror the Ctrl+C interrupt decision logic from +page.svelte +function shouldInterruptOnCtrlC(isProcessing: boolean, hasSelection: boolean): boolean { + return isProcessing && !hasSelection; +} + +describe("Ctrl+C interrupt logic", () => { + it("interrupts when Claude is processing and no text is selected", () => { + expect(shouldInterruptOnCtrlC(true, false)).toBe(true); + }); + + it("does not interrupt when text is selected, even if Claude is processing", () => { + expect(shouldInterruptOnCtrlC(true, true)).toBe(false); + }); + + it("does not interrupt when Claude is idle and no text is selected", () => { + expect(shouldInterruptOnCtrlC(false, false)).toBe(false); + }); + + it("does not interrupt when Claude is idle and text is selected", () => { + expect(shouldInterruptOnCtrlC(false, true)).toBe(false); + }); +});