mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 12:39:42 +02:00
Closes #211. Copying from the terminal only worked through the browser context menu, because xterm turns Ctrl+C into 0x03 and cancels the keydown, so the muscle-memory copy failed silently and read as "no copy-paste at all". With a selection, Ctrl+C now copies it, toasts, clears the selection and sends nothing to the PTY. With no selection it falls through unchanged, so the interrupt is intact. Ctrl+Shift+C is an explicit copy chord that never falls through: an explicit copy that interrupts a running agent because the selection happened to be empty would be a footgun. Three details that keep the interrupt safe: - The decision lives in attachCustomKeyEventHandler (terminal-ui.js) and the no-selection path returns true WITHOUT preventDefault. xterm calls the custom handler before its own cancel(), so returning false alone does not cancel the event; the copy path therefore calls preventDefault explicitly, or the browser would run its native copy on top of ours. - copy-selection is a full registry entry (rebindable and disableable in App Settings) whose action is deliberately absent from SHORTCUT_ACTIONS, the same trick command-palette uses: the generic capture loop preventDefaults every match it dispatches, which would cost the user the interrupt key. - The gate is keydown-only, since the custom handler also runs for keypress and keyup. Copy goes through _copyText (Clipboard API, then hidden-textarea + execCommand) rather than raw navigator.clipboard, because install.sh's LAN option serves plain HTTP where navigator.clipboard is undefined; the fallback steals focus, so the terminal is refocused afterwards. Tests: test/terminal-copy-selection.test.ts pins the gate and the SHORTCUT_ACTIONS invariant; test/terminal-copy-shortcut.test.ts drives real key presses in chromium and asserts on the clipboard plus the bytes xterm emitted (browser-driven, so excluded from test:ci like the other Playwright suites). Verified manually on an isolated beta instance before landing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
35 lines
1.2 KiB
TypeScript
35 lines
1.2 KiB
TypeScript
import { resolve } from 'node:path';
|
|
import { defineConfig, configDefaults } from 'vitest/config';
|
|
|
|
const root = resolve(import.meta.dirname, '..');
|
|
|
|
/**
|
|
* CI test config — same as vitest.config.ts but EXCLUDES the browser-driven
|
|
* mobile suite (test/mobile/**). Those are Playwright visual-regression tests
|
|
* that need a live server + chromium + environment-specific PNG baselines, so
|
|
* they are run/maintained separately and are not part of the CI gate.
|
|
*
|
|
* Keep the rest in sync with config/vitest.config.ts.
|
|
*/
|
|
export default defineConfig({
|
|
test: {
|
|
root,
|
|
globals: true,
|
|
environment: 'node',
|
|
include: ['test/**/*.test.ts'],
|
|
exclude: [
|
|
...configDefaults.exclude,
|
|
'test/mobile/**', // browser/visual (Playwright + chromium)
|
|
'test/perf-*.test.ts', // timing-sensitive perf benchmarks (flaky in CI)
|
|
'test/inline-rename.test.ts', // browser (Playwright)
|
|
'test/opencode-resize.test.ts', // browser (Playwright)
|
|
'test/webgl-fallback.test.ts', // browser (Playwright)
|
|
'test/terminal-copy-shortcut.test.ts', // browser (Playwright)
|
|
],
|
|
setupFiles: ['./test/setup.ts'],
|
|
fileParallelism: false,
|
|
testTimeout: 30000,
|
|
teardownTimeout: 60000,
|
|
},
|
|
});
|