Files
Codeman/config/test-suites.ts
T
Codeman maintainer 4cedeec529 feat(desktop): server tabs, several Codeman servers open in one window
The Mac app showed one server at a time, and moving to another machine
meant Switch Server and a fresh connect. Now every server gets a tab in
the title bar, and every tab stays live.

- Tab strip: a small bundled page (assets/tabs.html) in its own web view
  across the top of the window, with the traffic lights inset into it.
  Each tab has a colour and a status badge: a red count when sessions
  need you, an amber dot when they are waiting, a blue ring while they
  work, a dashed circle while the server does not answer.
- The status comes from the app, not from the page: one thread per tab
  reads GET /api/sessions every 2 seconds (macOS stalls hidden web
  views), backs off for 60 s on a 429 and stops on 401/403, so a wrong
  password is never retried in a loop.
- + or ⌘T opens the connect screen in a new tab. A server that is
  already open just brings its tab forward instead of opening twice,
  also when two connects race (checked again when the probe ends).
- Double-click or the right-click menu renames a tab; the same menu
  sets the colour, reloads, reconnects, closes, or closes the others.
  Tabs can be dragged. A new Server menu carries ⌘T, ⌘W, ⇧⌘T (reopen
  closed tab, last 10), ⌘0, ⇧⌘[ / ⇧⌘] and ⌘1 to ⌘8 (⌘9 is the last
  tab once there are nine). Close Window moves to ⇧⌘W. Ctrl+Tab and
  Alt+1..9 stay with Codeman's own session switching.
- ⌘0 shows every server at once (assets/overview.html): the ones that
  need you first, up to four sessions each with what they ask, and a
  click on a session opens its tab and selects it.
- Tabs are saved in desktop.json (tabs, activeTab) and come back at
  launch, connecting by themselves when auto-connect is on.
- Logins: each tab keeps its own Basic credentials, and a challenge is
  answered only with the login of the tab whose web view asked
  (macos.rs binds each WKWebView to its tab).
- Cookies: on macOS 14 and later every server gets its own WebKit data
  store (WKWebsiteDataStore dataStoreForIdentifier, with a stable id
  hashed from the server URL), so a server on port 3000 and a beta on
  5000 of the same host cannot log each other out. Before macOS 14 a
  second tab on a host that is already open is refused with a message.
  The server used last before this change keeps the default store, so
  its per-device settings (font size, skin) survive; every other
  server starts those fresh once.
- The lid logo blink watches all open servers, and Keep This Mac Awake
  follows the tab that runs on this Mac.

New pure model in src/tabs.rs (names, colours, order, shortcuts, strip
and overview state) with unit tests; agents.rs reads the per-session
detail for the badges and the overview; policy.rs parses the strip and
overview IPC and refuses it from any other frame. Browser tests drive
both bundled pages (test/desktop-tabs-pages.browser.test.ts) and the
connect page's restored-tab path.

Not yet run in a real window: the Mac mini has no screen session. The
owner checks the traffic-light placement, clicks under the transparent
title bar, window drag and zoom from the strip, keyboard focus after
strip clicks, and two logged-in servers side by side.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-14 18:36:08 +01:00

89 lines
4.0 KiB
TypeScript

/**
* The test suites that `npm test` deliberately does NOT run, in one place.
*
* Why this file exists: the exclusion list used to live only in
* config/vitest.ci.config.ts, as literals. Anything excluded there was
* therefore reachable only by running the everything-config by hand and reading
* past its failures — and a newly excluded file was reachable by nothing at
* all, silently, because nothing pointed at it. Both configs now derive their
* globs from the arrays below, so adding a suite here puts it in exactly one
* runner and takes it out of exactly one gate.
*
* Adding a new test that cannot run in CI: put its glob in the array that
* describes WHY it cannot, not in whichever one is shortest.
*/
/**
* Playwright-driven: needs chromium and, in most cases, a live Codeman server
* on a real port. Deterministic where the environment provides both, which is
* why these are a runnable suite (`npm run test:browser`) rather than skipped.
*/
export const BROWSER_TEST_GLOBS = [
'test/wrapped-file-paths.browser.test.ts',
'test/command-palette-agent-arrows.browser.test.ts',
'test/voice-input.browser.test.ts',
'test/tmux-capture-sgr.browser.test.ts',
'test/tab-rail-resize.browser.test.ts',
'test/tab-activation.browser.test.ts',
'test/tab-layout-editing.browser.test.ts',
'test/tab-rail-search.browser.test.ts',
'test/tab-focus.browser.test.ts',
'test/session-sidebar-ux.browser.test.ts',
'test/header-divider.browser.test.ts',
'test/tab-strip-corner.browser.test.ts',
'test/header-host-sensors.browser.test.ts',
'test/session-options-responsive.browser.test.ts',
'test/inline-rename.test.ts',
'test/opencode-resize.test.ts',
'test/webgl-fallback.test.ts',
'test/terminal-copy-shortcut.test.ts',
'test/terminal-keycode229-recovery.browser.test.ts',
'test/capture-load-window.browser.test.ts',
'test/capture-geometry-retry.browser.test.ts',
'test/codex-predictive-echo.test.ts', // also needs a real codex binary
'test/split-pane-terminal.browser.test.ts',
'test/terminal-tile-scroll.browser.test.ts',
'test/codex-wheel-routing.browser.test.ts',
'test/terminal-touch-paging.browser.test.ts',
'test/shift-enter-keypress.browser.test.ts',
'test/key-tester.browser.test.ts',
'test/webhook-settings.browser.test.ts',
'test/case-custom-path.browser.test.ts',
'test/doctor-settings.browser.test.ts',
'test/git-status.browser.test.ts',
'test/edit-history.browser.test.ts',
'test/sync-case-state.browser.test.ts',
'test/split-pane-orchestration.browser.test.ts',
'test/split-pane-auto-collapse.browser.test.ts',
'test/spreadsheet-preview.browser.test.ts',
'test/mobile-ime-preview.browser.test.ts',
'test/run-mode-menu-scroll.browser.test.ts',
'test/markdown-anchor-links.browser.test.ts',
'test/fullscreen-tab-switch-capture.browser.test.ts',
'test/terminal-touch-swipe-axis.browser.test.ts',
'test/phone-press-feedback.browser.test.ts',
'test/desktop-connect-page.browser.test.ts', // no server: the page is served by request interception
'test/desktop-tabs-pages.browser.test.ts', // no server: the pages are served by request interception
'test/local-model-ui.browser.test.ts',
'test/home-breakpoint-swap.browser.test.ts',
'test/log-viewer-reconnect.browser.test.ts',
];
/**
* Wall-clock benchmarks. They assert on durations, so a loaded shared runner
* fails them for reasons that have nothing to do with the diff under test.
*/
export const PERF_TEST_GLOBS = ['test/perf-*.test.ts'];
/**
* Browser + visual regression: chromium AND environment-specific PNG baselines
* that are generated per machine. Has its own config
* (test/mobile/vitest.config.ts) because it needs serial execution, a longer
* timeout and the `pretest:mobile` vendor step — run it with
* `npm run test:mobile`, not through the configs here.
*/
export const MOBILE_TEST_GLOBS = ['test/mobile/**'];
/** Everything `npm test` skips. */
export const NON_CI_TEST_GLOBS = [...MOBILE_TEST_GLOBS, ...PERF_TEST_GLOBS, ...BROWSER_TEST_GLOBS];