Files
Codeman/test/mobile/helpers/server.ts
T
arkonandClaude Opus 4.7 7beec7194a fix(client): harden inline rename against CJK, mid-rename deletion, and double-fire
Three follow-up fixes to the inline rename input introduced in #81:

1. IME composition guard. Pressing Enter to confirm a Chinese pinyin
   candidate (or any IME composition) was committing the half-composed
   text as the session name. Skip the keydown handler when isComposing
   is true or when keyCode is the legacy 229 sentinel that older
   Safari/Edge versions report on the Enter that triggers compositionend.

2. Ghost tab on mid-rename deletion. If a session was deleted via SSE
   while its tab was being renamed, the render-skip flag suppressed
   _renderSessionTabs() and the orphaned <input> stayed on screen until
   blur — at which point the rename PUT 404'd against the dead session.
   Replace the boolean _inlineRenameActive with a _activeRename
   {sessionId, cancel} object so _cleanupSessionData can abort an
   in-flight rename targeting the deleted session, and finishRename
   skips the API call when the session is gone.

3. Stuck-flag risk. Move the settle-once guard into a closure-local
   `settled` boolean so blur / Enter / Escape / external cancel all
   converge to a single idempotent path. Register _activeRename only
   after the input is fully wired so a throw earlier in setup can't
   strand state.

Adds test/inline-rename.test.ts with 7 Playwright tests that drive
startInlineRename via page.evaluate() against a stubbed session and
synthetic .tab-name node — no real PTY/tmux needed, runs in ~1.3s.

Also fixes test/mobile/helpers/server.ts which imported the WebServer
via a path one directory short of the repo root, breaking the entire
mobile test suite under the main vitest config.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 09:57:08 +02:00

31 lines
751 B
TypeScript

import { WebServer } from '../../../src/web/server.js';
let servers: Map<number, WebServer> = new Map();
export async function createTestServer(port: number): Promise<WebServer> {
if (servers.has(port)) {
return servers.get(port)!;
}
const server = new WebServer(port, false, true); // testMode = true
await server.start();
servers.set(port, server);
return server;
}
export async function stopTestServer(server: WebServer): Promise<void> {
await server.stop();
for (const [port, s] of servers) {
if (s === server) {
servers.delete(port);
break;
}
}
}
export async function stopAllTestServers(): Promise<void> {
for (const server of servers.values()) {
await server.stop();
}
servers.clear();
}