From a0f75207ced2f74a329da222131025be23e0d99e Mon Sep 17 00:00:00 2001 From: OrcaWin Date: Sat, 31 Oct 2026 07:38:33 -0700 Subject: [PATCH] test: remove 17 low-value suites and 133 individual cases (#36700) --- config/reliability-gates.jsonc | 36 +---- config/scripts/ci-shard-timings.json | 16 -- .../server-claude-blocked-prompt.test.ts | 9 -- .../browser/extensions/api/management.test.ts | 31 ---- .../browser-extension-install-store.test.ts | 40 +---- ...browser-extension-session-services.test.ts | 23 +-- .../claude-account-folder.test.ts | 31 +--- .../claude-command-process.test.ts | 44 ------ .../codex-reset-credit-ledger.test.ts | 10 -- .../daemon-pty-router-legacy-owner.test.ts | 14 -- src/main/git/branch-rename.test.ts | 58 +------- .../git/worktree-git-capabilities.test.ts | 30 ---- src/main/gitea/repository-ref.test.ts | 136 ----------------- .../account-binding-required-host.test.ts | 134 ----------------- src/main/github/review-head-remote.test.ts | 134 ----------------- .../pty-producer-flow-control.test.ts | 36 ----- .../pty/ipc/spawn-reattach-size-cache.test.ts | 8 - .../ipc/rebinding-file-watch-noise.test.ts | 29 ---- .../issue-command-wsl-stopped-distro.test.ts | 15 -- src/main/kimi/kimi-runtime-home.test.ts | 81 +--------- .../orcad-managed-update-on-restore.test.ts | 45 ------ .../journal-outcome-sweeper.test.ts | 17 --- ...-agent-session-command-publication.test.ts | 40 +---- ...ctured-agent-session-host-teardown.test.ts | 94 +----------- ...-session-restart-continuation-wait.test.ts | 33 +---- .../opencode/opencode-cli-version.test.ts | 59 -------- ...y-foreground-inspection-cheap-tier.test.ts | 20 --- ...foreground-process-inspection-cost.test.ts | 14 -- .../host-terminal-scrollback-read.test.ts | 41 ------ .../runtime/leaf-pty-verdict-expiry.test.ts | 32 ---- ...-runtime-agent-session-account-env.test.ts | 11 -- ...ser-screencast-pending-frame-retry.test.ts | 9 -- ...ime-failed-start-pane-layout-owner.test.ts | 19 --- .../orca-runtime-git-diff-budget.test.ts | 39 ----- ...ntime-worktree-change-invalidation.test.ts | 9 -- .../terminal-multiplex-escape-tail.test.ts | 135 ----------------- .../runtime-reference-integration.test.ts | 47 ------ ...-agent-create-support-opencode-rig.test.ts | 7 - ...structured-worker-hook-attestation.test.ts | 21 --- .../runtime/tui-idle-codex-plan-menu.test.ts | 10 -- ...worktree-ps-unverifiable-terminals.test.ts | 12 -- src/main/speech/speech-model-deletion.test.ts | 35 ----- src/main/ssh/ssh-tcp-forwarding-probe.test.ts | 68 +-------- src/main/updater-release-api-token.test.ts | 42 ------ .../window/renderer-liveness-at-death.test.ts | 24 --- src/preload/hidden-window-frame-pump.test.ts | 132 ----------------- .../editor/rich-markdown-auto-focus.test.ts | 43 ------ .../editor/rich-markdown-local-image.test.ts | 19 --- ...se-markdown-document-watch-refresh.test.ts | 41 ------ ...arkdownReviewController.open-guard.test.ts | 43 ------ .../NativeChatComposerNotices.test.tsx | 134 ----------------- .../native-chat/NativeChatPaneHeader.test.tsx | 48 ------ .../NativeChatStructuredQuestionCard.test.tsx | 5 - .../use-native-chat-font-size.test.tsx | 21 --- .../NewWorkspaceComposerNameSection.test.tsx | 31 ---- .../pet/usePetPointerInteraction.test.ts | 135 ----------------- .../state/use-plugin-install-link.test.tsx | 16 -- .../ai-vault-session-account.test.ts | 14 -- .../useFileExplorerWatch.broker.test.tsx | 8 - .../settings/MachineNameField.test.tsx | 47 ------ .../settings/ShareSkillsSettingsPane.test.tsx | 138 ------------------ .../use-setup-guide-telemetry.test.ts | 134 ----------------- ...orktree-context-menu-delete-intent.test.ts | 134 ----------------- .../listing/use-order-hold.test.ts | 14 -- .../skills/SkillFreshnessStatusPill.test.tsx | 135 ----------------- ...SkillFreshnessUpdateDialog.target.test.tsx | 21 +-- .../status-bar/usage-roster-row-state.test.ts | 132 ----------------- ...e-runtime-pty-snapshot-escape-tail.test.ts | 2 +- .../terminal-captured-input-dispatch.test.ts | 77 +--------- ...erminal-pane-layout-owner-commands.test.ts | 33 ----- .../terminal-parking-e2e-overrides.test.ts | 134 ----------------- .../terminal-quick-command-dispatch.test.ts | 136 ----------------- .../composer-state/draft-target-sync.test.ts | 131 ----------------- .../browser-request-ipc-bridge.split.test.ts | 6 - ...pc-tab-switch-structured-tab-cycle.test.ts | 21 --- ...Events-browser-certificate-failure.test.ts | 16 -- .../pane-close-focus-successor.test.ts | 36 ----- .../pane-terminal-gpu-acceleration.test.ts | 133 ----------------- ...on-legacy-relay-bridged-activation.test.ts | 21 --- .../github-pr-refresh-host-guard.test.ts | 25 ---- ...me-managed-repair-keeps-workspaces.test.ts | 12 -- .../slices/store-sleep-layout-owner.test.ts | 23 --- .../usage-snapshot-refresh.benchmark.test.ts | 136 ----------------- ...untime-connection-generation-fence.test.ts | 12 -- 84 files changed, 32 insertions(+), 4165 deletions(-) delete mode 100644 src/main/gitea/repository-ref.test.ts delete mode 100644 src/main/github/account-binding-required-host.test.ts delete mode 100644 src/main/github/review-head-remote.test.ts delete mode 100644 src/main/runtime/rpc/terminal-multiplex-escape-tail.test.ts delete mode 100644 src/preload/hidden-window-frame-pump.test.ts delete mode 100644 src/renderer/src/components/native-chat/NativeChatComposerNotices.test.tsx delete mode 100644 src/renderer/src/components/pet/usePetPointerInteraction.test.ts delete mode 100644 src/renderer/src/components/settings/ShareSkillsSettingsPane.test.tsx delete mode 100644 src/renderer/src/components/setup-guide/use-setup-guide-telemetry.test.ts delete mode 100644 src/renderer/src/components/sidebar/worktree-context-menu-delete-intent.test.ts delete mode 100644 src/renderer/src/components/skills/SkillFreshnessStatusPill.test.tsx delete mode 100644 src/renderer/src/components/status-bar/usage-roster-row-state.test.ts delete mode 100644 src/renderer/src/components/terminal-pane/terminal-parking-e2e-overrides.test.ts delete mode 100644 src/renderer/src/components/terminal-pane/terminal-quick-command-dispatch.test.ts delete mode 100644 src/renderer/src/hooks/composer-state/draft-target-sync.test.ts delete mode 100644 src/renderer/src/lib/pane-manager/pane-terminal-gpu-acceleration.test.ts delete mode 100644 src/renderer/src/store/slices/usage-snapshot-refresh.benchmark.test.ts diff --git a/config/reliability-gates.jsonc b/config/reliability-gates.jsonc index 839d0cea47f..ea07e87a157 100644 --- a/config/reliability-gates.jsonc +++ b/config/reliability-gates.jsonc @@ -8536,12 +8536,12 @@ "providers": ["local", "daemon", "ssh", "remote-runtime", "wsl"], "coveredPlatforms": ["macos"], "coveredProviders": ["local", "daemon", "remote-runtime"], - "coverageNotes": "Deterministic host/parser, process-classifier, snapshot-publication, mixed-version, renderer, and macOS Electron coverage proves the local and shared paired-runtime contracts. Direct SSH intentionally publishes no shell proof and immediately preserves incumbent behavior. WSL, Windows ConPTY, Linux desktop, and paired headed/headless journeys remain gaps.", + "coverageNotes": "Deterministic host/parser, process-classifier, snapshot-publication, mixed-version, renderer, and macOS Electron coverage proves the local and shared paired-runtime contracts. Direct SSH intentionally publishes no shell proof and immediately preserves incumbent behavior. WSL, Windows ConPTY, Linux desktop, and paired headed/headless journeys remain gaps. The audit removed the isolated terminal-multiplex pending-escape-tail forwarding test. Its direct RPC snapshot field-copy alarm is lost; retained parser, snapshot and lifecycle suites do not establish equivalent RPC field coverage.", "motivatingLinks": ["https://github.com/stablyai/orca/pull/16379"], "invariant": "After a TUI exits or is killed, reveal, reattach, snapshot replay, or renderer remount must not deliver terminal-owned mouse or alternate-screen protocol bytes to the surviving shell. Recovery is an ordered output barrier in the daemon session data path: an OSC 133;D completing while the alternate screen is still active pauses the stream at that exact byte boundary, a fresh execution-host process inspection proves shell ownership, and on proof a mode reset is injected as in-stream output so every consumer converges by parsing the same bytes and the queued post-boundary shell output (the prompt) lands on the normal buffer. Snapshots are pure reads. Any failure — refuted proof, timeout, queue overflow, session death, disposal — flushes the queue unmodified, preserving incumbent behavior; later command or mode bytes revoke proof. Clean alternate-screen exits prove ownership asynchronously without pausing.", "oracle": "Run one fixed child-TUI journey for normal exit and cleanup-free SIGKILL. Assert renderer and host normal-buffer/non-mouse state, host snapshot terminalOwner metadata, exact PTY writes with no post-exit mouse report, unrelated-pane survival, post-boundary prompt output preserved (normal exit), ordered proof invalidation, bounded settlement and bail-out flush, one inspection per unclean episode with zero scans for ordinary output, split-escape safety at every chunk boundary, and old/new client-host fallback parity.", "commands": [ - "pnpm exec vitest run --config config/vitest.config.ts src/main/daemon/terminal-shell-lifecycle-scanner.test.ts src/main/daemon/terminal-shell-recovery-barrier.test.ts src/main/daemon/session-shell-recovery.test.ts src/main/daemon/session.test.ts src/main/daemon/terminal-host-concurrent-create.test.ts src/main/daemon/daemon-pty-adapter.test.ts src/main/daemon/daemon-restore-scrollback-depth.test.ts src/main/daemon/terminal-checkpoint-serializer.test.ts src/main/providers/agent-foreground-process.test.ts src/main/runtime/orca-runtime.test.ts src/main/runtime/mobile-presence-lock.test.ts src/main/runtime/rpc/terminal-multiplex-escape-tail.test.ts src/renderer/src/components/terminal-pane/pty-connection-visibility-and-exit.test.ts src/renderer/src/components/terminal-pane/pty-connection-input-and-repaint.test.ts src/renderer/src/components/terminal-pane/pty-connection-hidden-replay.test.ts src/renderer/src/components/terminal-pane/remote-runtime-pty-snapshot-escape-tail.test.ts src/shared/terminal-partial-escape-tail.test.ts src/shared/terminal-partial-escape-tail.fuzz.test.ts --reporter=dot", + "pnpm exec vitest run --config config/vitest.config.ts src/main/daemon/terminal-shell-lifecycle-scanner.test.ts src/main/daemon/terminal-shell-recovery-barrier.test.ts src/main/daemon/session-shell-recovery.test.ts src/main/daemon/session.test.ts src/main/daemon/terminal-host-concurrent-create.test.ts src/main/daemon/daemon-pty-adapter.test.ts src/main/daemon/daemon-restore-scrollback-depth.test.ts src/main/daemon/terminal-checkpoint-serializer.test.ts src/main/providers/agent-foreground-process.test.ts src/main/runtime/orca-runtime.test.ts src/main/runtime/mobile-presence-lock.test.ts src/renderer/src/components/terminal-pane/pty-connection-visibility-and-exit.test.ts src/renderer/src/components/terminal-pane/pty-connection-input-and-repaint.test.ts src/renderer/src/components/terminal-pane/pty-connection-hidden-replay.test.ts src/renderer/src/components/terminal-pane/remote-runtime-pty-snapshot-escape-tail.test.ts src/shared/terminal-partial-escape-tail.test.ts src/shared/terminal-partial-escape-tail.fuzz.test.ts --reporter=dot", "pnpm exec vitest run --config config/vitest.config.ts tests/e2e/cross-version-wire/cross-version-terminal-wire.unit.test.ts --reporter=dot", "pnpm exec electron-vite build --mode e2e", "SKIP_BUILD=1 pnpm exec playwright test tests/e2e/terminal-hidden-child-tui-kill-mode-reset.spec.ts --config tests/playwright.config.ts --project electron-headless --workers=1" @@ -8558,7 +8558,6 @@ "src/main/providers/agent-foreground-process.test.ts", "src/main/runtime/orca-runtime.test.ts", "src/main/runtime/mobile-presence-lock.test.ts", - "src/main/runtime/rpc/terminal-multiplex-escape-tail.test.ts", "src/renderer/src/components/terminal-pane/pty-connection-visibility-and-exit.test.ts", "src/renderer/src/components/terminal-pane/pty-connection-input-and-repaint.test.ts", "src/renderer/src/components/terminal-pane/pty-connection-hidden-replay.test.ts", @@ -8645,7 +8644,8 @@ "WSL and Windows ConPTY process-membership behavior has no physical-host proof yet.", "Any stopped (Ctrl-Z) descendant in the shell's tree refutes the proof, so a suspended unrelated job silently disables recovery for that pane (fails closed to incumbent behavior).", "Attach is deliberately settle-free: a viewer connecting inside an in-flight proof (~100ms typical) receives the pre-reset snapshot as its first frame and self-heals when the in-stream reset arrives; snapshot RPC and remote serialize paths still inherit a bounded (750ms) settle wait while a proof is in flight.", - "Paired headed and headless remote-runtime topologies have not yet run the full pointer-input oracle." + "Paired headed and headless remote-runtime topologies have not yet run the full pointer-input oracle.", + "The audit removed the isolated terminal-multiplex pending-escape-tail forwarding test. Its direct RPC snapshot field-copy alarm is lost; retained parser, snapshot and lifecycle suites do not establish equivalent RPC field coverage." ], "demotionRule": "Keep experimental or demote if missing ownership proof changes incumbent behavior, a live TUI loses mouse/focus modes, foreground inspection enters ordinary output/reveal paths, or the focused Electron journey flakes without an identified product or harness fault." }, @@ -12049,7 +12049,7 @@ "providers": ["paired-runtime", "ssh"], "coveredPlatforms": ["macos"], "coveredProviders": ["paired-runtime"], - "coverageNotes": "Deterministic headed macOS runs launch an isolated Orca desktop server and a separate paired web client. A byte-identical headless run uses an isolated `orca serve` host. Both create six real paired host PTYs with bounded high-output scrollback, prove sustained output while all six client xterms are warm-mounted but hidden causes zero renderer scheduler work, then drive 180 timed real-PTY spinner frames through a second production `session.tabs.subscribeAll` transport and the real Zustand store. Each worktree must publish and apply only its exact initial-working and final-idle titles. Both topologies ordinary-park five xterms without enabling the lossy retention budget, assert bounded cells/heap/timer lag, then restore the bounded authoritative tail exactly once on the original PTY including output produced while parked and continued input/output. The headed oracle additionally keeps every remote target workspace and terminal unmounted in the host renderer before and after client recovery. Production-parity React contracts reproduce and remove the independent cold-park watcher/title feedback loop, including memo-cache discard, StrictMode cleanup replay, detached split-PTY replacement, and the zero-park fast path. A deterministic cross-boundary contract drives 24 real PTY trackers in distinct worktrees through 2,880 decorative spinner and bare-native redraw chunks and counts host publications, serialized bytes, renderer apply calls, and store mutations while preserving exact per-PTY raw chunks and per-worktree semantic transitions. Fake-clock continuation beyond the 30-minute stale boundary requires one deduplicated refresh per worktree every 15 minutes, globally spaced by at least 50 ms, with every mirrored working status still fresh. Exact-identical Pi plus rotating normalized Pi/Grok frames renew coarse working/permission state; rich prompt/tool/question fields retain their original 30-minute lease, and `stateStartedAt`/acknowledgement identity remain stable across title/hook source swaps. A separate headed desktop-client journey relaunches the host main process while retaining the daemon and a daemon-backgrounded PTY, then requires first-observation foreground sync and continued input/output on the same PTY. Unit coverage keeps layout versions out of snapshot output high-waters when a restored snapshot has no output sequence and retries an existing subscriber only after authoritative provider inventory proves the retained PTY exists. Separate headed/headless ACK-starvation tests recover one stalled stream without replacing its PTY. A headed output-drop oracle proves a successful snapshot probe cannot certify a stale live stream when the authoritative PTY sequence advanced beyond the client high-water. Unit coverage requires an unsequenced client to establish a first-probe baseline, remain attached at the same sequence, and recover only after a later probe advances. A capability-disabled run proves legacy hosts retain the prior lossy limit/TTL fallback. Unit tests cover exact-owner capability routing, raw-stream release, singleton side-effect facts with timed handoff cleanup, 64 simultaneous synthetic-title sources with zero decorative client events after convergence, per-client late-subscribe recovery, semantic bell/title transitions, local animation-frame preservation, legacy no-output-pause delivery gating with exact snapshot restore, provider-authoritative snapshots, 128 active streams plus retry after a 129th-stream capacity rejection, capacity-pressure backoff, full split-leaf remint reconciliation, truncation, and manual-disconnect queue fencing. Linux, Windows, live SSH, and production-scale paired hosts remain gaps.", + "coverageNotes": "Deterministic headed macOS runs launch an isolated Orca desktop server and a separate paired web client. A byte-identical headless run uses an isolated `orca serve` host. Both create six real paired host PTYs with bounded high-output scrollback, prove sustained output while all six client xterms are warm-mounted but hidden causes zero renderer scheduler work, then drive 180 timed real-PTY spinner frames through a second production `session.tabs.subscribeAll` transport and the real Zustand store. Each worktree must publish and apply only its exact initial-working and final-idle titles. Both topologies ordinary-park five xterms without enabling the lossy retention budget, assert bounded cells/heap/timer lag, then restore the bounded authoritative tail exactly once on the original PTY including output produced while parked and continued input/output. The headed oracle additionally keeps every remote target workspace and terminal unmounted in the host renderer before and after client recovery. Production-parity React contracts reproduce and remove the independent cold-park watcher/title feedback loop, including memo-cache discard, StrictMode cleanup replay, detached split-PTY replacement, and the zero-park fast path. A deterministic cross-boundary contract drives 24 real PTY trackers in distinct worktrees through 2,880 decorative spinner and bare-native redraw chunks and counts host publications, serialized bytes, renderer apply calls, and store mutations while preserving exact per-PTY raw chunks and per-worktree semantic transitions. Fake-clock continuation beyond the 30-minute stale boundary requires one deduplicated refresh per worktree every 15 minutes, globally spaced by at least 50 ms, with every mirrored working status still fresh. Exact-identical Pi plus rotating normalized Pi/Grok frames renew coarse working/permission state; rich prompt/tool/question fields retain their original 30-minute lease, and `stateStartedAt`/acknowledgement identity remain stable across title/hook source swaps. A separate headed desktop-client journey relaunches the host main process while retaining the daemon and a daemon-backgrounded PTY, then requires first-observation foreground sync and continued input/output on the same PTY. Unit coverage keeps layout versions out of snapshot output high-waters when a restored snapshot has no output sequence and retries an existing subscriber only after authoritative provider inventory proves the retained PTY exists. Separate headed/headless ACK-starvation tests recover one stalled stream without replacing its PTY. A headed output-drop oracle proves a successful snapshot probe cannot certify a stale live stream when the authoritative PTY sequence advanced beyond the client high-water. Unit coverage requires an unsequenced client to establish a first-probe baseline, remain attached at the same sequence, and recover only after a later probe advances. A capability-disabled run proves legacy hosts retain the prior lossy limit/TTL fallback. Unit tests cover exact-owner capability routing, raw-stream release, singleton side-effect facts with timed handoff cleanup, 64 simultaneous synthetic-title sources with zero decorative client events after convergence, per-client late-subscribe recovery, semantic bell/title transitions, local animation-frame preservation, legacy no-output-pause delivery gating with exact snapshot restore, provider-authoritative snapshots, 128 active streams plus retry after a 129th-stream capacity rejection, capacity-pressure backoff, full split-leaf remint reconciliation, truncation, and manual-disconnect queue fencing. Linux, Windows, live SSH, and production-scale paired hosts remain gaps. The audit removed the E2E parking override/debug-handle suite. Override exposure guards, delay/retention independence, TTL filtering and debug-handle forwarding alarms are lost. Retained real parking journeys do not establish equivalent test-harness configuration coverage.", "motivatingLinks": [ "https://github.com/stablyai/orca/issues/8652", "https://github.com/stablyai/orca/pull/10625" @@ -12063,7 +12063,7 @@ "ORCA_BACKGROUND_LAUNCH=1 pnpm exec playwright test tests/e2e/paired-client-first-terminal-unopened-host-worktree.spec.ts --config tests/playwright.config.ts --project electron-headless --workers=1", "pnpm exec vitest run --config config/vitest.config.ts src/main/runtime/mobile-session-tabs-agent-status-heartbeat.test.ts src/main/runtime/orca-runtime-hook-agent-status-projection.test.ts tests/e2e/session-tabs-decorative-title-fanout.unit.test.ts tests/e2e/session-tabs-rich-status-boundaries.unit.test.ts --maxWorkers=1", "pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/terminal-pane/terminal-cold-park-pre-gate-loop.react185.test.tsx src/renderer/src/components/terminal-pane/use-parked-terminal-watcher-synchronization.react185.test.tsx src/renderer/src/components/terminal-pane/terminal-cold-park-verdict-loop.test.tsx src/renderer/src/components/terminal-pane/use-terminal-tab-cold-parking.test.ts --maxWorkers=1", - "pnpm exec vitest run --config config/vitest.config.ts src/main/runtime/orca-runtime.test.ts src/main/runtime/rpc/terminal-multiplex-initial-snapshot-buffering.test.ts src/main/runtime/rpc/terminal-multiplex-snapshot-serialization.test.ts src/main/runtime/rpc/terminal-multiplex-pty-wait-capacity.test.ts src/main/runtime/rpc/terminal-subscribe-buffer.test.ts src/renderer/src/components/terminal-pane/parked-terminal-byte-watcher.test.ts src/renderer/src/components/terminal-pane/terminal-side-effect-facts-handler.test.ts src/renderer/src/components/terminal-pane/pty-connection-hidden-replay.test.ts src/renderer/src/components/terminal-pane/pty-connection-visibility-and-exit.test.ts src/renderer/src/components/terminal-pane/remote-runtime-pty-transport-activation-inventory-fallback.test.ts src/renderer/src/components/terminal-pane/terminal-hidden-view-parking.test.ts src/renderer/src/components/terminal-pane/terminal-hidden-worktree-retention.test.ts src/renderer/src/components/terminal-pane/terminal-parked-tab-watchers.test.ts src/renderer/src/components/terminal-pane/terminal-parked-watcher-reconciliation.test.ts src/renderer/src/components/terminal-pane/terminal-parked-watcher-partial-reconciliation.test.ts src/renderer/src/components/terminal-pane/terminal-parking-e2e-overrides.test.ts src/renderer/src/runtime/remote-runtime-terminal-stall-recovery.test.ts src/renderer/src/runtime/runtime-client-events.test.ts src/renderer/src/web/web-preload-api-runtime-environment.test.ts src/main/ipc/runtime-environments/runtime-environments-pairing.test.ts", + "pnpm exec vitest run --config config/vitest.config.ts src/main/runtime/orca-runtime.test.ts src/main/runtime/rpc/terminal-multiplex-initial-snapshot-buffering.test.ts src/main/runtime/rpc/terminal-multiplex-snapshot-serialization.test.ts src/main/runtime/rpc/terminal-multiplex-pty-wait-capacity.test.ts src/main/runtime/rpc/terminal-subscribe-buffer.test.ts src/renderer/src/components/terminal-pane/parked-terminal-byte-watcher.test.ts src/renderer/src/components/terminal-pane/terminal-side-effect-facts-handler.test.ts src/renderer/src/components/terminal-pane/pty-connection-hidden-replay.test.ts src/renderer/src/components/terminal-pane/pty-connection-visibility-and-exit.test.ts src/renderer/src/components/terminal-pane/remote-runtime-pty-transport-activation-inventory-fallback.test.ts src/renderer/src/components/terminal-pane/terminal-hidden-view-parking.test.ts src/renderer/src/components/terminal-pane/terminal-hidden-worktree-retention.test.ts src/renderer/src/components/terminal-pane/terminal-parked-tab-watchers.test.ts src/renderer/src/components/terminal-pane/terminal-parked-watcher-reconciliation.test.ts src/renderer/src/components/terminal-pane/terminal-parked-watcher-partial-reconciliation.test.ts src/renderer/src/runtime/remote-runtime-terminal-stall-recovery.test.ts src/renderer/src/runtime/runtime-client-events.test.ts src/renderer/src/web/web-preload-api-runtime-environment.test.ts src/main/ipc/runtime-environments/runtime-environments-pairing.test.ts", "pnpm exec vitest run --config config/vitest.config.ts src/main/runtime/terminal-subscriber-driven-daemon-attach.test.ts", "pnpm exec vitest run --config config/vitest.config.ts src/main/runtime/session-tabs-inventory-publication.test.ts src/main/runtime/rpc/methods/session-tabs-inventory-census-race.test.ts src/main/runtime/rpc/methods/session-tabs.test.ts src/renderer/src/runtime/host-session-mirror-empty-inventory-settle.test.ts src/main/daemon/terminal-host-agent-session.test.ts tests/e2e/session-tabs-empty-inventory-daemon-oracle.unit.test.ts --maxWorkers=1", "pnpm exec vitest run --config config/vitest.config.ts src/shared/remote-runtime/control/remote-runtime-shared-control-connection.test.ts", @@ -12115,7 +12115,6 @@ "src/renderer/src/components/terminal-pane/terminal-parked-tab-watchers.test.ts", "src/renderer/src/components/terminal-pane/terminal-parked-watcher-reconciliation.test.ts", "src/renderer/src/components/terminal-pane/terminal-parked-watcher-partial-reconciliation.test.ts", - "src/renderer/src/components/terminal-pane/terminal-parking-e2e-overrides.test.ts", "src/renderer/src/runtime/remote-runtime-terminal-stall-recovery.test.ts", "src/renderer/src/runtime/remote-runtime-terminal-parse-backpressure.test.ts", "src/renderer/src/runtime/runtime-client-events.test.ts", @@ -12455,16 +12454,6 @@ "durationSeconds": 12.5, "summary": "With the parking override captured by both host launches, the isolated headed host and separate paired desktop client retained the daemon PID and PTY ID across host relaunch, emitted one target foreground transition, and delivered target plus post-relaunch control input/output. The byte-identical run with only the unknown-state fix reverted failed at the missing target foreground transition." }, - { - "date": "2026-08-02", - "runner": "local", - "platform": "macos", - "command": "pnpm exec vitest run --config config/vitest.config.ts src/main/runtime/orca-runtime.test.ts src/main/runtime/rpc/terminal-multiplex-initial-snapshot-buffering.test.ts src/main/runtime/rpc/terminal-multiplex-snapshot-serialization.test.ts src/main/runtime/rpc/terminal-multiplex-pty-wait-capacity.test.ts src/main/runtime/rpc/terminal-subscribe-buffer.test.ts src/renderer/src/components/terminal-pane/parked-terminal-byte-watcher.test.ts src/renderer/src/components/terminal-pane/terminal-side-effect-facts-handler.test.ts src/renderer/src/components/terminal-pane/pty-connection-hidden-output-restore.test.ts src/renderer/src/components/terminal-pane/pty-connection-park-reveal-model-snapshot.test.ts src/renderer/src/components/terminal-pane/remote-runtime-pty-transport-activation-inventory-fallback.test.ts src/renderer/src/components/terminal-pane/terminal-hidden-view-parking.test.ts src/renderer/src/components/terminal-pane/terminal-hidden-worktree-retention.test.ts src/renderer/src/components/terminal-pane/terminal-parked-tab-watchers.test.ts src/renderer/src/components/terminal-pane/terminal-parked-watcher-reconciliation.test.ts src/renderer/src/components/terminal-pane/terminal-parked-watcher-partial-reconciliation.test.ts src/renderer/src/components/terminal-pane/terminal-parking-e2e-overrides.test.ts src/renderer/src/runtime/remote-runtime-terminal-stall-recovery.test.ts src/renderer/src/runtime/runtime-client-events.test.ts src/renderer/src/web/web-preload-api-runtime-environment.test.ts src/main/ipc/runtime-environments/runtime-environments-pairing.test.ts", - "result": "passed", - "durationSeconds": 18.71, - "summary": "Seventeen focused files passed 2,044 tests with one existing skip, including the 64-PTY decorative-title bound, per-client late subscription, semantic-fact preservation, and the true no-output-pause legacy client shape.", - "currentCommand": "pnpm exec vitest run --config config/vitest.config.ts src/main/runtime/orca-runtime.test.ts src/main/runtime/rpc/terminal-multiplex-initial-snapshot-buffering.test.ts src/main/runtime/rpc/terminal-multiplex-snapshot-serialization.test.ts src/main/runtime/rpc/terminal-multiplex-pty-wait-capacity.test.ts src/main/runtime/rpc/terminal-subscribe-buffer.test.ts src/renderer/src/components/terminal-pane/parked-terminal-byte-watcher.test.ts src/renderer/src/components/terminal-pane/terminal-side-effect-facts-handler.test.ts src/renderer/src/components/terminal-pane/pty-connection-hidden-replay.test.ts src/renderer/src/components/terminal-pane/pty-connection-visibility-and-exit.test.ts src/renderer/src/components/terminal-pane/remote-runtime-pty-transport-activation-inventory-fallback.test.ts src/renderer/src/components/terminal-pane/terminal-hidden-view-parking.test.ts src/renderer/src/components/terminal-pane/terminal-hidden-worktree-retention.test.ts src/renderer/src/components/terminal-pane/terminal-parked-tab-watchers.test.ts src/renderer/src/components/terminal-pane/terminal-parked-watcher-reconciliation.test.ts src/renderer/src/components/terminal-pane/terminal-parked-watcher-partial-reconciliation.test.ts src/renderer/src/components/terminal-pane/terminal-parking-e2e-overrides.test.ts src/renderer/src/runtime/remote-runtime-terminal-stall-recovery.test.ts src/renderer/src/runtime/runtime-client-events.test.ts src/renderer/src/web/web-preload-api-runtime-environment.test.ts src/main/ipc/runtime-environments/runtime-environments-pairing.test.ts" - }, { "date": "2026-08-02", "runner": "local", @@ -12492,16 +12481,6 @@ "durationSeconds": 17.3, "summary": "The headed paired oracle dropped and acknowledged output only for the original client stream, proved the fixture consumed input while the host model advanced and the client stayed stale, then replaced the stream, repainted exact fixture output, preserved authoritative PTY identity and target-tab cardinality, and resumed live I/O." }, - { - "date": "2026-07-29", - "runner": "local", - "platform": "macos", - "command": "pnpm exec vitest run --config config/vitest.config.ts src/main/runtime/orca-runtime.test.ts src/main/runtime/rpc/terminal-multiplex-initial-snapshot-buffering.test.ts src/main/runtime/rpc/terminal-multiplex-snapshot-serialization.test.ts src/main/runtime/rpc/terminal-multiplex-pty-wait-capacity.test.ts src/main/runtime/rpc/terminal-subscribe-buffer.test.ts src/renderer/src/components/terminal-pane/parked-terminal-byte-watcher.test.ts src/renderer/src/components/terminal-pane/terminal-side-effect-facts-handler.test.ts src/renderer/src/components/terminal-pane/pty-connection-hidden-output-restore.test.ts src/renderer/src/components/terminal-pane/pty-connection-park-reveal-model-snapshot.test.ts src/renderer/src/components/terminal-pane/remote-runtime-pty-transport-activation-inventory-fallback.test.ts src/renderer/src/components/terminal-pane/terminal-hidden-view-parking.test.ts src/renderer/src/components/terminal-pane/terminal-hidden-worktree-retention.test.ts src/renderer/src/components/terminal-pane/terminal-parked-tab-watchers.test.ts src/renderer/src/components/terminal-pane/terminal-parked-watcher-reconciliation.test.ts src/renderer/src/components/terminal-pane/terminal-parked-watcher-partial-reconciliation.test.ts src/renderer/src/components/terminal-pane/terminal-parking-e2e-overrides.test.ts src/renderer/src/runtime/remote-runtime-terminal-stall-recovery.test.ts src/renderer/src/runtime/runtime-client-events.test.ts src/renderer/src/web/web-preload-api-runtime-environment.test.ts src/main/ipc/runtime-environments/runtime-environments-pairing.test.ts", - "result": "passed", - "durationSeconds": 19.54, - "summary": "Seventeen focused files passed 1,938 tests with one existing skip, including 128 active streams, retryable rejection at 129, released-slot snapshot recovery, bounded liveness probes, and balanced subscriber cleanup.", - "currentCommand": "pnpm exec vitest run --config config/vitest.config.ts src/main/runtime/orca-runtime.test.ts src/main/runtime/rpc/terminal-multiplex-initial-snapshot-buffering.test.ts src/main/runtime/rpc/terminal-multiplex-snapshot-serialization.test.ts src/main/runtime/rpc/terminal-multiplex-pty-wait-capacity.test.ts src/main/runtime/rpc/terminal-subscribe-buffer.test.ts src/renderer/src/components/terminal-pane/parked-terminal-byte-watcher.test.ts src/renderer/src/components/terminal-pane/terminal-side-effect-facts-handler.test.ts src/renderer/src/components/terminal-pane/pty-connection-hidden-replay.test.ts src/renderer/src/components/terminal-pane/pty-connection-visibility-and-exit.test.ts src/renderer/src/components/terminal-pane/remote-runtime-pty-transport-activation-inventory-fallback.test.ts src/renderer/src/components/terminal-pane/terminal-hidden-view-parking.test.ts src/renderer/src/components/terminal-pane/terminal-hidden-worktree-retention.test.ts src/renderer/src/components/terminal-pane/terminal-parked-tab-watchers.test.ts src/renderer/src/components/terminal-pane/terminal-parked-watcher-reconciliation.test.ts src/renderer/src/components/terminal-pane/terminal-parked-watcher-partial-reconciliation.test.ts src/renderer/src/components/terminal-pane/terminal-parking-e2e-overrides.test.ts src/renderer/src/runtime/remote-runtime-terminal-stall-recovery.test.ts src/renderer/src/runtime/runtime-client-events.test.ts src/renderer/src/web/web-preload-api-runtime-environment.test.ts src/main/ipc/runtime-environments/runtime-environments-pairing.test.ts" - }, { "date": "2026-07-29", "runner": "local", @@ -12604,7 +12583,8 @@ "Display-off reveal latency is a separate atlas and viewport-reflow class and is not covered by this gate.", "Historical field trace archives are still required to order replay-wedge events against renderer heartbeat loss and deduplicate archived records.", "The legacy protocol shape is deterministic unit coverage; a packaged pre-v1.4.163 host has not yet run the full headed memory oracle.", - "The live windows-issues incident recorded two fast snapshot-probe successes while fresh output remained stale, but that release did not log the returned snapshot sequence; the deterministic sequence-gap oracle matches the observed false-health boundary without proving the field transport's lower-level drop mechanism." + "The live windows-issues incident recorded two fast snapshot-probe successes while fresh output remained stale, but that release did not log the returned snapshot sequence; the deterministic sequence-gap oracle matches the observed false-health boundary without proving the field transport's lower-level drop mechanism.", + "The audit removed the E2E parking override/debug-handle suite. Override exposure guards, delay/retention independence, TTL filtering and debug-handle forwarding alarms are lost. Retained real parking journeys do not establish equivalent test-harness configuration coverage." ], "demotionRule": "Keep experimental or demote to protection none if decorative title frequency changes paired client-event or session-tabs publication volume after convergence, a semantic fact is dropped, paired first paint is blank, passive work reconnects after manual disconnect, a capable hidden paired manager survives ordinary parking, a legacy hidden pane schedules raw xterm output or bypasses its fallback, reveal loses requested bounded history or live PTY identity, retained buffer cells do not fall, or either headed/headless scenario flakes." }, diff --git a/config/scripts/ci-shard-timings.json b/config/scripts/ci-shard-timings.json index 720c0bcd277..4d25a993120 100644 --- a/config/scripts/ci-shard-timings.json +++ b/config/scripts/ci-shard-timings.json @@ -2555,8 +2555,6 @@ "src/main/git/wsl-windows-checkout-sample-script.test.ts": 107, "src/main/gitea/client-scan-invalidation.test.ts": 485, "src/main/gitea/client.test.ts": 385, - "src/main/gitea/repository-ref.test.ts": 436, - "src/main/github/account-binding-required-host.test.ts": 220, "src/main/github/auth-diagnose.test.ts": 58, "src/main/github/client-create-pr.test.ts": 451, "src/main/github/client-file-viewed.test.ts": 378, @@ -2642,7 +2640,6 @@ "src/main/github/project-view/project-view-table.test.ts": 429, "src/main/github/project-view/repository-field-options.test.ts": 51, "src/main/github/rate-limit.test.ts": 64, - "src/main/github/review-head-remote.test.ts": 45, "src/main/github/stacked-pr-creation.test.ts": 477, "src/main/github/work-item-details-concurrency.test.ts": 85, "src/main/github/work-item-details-config-change.test.ts": 563, @@ -5467,7 +5464,6 @@ "src/main/runtime/rpc/terminal-multiplex-desktop-resize-routing.test.ts": 2016, "src/main/runtime/rpc/terminal-multiplex-end-verdict.test.ts": 2309, "src/main/runtime/rpc/terminal-multiplex-endpoint-loss-notice.test.ts": 1620, - "src/main/runtime/rpc/terminal-multiplex-escape-tail.test.ts": 1040, "src/main/runtime/rpc/terminal-multiplex-flow-control.bench.test.ts": 44, "src/main/runtime/rpc/terminal-multiplex-initial-snapshot-buffering.test.ts": 1870, "src/main/runtime/rpc/terminal-multiplex-input-sequence-replay.test.ts": 2197, @@ -7619,7 +7615,6 @@ "src/renderer/src/components/native-chat/NativeChatComposer.resume-command.test.tsx": 954, "src/renderer/src/components/native-chat/NativeChatComposer.test.tsx": 1476, "src/renderer/src/components/native-chat/NativeChatComposerActions.test.tsx": 624, - "src/renderer/src/components/native-chat/NativeChatComposerNotices.test.tsx": 527, "src/renderer/src/components/native-chat/NativeChatContextUsageRing.test.tsx": 519, "src/renderer/src/components/native-chat/NativeChatEmptyState.test.tsx": 388, "src/renderer/src/components/native-chat/NativeChatImageAttachmentPreview.test.tsx": 2300, @@ -7996,7 +7991,6 @@ "src/renderer/src/components/pet/pet-blob-cache.test.ts": 55, "src/renderer/src/components/pet/pet-overlay-visibility.test.ts": 46, "src/renderer/src/components/pet/sprite-animation-css.test.ts": 44, - "src/renderer/src/components/pet/usePetPointerInteraction.test.ts": 257, "src/renderer/src/components/pet/usePetUrl.test.tsx": 275, "src/renderer/src/components/plain-ssh-terminal/PlainSshTerminalPanels.test.tsx": 2203, "src/renderer/src/components/ports/WorkspacePortScanner.test.tsx": 1978, @@ -8375,7 +8369,6 @@ "src/renderer/src/components/settings/SettingsConstants.test.ts": 97, "src/renderer/src/components/settings/SettingsFormControls.font-autocomplete.test.tsx": 789, "src/renderer/src/components/settings/SettingsFormControls.segmented-control.test.tsx": 548, - "src/renderer/src/components/settings/ShareSkillsSettingsPane.test.tsx": 601, "src/renderer/src/components/settings/ShortcutFilterRail.test.ts": 157, "src/renderer/src/components/settings/SparsePresetSettingsSection.test.tsx": 785, "src/renderer/src/components/settings/SshHostDeltaMoveDialog.test.tsx": 467, @@ -8475,7 +8468,6 @@ "src/renderer/src/components/settings/worktree-symlink-path-filter.test.ts": 107, "src/renderer/src/components/setup-guide/SetupGuideModal.mount-gating.test.tsx": 2270, "src/renderer/src/components/setup-guide/use-setup-guide-progress.test.ts": 1278, - "src/renderer/src/components/setup-guide/use-setup-guide-telemetry.test.ts": 42, "src/renderer/src/components/shared/MacFolderAccessFixDialog.test.tsx": 1178, "src/renderer/src/components/shared/kill-all-terminal-surfaces.test.ts": 1501, "src/renderer/src/components/shared/useDaemonActions.test.tsx": 342, @@ -8725,7 +8717,6 @@ "src/renderer/src/components/sidebar/worktree-card-send-target-inputs.test.ts": 26, "src/renderer/src/components/sidebar/worktree-card-status-inputs.test.ts": 38, "src/renderer/src/components/sidebar/worktree-card-title-display.test.ts": 39, - "src/renderer/src/components/sidebar/worktree-context-menu-delete-intent.test.ts": 646, "src/renderer/src/components/sidebar/worktree-delete-host-qualification.test.ts": 1051, "src/renderer/src/components/sidebar/worktree-delete-position-scaling.test.ts": 285, "src/renderer/src/components/sidebar/worktree-delete-request.test.ts": 27, @@ -8812,7 +8803,6 @@ "src/renderer/src/components/sidebar/worktree-unnest.test.ts": 94, "src/renderer/src/components/sidebar/wsl-host-row-status.test.ts": 282, "src/renderer/src/components/skills/SkillFreshnessNudge.test.tsx": 292, - "src/renderer/src/components/skills/SkillFreshnessStatusPill.test.tsx": 2390, "src/renderer/src/components/skills/SkillFreshnessUpdateDialog.target.test.tsx": 3500, "src/renderer/src/components/skills/SkillFreshnessUpdateDialog.test.tsx": 764, "src/renderer/src/components/skills/SkillInstallDialog.test.tsx": 2928, @@ -8895,7 +8885,6 @@ "src/renderer/src/components/status-bar/usage-percentage-label.localization.test.ts": 185, "src/renderer/src/components/status-bar/usage-percentage-label.test.ts": 20, "src/renderer/src/components/status-bar/usage-pool-label.test.ts": 76, - "src/renderer/src/components/status-bar/usage-roster-row-state.test.ts": 71, "src/renderer/src/components/status-bar/usage-unit-label-parity.test.tsx": 335, "src/renderer/src/components/status-bar/use-owner-usage-rate-limits.test.tsx": 261, "src/renderer/src/components/status-bar/use-resource-memory-snapshot.test.tsx": 198, @@ -9539,7 +9528,6 @@ "src/renderer/src/components/terminal-pane/terminal-parked-watcher-registry.test.ts": 132, "src/renderer/src/components/terminal-pane/terminal-parked-watcher-sleep-preserved-exit.test.ts": 449, "src/renderer/src/components/terminal-pane/terminal-parked-watcher-sole-newborn-exit.test.ts": 410, - "src/renderer/src/components/terminal-pane/terminal-parking-e2e-overrides.test.ts": 2144, "src/renderer/src/components/terminal-pane/terminal-parser-handler-guard.test.ts": 36, "src/renderer/src/components/terminal-pane/terminal-paste-coordinator.test.ts": 118, "src/renderer/src/components/terminal-pane/terminal-paste-executor-default-yield.test.ts": 86, @@ -9551,7 +9539,6 @@ "src/renderer/src/components/terminal-pane/terminal-path-exists-cache.test.ts": 30, "src/renderer/src/components/terminal-pane/terminal-process-exit-restart.test.ts": 42, "src/renderer/src/components/terminal-pane/terminal-programmatic-text-paste.test.ts": 272, - "src/renderer/src/components/terminal-pane/terminal-quick-command-dispatch.test.ts": 59, "src/renderer/src/components/terminal-pane/terminal-remote-runtime-recovery-ui-state.test.ts": 22, "src/renderer/src/components/terminal-pane/terminal-render-desync-evidence-persistence.test.ts": 52, "src/renderer/src/components/terminal-pane/terminal-render-desync-frame.test.ts": 25, @@ -9743,7 +9730,6 @@ "src/renderer/src/hooks/composer-state/composer-review-base-submit-cache.test.ts": 1531, "src/renderer/src/hooks/composer-state/composer-submit-source-ownership.test.ts": 1691, "src/renderer/src/hooks/composer-state/composer-target-state.jira-mapping.test.tsx": 2116, - "src/renderer/src/hooks/composer-state/draft-target-sync.test.ts": 208, "src/renderer/src/hooks/composer-state/imported-project-group-selection.test.tsx": 1633, "src/renderer/src/hooks/composer-state/jira-mapped-owner-flow.integration.test.tsx": 3271, "src/renderer/src/hooks/composer-state/multiple-create-reset.test.ts": 1565, @@ -10253,7 +10239,6 @@ "src/renderer/src/lib/pane-manager/pane-split-close.test.ts": 83, "src/renderer/src/lib/pane-manager/pane-split-scroll.test.ts": 57, "src/renderer/src/lib/pane-manager/pane-terminal-foreground-render-settle.test.ts": 64, - "src/renderer/src/lib/pane-manager/pane-terminal-gpu-acceleration.test.ts": 69, "src/renderer/src/lib/pane-manager/pane-terminal-mouse-wheel.test.ts": 55, "src/renderer/src/lib/pane-manager/pane-terminal-output-queue-chunks.test.ts": 45, "src/renderer/src/lib/pane-manager/pane-terminal-output-scheduler-ack-credit.test.ts": 112, @@ -11268,7 +11253,6 @@ "src/renderer/src/store/slices/ui-notice-dismissals.test.ts": 458, "src/renderer/src/store/slices/ui-page-navigation.test.ts": 408, "src/renderer/src/store/slices/ui/ui-slice-surface-actions.test.ts": 1213, - "src/renderer/src/store/slices/usage-snapshot-refresh.benchmark.test.ts": 66, "src/renderer/src/store/slices/workspace-activation-preparation.test.ts": 1494, "src/renderer/src/store/slices/workspace-attention/workspace-unread-characterization.test.ts": 1602, "src/renderer/src/store/slices/workspace-attention/workspace-unread-flag-host-raises.test.ts": 2305, diff --git a/src/main/agent-hooks/server-claude-blocked-prompt.test.ts b/src/main/agent-hooks/server-claude-blocked-prompt.test.ts index 8edce7d34c3..552aefb1829 100644 --- a/src/main/agent-hooks/server-claude-blocked-prompt.test.ts +++ b/src/main/agent-hooks/server-claude-blocked-prompt.test.ts @@ -78,15 +78,6 @@ describe('Claude prompt blocked by a UserPromptSubmit hook', () => { expectSettledLikeStop() }) - it('keeps a finished turn for its Stop hook', async () => { - program('working') - await promptHook() - program('done') - expect(row().state).toBe('working') - await hook({ hook_event_name: 'Stop', last_assistant_message: 'Done.' }) - expectSettledLikeStop() - }) - it("ignores another program's idle in the same pane", async () => { program('working') await promptHook() diff --git a/src/main/browser/extensions/api/management.test.ts b/src/main/browser/extensions/api/management.test.ts index 17823fd2a0f..0e79c48d9b1 100644 --- a/src/main/browser/extensions/api/management.test.ts +++ b/src/main/browser/extensions/api/management.test.ts @@ -83,37 +83,6 @@ beforeEach(() => { }) describe('chrome.management', () => { - it("lists the profile's installed extensions as Chrome's ExtensionInfo", async () => { - mocks.enabled.delete(SELF) - await expect(call('getAll', [])).resolves.toEqual([ - expect.objectContaining({ id: SELF, enabled: false, disabledReason: 'unknown' }), - { - id: OTHER, - name: 'Blocker', - shortName: 'Blk', - description: 'Blocks things', - version: '2.1', - mayDisable: true, - enabled: true, - isApp: false, - type: 'extension', - offlineEnabled: false, - optionsUrl: `chrome-extension://${OTHER}/options.html`, - icons: [ - { size: 16, url: `chrome-extension://${OTHER}/i16.png` }, - { size: 128, url: `chrome-extension://${OTHER}/i128.png` } - ], - permissions: ['storage'], - hostPermissions: ['https://*/*'], - installType: 'development' - } - ]) - await expect(call('get', [SELF])).resolves.toMatchObject({ installType: 'normal' }) - await expect(call('get', ['c'.repeat(32)])).rejects.toThrow( - `Failed to find extension with id ${'c'.repeat(32)}.` - ) - }) - it('turns other extensions off, and on only from a user gesture', async () => { await call('setEnabled', [OTHER, false]) expect(mocks.setEnabled).toHaveBeenCalledWith('default', OTHER, false) diff --git a/src/main/browser/extensions/browser-extension-install-store.test.ts b/src/main/browser/extensions/browser-extension-install-store.test.ts index 39a1bf864cd..d7f92fe997c 100644 --- a/src/main/browser/extensions/browser-extension-install-store.test.ts +++ b/src/main/browser/extensions/browser-extension-install-store.test.ts @@ -7,8 +7,7 @@ import type { InstalledBrowserExtension } from '../../../shared/browser-extensio vi.mock('electron', () => ({ app: { getPath: () => tmpdir() } })) const { BrowserExtensionInstallStore } = await import('./browser-extension-install-store') -const { readBrowserExtensionIconDataUrl, readBrowserExtensionManifest } = - await import('./browser-extension-manifest') +const { readBrowserExtensionIconDataUrl } = await import('./browser-extension-manifest') const STORE_ID = 'a'.repeat(32) const UNPACKED_ID = 'b'.repeat(32) @@ -37,13 +36,6 @@ afterEach(() => { }) describe('BrowserExtensionInstallStore', () => { - it('persists the installed list across instances', () => { - const store = new BrowserExtensionInstallStore(join(root, 'browser-extensions')) - store.save(record({ path: store.installDirectory(STORE_ID, '1.2.3') })) - const reopened = new BrowserExtensionInstallStore(join(root, 'browser-extensions')) - expect(reopened.get(STORE_ID)?.path).toBe(join(root, 'browser-extensions', STORE_ID, '1.2.3')) - }) - it('deletes the folder of a store install but never an unpacked folder', async () => { const store = new BrowserExtensionInstallStore(join(root, 'browser-extensions')) const storeDir = store.installDirectory(STORE_ID, '1.2.3') @@ -89,36 +81,6 @@ describe('BrowserExtensionInstallStore', () => { }) describe('readBrowserExtensionManifest', () => { - it('localizes the name, splits host permissions and finds the options page and icon', async () => { - writeFileSync( - join(root, 'manifest.json'), - JSON.stringify({ - manifest_version: 3, - name: '__MSG_extName__', - version: '2024.1.0', - default_locale: 'en', - permissions: ['tabs', 'webNavigation', ''], - host_permissions: ['https://*.example.com/*'], - options_ui: { page: 'options.html' }, - icons: { '16': 'icon16.png', '128': 'icon128.png', '256': 'icon256.png' } - }) - ) - mkdirSync(join(root, '_locales', 'en'), { recursive: true }) - writeFileSync( - join(root, '_locales', 'en', 'messages.json'), - JSON.stringify({ ExtName: { message: 'Vault Manager' } }) - ) - - await expect(readBrowserExtensionManifest(root)).resolves.toEqual({ - name: 'Vault Manager', - version: '2024.1.0', - iconPath: 'icon128.png', - permissions: ['tabs', 'webNavigation'], - hostPermissions: ['', 'https://*.example.com/*'], - optionsPage: 'options.html' - }) - }) - it('reads icons only from inside the extension folder', async () => { writeFileSync(join(root, 'icon.png'), Buffer.from([1, 2, 3])) await expect(readBrowserExtensionIconDataUrl(root, 'icon.png')).resolves.toBe( diff --git a/src/main/browser/extensions/browser-extension-session-services.test.ts b/src/main/browser/extensions/browser-extension-session-services.test.ts index 9f6c9d744e5..221bf5f185d 100644 --- a/src/main/browser/extensions/browser-extension-session-services.test.ts +++ b/src/main/browser/extensions/browser-extension-session-services.test.ts @@ -63,7 +63,7 @@ vi.mock('./browser-extension-web-request', () => ({ const { installBrowserExtensionSessionServices } = await import('./browser-extension-session-services') -const { getBrowserExtensionActionState } = await import('./browser-extension-action-registry') +await import('./browser-extension-action-registry') const { grantBrowserExtensionActiveTab, hasBrowserExtensionActiveTab } = await import('./browser-extension-active-tab') @@ -87,14 +87,6 @@ function extension(id: string): Electron.Extension { installBrowserExtensionSessionServices() describe('extension unload in an attached session', () => { - it('drops action state set before any toolbar asked for it', () => { - const sess = attachedSession() - const vault = extension('vault') - getBrowserExtensionActionState('default', vault).set('badgeText', 'OLD', null) - sess.extensions.emit('extension-unloaded', {}, vault) - expect(getBrowserExtensionActionState('default', vault).get(null).badgeText).toBe('') - }) - it("revokes the extension's activeTab grants on that session's tabs only", () => { const sess = attachedSession() const other = attachedSession() @@ -109,19 +101,6 @@ describe('extension unload in an attached session', () => { }) }) -it('removes stale enabled and pinned ids only in the affected browser profile', () => { - attachHook?.uninstalled('work', new Set(['removed'])) - const before = { work: ['removed', 'kept'], home: ['removed'] } - expect(mocks.updateEnabled.mock.calls.at(-1)?.[0](before)).toEqual({ - work: ['kept'], - home: ['removed'] - }) - expect(mocks.updatePinned.mock.calls.at(-1)?.[0](before)).toEqual({ - work: ['kept'], - home: ['removed'] - }) -}) - it('refuses to acknowledge stale removal when browser metadata failed to persist', () => { mocks.persistedEnabled.push('removed') try { diff --git a/src/main/claude-accounts/claude-account-folder.test.ts b/src/main/claude-accounts/claude-account-folder.test.ts index 83027316a96..703d118f7e7 100644 --- a/src/main/claude-accounts/claude-account-folder.test.ts +++ b/src/main/claude-accounts/claude-account-folder.test.ts @@ -29,11 +29,8 @@ vi.mock('../macos-keychain/generic-password', () => ({ } })) -import { - readClaudeFolderLogin, - readClaudeFolderLoginAsync, - removeClaudeAccountFolder -} from './claude-account-folder' +import { readClaudeFolderLoginAsync, removeClaudeAccountFolder } from './claude-account-folder' + import { claudeKeychainService } from './keychain' const roots: string[] = [] @@ -53,30 +50,6 @@ function fixture() { } describe('claude account folder', () => { - it("reads the folder's login and treats a signed-out state file as no login", () => { - const { home } = fixture() - const stateFile = join(home, '.claude.json') - expect(readClaudeFolderLogin(stateFile)).toBeNull() - writeFileSync(stateFile, JSON.stringify({ oauthAccount: { emailAddress: ' a@example.test ' } })) - expect(readClaudeFolderLogin(stateFile)).toEqual({ - email: 'a@example.test', - organizationUuid: null, - organizationName: null - }) - writeFileSync(stateFile, JSON.stringify({ numStartups: 2 })) - expect(readClaudeFolderLogin(stateFile)).toBeNull() - }) - - it('reuses a recent answer within maxAgeMs even though the file changed', () => { - const { home } = fixture() - const stateFile = join(home, '.claude.json') - writeFileSync(stateFile, JSON.stringify({ oauthAccount: { emailAddress: 'a@example.test' } })) - expect(readClaudeFolderLogin(stateFile, 5_000)?.email).toBe('a@example.test') - writeFileSync(stateFile, JSON.stringify({ oauthAccount: { emailAddress: 'b@example.test!' } })) - expect(readClaudeFolderLogin(stateFile, 5_000)?.email).toBe('a@example.test') - expect(readClaudeFolderLogin(stateFile)?.email).toBe('b@example.test!') - }) - it('rereads a state file over a share only when its mtime or size changes', async () => { const { home } = fixture() const stateFile = join(home, '.claude.json') diff --git a/src/main/claude-accounts/claude-command-process.test.ts b/src/main/claude-accounts/claude-command-process.test.ts index 35b50d00887..b23f759b192 100644 --- a/src/main/claude-accounts/claude-command-process.test.ts +++ b/src/main/claude-accounts/claude-command-process.test.ts @@ -64,20 +64,6 @@ describe('runClaudeCommandProcess', () => { warn.mockRestore() }) - it("logs in on the host with CLAUDE_CONFIG_DIR set to the account's folder", async () => { - Object.defineProperty(process, 'platform', { value: 'darwin' }) - await runClaudeCommandProcess( - ['auth', 'login', '--claudeai'], - { windowsPath: '/data/claude-profiles/a/home', linuxPath: null, wslDistro: null }, - 1000 - ) - expect(spawned.specs[0]).toMatchObject({ - program: 'claude', - args: ['auth', 'login', '--claudeai'] - }) - expect(spawned.specs[0].env?.CLAUDE_CONFIG_DIR).toBe('/data/claude-profiles/a/home') - }) - it("logs in through the distro's login shell with --exec for a WSL account", async () => { Object.defineProperty(process, 'platform', { value: 'win32' }) await runClaudeCommandProcess( @@ -99,34 +85,4 @@ describe('runClaudeCommandProcess', () => { ) expect(spec.env?.CLAUDE_CONFIG_DIR).toBe(process.env.CLAUDE_CONFIG_DIR) }) - - it('hands BROWSER to a host login', async () => { - Object.defineProperty(process, 'platform', { value: 'darwin' }) - await runClaudeCommandProcess( - ['auth', 'login', '--claudeai'], - { windowsPath: '/data/a/home', linuxPath: null, wslDistro: null }, - 1000, - { browser: '/data/a/home/.orca-sign-in-browser' } - ) - expect(spawned.specs[0].env?.BROWSER).toBe('/data/a/home/.orca-sign-in-browser') - }) - - it('makes the BROWSER helper executable inside the distro before a WSL login', async () => { - Object.defineProperty(process, 'platform', { value: 'win32' }) - await runClaudeCommandProcess( - ['auth', 'login', '--claudeai'], - { - windowsPath: '\\\\wsl.localhost\\Ubuntu\\home\\u\\a', - linuxPath: '/home/u/a', - wslDistro: 'Ubuntu' - }, - 1000, - { browser: '/home/u/a/.orca-sign-in-browser' } - ) - expect(spawned.specs[0].args?.[5]).toBe( - buildWslLoginShellCommand( - `chmod 700 '/home/u/a/.orca-sign-in-browser'; exec env CLAUDE_CONFIG_DIR='/home/u/a' BROWSER='/home/u/a/.orca-sign-in-browser' claude 'auth' 'login' '--claudeai'` - ) - ) - }) }) diff --git a/src/main/codex-accounts/codex-reset-credit-ledger.test.ts b/src/main/codex-accounts/codex-reset-credit-ledger.test.ts index 2a7c0cf1252..87dc3ae4cd7 100644 --- a/src/main/codex-accounts/codex-reset-credit-ledger.test.ts +++ b/src/main/codex-accounts/codex-reset-credit-ledger.test.ts @@ -96,16 +96,6 @@ describe('async reset-credit ledger', () => { expect(ledger.get('second')).toBe(second) }) - it('retains the removed account guard when its async durability barrier fails', async () => { - const { ledger, barrier } = setup() - const attempt = ledger.createFresh('first', scope('account-1')) - await ledger.markProviderPending('first', attempt) - barrier.mockRejectedValueOnce(new Error('disk full')) - await expect(ledger.discardForRemovedAccount('account-1')).rejects.toThrow('disk full') - expect(ledger.get('first')).toBe(attempt) - expect(ledger.getUnresolvedKey(attempt.accountScopeKey)).toBe('first') - }) - it('fails queued and future mutations closed when a commit outcome is unknown', async () => { const { ledger, store, barrier } = setup() const attempt = ledger.createFresh('first', scope('account-1')) diff --git a/src/main/daemon/daemon-pty-router-legacy-owner.test.ts b/src/main/daemon/daemon-pty-router-legacy-owner.test.ts index 69d094c066d..55606e039c6 100644 --- a/src/main/daemon/daemon-pty-router-legacy-owner.test.ts +++ b/src/main/daemon/daemon-pty-router-legacy-owner.test.ts @@ -82,20 +82,6 @@ describe('DaemonPtyRouter keeps live sessions on their older daemon', () => { expect(legacy.spawn).not.toHaveBeenCalled() }) - it('creates on the current daemon once the older daemon no longer runs the id', async () => { - const current = createAdapter('current') - const legacy = createAdapter('legacy', []) - const router = new DaemonPtyRouter({ current, legacy: [legacy] }) - - await router.spawn({ ...SPAWN, sessionId: 'exited-session' }) - await router.spawn({ ...SPAWN, sessionId: 'fresh-id', isNewSession: true }) - await router.spawn(SPAWN) - - expect(current.spawn).toHaveBeenCalledTimes(3) - expect(legacy.spawn).not.toHaveBeenCalled() - expect(legacy.probePtyLiveness).toHaveBeenCalledOnce() - }) - it('refuses while the older daemon socket answers even if its pid is gone', async () => { const current = createAdapter('current') const legacy = createAdapter('legacy', ['claude-session']) diff --git a/src/main/git/branch-rename.test.ts b/src/main/git/branch-rename.test.ts index fa74878f019..f01150e5710 100644 --- a/src/main/git/branch-rename.test.ts +++ b/src/main/git/branch-rename.test.ts @@ -1,10 +1,5 @@ import { describe, expect, it, vi } from 'vitest' -import { - probeBranchUpstream, - renameCurrentBranch, - resolveUniqueBranchName, - type GitExec -} from './branch-rename' +import { probeBranchUpstream, resolveUniqueBranchName, type GitExec } from './branch-rename' const noUpstreamError = new Error( "fatal: no upstream configured for branch 'feature'\n" + @@ -13,35 +8,6 @@ const noUpstreamError = new Error( ) describe('probeBranchUpstream', () => { - it('reports has-upstream when @{u} resolves to a tracking ref', async () => { - const exec: GitExec = vi.fn(async (args: string[]) => { - if (args[0] === 'symbolic-ref') { - return { stdout: 'refs/heads/feature\n', stderr: '' } - } - if (args[0] === 'rev-parse' && args.includes('HEAD@{u}')) { - return { stdout: 'origin/feature\n', stderr: '' } - } - throw new Error(`unexpected git args: ${args.join(' ')}`) - }) - expect(await probeBranchUpstream(exec)).toEqual({ outcome: 'has-upstream' }) - }) - - it('reports no-upstream when there is no upstream', async () => { - const exec: GitExec = vi.fn(async (args: string[]) => { - if (args[0] === 'symbolic-ref') { - return { stdout: 'refs/heads/feature\n', stderr: '' } - } - if (args[0] === 'rev-parse' && args.includes('HEAD@{u}')) { - throw noUpstreamError - } - if (args[0] === 'rev-parse' && args.includes('refs/remotes/origin/feature')) { - throw new Error('not found') - } - throw new Error(`unexpected git args: ${args.join(' ')}`) - }) - expect(await probeBranchUpstream(exec)).toEqual({ outcome: 'no-upstream' }) - }) - it('reports has-upstream when a same-name origin tracking ref exists without configured upstream', async () => { const exec: GitExec = vi.fn(async (args: string[]) => { if (args[0] === 'symbolic-ref') { @@ -58,14 +24,6 @@ describe('probeBranchUpstream', () => { expect(await probeBranchUpstream(exec)).toEqual({ outcome: 'has-upstream' }) }) - it('reports probe-failed on an unexpected failure', async () => { - const exec: GitExec = vi.fn().mockRejectedValue(new Error('fatal: not a git repository')) - expect(await probeBranchUpstream(exec)).toEqual({ - outcome: 'probe-failed', - message: 'fatal: not a git repository' - }) - }) - it('scrubs credential-bearing URLs from the probe-failed message', async () => { const exec: GitExec = vi .fn() @@ -97,12 +55,6 @@ describe('probeBranchUpstream', () => { describe('resolveUniqueBranchName', () => { const compute = (leaf: string): string => `you/${leaf}` - it('returns the first candidate when no branch collides', async () => { - const exec: GitExec = vi.fn().mockRejectedValue(new Error('not found')) - const result = await resolveUniqueBranchName(exec, 'fix-auth', compute, 'you/Nautilus') - expect(result).toBe('you/fix-auth') - }) - it('suffixes when the first candidate already exists', async () => { const exec: GitExec = vi.fn(async (args: string[]) => { const ref = args.at(-1) @@ -121,11 +73,3 @@ describe('resolveUniqueBranchName', () => { expect(result).toBe('you/octopus') }) }) - -describe('renameCurrentBranch', () => { - it('runs git branch -m with the new name', async () => { - const exec: GitExec = vi.fn().mockResolvedValue({ stdout: '', stderr: '' }) - await renameCurrentBranch(exec, 'you/fix-auth') - expect(exec).toHaveBeenCalledWith(['branch', '-m', 'you/fix-auth']) - }) -}) diff --git a/src/main/git/worktree-git-capabilities.test.ts b/src/main/git/worktree-git-capabilities.test.ts index 36a7c059315..d59174702f0 100644 --- a/src/main/git/worktree-git-capabilities.test.ts +++ b/src/main/git/worktree-git-capabilities.test.ts @@ -79,36 +79,6 @@ describe('worktree Git capabilities', () => { ]) }) - it('does not repeat a known-unsupported rev-parse --path-format probe', async () => { - gitExecFileAsyncMock.mockImplementation((args: string[]) => { - if (args[0] === 'worktree') { - return Promise.resolve({ - stdout: 'worktree /git-store/project.git\nHEAD abc123\nbranch refs/heads/main\n' - }) - } - if (args.includes('--path-format=absolute')) { - return Promise.reject( - Object.assign(new Error('unknown option: --path-format=absolute'), { - stderr: 'error: unknown option `path-format=absolute`\n' - }) - ) - } - return Promise.resolve({ stdout: '/repo\n/git-store/project.git\n/git-store/project.git\n' }) - }) - - await listWorktrees('/repo') - await listWorktrees('/repo') - - const revParseCalls = gitExecFileAsyncMock.mock.calls.filter( - ([args]) => (args as string[])[0] === 'rev-parse' - ) - expect(revParseCalls.map(([args]) => args)).toEqual([ - ['rev-parse', '--path-format=absolute', '--show-toplevel', '--git-common-dir', '--git-dir'], - ['rev-parse', '--show-toplevel', '--git-common-dir', '--git-dir'], - ['rev-parse', '--show-toplevel', '--git-common-dir', '--git-dir'] - ]) - }) - it('remembers old Git that echoes --path-format while exiting successfully', async () => { gitExecFileAsyncMock.mockImplementation((args: string[]) => { if (args[0] === 'worktree') { diff --git a/src/main/gitea/repository-ref.test.ts b/src/main/gitea/repository-ref.test.ts deleted file mode 100644 index 031e9417eae..00000000000 --- a/src/main/gitea/repository-ref.test.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' - -const { gitExecFileAsyncMock } = vi.hoisted(() => ({ - gitExecFileAsyncMock: vi.fn() -})) - -vi.mock('../git/runner', () => ({ - gitExecFileAsync: gitExecFileAsyncMock -})) - -import { - _getGiteaRepoRefCacheSize, - _resetGiteaRepoRefCache, - getGiteaRepoRef, - parseGiteaRepoRef -} from './repository-ref' -import { REMOTE_URL_PROBE_TIMEOUT_MS } from '../git/remote-url-probe' - -describe('Gitea repository ref parsing', () => { - beforeEach(() => { - gitExecFileAsyncMock.mockReset() - _resetGiteaRepoRefCache() - }) - - afterEach(() => {}) - - it('parses HTTPS remotes and derives the API base URL', () => { - expect(parseGiteaRepoRef('https://git.example.com/team/project.git')).toEqual({ - host: 'git.example.com', - owner: 'team', - repo: 'project', - apiBaseUrl: 'https://git.example.com/api/v1', - webBaseUrl: 'https://git.example.com' - }) - }) - - it('strips trailing slashes after .git suffixes', () => { - expect(parseGiteaRepoRef('https://git.example.com/team/project.git/')).toEqual({ - host: 'git.example.com', - owner: 'team', - repo: 'project', - apiBaseUrl: 'https://git.example.com/api/v1', - webBaseUrl: 'https://git.example.com' - }) - expect(parseGiteaRepoRef('git@gitea.example.test:team/project.git/')).toMatchObject({ - host: 'gitea.example.test', - owner: 'team', - repo: 'project' - }) - }) - - it('preserves an HTTP subpath when deriving the API base URL', () => { - expect(parseGiteaRepoRef('https://git.example.com/code/team/project.git')).toEqual({ - host: 'git.example.com', - owner: 'team', - repo: 'project', - apiBaseUrl: 'https://git.example.com/code/api/v1', - webBaseUrl: 'https://git.example.com/code' - }) - }) - - it('parses scp-like SSH remotes with an HTTPS web/API base', () => { - expect(parseGiteaRepoRef('git@gitea.example.test:team/project.git')).toEqual({ - host: 'gitea.example.test', - owner: 'team', - repo: 'project', - apiBaseUrl: 'https://gitea.example.test/api/v1', - webBaseUrl: 'https://gitea.example.test' - }) - }) - - it('preserves a scp-like SSH subpath when deriving the API base URL', () => { - expect(parseGiteaRepoRef('git@gitea.example.test:code/team/project.git')).toEqual({ - host: 'gitea.example.test', - owner: 'team', - repo: 'project', - apiBaseUrl: 'https://gitea.example.test/code/api/v1', - webBaseUrl: 'https://gitea.example.test/code' - }) - }) - - it('parses ssh:// remotes without carrying the SSH port into web/API URLs', () => { - expect(parseGiteaRepoRef('ssh://git@gitea.example.test:2222/team/project.git')).toEqual({ - host: 'gitea.example.test', - owner: 'team', - repo: 'project', - apiBaseUrl: 'https://gitea.example.test/api/v1', - webBaseUrl: 'https://gitea.example.test' - }) - }) - - it('does not claim public hosts handled by more specific providers', () => { - expect(parseGiteaRepoRef('git@github.com:team/project.git')).toBeNull() - expect(parseGiteaRepoRef('https://gitlab.com/team/project.git')).toBeNull() - expect(parseGiteaRepoRef('https://bitbucket.org/team/project.git')).toBeNull() - expect(parseGiteaRepoRef('git@ssh.bitbucket.org:team/project.git')).toBeNull() - expect(parseGiteaRepoRef('https://dev.azure.com/team/project/_git/repo')).toBeNull() - expect(parseGiteaRepoRef('https://team.visualstudio.com/project/_git/repo')).toBeNull() - }) - - it('reads and caches the origin remote', async () => { - gitExecFileAsyncMock.mockResolvedValueOnce({ - stdout: 'https://git.example.com/team/project.git\n', - stderr: '' - }) - - await expect(getGiteaRepoRef('/repo')).resolves.toMatchObject({ - host: 'git.example.com', - owner: 'team', - repo: 'project' - }) - await expect(getGiteaRepoRef('/repo')).resolves.toMatchObject({ - host: 'git.example.com', - owner: 'team', - repo: 'project' - }) - expect(gitExecFileAsyncMock).toHaveBeenCalledTimes(1) - expect(gitExecFileAsyncMock).toHaveBeenCalledWith(['remote', 'get-url', 'origin'], { - cwd: '/repo', - timeout: REMOTE_URL_PROBE_TIMEOUT_MS - }) - }) - - it('bounds cached repository refs for distinct repo paths', async () => { - gitExecFileAsyncMock.mockResolvedValue({ - stdout: 'https://git.example.com/team/project.git\n', - stderr: '' - }) - - for (let i = 0; i < 513; i += 1) { - await getGiteaRepoRef(`/repo-${i}`) - } - - expect(_getGiteaRepoRefCacheSize()).toBe(512) - }) -}) diff --git a/src/main/github/account-binding-required-host.test.ts b/src/main/github/account-binding-required-host.test.ts deleted file mode 100644 index 5d0470317d6..00000000000 --- a/src/main/github/account-binding-required-host.test.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { describe, expect, it, vi } from 'vitest' -import { normalizeGitRemoteUrl } from '../../shared/git-remote-identity' -import { resolveGhAccountRequiredHost } from './account-binding-required-host' - -function repoFor(remoteUrl: string) { - return { - path: '/repos/sample-app', - gitRemoteIdentity: { - remoteName: 'origin', - remoteUrl, - canonicalKey: normalizeGitRemoteUrl(remoteUrl) ?? '' - } - } -} - -describe('resolveGhAccountRequiredHost', () => { - it('keeps a github.com remote filtered to github.com', async () => { - const resolveAlias = vi.fn() - await expect( - resolveGhAccountRequiredHost( - repoFor('git@github.com:example/sample-app.git'), - {}, - resolveAlias - ) - ).resolves.toBe('github.com') - expect(resolveAlias).not.toHaveBeenCalled() - }) - - it('keeps a real enterprise host without resolving an alias', async () => { - const resolveAlias = vi.fn() - await expect( - resolveGhAccountRequiredHost( - repoFor('git@ghe.example.com:example/sample-app.git'), - {}, - resolveAlias - ) - ).resolves.toBe('ghe.example.com') - expect(resolveAlias).not.toHaveBeenCalled() - }) - - it('filters an alias that resolves to github.com the same as a direct github.com remote', async () => { - const resolveAlias = vi.fn(async () => ({ hostname: 'github.com' })) - await expect( - resolveGhAccountRequiredHost( - repoFor('git@github-personal:example/sample-app.git'), - {}, - resolveAlias - ) - ).resolves.toBe('github.com') - expect(resolveAlias).toHaveBeenCalledWith('github-personal', { - repoPath: '/repos/sample-app', - connectionId: null - }) - }) - - it('folds ssh.github.com and www.github.com to github.com', async () => { - for (const hostname of ['ssh.github.com', 'www.github.com']) { - await expect( - resolveGhAccountRequiredHost( - repoFor('git@github-work:example/sample-app.git'), - {}, - async () => ({ hostname }) - ) - ).resolves.toBe('github.com') - } - }) - - it('keeps the exact resolved enterprise hostname, including a www prefix', async () => { - await expect( - resolveGhAccountRequiredHost( - repoFor('git@github-work:example/sample-app.git'), - {}, - async () => ({ hostname: 'GHE.Example.com' }) - ) - ).resolves.toBe('ghe.example.com') - await expect( - resolveGhAccountRequiredHost( - repoFor('git@github-work:example/sample-app.git'), - {}, - async () => ({ hostname: 'www.ghe.example.com' }) - ) - ).resolves.toBe('www.ghe.example.com') - }) - - it('resolves the alias in the WSL distro that runs gh', async () => { - const resolveAlias = vi.fn(async () => ({ hostname: 'github.com' })) - await resolveGhAccountRequiredHost( - repoFor('git@github-personal:example/sample-app.git'), - { wslDistro: 'Ubuntu' }, - resolveAlias - ) - expect(resolveAlias).toHaveBeenCalledWith('github-personal', { - repoPath: '/repos/sample-app', - connectionId: null, - wslDistro: 'Ubuntu' - }) - }) - - it('resolves the alias with its original case', async () => { - const resolveAlias = vi.fn(async () => ({ hostname: 'github.com' })) - await resolveGhAccountRequiredHost( - repoFor('git@GitHub-Work:example/sample-app.git'), - {}, - resolveAlias - ) - expect(resolveAlias).toHaveBeenCalledWith('GitHub-Work', expect.anything()) - }) - - it('keeps a dotless HTTPS host literal without consulting ssh config', async () => { - const resolveAlias = vi.fn(async () => ({ hostname: 'elsewhere.example.com' })) - await expect( - resolveGhAccountRequiredHost(repoFor('https://ghe/example/sample-app.git'), {}, resolveAlias) - ).resolves.toBe('ghe') - expect(resolveAlias).not.toHaveBeenCalled() - }) - - it('does not filter when the alias cannot be resolved', async () => { - for (const resolveAlias of [ - async () => ({ hostname: null }), - async () => ({ hostname: 'github-personal' }), - async () => { - throw new Error('ssh -G failed') - } - ]) { - await expect( - resolveGhAccountRequiredHost( - repoFor('git@github-personal:example/sample-app.git'), - {}, - resolveAlias - ) - ).resolves.toBeUndefined() - } - }) -}) diff --git a/src/main/github/review-head-remote.test.ts b/src/main/github/review-head-remote.test.ts deleted file mode 100644 index e2853ada0d7..00000000000 --- a/src/main/github/review-head-remote.test.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { beforeEach, describe, expect, it, vi } from 'vitest' - -const { getDefaultRemoteMock, getGitHubApiRepositoryForRemoteMock } = vi.hoisted(() => ({ - getDefaultRemoteMock: vi.fn(), - getGitHubApiRepositoryForRemoteMock: vi.fn() -})) - -vi.mock('../git/repo', () => ({ getDefaultRemote: getDefaultRemoteMock })) -vi.mock('./github-api-repository', () => ({ - getGitHubApiRepositoryForRemote: getGitHubApiRepositoryForRemoteMock -})) - -import { resolveGitHubReviewHeadRemote } from './review-head-remote' - -function gitExecWithRemotes(remotes: string[]) { - return vi.fn(async (args: string[]) => { - if (args[0] === 'remote') { - return { stdout: `${remotes.join('\n')}\n`, stderr: '' } - } - throw new Error(`unexpected git call: ${args.join(' ')}`) - }) -} - -describe('resolveGitHubReviewHeadRemote', () => { - beforeEach(() => { - getDefaultRemoteMock.mockReset() - getGitHubApiRepositoryForRemoteMock.mockReset() - }) - - it('prefers upstream on a contributor clone whose origin is a fork', async () => { - // Upstream PR head refs are unavailable on the fork's origin. - getGitHubApiRepositoryForRemoteMock.mockImplementation(async (_path, remote) => - remote === 'upstream' - ? { owner: 'org', repo: 'project' } - : { owner: 'contributor', repo: 'project' } - ) - - const remote = await resolveGitHubReviewHeadRemote({ - repoPath: '/repo', - issueSourcePreference: 'auto', - gitExec: gitExecWithRemotes(['origin', 'upstream']) - }) - - expect(remote).toBe('upstream') - expect(getDefaultRemoteMock).not.toHaveBeenCalled() - }) - - it('falls back to origin when upstream is not a GitHub project', async () => { - getGitHubApiRepositoryForRemoteMock.mockImplementation(async (_path, remote) => - remote === 'origin' ? { owner: 'org', repo: 'project' } : null - ) - - const remote = await resolveGitHubReviewHeadRemote({ - repoPath: '/repo', - issueSourcePreference: 'upstream', - gitExec: gitExecWithRemotes(['origin', 'upstream']) - }) - - expect(remote).toBe('origin') - }) - - it('uses explicit origin without probing hosting identity on a dual-remote clone', async () => { - getGitHubApiRepositoryForRemoteMock.mockResolvedValue({ owner: 'org', repo: 'project' }) - - const remote = await resolveGitHubReviewHeadRemote({ - repoPath: '/repo', - issueSourcePreference: 'origin', - gitExec: gitExecWithRemotes(['origin', 'upstream']) - }) - - expect(remote).toBe('origin') - expect(getGitHubApiRepositoryForRemoteMock).not.toHaveBeenCalled() - expect(getDefaultRemoteMock).not.toHaveBeenCalled() - }) - - it('rejects explicit origin when that remote is not configured', async () => { - await expect( - resolveGitHubReviewHeadRemote({ - repoPath: '/repo', - issueSourcePreference: 'origin', - gitExec: gitExecWithRemotes(['upstream']) - }) - ).rejects.toThrow('Repo has no configured origin remote.') - - expect(getGitHubApiRepositoryForRemoteMock).not.toHaveBeenCalled() - expect(getDefaultRemoteMock).not.toHaveBeenCalled() - }) - - it('skips identity probes for a single-remote clone and uses the local default', async () => { - getDefaultRemoteMock.mockResolvedValue('origin') - - const remote = await resolveGitHubReviewHeadRemote({ - repoPath: '/repo', - localGitOptions: { wslDistro: 'Ubuntu' }, - gitExec: gitExecWithRemotes(['origin']) - }) - - expect(remote).toBe('origin') - expect(getGitHubApiRepositoryForRemoteMock).not.toHaveBeenCalled() - expect(getDefaultRemoteMock).toHaveBeenCalledWith('/repo', { wslDistro: 'Ubuntu' }, ['origin']) - }) - - it('prefers origin over other remotes on SSH repos when no identity resolves', async () => { - getGitHubApiRepositoryForRemoteMock.mockResolvedValue(null) - - const remote = await resolveGitHubReviewHeadRemote({ - repoPath: '/remote/repo', - connectionId: 'ssh-1', - gitExec: gitExecWithRemotes(['fork', 'origin']) - }) - - expect(remote).toBe('origin') - expect(getDefaultRemoteMock).not.toHaveBeenCalled() - }) - - it('threads connection and WSL options through the identity probe', async () => { - getGitHubApiRepositoryForRemoteMock.mockResolvedValue({ owner: 'org', repo: 'project' }) - - await resolveGitHubReviewHeadRemote({ - repoPath: '/repo', - connectionId: 'ssh-1', - localGitOptions: { - wslDistro: 'Ubuntu', - ghAccount: { host: 'github.acme.com', user: 'alice' } - }, - gitExec: gitExecWithRemotes(['origin', 'upstream']) - }) - - expect(getGitHubApiRepositoryForRemoteMock).toHaveBeenCalledWith('/repo', 'upstream', 'ssh-1', { - wslDistro: 'Ubuntu', - ghAccount: { host: 'github.acme.com', user: 'alice' } - }) - }) -}) diff --git a/src/main/ipc/pty/delivery/pty-producer-flow-control.test.ts b/src/main/ipc/pty/delivery/pty-producer-flow-control.test.ts index dd469f00db9..b551cf0bfc9 100644 --- a/src/main/ipc/pty/delivery/pty-producer-flow-control.test.ts +++ b/src/main/ipc/pty/delivery/pty-producer-flow-control.test.ts @@ -28,33 +28,6 @@ describe('PtyProducerFlowController', () => { vi.useRealTimers() }) - it('does not pause at or below the high watermark', () => { - controller.update('pty-1', 0) - controller.update('pty-1', LOW) - controller.update('pty-1', HIGH) - expect(pauseProducer).not.toHaveBeenCalled() - expect(controller.isPaused('pty-1')).toBe(false) - }) - - it('pauses exactly once when pending crosses the high watermark, not per chunk', () => { - controller.update('pty-1', HIGH + 1) - controller.update('pty-1', HIGH + 64 * 1024) - controller.update('pty-1', HIGH + 128 * 1024) - expect(pauseProducer).toHaveBeenCalledTimes(1) - expect(pauseProducer).toHaveBeenCalledWith('pty-1') - expect(controller.isPaused('pty-1')).toBe(true) - }) - - it('resumes exactly once when pending drains below the low watermark', () => { - controller.update('pty-1', HIGH + 1) - controller.update('pty-1', LOW - 1) - expect(resumeProducer).toHaveBeenCalledTimes(1) - expect(resumeProducer).toHaveBeenCalledWith('pty-1') - expect(controller.isPaused('pty-1')).toBe(false) - controller.update('pty-1', 0) - expect(resumeProducer).toHaveBeenCalledTimes(1) - }) - it('holds hysteresis: no flapping while pending sits between the watermarks', () => { controller.update('pty-1', HIGH + 1) expect(pauseProducer).toHaveBeenCalledTimes(1) @@ -86,15 +59,6 @@ describe('PtyProducerFlowController', () => { expect(pauseProducer).toHaveBeenCalledTimes(2) }) - it('release resumes only ptys that are actually paused', () => { - controller.update('paused-pty', HIGH + 1) - controller.release('paused-pty') - controller.release('never-paused-pty') - expect(resumeProducer).toHaveBeenCalledTimes(1) - expect(resumeProducer).toHaveBeenCalledWith('paused-pty') - expect(controller.isPaused('paused-pty')).toBe(false) - }) - it('releaseAll resumes every paused pty', () => { controller.update('pty-1', HIGH + 1) controller.update('pty-2', HIGH + 1) diff --git a/src/main/ipc/pty/ipc/spawn-reattach-size-cache.test.ts b/src/main/ipc/pty/ipc/spawn-reattach-size-cache.test.ts index 21edc76dad8..741db3721c4 100644 --- a/src/main/ipc/pty/ipc/spawn-reattach-size-cache.test.ts +++ b/src/main/ipc/pty/ipc/spawn-reattach-size-cache.test.ts @@ -82,14 +82,6 @@ describe('spawn size cache on reattach', () => { ) }) - it('records the requested grid for a genuinely fresh spawn', async () => { - const { runtime, preAttachSize } = await runSpawn({ cols: 120, rows: 40 }, { id: SESSION_ID }) - - expect(preAttachSize).toEqual({ cols: 120, rows: 40 }) - expect(ptySizes.get(SESSION_ID)).toEqual({ cols: 120, rows: 40 }) - expect(runtime.reflowHeadlessTerminalToPtyGrid).toHaveBeenCalledWith(SESSION_ID, 120, 40) - }) - // Unmeasured attach skips pre-seeding; if the daemon recreates it, commit must size the model. it('reflows a hidden attach the daemon answered with a fresh session onto the request', async () => { const { runtime, preAttachSize } = await runSpawn( diff --git a/src/main/ipc/rebinding-file-watch-noise.test.ts b/src/main/ipc/rebinding-file-watch-noise.test.ts index 7e278ceb720..f32ed1110f0 100644 --- a/src/main/ipc/rebinding-file-watch-noise.test.ts +++ b/src/main/ipc/rebinding-file-watch-noise.test.ts @@ -61,35 +61,6 @@ async function settle(): Promise { await new Promise((resolve) => setTimeout(resolve, 250)) } -describe('watchFileAcrossReplacement event filtering', () => { - it('drops attribute-only events such as macOS mmap reads of git metadata', async () => { - const path = join(directory, 'packed-refs') - writeFileSync(path, 'refs') - const onChange = vi.fn() - fileWatch = watchFileAcrossReplacement(path, onChange, (error) => { - throw error - }) - await settle() - - const watchesBeforeNoise = nativeEvents.length - for (let read = 0; read < 50; read++) { - nativeEvents.at(-1)?.() - } - // The rebind is the coalesced refresh having stat'ed the file, so the absence below is read after it. - await vi.waitFor(() => expect(nativeEvents.length).toBeGreaterThan(watchesBeforeNoise)) - expect(onChange).not.toHaveBeenCalled() - - writeFileSync(path, 'refs and more') - for (let read = 0; read < 50; read++) { - nativeEvents.at(-1)?.() - } - // Noise backed the coalesce window off, so the write lands on its own schedule rather than a clock's. - await vi.waitFor(() => expect(onChange).toHaveBeenCalled(), { timeout: 5_000 }) - await settle() - expect(onChange).toHaveBeenCalledOnce() - }) -}) - describe('watchFileAcrossReplacement after a watcher error', () => { it('closes promptly and rebinds once the runtime has closed the errored watcher', async () => { const path = join(directory, 'index') diff --git a/src/main/issue-command-wsl-stopped-distro.test.ts b/src/main/issue-command-wsl-stopped-distro.test.ts index 5a964600db8..2b6e1c08bde 100644 --- a/src/main/issue-command-wsl-stopped-distro.test.ts +++ b/src/main/issue-command-wsl-stopped-distro.test.ts @@ -67,21 +67,6 @@ describe('issue command reads for a stopped WSL distro (E9)', () => { expect(mocks.loadHooks).not.toHaveBeenCalled() }) - it('reads for a launch, a user act that may start the distro', async () => { - const result = await readIssueCommandUnlessWslStopped(WSL_REPO, { wakeWslDistro: true }) - expect(result).not.toHaveProperty('status') - expect(mocks.existsSync).toHaveBeenCalled() - expect(mocks.loadHooks).toHaveBeenCalledWith(WSL_REPO) - }) - - it('reads host repos and running distros as before', async () => { - await readIssueCommandUnlessWslStopped(HOST_REPO) - expect(mocks.loadHooks).toHaveBeenCalledWith(HOST_REPO) - mocks.readWslDistroRunningState.mockResolvedValue('running') - await readIssueCommandUnlessWslStopped(WSL_REPO) - expect(mocks.loadHooks).toHaveBeenCalledWith(WSL_REPO) - }) - it("gates the runtime read a paired client's Settings pane makes, and passes a launch's wake", async () => { const reader = new RuntimeRepositoryIssueCommand({ resolveRepo: async () => ({ diff --git a/src/main/kimi/kimi-runtime-home.test.ts b/src/main/kimi/kimi-runtime-home.test.ts index 3dd5c51f482..7cad982351b 100644 --- a/src/main/kimi/kimi-runtime-home.test.ts +++ b/src/main/kimi/kimi-runtime-home.test.ts @@ -9,44 +9,7 @@ const wslMocks = vi.hoisted(() => ({ vi.mock('../wsl', () => wslMocks) vi.mock('node:os', () => ({ homedir: () => 'C:\\Users\\neil' })) -import { getHostKimiHome, getKimiRuntimeTarget, resolveKimiHome } from './kimi-runtime-home' -import type { GlobalSettings } from '../../shared/global-settings-types' - -function settings(overrides: Partial): GlobalSettings { - return overrides as GlobalSettings -} - -describe('getKimiRuntimeTarget', () => { - it('follows the configured WSL runtime on Windows', () => { - expect( - getKimiRuntimeTarget( - settings({ localAccountRuntime: 'wsl', localAccountWslDistro: ' Ubuntu ' }), - 'win32' - ) - ).toEqual({ runtime: 'wsl', wslDistro: 'Ubuntu' }) - }) - - it('pins to host off Windows even when the setting says wsl', () => { - expect( - getKimiRuntimeTarget( - settings({ localAccountRuntime: 'wsl', localAccountWslDistro: 'Ubuntu' }), - 'darwin' - ) - ).toEqual({ runtime: 'host', wslDistro: null }) - }) - - it('follows the Windows runtime default when the policy is auto', () => { - expect( - getKimiRuntimeTarget( - settings({ - localAccountRuntime: 'auto', - localWindowsRuntimeDefault: { kind: 'wsl', distro: 'Debian' } - }), - 'win32' - ) - ).toEqual({ runtime: 'wsl', wslDistro: 'Debian' }) - }) -}) +import { getHostKimiHome, resolveKimiHome } from './kimi-runtime-home' describe('resolveKimiHome', () => { const originalKimiCodeHome = process.env.KIMI_CODE_HOME @@ -66,23 +29,6 @@ describe('resolveKimiHome', () => { } }) - it('resolves the host home for a host target', async () => { - expect(await resolveKimiHome({ runtime: 'host', wslDistro: null }, 'win32')).toEqual({ - runtime: 'host', - wslDistro: null, - path: getHostKimiHome() - }) - expect(wslMocks.getWslHomeAsync).not.toHaveBeenCalled() - }) - - it('resolves the WSL distro home for a WSL target', async () => { - expect(await resolveKimiHome({ runtime: 'wsl', wslDistro: 'Ubuntu' }, 'win32')).toEqual({ - runtime: 'wsl', - wslDistro: 'Ubuntu', - path: '\\\\wsl.localhost\\Ubuntu\\home\\neil\\.kimi-code' - }) - }) - it('ignores the host KIMI_CODE_HOME when reading a WSL home', async () => { process.env.KIMI_CODE_HOME = 'D:\\kimi-home' expect((await resolveKimiHome({ runtime: 'wsl', wslDistro: 'Ubuntu' }, 'win32')).path).toBe( @@ -90,13 +36,6 @@ describe('resolveKimiHome', () => { ) }) - it('falls back to the default distro when none is configured', async () => { - expect(await resolveKimiHome({ runtime: 'wsl', wslDistro: null }, 'win32')).toMatchObject({ - wslDistro: 'Ubuntu' - }) - expect(wslMocks.getWslHomeAsync).toHaveBeenCalledWith('Ubuntu') - }) - it('reports no path without probing the home while the distro is stopped', async () => { wslMocks.listRunningWslDistrosAsync.mockResolvedValue([]) expect(await resolveKimiHome({ runtime: 'wsl', wslDistro: 'Ubuntu' }, 'win32')).toEqual({ @@ -107,24 +46,6 @@ describe('resolveKimiHome', () => { expect(wslMocks.getWslHomeAsync).not.toHaveBeenCalled() }) - it('reports no path when the distro home cannot be probed', async () => { - wslMocks.getWslHomeAsync.mockResolvedValue(null) - expect(await resolveKimiHome({ runtime: 'wsl', wslDistro: 'Ubuntu' }, 'win32')).toEqual({ - runtime: 'wsl', - wslDistro: 'Ubuntu', - path: null - }) - }) - - it('reports no path when no distro exists at all', async () => { - wslMocks.listWslDistrosAsync.mockResolvedValue([]) - expect(await resolveKimiHome({ runtime: 'wsl', wslDistro: null }, 'win32')).toEqual({ - runtime: 'wsl', - wslDistro: null, - path: null - }) - }) - it('never probes WSL off Windows', async () => { expect(await resolveKimiHome({ runtime: 'wsl', wslDistro: 'Ubuntu' }, 'darwin')).toEqual({ runtime: 'host', diff --git a/src/main/managed-server/lifecycle/orcad-managed-update-on-restore.test.ts b/src/main/managed-server/lifecycle/orcad-managed-update-on-restore.test.ts index 715eba14cf8..808028c57a1 100644 --- a/src/main/managed-server/lifecycle/orcad-managed-update-on-restore.test.ts +++ b/src/main/managed-server/lifecycle/orcad-managed-update-on-restore.test.ts @@ -1,4 +1,3 @@ -import type { ManagedServerUpdateDeps } from '../../ssh/managed-server-update-check' import { beforeEach, describe, expect, it, vi } from 'vitest' import type { SshTarget } from '../../../shared/ssh-types' import type { ManagedOrcadAutoUpdateOutcome } from './orcad-managed-auto-update' @@ -9,10 +8,6 @@ import { type ManagedOrcadRestoreUpdateDeps } from './orcad-managed-update-on-restore' -// Read the last locked retry decision rather than an earlier overlapping attempt. -const failedBeforeOf = (autoUpdate: ManagedServerUpdateDeps['autoUpdate']) => - vi.mocked(autoUpdate).mock.lastCall?.[1].failedBefore() - const target: SshTarget = { id: 'ssh-1', label: 'Box', host: 'box', port: 22, username: 'me' } function deps( @@ -39,16 +34,6 @@ function deps( describe('updating a managed server when the launch restores its tunnel', () => { beforeEach(() => resetManagedOrcadRestoreUpdatesForTests()) - it('runs the same update check a connect runs, and publishes it', async () => { - const d = deps({ outcome: 'updated', activeVersion: '0.1.0+b' }) - await updateManagedOrcadOnRestore('env-1', () => d) - expect(failedBeforeOf(d.autoUpdate)).toBe(false) - expect(vi.mocked(d.publish).mock.calls).toEqual([ - [target, 'env-1', 'updating'], - [target, 'env-1', 'settled', undefined] - ]) - }) - it('checks each server once per session, however often its tunnel is ensured', async () => { const d = deps({ outcome: 'skipped', reason: 'current' }) await updateManagedOrcadOnRestore('env-1', () => d) @@ -56,36 +41,6 @@ describe('updating a managed server when the launch restores its tunnel', () => expect(d.autoUpdate).toHaveBeenCalledTimes(1) }) - it('keeps the same safety: waits on terminals, never downgrades, records a failure', async () => { - const waiting = deps({ - outcome: 'deferred', - code: 'orcad_update_terminals_running', - reason: 'r' - }) - await updateManagedOrcadOnRestore('env-wait', () => waiting) - expect(waiting.publish).toHaveBeenLastCalledWith(target, 'env-wait', 'settled', { - state: 'deferred', - detail: 'r' - }) - - const newer = deps({ outcome: 'skipped', reason: 'host-newer' }) - await updateManagedOrcadOnRestore('env-newer', () => newer) - expect(newer.publish).toHaveBeenLastCalledWith(target, 'env-newer', 'settled', { - state: 'host-newer' - }) - - const failed = deps({ outcome: 'failed', reason: 'rolled back' }) - await updateManagedOrcadOnRestore('env-failed', () => failed) - expect(failed.recordUpdateFailure).toHaveBeenCalledWith(target, 'rolled back') - - const held = deps( - { outcome: 'skipped', reason: 'failed-before' }, - { recordedUpdateFailure: () => 'rolled back' } - ) - await updateManagedOrcadOnRestore('env-held', () => held) - expect(failedBeforeOf(held.autoUpdate)).toBe(true) - }) - it('never fails the restore that triggered it', async () => { const thrown = deps( { outcome: 'skipped', reason: 'current' }, diff --git a/src/main/native-chat/agent-session-journal/journal-outcome-sweeper.test.ts b/src/main/native-chat/agent-session-journal/journal-outcome-sweeper.test.ts index 0acb87d871c..8a2d7b8db03 100644 --- a/src/main/native-chat/agent-session-journal/journal-outcome-sweeper.test.ts +++ b/src/main/native-chat/agent-session-journal/journal-outcome-sweeper.test.ts @@ -112,20 +112,3 @@ it('retries a failed pass at the next periodic pass, and runs none after it stop await vi.advanceTimersByTimeAsync(12 * 60 * 60_000) expect(retiredRecords()).toBe(10) }) - -it('rests nine times as long as each page worked, holding the sweep to a 10% duty cycle', async () => { - retire(100) - // Every page takes 30 ms on the sweeper's clock. - let clock = 0 - const rests = vi.fn(async (_ms: number) => {}) - const sweeper = new JournalOutcomeSweeper({ - database: () => database, - now: () => (clock += 30), - delay: rests - }) - sweepers.push(sweeper) - await sweeper.pass() - expect(retiredRecords()).toBe(0) - // Four record pages, each followed by its rest; the last page finds nothing more to do. - expect(rests.mock.calls).toEqual([[270], [270], [270], [270]]) -}) diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-command-publication.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-command-publication.test.ts index c6fda61af08..6899d1769fa 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-command-publication.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-command-publication.test.ts @@ -1,7 +1,8 @@ import { mkdtemp, rm } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' -import { expect, it, vi } from 'vitest' +import { expect, it } from 'vitest' + import type { AgentSessionBackgroundTaskState, AgentSessionSlashCommand, @@ -14,42 +15,7 @@ import { } from '../../../shared/structured-agent-session-reducer' import { createTrackedJournalOpener } from '../agent-session-journal/journal-host-database-test-support' import { AgentSessionSubscribers } from './structured-agent-session-subscribers' -import { - adapterFor, - fakeClaude, - identityFor, - PROVIDER_SESSION_ID -} from '../../claude/claude-structured-session-test-support' - -it('publishes idle provider reloads only when the actual command catalog changes', async () => { - const claude = fakeClaude() - const adapter = adapterFor(claude) - const publish = vi.fn() - await adapter.acquire({ - identity: identityFor(), - fence: 7, - spawnToken: 'commands', - events: { - appendItem: vi.fn(), - appendTombstone: vi.fn(), - publish - } - }) - publish.mockClear() - const message = { - type: 'system', - subtype: 'commands_changed', - session_id: PROVIDER_SESSION_ID, - commands: [{ name: 'new-skill', description: '', argumentHint: '' }] - } - claude.connections[0].handlers.onMessage?.(message) - expect(adapter.readCommands(identityFor().sessionId)).toEqual([ - { name: 'new-skill', kind: 'command', kindUnspecified: true } - ]) - expect(publish).toHaveBeenCalledTimes(1) - claude.connections[0].handlers.onMessage?.(message) - expect(publish).toHaveBeenCalledTimes(1) -}) +import { identityFor } from '../../claude/claude-structured-session-test-support' it('delivers catalog changes through existing frames without resending them on ordinary output', async () => { const root = await mkdtemp(join(tmpdir(), 'orca-command-publication-')) diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-host-teardown.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-host-teardown.test.ts index 74d44ef07d5..a34438dc20d 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-host-teardown.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-host-teardown.test.ts @@ -1,98 +1,10 @@ import { describe, expect, it, vi } from 'vitest' -import { WILL_QUIT_TEARDOWN_DEADLINE_MS } from '../../../shared/quit-teardown-deadline' -import { - GRACEFUL_EXIT_MS as CLAUDE_WINDOWS_GRACEFUL_EXIT_MS, - SUPERVISED_GRACEFUL_EXIT_MS -} from '../../claude/claude-child-exit-proof-ladder' -import { GRACEFUL_EXIT_MS as CODEX_WINDOWS_GRACEFUL_EXIT_MS } from '../../codex/codex-app-server-connection' -import { PROVIDER_SUPERVISOR_MAX_STOP_MS } from '../../provider-process/provider-process-supervisor' -import { SNAPSHOT_DRAIN_TIMEOUT_MS } from './structured-agent-session-eviction' -import { - CHILD_EVICTION_TIMEOUT_MS, - EVICTION_MARGIN_MS, - RESUME_MARKER_RECORD_TIMEOUT_MS, - structuredAgentSessionHostTeardownPhases -} from './structured-agent-session-host-teardown' -import { createStructuredAgentSessionLogger } from './structured-agent-session-logger' + +import { structuredAgentSessionHostTeardownPhases } from './structured-agent-session-host-teardown' + import { recordingStructuredAgentSessionLogger } from './structured-agent-session-logger-test-support' -const noop = async (): Promise => undefined - describe('structured agent-session host teardown', () => { - it('names every phase, so the quit-path order is pinned rather than incidental', () => { - const phases = structuredAgentSessionHostTeardownPhases({ - logger: createStructuredAgentSessionLogger(), - idleSweep: { dispose: noop }, - runtimeState: { - stopLeaseRenewal: () => undefined, - flushAllEventSinks: noop, - acquireAborts: { abortAll: () => {} } - }, - tasks: { drainAttaches: noop }, - evictOwnedSessions: noop, - beginResumeMarkers: () => {}, - recordResumeMarkers: noop - }) - expect(phases.map((phase) => phase.name)).toEqual([ - 'begin-resume-markers', - 'dispose-idle-sweep', - 'stop-lease-renewal', - 'abort-acquires', - 'drain-attaches', - 'evict-owned-sessions', - 'record-resume-markers', - 'flush-event-sinks' - ]) - }) - - it("derives quit's child-eviction bound from every provider's supervised close", () => { - // Bound drain/graceful close; supervisors finish tree cleanup after main exits, with leases recovered on launch. - const closes = { - claude: SUPERVISED_GRACEFUL_EXIT_MS, - codex: PROVIDER_SUPERVISOR_MAX_STOP_MS, - // Windows lacks supervisors and uses shorter close bounds. - claudeWindows: CLAUDE_WINDOWS_GRACEFUL_EXIT_MS, - codexWindows: CODEX_WINDOWS_GRACEFUL_EXIT_MS - } - for (const closeMs of Object.values(closes)) { - expect(SNAPSHOT_DRAIN_TIMEOUT_MS + closeMs + EVICTION_MARGIN_MS).toBeLessThanOrEqual( - CHILD_EVICTION_TIMEOUT_MS - ) - } - expect(CHILD_EVICTION_TIMEOUT_MS + RESUME_MARKER_RECORD_TIMEOUT_MS).toBeLessThan( - WILL_QUIT_TEARDOWN_DEADLINE_MS - ) - }) - - it('ends child eviction as soon as every chat has closed, not at its bound', async () => { - vi.useFakeTimers({ toFake: ['setTimeout', 'clearTimeout'] }) - const evict = structuredAgentSessionHostTeardownPhases({ - logger: createStructuredAgentSessionLogger(), - idleSweep: { dispose: noop }, - runtimeState: { - stopLeaseRenewal: () => undefined, - flushAllEventSinks: noop, - acquireAborts: { abortAll: () => {} } - }, - tasks: { drainAttaches: noop }, - evictOwnedSessions: noop, - beginResumeMarkers: () => {}, - recordResumeMarkers: noop - }).find((phase) => phase.name === 'evict-owned-sessions') - try { - let finished = false - const run = Promise.resolve(evict?.run()).then(() => { - finished = true - }) - await vi.advanceTimersByTimeAsync(0) - expect(finished).toBe(true) - await run - expect(vi.getTimerCount()).toBe(0) - } finally { - vi.useRealTimers() - } - }) - it('bounds stalled recovery publication without preventing later cleanup', async () => { vi.useFakeTimers({ toFake: ['setTimeout', 'clearTimeout'] }) const log = recordingStructuredAgentSessionLogger() diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-restart-continuation-wait.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-restart-continuation-wait.test.ts index bcecdf2156b..55d8d6cd49c 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-restart-continuation-wait.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-restart-continuation-wait.test.ts @@ -1,9 +1,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import type { AgentJournalSubmission } from '../../../shared/agent-session-journal-types' -import { - STRUCTURED_AGENT_SESSION_RESTART_CONTINUATION_CALLER, - structuredAgentSessionRestartResumeSurfaces -} from './structured-agent-session-restart-resume-wiring' +import { structuredAgentSessionRestartResumeSurfaces } from './structured-agent-session-restart-resume-wiring' + import { StructuredAgentSessionSendSettlement } from './structured-agent-session-send-settlement' const SESSION = 'session-1' @@ -109,30 +107,3 @@ describe('a restart batch holds a chat until its continuation is handed over', ( await expect(handedOver).resolves.toBeUndefined() }) }) - -// Host-origin continuations must not become personal kept cards on close/restart. -it('sends the continuation with no source, as Orca’s and no person’s', async () => { - const send = vi.fn(async () => { - throw new Error('refused') - }) - const surfaces = structuredAgentSessionRestartResumeSurfaces( - { - revealSession: async () => ({ readable: true }), - send, - waitForSendSettlement: async () => undefined - }, - () => 0 - ) - const envelope = { - sessionId: SESSION, - clientOperationId: MESSAGE, - expectedRuntimeFence: 2, - payloadFingerprint: 'fingerprint' - } - const body = { kind: 'message' as const, role: 'user' as const, blocks: [] } - await expect(surfaces.send({ envelope, body })).rejects.toThrow('refused') - expect(send.mock.calls[0]).toEqual([ - { callerKey: STRUCTURED_AGENT_SESSION_RESTART_CONTINUATION_CALLER }, - { envelope, body } - ]) -}) diff --git a/src/main/opencode/opencode-cli-version.test.ts b/src/main/opencode/opencode-cli-version.test.ts index f56a28172dd..272c32b922f 100644 --- a/src/main/opencode/opencode-cli-version.test.ts +++ b/src/main/opencode/opencode-cli-version.test.ts @@ -5,65 +5,6 @@ import { probeOpenCodeCliVersion } from './opencode-cli-version' vi.mock('@orca/process-host', () => ({ runProcess: vi.fn() })) beforeEach(() => vi.mocked(runProcess).mockReset()) -it('shares concurrent probes and isolates executable, host and environment identities', async () => { - vi.mocked(runProcess).mockResolvedValue({ - code: 0, - signal: null, - stdout: '1.1.23', - stderr: '', - timedOut: false - }) - const options = { - executablePath: '/test/opencode', - env: { PATH: '/runtime', XDG_CONFIG_HOME: '/one' }, - hostIdentity: 'native' - } - const results = await Promise.all([ - probeOpenCodeCliVersion(options), - probeOpenCodeCliVersion(options) - ]) - expect(results[0].pluginApi).toBe('v1') - expect(runProcess).toHaveBeenCalledTimes(1) - await probeOpenCodeCliVersion({ ...options, executablePath: '/other/opencode' }) - await probeOpenCodeCliVersion({ ...options, hostIdentity: 'wsl:ubuntu' }) - await probeOpenCodeCliVersion({ ...options, env: { ...options.env, XDG_CONFIG_HOME: '/two' } }) - expect(runProcess).toHaveBeenCalledTimes(4) - expect(runProcess).toHaveBeenCalledWith( - expect.objectContaining({ args: ['--version'], timeoutMs: 5_000, maxOutputBytes: 4_096 }) - ) -}) - -it('degrades timeouts and missing executables to unknown', async () => { - vi.mocked(runProcess).mockResolvedValueOnce({ - code: null, - signal: 'SIGTERM', - stdout: '2.0.16', - stderr: '', - timedOut: true - }) - expect( - (await probeOpenCodeCliVersion({ executablePath: '/timeout/opencode', env: {} })).pluginApi - ).toBe('unknown') - vi.mocked(runProcess).mockRejectedValueOnce(new Error('ENOENT')) - expect( - (await probeOpenCodeCliVersion({ executablePath: '/missing/opencode', env: {} })).version - ).toBeNull() -}) - -it('shares a bounded execution-host callback without probing the native machine', async () => { - const execute = vi - .fn() - .mockResolvedValue({ code: 0, timedOut: false, stdout: 'opencode v2.0.16' }) - const options = { executablePath: 'opencode', env: {}, hostIdentity: 'wsl:private', execute } - const results = await Promise.all([ - probeOpenCodeCliVersion(options), - probeOpenCodeCliVersion(options) - ]) - expect(results[0].promptMode).toBe('prefill') - expect(execute).toHaveBeenCalledTimes(1) - expect(runProcess).not.toHaveBeenCalled() -}) - it('shares probes across pane identities while preserving launch-affecting environment keys', async () => { vi.mocked(runProcess).mockResolvedValue({ code: 0, diff --git a/src/main/providers/local-pty-foreground-inspection-cheap-tier.test.ts b/src/main/providers/local-pty-foreground-inspection-cheap-tier.test.ts index 0d906dbd661..8c6f8fa25c6 100644 --- a/src/main/providers/local-pty-foreground-inspection-cheap-tier.test.ts +++ b/src/main/providers/local-pty-foreground-inspection-cheap-tier.test.ts @@ -90,17 +90,6 @@ describe('local POSIX provider cheap-tier revalidation', () => { } }) - it('a pane with NO recognized anchor never consults the cheap tier', async () => { - table = 'shell-only' - proc.process = 'zsh' - for (let i = 0; i < 3; i += 1) { - expect(await getLocalPtyForegroundProcess(ID)).toBe('zsh') - } - expect(cheapSnapshotMock).not.toHaveBeenCalled() - expect(resolveMock).toHaveBeenCalledTimes(3) - expect(ptyLastRecognizedForeground.get(ID)).toBeUndefined() - }) - it('once recognized, an unchanged pane re-proves the agent from the cheap tier without a full scan', async () => { expect(await getLocalPtyForegroundProcess(ID)).toBe('claude') expect(resolveMock).toHaveBeenCalledTimes(1) @@ -120,15 +109,6 @@ describe('local POSIX provider cheap-tier revalidation', () => { expect(ptyLastRecognizedForeground.get(ID)).toBeUndefined() }) - it('a changed node-pty foreground name escalates without consulting the cheap tier', async () => { - expect(await getLocalPtyForegroundProcess(ID)).toBe('claude') - proc.process = 'zsh' - table = 'shell-only' - expect(await getLocalPtyForegroundProcess(ID)).toBe('zsh') - expect(cheapSnapshotMock).not.toHaveBeenCalled() - expect(resolveMock).toHaveBeenCalledTimes(2) - }) - it('a cheap capture failure falls through to the full scan', async () => { expect(await getLocalPtyForegroundProcess(ID)).toBe('claude') cheapSnapshotMock.mockRejectedValueOnce(new Error('ps died')) diff --git a/src/main/providers/windows-foreground-process-inspection-cost.test.ts b/src/main/providers/windows-foreground-process-inspection-cost.test.ts index 021d8000dc9..3755b5f99bf 100644 --- a/src/main/providers/windows-foreground-process-inspection-cost.test.ts +++ b/src/main/providers/windows-foreground-process-inspection-cost.test.ts @@ -96,15 +96,6 @@ describe('windows foreground inspection cost per pane', () => { return resolved } - it('never sets the Memory flag on the snapshot', async () => { - await queryWindowsPaneProcessInventory(shellPid(0)) - expect(flagsSeen).toHaveLength(1) - // Memory flags add a second PROCESS_VM_READ OpenProcess per row; foreground inspection does not need it. - expect(flagsSeen[0]! & 1).toBe(0) - // CommandLine (2) | CreationTime (4). - expect(flagsSeen[0]).toBe(6) - }) - it('projects the shared snapshot once for the whole pane fan-out', async () => { const probeRows: unknown[] = [] for (let pane = 0; pane < PANE_COUNT; pane += 1) { @@ -129,9 +120,4 @@ describe('windows foreground inspection cost per pane', () => { // A warm shared index must avoid a whole-table Map rebuild per pane. expect(insertions).toBeLessThan(TABLE_SIZE) }) - - it('resolves the same foreground child for every pane as an unshared scan would', async () => { - const resolved = await sweepPanes() - expect(resolved).toEqual(Array.from({ length: PANE_COUNT }, (_, pane) => agentPid(pane))) - }) }) diff --git a/src/main/runtime/host-terminal-scrollback-read.test.ts b/src/main/runtime/host-terminal-scrollback-read.test.ts index 5cc7e3492c6..947116d31e1 100644 --- a/src/main/runtime/host-terminal-scrollback-read.test.ts +++ b/src/main/runtime/host-terminal-scrollback-read.test.ts @@ -68,16 +68,6 @@ function deps(overrides: Partial = {}) { } describe('readHostTerminalScrollback', () => { - it('returns the stored bytes for a ref a tab of the caller worktree names', async () => { - const { resolved } = deps() - await expect( - readHostTerminalScrollback(resolved, { - worktree: 'id:repo::/wt-a', - ref: HELD_REF - }) - ).resolves.toEqual({ buffer: 'stored history' }) - }) - it('refuses a ref named only by another worktree without touching the store', async () => { const { resolved, readSnapshot } = deps() await expect( @@ -89,37 +79,6 @@ describe('readHostTerminalScrollback', () => { expect(readSnapshot).not.toHaveBeenCalled() }) - it('refuses a worktree the host cannot resolve', async () => { - const { resolved, readSnapshot } = deps() - await expect( - readHostTerminalScrollback(resolved, { - worktree: 'path:/elsewhere', - ref: HELD_REF - }) - ).rejects.toThrow('selector_not_found') - expect(readSnapshot).not.toHaveBeenCalled() - }) - - it('answers not-found when the named snapshot file is missing', async () => { - const { resolved } = deps({ statSnapshotSize: async () => null }) - await expect( - readHostTerminalScrollback(resolved, { - worktree: 'id:repo::/wt-a', - ref: HELD_REF - }) - ).rejects.toThrow('terminal_scrollback_not_found') - }) - - it('answers not-found when the host has no session for the worktree', async () => { - const { resolved } = deps({ getWorkspaceSession: () => null }) - await expect( - readHostTerminalScrollback(resolved, { - worktree: 'id:repo::/wt-a', - ref: HELD_REF - }) - ).rejects.toThrow('terminal_scrollback_not_found') - }) - it('refuses a file over the store limit before reading any of it', async () => { const { resolved, readSnapshot } = deps({ statSnapshotSize: async () => TERMINAL_SCROLLBACK_STORE_BYTE_LIMIT + 1 diff --git a/src/main/runtime/leaf-pty-verdict-expiry.test.ts b/src/main/runtime/leaf-pty-verdict-expiry.test.ts index 370532c2459..5c878ceb577 100644 --- a/src/main/runtime/leaf-pty-verdict-expiry.test.ts +++ b/src/main/runtime/leaf-pty-verdict-expiry.test.ts @@ -30,21 +30,6 @@ function createRuntime( afterEach(() => vi.restoreAllMocks()) describe('leaf PTY verdict expiry', () => { - it('retires old unique IDs on a live-PTY consult without probing that live PTY', async () => { - const now = vi.spyOn(Date, 'now').mockReturnValue(100_000) - const { verdicts, isAbsent, probe } = createRuntime() - for (let index = 0; index < 1_000; index++) { - await expect(isAbsent(`retired-${index}`)).resolves.toBe(true) - } - expect(verdicts.size).toBe(1_000) - now.mockReturnValue(100_000 + TTL_MS) - - await expect(isAbsent('live')).resolves.toBe(false) - - expect(verdicts.size).toBe(0) - expect(probe).toHaveBeenCalledTimes(1_000) - }) - it('preserves every fresh verdict and the exact per-key TTL between bulk sweeps', async () => { const now = vi.spyOn(Date, 'now').mockReturnValue(100_000) const { verdicts, isAbsent, probe } = createRuntime() @@ -71,23 +56,6 @@ describe('leaf PTY verdict expiry', () => { expect(verdicts.has('fresh-0')).toBe(false) }) - it('sweeps at most once per TTL through a burst of probes and live sends', async () => { - const now = vi.spyOn(Date, 'now').mockReturnValue(100_000) - const { verdicts, isAbsent } = createRuntime() - const iterations = vi.spyOn(verdicts, Symbol.iterator) - for (let index = 0; index < 1_000; index++) { - await isAbsent(`dead-${index}`) - await isAbsent('live') - } - expect(iterations).toHaveBeenCalledOnce() - now.mockReturnValue(100_000 + TTL_MS) - for (let index = 0; index < 1_000; index++) { - await isAbsent('live') - } - expect(iterations).toHaveBeenCalledTimes(2) - expect(verdicts.size).toBe(0) - }) - it('cleans old entries when a delayed probe completes after the next sweep is due', async () => { const now = vi.spyOn(Date, 'now').mockReturnValue(100_000) const { verdicts, isAbsent, probe } = createRuntime() diff --git a/src/main/runtime/orca-runtime-agent-session-account-env.test.ts b/src/main/runtime/orca-runtime-agent-session-account-env.test.ts index 1315e5e2961..40a0cbc22d3 100644 --- a/src/main/runtime/orca-runtime-agent-session-account-env.test.ts +++ b/src/main/runtime/orca-runtime-agent-session-account-env.test.ts @@ -90,17 +90,6 @@ describe('agent-session creates with a desktop-prepared accountEnv', () => { expect(createTerminal).toHaveBeenCalledOnce() }) - it('leaves the launch env as built when an older client sends none', async () => { - const runtime = createRuntime() - const { planned } = planCreates(runtime) - await runtime.createAgentSession({ - clientOperationId: operationId(), - worktree: 'id:worktree-1', - agent: 'codex' - }) - expect(planned[0]?.env).toMatchObject({ CODEX_HOME: '/stale' }) - }) - it('puts the host-selected account over Settings agent env', async () => { const runtime = createRuntime() runtime.setHostAccountLaunchEnv( diff --git a/src/main/runtime/orca-runtime-browser-screencast-pending-frame-retry.test.ts b/src/main/runtime/orca-runtime-browser-screencast-pending-frame-retry.test.ts index 18dfe14af92..9be1d5ebb0b 100644 --- a/src/main/runtime/orca-runtime-browser-screencast-pending-frame-retry.test.ts +++ b/src/main/runtime/orca-runtime-browser-screencast-pending-frame-retry.test.ts @@ -98,15 +98,6 @@ describe('screencast frames a viewer refused', () => { subscription.session.stop() }) - // Lossy frames must not queue behind backlog; retries deliver only the newest. - it('asks the transport to drop frames while the socket is backlogged', async () => { - const sendBinary = vi.fn(() => true) - const { subscription, onFrame } = await subscribe(sendBinary) - onFrame(new Uint8Array([1])) - expect(sendBinary).toHaveBeenCalledWith(new Uint8Array([1]), { dropWhenBacklogged: true }) - subscription.session.stop() - }) - it('stops retrying once the viewer leaves', async () => { const sendBinary = vi.fn(() => false) const { subscription, onFrame } = await subscribe(sendBinary) diff --git a/src/main/runtime/orca-runtime-failed-start-pane-layout-owner.test.ts b/src/main/runtime/orca-runtime-failed-start-pane-layout-owner.test.ts index 6c51f498daa..d51df169bb6 100644 --- a/src/main/runtime/orca-runtime-failed-start-pane-layout-owner.test.ts +++ b/src/main/runtime/orca-runtime-failed-start-pane-layout-owner.test.ts @@ -75,15 +75,6 @@ describe('layout-owner build: a start main could not make keeps its pane, showin expect(runtime.startStatusOf(`${tabId}:${leafId}`)).toBeNull() }) - it('still takes back the pane of a start that did not ask to keep it', async () => { - const { runtime, spawn, session } = setupLayoutOwnerRuntime() - spawn.mockRejectedValueOnce(new Error('shell not found')) - - await expect(runtime.createTerminal(`id:${WORKTREE_ID}`)).rejects.toThrow('shell not found') - - expect(session().tabsByWorktree[WORKTREE_ID] ?? []).toEqual([]) - }) - it('does not bring back a pane the user closed while its start was failing', async () => { const { runtime, spawn, session } = setupLayoutOwnerRuntime() spawn.mockImplementationOnce(async ({ tabId }) => { @@ -121,14 +112,4 @@ describe('layout-owner build: a start main could not make keeps its pane, showin const { tabId, leafId } = spawn.mock.calls[0]![0] expect(runtime.startStatusOf(`${tabId}:${leafId}`)).toBeNull() }) - - it('clears the status of a start whose pane it took back', async () => { - const { runtime, spawn } = setupLayoutOwnerRuntime() - spawn.mockRejectedValueOnce(new Error('shell not found')) - - await expect(runtime.createTerminal(`id:${WORKTREE_ID}`)).rejects.toThrow('shell not found') - - const { tabId, leafId } = spawn.mock.calls[0]![0] - expect(runtime.startStatusOf(`${tabId}:${leafId}`)).toBeNull() - }) }) diff --git a/src/main/runtime/orca-runtime-git-diff-budget.test.ts b/src/main/runtime/orca-runtime-git-diff-budget.test.ts index 44c7575983a..b9998638a3d 100644 --- a/src/main/runtime/orca-runtime-git-diff-budget.test.ts +++ b/src/main/runtime/orca-runtime-git-diff-budget.test.ts @@ -75,12 +75,6 @@ describe('runtime git diff transport budget', () => { expect(mocks.getDiff).toHaveBeenCalled() }) - it('leaves a local-repo diff uncapped when no budget is supplied', async () => { - await expect( - commands().getRuntimeGitDiff('id:wt-1', 'assets/logo.png', false) - ).resolves.toMatchObject({ modifiedContent: OVERSIZED_BASE64 }) - }) - it('caps a local-repo branch diff that exceeds the budget', async () => { await expect( commands().getRuntimeGitBranchDiff( @@ -94,43 +88,10 @@ describe('runtime git diff transport budget', () => { expect(mocks.getBranchDiff).toHaveBeenCalled() }) - it('leaves a local-repo branch diff uncapped when no budget is supplied', async () => { - await expect( - commands().getRuntimeGitBranchDiff('id:wt-1', BRANCH_COMPARE, 'assets/logo.png') - ).resolves.toMatchObject({ modifiedContent: OVERSIZED_BASE64 }) - }) - it('caps a local-repo commit diff that exceeds the budget', async () => { await expect( commands().getRuntimeGitCommitDiff('id:wt-1', COMMIT_ARGS, REMOTE_RPC_MAX_CONTENT_BYTES) ).rejects.toMatchObject(TOO_LARGE) expect(mocks.getCommitDiff).toHaveBeenCalled() }) - - it('leaves a local-repo commit diff uncapped when no budget is supplied', async () => { - await expect(commands().getRuntimeGitCommitDiff('id:wt-1', COMMIT_ARGS)).resolves.toMatchObject( - { - modifiedContent: OVERSIZED_BASE64 - } - ) - }) - - it('prioritizes local file diff reads without losing WSL routing', async () => { - const runtime = commands({ wslDistro: 'Ubuntu' }) - - await runtime.getRuntimeGitBranchDiff('id:wt-1', BRANCH_COMPARE, 'assets/logo.png') - await runtime.getRuntimeGitCommitDiff('id:wt-1', COMMIT_ARGS) - - const options = { admissionTier: 'interactive', wslDistro: 'Ubuntu' } - expect(mocks.getBranchDiff).toHaveBeenLastCalledWith( - '/remote/repo', - expect.objectContaining({ filePath: 'assets/logo.png' }), - options - ) - expect(mocks.getCommitDiff).toHaveBeenLastCalledWith( - '/remote/repo', - expect.objectContaining({ filePath: 'assets/logo.png' }), - options - ) - }) }) diff --git a/src/main/runtime/orca-runtime-worktree-change-invalidation.test.ts b/src/main/runtime/orca-runtime-worktree-change-invalidation.test.ts index a06e1ebb128..b3c8244ca7a 100644 --- a/src/main/runtime/orca-runtime-worktree-change-invalidation.test.ts +++ b/src/main/runtime/orca-runtime-worktree-change-invalidation.test.ts @@ -87,15 +87,6 @@ describe('runtime worktree change invalidation', () => { listWorktreesStrictMock.mockResolvedValue([row(REPO_PATH)]) }) - it('moves the scan generation the runtime listing witnesses', () => { - makeRuntime() - const before = getLocalWorktreeScanGeneration(REPO_ID) - - runWorktreeChangeInvalidators(REPO_ID) - - expect(getLocalWorktreeScanGeneration(REPO_ID)).not.toBe(before) - }) - it('bumps that generation from the change event the runtime itself sends, with no window notifier attached', () => { const runtime = makeRuntimeService() const before = getLocalWorktreeScanGeneration(REPO_ID) diff --git a/src/main/runtime/rpc/terminal-multiplex-escape-tail.test.ts b/src/main/runtime/rpc/terminal-multiplex-escape-tail.test.ts deleted file mode 100644 index 926b15d7e42..00000000000 --- a/src/main/runtime/rpc/terminal-multiplex-escape-tail.test.ts +++ /dev/null @@ -1,135 +0,0 @@ -import './unused-default-rpc-methods.test-fixture' -import { describe, expect, it, vi } from 'vitest' -import { RpcDispatcher } from './dispatcher' -import type { RpcRequest } from './core' -import type { OrcaRuntimeService } from '../orca-runtime' -import { TERMINAL_METHODS } from './methods/terminal' -import type { RuntimeTerminalWait } from '../../../shared/runtime-types' -import { - TerminalStreamOpcode, - decodeTerminalStreamFrame, - decodeTerminalStreamJson, - encodeTerminalStreamFrame, - encodeTerminalStreamJson -} from '../../../shared/terminal-stream-protocol' - -// Preserve pendingEscapeTailAnsi through SnapshotStart (#7329); after reset, missing partial escapes make subsequent live bytes render literally. - -function stubRuntime(overrides: Partial = {}): OrcaRuntimeService { - // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: This partial runtime supplies the terminal RPC methods these tests invoke. - return { - getRuntimeId: () => 'test-runtime', - getPtyExecutionHostMetadata: () => ({ incarnationId: 'test-incarnation' }), - getTerminalLaunchResult: () => undefined, - ...overrides - } as OrcaRuntimeService -} - -function makeRequest(method: string, params?: unknown): RpcRequest { - return { id: 'req-1', authToken: 'tok', method, params } -} - -describe('terminal.multiplex pending-escape-tail threading (#7329)', () => { - it('carries the daemon pendingEscapeTailAnsi through the SnapshotStart frame', async () => { - vi.useFakeTimers() - try { - const messages: string[] = [] - const binaryFrames: Uint8Array[] = [] - const handlers = new Map< - number, - (frame: NonNullable>) => void - >() - const cleanups = new Map void>() - const runtime = stubRuntime({ - resolveLiveLeafForHandle: vi.fn().mockReturnValue({ ptyId: 'pty-1' }), - readTerminal: vi.fn().mockResolvedValue({ tail: [], truncated: false }), - serializeTerminalBuffer: vi.fn().mockResolvedValue({ - data: 'user@host:~$ ', - cols: 80, - rows: 24, - seq: 7, - // The dangling partial the emulator could not serialize. - pendingEscapeTailAnsi: '\x1b[3', - alternateScreen: false, - terminalOwner: 'shell' - }), - getTerminalSize: vi.fn().mockReturnValue({ cols: 80, rows: 24 }), - getMobileDisplayMode: vi.fn().mockReturnValue('auto'), - getLayout: vi.fn().mockReturnValue({ seq: 1 }), - registerRemoteTerminalViewSubscriber: vi.fn(() => () => {}), - subscribeToTerminalData: vi.fn().mockReturnValue(vi.fn()), - subscribeToTerminalResize: vi.fn().mockReturnValue(vi.fn()), - subscribeToFitOverrideChanges: vi.fn().mockReturnValue(vi.fn()), - subscribeToDriverChanges: vi.fn().mockReturnValue(vi.fn()), - getTerminalFitOverride: vi.fn().mockReturnValue(null), - getDriver: vi.fn().mockReturnValue({ kind: 'idle' }), - registerSubscriptionCleanup: vi.fn((id: string, cleanup: () => void) => { - cleanups.set(id, cleanup) - }), - cleanupSubscription: vi.fn((id: string) => { - const cleanup = cleanups.get(id) - cleanups.delete(id) - cleanup?.() - }), - waitForTerminal: vi.fn(() => new Promise(() => {})), - updateDesktopViewport: vi.fn().mockResolvedValue(true) - }) - const dispatcher = new RpcDispatcher({ - runtime, - methods: TERMINAL_METHODS - }) - - const dispatchPromise = dispatcher.dispatchStreaming( - makeRequest('terminal.multiplex', {}), - (msg) => messages.push(msg), - { - connectionId: 'conn-1', - sendBinary: (bytes) => { - binaryFrames.push(bytes) - }, - registerBinaryStreamHandler: (streamId, handler) => { - handlers.set(streamId, handler) - return () => handlers.delete(streamId) - } - } - ) - - await vi.runOnlyPendingTimersAsync() - expect(messages.some((msg) => JSON.parse(msg).result?.type === 'ready')).toBe(true) - - handlers.get(0)?.( - decodeTerminalStreamFrame( - encodeTerminalStreamFrame({ - opcode: TerminalStreamOpcode.Subscribe, - streamId: 0, - seq: 1, - payload: encodeTerminalStreamJson({ - streamId: 5, - terminal: 'terminal-1', - client: { id: 'desktop-1', type: 'desktop' } - }) - }) - )! - ) - - // Finish read/serialize awaits and the output-batcher flush timer. - for (let i = 0; i < 5; i += 1) { - await vi.runOnlyPendingTimersAsync() - } - - const snapshotStart = binaryFrames - .map((frame) => decodeTerminalStreamFrame(frame)) - .find((frame) => frame?.opcode === TerminalStreamOpcode.SnapshotStart)! - expect(decodeTerminalStreamJson(snapshotStart.payload)).toMatchObject({ - pendingEscapeTailAnsi: '\x1b[3', - alternateScreen: false, - terminalOwner: 'shell' - }) - - runtime.cleanupSubscription('terminal-multiplex:conn-1') - await dispatchPromise - } finally { - vi.useRealTimers() - } - }) -}) diff --git a/src/main/runtime/runtime-reference-integration.test.ts b/src/main/runtime/runtime-reference-integration.test.ts index a6f79c34e82..33d25d59641 100644 --- a/src/main/runtime/runtime-reference-integration.test.ts +++ b/src/main/runtime/runtime-reference-integration.test.ts @@ -7,8 +7,6 @@ import { } from './orca-runtime-test-mocks.spec' import { store, TEST_WORKTREE_ID } from './orca-runtime-test-fixtures.spec' import { parseWorkspaceReferenceUrl } from '../../shared/workspace-reference-identity' -import type { RuntimeLinearCommands } from './runtime-linear-connection-commands' -import type { ResolvedWorktree } from './runtime-worktree-path-identity' vi.mock('./agent-session-record-store-slot', () => ({ peekOpenedAgentSessionRecordStore: () => null, @@ -89,48 +87,3 @@ describe('reference find runtime integration', () => { expect(result.matches.map(({ workspace }) => workspace.id)).toEqual([TEST_WORKTREE_ID]) }) }) - -class LinearOwnerRuntime extends OrcaRuntimeService { - override listResolvedWorktrees(): Promise { - return Promise.resolve([]) - } -} - -describe('Linear installed owner', () => { - it('forwards the command promise unchanged', async () => { - const runtime = new OrcaRuntimeService() - const result: ReturnType = Promise.resolve([]) - const comments = vi.spyOn(runtime.linearCommands, 'linearIssueComments').mockReturnValue(result) - expect(runtime.linearIssueComments('issue-1', 'workspace-1')).toBe(result) - expect(comments).toHaveBeenCalledExactlyOnceWith('issue-1', 'workspace-1') - await result - }) - - it('keeps terminal lookup late-bound after construction', async () => { - const runtime = new OrcaRuntimeService(store) - const first = vi.spyOn(runtime, 'showTerminal').mockRejectedValue(new Error('first hook')) - await expect( - runtime.linearResolveCurrentIssue({ terminalHandle: 'pane-1', remote: true }) - ).rejects.toMatchObject({ code: 'linear_issue_required' }) - expect(first).toHaveBeenCalledExactlyOnceWith('pane-1') - first.mockRestore() - const second = vi - .spyOn(runtime, 'showTerminal') - .mockRejectedValue(new Error('replacement hook')) - await expect( - runtime.linearResolveCurrentIssue({ terminalHandle: 'pane-2', remote: true }) - ).rejects.toMatchObject({ code: 'linear_issue_required' }) - expect(second).toHaveBeenCalledExactlyOnceWith('pane-2') - }) - - it('keeps worktree lookup late-bound and passes no arguments', async () => { - const runtime = new LinearOwnerRuntime() - const first = vi.spyOn(runtime, 'listResolvedWorktrees').mockResolvedValue([]) - await expect(runtime.resolveWorktreeForContainedPath(process.cwd())).resolves.toBeNull() - expect(first).toHaveBeenCalledExactlyOnceWith() - first.mockRestore() - const second = vi.spyOn(runtime, 'listResolvedWorktrees').mockResolvedValue([]) - await expect(runtime.resolveWorktreeForContainedPath(process.cwd())).resolves.toBeNull() - expect(second).toHaveBeenCalledExactlyOnceWith() - }) -}) diff --git a/src/main/runtime/structured-agent-create-support-opencode-rig.test.ts b/src/main/runtime/structured-agent-create-support-opencode-rig.test.ts index 40c5ad51f0a..3c33fe8acf7 100644 --- a/src/main/runtime/structured-agent-create-support-opencode-rig.test.ts +++ b/src/main/runtime/structured-agent-create-support-opencode-rig.test.ts @@ -101,13 +101,6 @@ describe.skipIf(process.platform === 'win32')('OpenCode create support under the ) }) - it('admits the 2.x first on the shell PATH when the Command names it', async () => { - vi.spyOn(console, 'info').mockImplementation(() => {}) - const homebrew = join(root, 'homebrew', 'opencode') - - expect(await createSupport(rigSettings(homebrew))).toEqual({ supported: true }) - }) - it('names the check that refused an older Command in the main log', async () => { const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}) const older = await fakeOpencode(join(root, 'older'), '1.18.30') diff --git a/src/main/runtime/structured-worker-hook-attestation.test.ts b/src/main/runtime/structured-worker-hook-attestation.test.ts index d8680014485..4db73780203 100644 --- a/src/main/runtime/structured-worker-hook-attestation.test.ts +++ b/src/main/runtime/structured-worker-hook-attestation.test.ts @@ -77,27 +77,6 @@ describe('structured worker hook attestation stays closed', () => { hostRef.current = null }) - it('leaves both the launch token hash and the pty id empty', () => { - const handle = registerStructuredWorker() - const authority = getAuthority.call(runtimeStub(), handle) - expect(authority).not.toBeNull() - expect(authority!.launchTokenHash).toBeNull() - // Non-empty would make the restored-authority receipt lookup reachable. - expect(authority!.ptyId).toBe('') - }) - - it('refuses to attest a structured handle as a compatibility caller', () => { - const handle = registerStructuredWorker() - const stub = runtimeStub() - expect( - verifyCaller.call(stub, { - terminalHandle: handle, - paneKey: structuredWorkerIdentities.get(handle)!.paneKey, - launchToken: 'anything-the-caller-claims' - }) - ).toBeNull() - }) - it('still refuses when a restored receipt exists under an empty pty id', () => { const handle = registerStructuredWorker() const identity = structuredWorkerIdentities.get(handle)! diff --git a/src/main/runtime/tui-idle-codex-plan-menu.test.ts b/src/main/runtime/tui-idle-codex-plan-menu.test.ts index 476968862df..a45062509d2 100644 --- a/src/main/runtime/tui-idle-codex-plan-menu.test.ts +++ b/src/main/runtime/tui-idle-codex-plan-menu.test.ts @@ -124,14 +124,4 @@ describe('Codex plan menu painted after its Stop hook', () => { // Held for the turn's last frame, then settled before the next poll sweep. expect(await waitOutcome(runtime, handle, 1000)).toBe('ready') }) - - it('settles at once on a done from a turn that proposed no plan', async () => { - let rows: AgentStatusIpcPayload[] = [] - const { runtime, handle } = await codexPane(() => rows) - paint(runtime, '• Done.\r\n') - await vi.advanceTimersByTimeAsync(100) - rows = [doneRow(Date.now())] - - expect(await waitOutcome(runtime, handle, 50)).toBe('ready') - }) }) diff --git a/src/main/runtime/worktree-ps-unverifiable-terminals.test.ts b/src/main/runtime/worktree-ps-unverifiable-terminals.test.ts index e0fac30b0e0..6399f7e9456 100644 --- a/src/main/runtime/worktree-ps-unverifiable-terminals.test.ts +++ b/src/main/runtime/worktree-ps-unverifiable-terminals.test.ts @@ -72,18 +72,6 @@ async function psRow(runtime: OrcaRuntimeService) { } describe('worktree.ps terminal verdicts for an SSH host', () => { - it('counts a terminal the reachable host lists as live', async () => { - const runtime = makeRuntime({ - hasPty: () => true, - listProcesses: async () => [{ id: PTY_ID, worktreeId: WORKTREE_ID }] - }) - - const row = await psRow(runtime) - - expect(row).toMatchObject({ liveTerminalCount: 1, hasAttachedPty: true }) - expect(row?.unverifiableTerminalCount).toBe(0) - }) - it('reports a terminal on an unreachable host as unverifiable, not zero', async () => { const runtime = makeRuntime({ hasPty: () => null, diff --git a/src/main/speech/speech-model-deletion.test.ts b/src/main/speech/speech-model-deletion.test.ts index e78fc0d175d..79c038b4873 100644 --- a/src/main/speech/speech-model-deletion.test.ts +++ b/src/main/speech/speech-model-deletion.test.ts @@ -23,41 +23,6 @@ function makeStore(initialVoice: VoiceSettings) { } describe('deleteLocalSpeechModel', () => { - it('clears the selected local model after deletion succeeds', async () => { - expect(localModel).toBeDefined() - const calls: string[] = [] - const voice = { ...getDefaultVoiceSettings(), enabled: true, sttModel: localModel!.id } - const store = makeStore(voice) - const modelManager = { - deleteModel: vi.fn(async () => { - calls.push('delete') - }) - } - const sttService = { - prepareModelForDeletion: vi.fn(async () => { - calls.push('prepare') - }) - } - - await deleteLocalSpeechModel({ - store, - modelManager, - sttService, - modelId: localModel!.id - }) - - expect(calls).toEqual(['prepare', 'delete']) - expect(store.updateSettings).toHaveBeenCalledWith( - { - voice: { - ...voice, - sttModel: '' - } - }, - { notifyListeners: true } - ) - }) - it('does not clear selection when another client selected a newer model', async () => { expect(localModel).toBeDefined() const voice = { ...getDefaultVoiceSettings(), enabled: true, sttModel: localModel!.id } diff --git a/src/main/ssh/ssh-tcp-forwarding-probe.test.ts b/src/main/ssh/ssh-tcp-forwarding-probe.test.ts index ba52452ec10..10f1dffd7e4 100644 --- a/src/main/ssh/ssh-tcp-forwarding-probe.test.ts +++ b/src/main/ssh/ssh-tcp-forwarding-probe.test.ts @@ -1,53 +1,11 @@ import { createServer, type Server, type Socket } from 'node:net' -import { afterEach, describe, expect, it, vi } from 'vitest' +import { afterEach, describe, expect, it } from 'vitest' + import type { ForwardChannelOpenFailure } from './port-forwarding/ssh-port-forward-provider' -import { checkForwardChannel, probeTcpForwarding } from './ssh-tcp-forwarding-probe' +import { checkForwardChannel } from './ssh-tcp-forwarding-probe' + import { lastChannelOpenFailure } from './port-forwarding/system-ssh-port-forward-provider' -type OpenCallback = (error: (Error & { reason?: number }) | undefined, channel?: unknown) => void - -function connectionAnswering(answer: (callback: OpenCallback) => void) { - const forwardOut = vi.fn((_srcHost, _srcPort, _host, _port, callback: OpenCallback) => - answer(callback) - ) - // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the probe calls only forwardOut on the client. - return { forwardOut, connection: { getClient: () => ({ forwardOut }) as never } } -} - -function openFailure(reason: number): Error & { reason: number } { - return Object.assign(new Error('open failed'), { reason }) -} - -describe('TCP forwarding probe', () => { - it('reads an administrative refusal as forwarding refused', async () => { - const { connection } = connectionAnswering((callback) => callback(openFailure(1))) - await expect(probeTcpForwarding(connection, 6768)).resolves.toBe('refused') - }) - - it('reads a connect failure as allowed: sshd tried, nothing listened yet', async () => { - const { connection, forwardOut } = connectionAnswering((callback) => callback(openFailure(2))) - await expect(probeTcpForwarding(connection, 6768)).resolves.toBe('allowed') - expect(forwardOut).toHaveBeenCalledWith('127.0.0.1', 0, '127.0.0.1', 6768, expect.any(Function)) - }) - - it('closes an opened channel and reads it as allowed', async () => { - const channel = { close: vi.fn() } - const { connection } = connectionAnswering((callback) => callback(undefined, channel)) - await expect(probeTcpForwarding(connection, 6768)).resolves.toBe('allowed') - expect(channel.close).toHaveBeenCalled() - }) - - it('is unverifiable without an ssh2 client, on a throw, or with no answer', async () => { - await expect(probeTcpForwarding({ getClient: () => null }, 6768)).resolves.toBe('unverifiable') - const throwing = connectionAnswering(() => { - throw new Error('Not connected') - }) - await expect(probeTcpForwarding(throwing.connection, 6768)).resolves.toBe('unverifiable') - const silent = connectionAnswering(() => {}) - await expect(probeTcpForwarding(silent.connection, 6768, 5)).resolves.toBe('unverifiable') - }) -}) - const servers: Server[] = [] afterEach(async () => { await Promise.all( @@ -86,14 +44,6 @@ describe('forward channel check (system SSH)', () => { await expect(checkForwardChannel(forward)).resolves.toBe('refused') }) - it('waits briefly for a refusal logged after the socket dropped', async () => { - const forward = await forwardAnswering((socket, log) => { - socket.destroy() - setTimeout(() => log('channel 1: open failed: administratively prohibited: open failed'), 50) - }) - await expect(checkForwardChannel(forward)).resolves.toBe('refused') - }) - it('reads a connect failure as allowed: sshd dialled, nothing listened yet', async () => { const forward = await forwardAnswering((socket, log) => { log('channel 1: open failed: connect failed: Connection refused') @@ -123,14 +73,4 @@ describe('forward channel check (system SSH)', () => { await new Promise((resolve) => servers.pop()?.close(resolve)) await expect(checkForwardChannel(closed, 300)).resolves.toBe('not-listening') }) - - it('reads the last channel failure OpenSSH logged', () => { - expect(lastChannelOpenFailure('Warning: Permanently added host\n')).toBeNull() - expect( - lastChannelOpenFailure( - 'channel 1: open failed: connect failed: Connection refused\n' + - 'channel 2: open failed: administratively prohibited: open failed\n' - ) - ).toBe('administratively-prohibited') - }) }) diff --git a/src/main/updater-release-api-token.test.ts b/src/main/updater-release-api-token.test.ts index 76118defefc..da03f274327 100644 --- a/src/main/updater-release-api-token.test.ts +++ b/src/main/updater-release-api-token.test.ts @@ -20,29 +20,6 @@ describe('resolveReleaseApiToken', () => { _resetReleaseApiTokenCache() }) - it('reads the github.com token through gh and trims it', async () => { - ghExecMock.mockResolvedValue({ stdout: 'gho_abc\n', stderr: '' }) - - await expect(resolveReleaseApiToken(T0)).resolves.toEqual({ - token: 'gho_abc', - rateLimitScope: 'native:github.com' - }) - - expect(ghExecMock.mock.calls[0][0]).toEqual(['auth', 'token', '--hostname', 'github.com']) - expect(ghExecMock.mock.calls[0][1]).toMatchObject({ idempotent: false }) - }) - - it('serves the cached token within its TTL and re-reads after it', async () => { - ghExecMock.mockResolvedValue({ stdout: 'gho_abc', stderr: '' }) - - await resolveReleaseApiToken(T0) - await resolveReleaseApiToken(T0 + TTL_MS - 1) - expect(ghExecMock).toHaveBeenCalledTimes(1) - - await resolveReleaseApiToken(T0 + TTL_MS + 1) - expect(ghExecMock).toHaveBeenCalledTimes(2) - }) - it('returns null when gh is missing or logged out and does not re-spawn within the TTL', async () => { ghExecMock.mockRejectedValueOnce(new Error('gh: not found')) @@ -57,25 +34,6 @@ describe('resolveReleaseApiToken', () => { }) }) - it('treats empty output as no token', async () => { - ghExecMock.mockResolvedValue({ stdout: '\n', stderr: '' }) - - await expect(resolveReleaseApiToken(T0)).resolves.toBeNull() - }) - - it('caches the successful WSL scope alongside the token', async () => { - ghExecMock.mockResolvedValue({ - stdout: 'gho_wsl\n', - stderr: '', - rateLimitScope: 'wsl:ubuntu:github.com' - }) - - const expected = { token: 'gho_wsl', rateLimitScope: 'wsl:ubuntu:github.com' } - await expect(resolveReleaseApiToken(T0)).resolves.toEqual(expected) - await expect(resolveReleaseApiToken(T0 + TTL_MS - 1)).resolves.toEqual(expected) - expect(ghExecMock).toHaveBeenCalledTimes(1) - }) - it('shares one in-flight read between concurrent callers', async () => { let finish: (value: { stdout: string; stderr: string }) => void = () => {} ghExecMock.mockReturnValue( diff --git a/src/main/window/renderer-liveness-at-death.test.ts b/src/main/window/renderer-liveness-at-death.test.ts index 327296e3a44..f1e2e584be6 100644 --- a/src/main/window/renderer-liveness-at-death.test.ts +++ b/src/main/window/renderer-liveness-at-death.test.ts @@ -31,20 +31,6 @@ describe('trackRendererLivenessAtDeath', () => { recordCoalescedDurableCrashBreadcrumb.mockClear() }) - it('reports a document that never loaded as a blank window with its age', () => { - const { window, contents } = createWindow() - const tracker = trackRendererLivenessAtDeath(window, () => now) - contents.emit('did-start-navigation', MAIN_FRAME_NAVIGATION) - now += 866_000 - - expect(tracker.takeAtRendererGone()).toEqual({ - rendererDocumentLoaded: false, - rendererDocumentAgeMs: 866_000, - mainWindowState: 'visible', - mainWindowFocused: false - }) - }) - it('reports how long the renderer has been hung, and clears it on responsive', () => { const { window, contents } = createWindow({ minimized: true }) const tracker = trackRendererLivenessAtDeath(window, () => now) @@ -81,16 +67,6 @@ describe('trackRendererLivenessAtDeath', () => { expect(tracker.takeAtRendererGone().rendererUnresponsiveForMs).toBeUndefined() }) - it('omits window state instead of throwing for a destroyed window', () => { - const { window } = createWindow({ destroyed: true }) - const tracker = trackRendererLivenessAtDeath(window, () => now) - - expect(tracker.takeAtRendererGone()).toEqual({ - rendererDocumentLoaded: false, - rendererDocumentAgeMs: 0 - }) - }) - it('reports a failed main-frame load as not loaded, though did-finish-load follows it', () => { const { window, contents } = createWindow() const tracker = trackRendererLivenessAtDeath(window, () => now) diff --git a/src/preload/hidden-window-frame-pump.test.ts b/src/preload/hidden-window-frame-pump.test.ts deleted file mode 100644 index d86e9665ee2..00000000000 --- a/src/preload/hidden-window-frame-pump.test.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { describe, expect, it, vi } from 'vitest' -import { - HIDDEN_WINDOW_FRAME_PUMP_INTERVAL_MS, - formatHiddenWindowFramePumpArgument -} from '../shared/hidden-window-frame-pump' -import { - installHiddenWindowFramePump, - startHiddenWindowFramePump -} from './hidden-window-frame-pump' - -function harness(initial?: { value: string; priority: string }) { - const props = new Map() - if (initial) { - props.set('background-color', initial) - } - const history: string[] = [] - const style = { - getPropertyValue: (name: string) => props.get(name)?.value ?? '', - getPropertyPriority: (name: string) => props.get(name)?.priority ?? '', - setProperty: (name: string, value: string | null, priority = '') => { - props.set(name, { value: value ?? '', priority }) - history.push(`set ${value} ${priority}`.trim()) - return undefined - }, - removeProperty: (name: string) => { - props.delete(name) - history.push('remove') - return '' - } - } - const frames: (() => void)[] = [] - let tick: (() => void) | null = null - let intervalMs = 0 - let cancelled = false - const stop = startHiddenWindowFramePump({ - rootStyle: () => style, - requestAnimationFrame: (callback) => frames.push(callback), - every: (callback, ms) => { - tick = callback - intervalMs = ms - return () => { - cancelled = true - } - } - }) - const runFrame = () => frames.shift()?.() - return { - props, - history, - frames, - stop, - tick: () => tick?.(), - runFrame, - intervalMs: () => intervalMs, - cancelled: () => cancelled - } -} - -describe('startHiddenWindowFramePump', () => { - it('damages exactly one frame per interval and removes the style it added', () => { - const h = harness() - expect(h.intervalMs()).toBe(HIDDEN_WINDOW_FRAME_PUMP_INTERVAL_MS) - - h.tick() - h.runFrame() - expect(h.props.get('background-color')?.value).toBe('rgb(1, 1, 1)') - h.runFrame() - - expect(h.props.has('background-color')).toBe(false) - expect(h.history).toEqual(['set rgb(1, 1, 1)', 'remove']) - }) - - it('restores an existing inline background and its priority exactly', () => { - const h = harness({ value: 'red', priority: 'important' }) - - h.tick() - h.runFrame() - h.runFrame() - - expect(h.props.get('background-color')).toEqual({ value: 'red', priority: 'important' }) - }) - - it('does not start a second flip while one is in flight', () => { - const h = harness() - - h.tick() - h.tick() - - expect(h.frames).toHaveLength(1) - }) - - it('cancels the interval on stop but still restores a flip in flight', () => { - const h = harness() - h.tick() - h.runFrame() - - h.stop() - h.runFrame() - h.tick() - - expect(h.cancelled()).toBe(true) - expect(h.props.has('background-color')).toBe(false) - expect(h.frames).toHaveLength(0) - }) -}) - -describe('installHiddenWindowFramePump', () => { - function deps() { - const every = vi.fn((_callback: () => void, _ms: number) => vi.fn()) - return { rootStyle: () => null, requestAnimationFrame: vi.fn(), every } - } - - it('does not start without the flag main stamps', () => { - const d = deps() - const onStopRequest = vi.fn() - installHiddenWindowFramePump(['--other'], onStopRequest, d) - - expect(d.every).not.toHaveBeenCalled() - expect(onStopRequest).not.toHaveBeenCalled() - }) - - it('starts with the flag and hands main the stop', () => { - const d = deps() - let stop: (() => void) | undefined - installHiddenWindowFramePump([formatHiddenWindowFramePumpArgument()], (s) => (stop = s), d) - const cancel = d.every.mock.results[0]?.value - - stop?.() - - expect(cancel).toHaveBeenCalledOnce() - }) -}) diff --git a/src/renderer/src/components/editor/rich-markdown-auto-focus.test.ts b/src/renderer/src/components/editor/rich-markdown-auto-focus.test.ts index 14642546d20..b0c4e89ebd9 100644 --- a/src/renderer/src/components/editor/rich-markdown-auto-focus.test.ts +++ b/src/renderer/src/components/editor/rich-markdown-auto-focus.test.ts @@ -48,36 +48,6 @@ describe('autoFocusRichEditor', () => { document.body.replaceChildren() }) - it('returns cleanup that cancels the pending focus frame', () => { - const cancelAnimationFrameMock = vi.fn() - vi.stubGlobal( - 'requestAnimationFrame', - vi.fn(() => 42) - ) - vi.stubGlobal('cancelAnimationFrame', cancelAnimationFrameMock) - - const cleanup = autoFocusRichEditor(createEditor(), null) - cleanup() - cleanup() - - expect(cancelAnimationFrameMock).toHaveBeenCalledTimes(1) - expect(cancelAnimationFrameMock).toHaveBeenCalledWith(42) - }) - - it('focuses the editor when the frame fires with neutral focus', () => { - const { focus, runFrame } = setupScheduledFocus(null) - runFrame() - - expect(focus).toHaveBeenCalledWith('start', { scrollIntoView: false }) - }) - - it('honors an explicit focus handoff', () => { - const { focus, runFrame } = setupScheduledFocus({}, true) - runFrame() - - expect(focus).toHaveBeenCalledWith('start', { scrollIntoView: false }) - }) - it('claims DOM focus synchronously on an explicit handoff', () => { const root = document.createElement('div') const editorDom = document.createElement('div') @@ -95,19 +65,6 @@ describe('autoFocusRichEditor', () => { expect(root.contains(document.activeElement)).toBe(true) }) - it('leaves DOM focus alone for an ordinary lazy mount', () => { - const domFocus = vi.fn() - vi.stubGlobal( - 'requestAnimationFrame', - vi.fn(() => 12) - ) - vi.stubGlobal('cancelAnimationFrame', vi.fn()) - - autoFocusRichEditor(createEditor(vi.fn(), domFocus), null, false) - - expect(domFocus).not.toHaveBeenCalled() - }) - it('does not run deferred focus after an explicit handoff expires', () => { let runFrame: FrameRequestCallback = () => {} let requestActive = true diff --git a/src/renderer/src/components/editor/rich-markdown-local-image.test.ts b/src/renderer/src/components/editor/rich-markdown-local-image.test.ts index 7e46821999d..ae5ea9c30b1 100644 --- a/src/renderer/src/components/editor/rich-markdown-local-image.test.ts +++ b/src/renderer/src/components/editor/rich-markdown-local-image.test.ts @@ -109,23 +109,4 @@ describe('rich markdown local images', () => { editor.destroy() } }) - - it('renders a mid-sentence image inside its paragraph without a block box', () => { - const host = document.createElement('div') - document.body.appendChild(host) - const editor = new Editor({ - element: host, - extensions: createRichMarkdownExtensions({ codec: createRichMarkdownEditorCodec() }), - content: 'before ![](diagram.png) after', - contentType: 'markdown' - }) - - try { - const img = host.querySelector('p img') - expect(img).not.toBeNull() - expect((img!.parentElement as HTMLElement).style.display).toBe('inline-block') - } finally { - editor.destroy() - } - }) }) diff --git a/src/renderer/src/components/editor/use-markdown-document-watch-refresh.test.ts b/src/renderer/src/components/editor/use-markdown-document-watch-refresh.test.ts index 134e273d6f2..244a08d11c6 100644 --- a/src/renderer/src/components/editor/use-markdown-document-watch-refresh.test.ts +++ b/src/renderer/src/components/editor/use-markdown-document-watch-refresh.test.ts @@ -52,18 +52,6 @@ afterEach(() => { }) describe('useMarkdownDocumentWatchRefresh', () => { - it('asks for a scan fresher than the latest change in the window', async () => { - const refresh = vi.fn(async () => {}) - await act(async () => root.render(createElement(Harness, { refresh }))) - change([{ kind: 'create', absolutePath: '/repo/a.md' }]) - await advance(100) - const latestChangeAt = performance.now() - change([{ kind: 'create', absolutePath: '/repo/b.md' }]) - await advance(100) - expect(refresh).toHaveBeenCalledTimes(1) - expect(refresh).toHaveBeenCalledWith(false, latestChangeAt) - }) - it('keeps one slow scan in flight and follows up once it settles', async () => { let inFlight = 0 let maxInFlight = 0 @@ -104,33 +92,4 @@ describe('useMarkdownDocumentWatchRefresh', () => { } expect(refresh.mock.calls.length).toBeGreaterThanOrEqual(2) }) - - it('lets a slow scan publish while membership changes never stop', async () => { - const scans: { startedAt: number; settledAt?: number }[] = [] - const refresh = vi.fn(() => { - const scan: { startedAt: number; settledAt?: number } = { - startedAt: Date.now() - } - scans.push(scan) - // Why: a 40 s listing outlives the 30 s watchdog. - return new Promise((resolve) => - setTimeout(() => { - scan.settledAt = Date.now() - resolve() - }, 40_000) - ) - }) - await act(async () => root.render(createElement(Harness, { refresh }))) - for (let i = 0; i < 60; i++) { - change([{ kind: 'create', absolutePath: `/repo/s${i}.md` }]) - await advance(5_000) - } - // A scan's result publishes only if no newer scan started before it settled. - const published = scans.filter( - (scan, index) => - scan.settledAt !== undefined && - scans.slice(index + 1).every((later) => later.startedAt >= scan.settledAt!) - ) - expect(published.length).toBeGreaterThanOrEqual(2) - }) }) diff --git a/src/renderer/src/components/editor/useRichMarkdownReviewController.open-guard.test.ts b/src/renderer/src/components/editor/useRichMarkdownReviewController.open-guard.test.ts index 42a606acf6c..12939cb66b6 100644 --- a/src/renderer/src/components/editor/useRichMarkdownReviewController.open-guard.test.ts +++ b/src/renderer/src/components/editor/useRichMarkdownReviewController.open-guard.test.ts @@ -91,47 +91,4 @@ describe('useRichMarkdownReviewController openAnnotationPopover draft guard', () expect(result.current.annotationPopover).toEqual(sampleTarget) expect(dispatch).not.toHaveBeenCalled() }) - - it('flushes the pending ProseMirror selection before reading the target', () => { - const flush = vi.fn() - const setSelection = vi.fn() - // An empty target makes opening no-op, isolating the requirement to flush native selection first. - const editorRef = { - current: { - view: { - dispatch: vi.fn(), - domObserver: { flush, currentSelection: { set: setSelection } } - }, - state: { selection: { empty: true } } - } as unknown as Editor - } - const rootRef = { current: document.createElement('div') } - const scrollContainerRef = { current: document.createElement('div') } - - const { result } = renderHook(() => - useRichMarkdownReviewController({ - addDiffComment: vi.fn(), - allDiffComments: [], - content: 'abc', - editorRef, - filePath: '/repo/notes.md', - markdownAnnotationsEnabled: true, - markdownReviewContent: 'abc', - markdownSourceLineOffset: 0, - rootRef, - scrollContainerRef, - worktreeId: 'wt-1', - worktreeRoot: '/repo' - }) - ) - - let opened = true - act(() => { - opened = result.current.openAnnotationPopover(true) - }) - - expect(flush).toHaveBeenCalledTimes(1) - expect(opened).toBe(false) - expect(result.current.annotationPopover).toBeNull() - }) }) diff --git a/src/renderer/src/components/native-chat/NativeChatComposerNotices.test.tsx b/src/renderer/src/components/native-chat/NativeChatComposerNotices.test.tsx deleted file mode 100644 index 3acba880bab..00000000000 --- a/src/renderer/src/components/native-chat/NativeChatComposerNotices.test.tsx +++ /dev/null @@ -1,134 +0,0 @@ -// @vitest-environment happy-dom -import '@testing-library/jest-dom/vitest' -import { cleanup, fireEvent, render, screen, within } from '@testing-library/react' -import { afterEach, describe, expect, it, vi } from 'vitest' -import { NativeChatComposerNotices } from './NativeChatComposerNotices' -import { CLIPBOARD_TEXT_TOO_LARGE_ERROR } from '../../../../shared/clipboard-text' -import { nativeChatNoticeFromError, setNativeChatPasteFailure } from './native-chat-composer-notice' - -afterEach(cleanup) - -describe('NativeChatComposerNotices', () => { - it('draws no card when there is nothing to say, but keeps its live region for the next notice', () => { - const { container } = render() - expect(container.querySelectorAll('li')).toHaveLength(0) - expect(container.querySelector('[aria-live="polite"]')).toBeInTheDocument() - }) - - it('puts errors first and keeps every notice, so one never hides another', () => { - const { container } = render( - - ) - const texts = screen.getAllByText(/./, { selector: 'p' }).map((node) => node.textContent) - expect(texts).toEqual([ - 'Orca couldn’t save your message.', - 'sonnet-9 is not an available model.', - 'Worktree not ready.', - 'Build box is offline' - ]) - expect(container.querySelectorAll('[data-notice-kind="error"]')).toHaveLength(2) - }) - - it('shows error text Orca did not write in its own block, with a copy button', () => { - const write = vi.fn().mockResolvedValue(undefined) - Object.assign(window, { api: { ui: { writeClipboardText: write } } }) - render( - - ) - const row = screen.getByRole('listitem') - expect(within(row).getByText('Your message was not sent.').tagName).toBe('P') - expect(within(row).getByText('connect ECONNREFUSED /tmp/agent-host.sock').tagName).toBe('PRE') - fireEvent.click(within(row).getByRole('button', { name: 'Copy error' })) - expect(write).toHaveBeenCalledWith('connect ECONNREFUSED /tmp/agent-host.sock') - }) - - it('offers the notice action and dismiss only where given', () => { - const retry = vi.fn() - const dismiss = vi.fn() - render( - - ) - expect(screen.getAllByRole('button', { name: 'Dismiss' })).toHaveLength(1) - fireEvent.click(screen.getByRole('button', { name: 'Retry' })) - fireEvent.click(screen.getByRole('button', { name: 'Dismiss' })) - expect(retry).toHaveBeenCalledTimes(1) - expect(dismiss).toHaveBeenCalledTimes(1) - }) -}) - -describe('nativeChatNoticeFromError', () => { - it('keeps a wrapped main-process error apart from the headline, without its wrapper', () => { - expect( - nativeChatNoticeFromError( - new Error( - "Error invoking remote method 'agentSession:send': Error: connect ECONNREFUSED /tmp/a.sock" - ), - 'Your message was not sent.' - ) - ).toEqual({ text: 'Your message was not sent.', errorText: 'connect ECONNREFUSED /tmp/a.sock' }) - }) - - it('keeps a local error apart unless the caller says it is already Orca’s words', () => { - const error = new Error('Pasted text is too large for this message.') - expect(nativeChatNoticeFromError(error, 'Paste failed.')).toEqual({ - text: 'Paste failed.', - errorText: 'Pasted text is too large for this message.' - }) - expect( - nativeChatNoticeFromError(error, 'Paste failed.', { localErrorIsOrcaWords: true }) - ).toEqual({ text: 'Pasted text is too large for this message.' }) - }) - - it("says a paste over the size limit in Orca's words, even when it comes back from the main process", () => { - const setNotice = vi.fn() - setNativeChatPasteFailure( - setNotice, - new Error( - `Error invoking remote method 'ui:readClipboardText': Error: ${CLIPBOARD_TEXT_TOO_LARGE_ERROR}` - ) - ) - expect(setNotice).toHaveBeenCalledWith(CLIPBOARD_TEXT_TOO_LARGE_ERROR) - }) - - it('keeps any other main-process paste failure apart under "Paste failed."', () => { - const setNotice = vi.fn() - setNativeChatPasteFailure( - setNotice, - new Error("Error invoking remote method 'ui:readClipboardText': Error: sftp down") - ) - expect(setNotice).toHaveBeenCalledWith('Paste failed.', 'sftp down') - }) - - it('says only the headline when the error carries no words', () => { - expect(nativeChatNoticeFromError(new Error(' '), 'Paste failed.')).toEqual({ - text: 'Paste failed.' - }) - expect(nativeChatNoticeFromError(undefined, 'Paste failed.')).toEqual({ text: 'Paste failed.' }) - }) -}) diff --git a/src/renderer/src/components/native-chat/NativeChatPaneHeader.test.tsx b/src/renderer/src/components/native-chat/NativeChatPaneHeader.test.tsx index 2087eaf617f..fc22f233a17 100644 --- a/src/renderer/src/components/native-chat/NativeChatPaneHeader.test.tsx +++ b/src/renderer/src/components/native-chat/NativeChatPaneHeader.test.tsx @@ -56,24 +56,6 @@ function renderHeader(handOff?: NativeChatHeaderHandOff, focused = true) { return source } -it('puts Hand Off first like the terminal header, only on the focused pane, and blocks a second open', () => { - const open = vi.fn() - renderHeader({ open, disabled: false }) - expect(screen.getAllByRole('button')[0].getAttribute('aria-label')).toBe( - 'Hand Off to Another Agent' - ) - fireEvent.click(screen.getByRole('button', { name: 'Hand Off to Another Agent' })) - expect(open).toHaveBeenCalledTimes(1) - cleanup() - renderHeader({ open, disabled: true }) - expect( - screen.getByRole('button', { name: 'Hand Off to Another Agent' }).hasAttribute('disabled') - ).toBe(true) - cleanup() - renderHeader({ open, disabled: false }, false) - expect(screen.queryByRole('button', { name: 'Hand Off to Another Agent' })).toBeNull() -}) - it('offers the terminal header action order and targets Resume and Close at the displayed chat', () => { const source = renderHeader() expect(screen.getAllByRole('button').map((button) => button.getAttribute('aria-label'))).toEqual([ @@ -104,33 +86,3 @@ it('offers the terminal header action order and targets Resume and Close at the target: { kind: 'tab', worktreeId: source.worktreeId, tabId: source.id } }) }) - -it('Split from the header keeps the source and opens a fresh chat on the same host', () => { - const source = renderHeader() - mocks.launch.mockImplementation((args: { worktreeId: string; groupId: string }) => { - useAppStore.getState().createUnifiedTab(args.worktreeId, 'agent-session', { - targetGroupId: args.groupId, - agentSessionAgent: 'codex', - executionHostId: 'runtime:remote-host' - }) - return { surface: { kind: 'local-chat', tabId: 'fresh-chat' } } - }) - fireEvent.click(screen.getByRole('button', { name: 'Split Chat Right' })) - const state = useAppStore.getState() - const destination = state.activeGroupIdByWorktree[source.worktreeId] - expect(destination).not.toBe(source.groupId) - expect(mocks.launch).toHaveBeenCalledExactlyOnceWith( - expect.objectContaining({ - agent: 'codex', - requestedSurface: 'chat', - selectedExecutionHostId: source.executionHostId, - worktreeId: source.worktreeId, - groupId: destination, - focusIntent: expect.objectContaining({ cancel: expect.any(Function) }) - }) - ) - const tabs = state.unifiedTabsByWorktree[source.worktreeId] - expect(tabs.find((tab) => tab.id === source.id)).toEqual(source) - expect(tabs).toHaveLength(2) - expect(tabs.find((tab) => tab.groupId === destination)?.entityId).not.toBe(source.entityId) -}) diff --git a/src/renderer/src/components/native-chat/NativeChatStructuredQuestionCard.test.tsx b/src/renderer/src/components/native-chat/NativeChatStructuredQuestionCard.test.tsx index 9404c25c30a..947da6cf4dc 100644 --- a/src/renderer/src/components/native-chat/NativeChatStructuredQuestionCard.test.tsx +++ b/src/renderer/src/components/native-chat/NativeChatStructuredQuestionCard.test.tsx @@ -76,11 +76,6 @@ describe('structured extension question cards', () => { }) }) - it('shows the default hint in an editor box that has no hint of its own', () => { - render({ ...input, freeTextInput: { allowEmpty: true, multiline: true, initialValue: '' } }) - expect(container.querySelector('textarea')?.placeholder).toBe('Type your answer') - }) - it('submits the text the user edited in the editor, not its prefill', () => { const { onAnswer } = render({ ...input, diff --git a/src/renderer/src/components/native-chat/use-native-chat-font-size.test.tsx b/src/renderer/src/components/native-chat/use-native-chat-font-size.test.tsx index ac4aae76664..3cf56d97c8a 100644 --- a/src/renderer/src/components/native-chat/use-native-chat-font-size.test.tsx +++ b/src/renderer/src/components/native-chat/use-native-chat-font-size.test.tsx @@ -83,27 +83,6 @@ describe('persisted chat font-size shortcuts', () => { expect(mocks.settings.nativeChatAppearance).toEqual({ codeFontSize: 16, width: 'wide' }) ) }) - it('writes an absent object on reset and ignores inactive panes', async () => { - const { rerender } = renderHook(({ enabled }) => useNativeChatFontSize(enabled), { - initialProps: { enabled: false } - }) - key('+') - expect(mocks.updateSettings).not.toHaveBeenCalled() - rerender({ enabled: true }) - key('-') - await waitFor(() => expect(mocks.settings.nativeChatAppearance).toEqual({ fontSize: 13 })) - key('0') - await waitFor(() => expect(mocks.settings.nativeChatAppearance).toBeUndefined()) - }) - it('does not listen to desktop DOM keys that are handled by the IPC bridge', () => { - mocks.web = false - renderHook(() => useNativeChatFontSize(true)) - key('+') - key('-') - key('0') - key('_') - expect(mocks.updateSettings).not.toHaveBeenCalled() - }) it('only handles keys originating in its chat root', async () => { const root = document.createElement('div') const input = document.createElement('input') diff --git a/src/renderer/src/components/new-workspace/NewWorkspaceComposerNameSection.test.tsx b/src/renderer/src/components/new-workspace/NewWorkspaceComposerNameSection.test.tsx index d0363de5cf7..c410c3ca40a 100644 --- a/src/renderer/src/components/new-workspace/NewWorkspaceComposerNameSection.test.tsx +++ b/src/renderer/src/components/new-workspace/NewWorkspaceComposerNameSection.test.tsx @@ -101,35 +101,4 @@ describe('NewWorkspaceComposerNameSection branch reuse', () => { expect(props.onNameValueChange).not.toHaveBeenCalled() expect(props.onClearSmartNameSelection).not.toHaveBeenCalled() }) - - it('removes the open action when the composer clears its existing-workspace target', () => { - const props = branchProps() - const { rerender } = render( - - ) - expect(screen.getByRole('button', { name: 'Open existing workspace' })).toBeTruthy() - - rerender() - - expect(screen.queryByRole('button', { name: 'Open existing workspace' })).toBeNull() - expect( - screen.getByRole('radio', { name: 'Existing branch' }).getAttribute('aria-checked') - ).toBe('false') - }) - - it('keeps reuse controls out of the accessible UI for a folder workspace', () => { - render( - - ) - - expect(screen.queryByRole('radio', { name: 'Existing branch' })).toBeNull() - expect(screen.queryByRole('button', { name: 'Open existing workspace' })).toBeNull() - expect(screen.getByRole('textbox', { name: 'Workspace name' })).toBeTruthy() - }) }) diff --git a/src/renderer/src/components/pet/usePetPointerInteraction.test.ts b/src/renderer/src/components/pet/usePetPointerInteraction.test.ts deleted file mode 100644 index c671d28d8a4..00000000000 --- a/src/renderer/src/components/pet/usePetPointerInteraction.test.ts +++ /dev/null @@ -1,135 +0,0 @@ -// @vitest-environment happy-dom - -import { act, renderHook } from '@testing-library/react' -import { describe, expect, it, vi } from 'vitest' -import { usePetPointerInteraction } from './usePetPointerInteraction' - -type HandlerName = keyof ReturnType['handlers'] - -function fakeTarget(): { - setPointerCapture: (id: number) => void - hasPointerCapture: (id: number) => boolean - releasePointerCapture: (id: number) => void -} { - const captured = new Set() - return { - setPointerCapture: (id) => void captured.add(id), - hasPointerCapture: (id) => captured.has(id), - releasePointerCapture: (id) => void captured.delete(id) - } -} - -function setup() { - const moveTo = vi.fn() - const target = fakeTarget() - const { result } = renderHook(() => usePetPointerInteraction({ x: 0, y: 0 }, moveTo)) - - const event = (props: { - clientX?: number - clientY?: number - pointerId?: number - button?: number - }) => - ({ - button: 0, - pointerId: 1, - clientX: 0, - clientY: 0, - currentTarget: target, - preventDefault: () => {}, - ...props - }) as unknown as Parameters< - ReturnType['handlers']['onPointerDown'] - >[0] - - const fire = (name: HandlerName, props: Parameters[0] = {}): void => { - act(() => result.current.handlers[name](event(props))) - } - - return { result, moveTo, fire, event } -} - -describe('usePetPointerInteraction', () => { - it('starts a drag and bumps the restart generation on a primary grab', () => { - const { result, fire } = setup() - fire('onPointerDown', { clientX: 50, clientY: 50 }) - expect(result.current.dragging).toBe(true) - expect(result.current.dragAnimation).toBe(null) - expect(result.current.dragGeneration).toBe(1) - }) - - it('runs toward the horizontal drag direction past the 4px deadzone', () => { - const { result, fire, moveTo } = setup() - fire('onPointerDown', { clientX: 50, clientY: 50 }) - fire('onPointerMove', { clientX: 58, clientY: 50 }) - expect(result.current.dragAnimation).toBe('running-right') - expect(moveTo).toHaveBeenLastCalledWith({ x: 8, y: 0 }) - fire('onPointerMove', { clientX: 40, clientY: 50 }) - expect(result.current.dragAnimation).toBe('running-left') - }) - - it('ignores sub-deadzone jitter and keeps the last direction on vertical moves', () => { - const { result, fire } = setup() - fire('onPointerDown', { clientX: 50, clientY: 50 }) - fire('onPointerMove', { clientX: 52, clientY: 52 }) - expect(result.current.dragAnimation).toBe(null) - fire('onPointerMove', { clientX: 58, clientY: 52 }) - expect(result.current.dragAnimation).toBe('running-right') - fire('onPointerMove', { clientX: 58, clientY: 100 }) - expect(result.current.dragAnimation).toBe('running-right') - }) - - it('accumulates horizontal travel across a slow diagonal drag', () => { - // Advance baseline only after accepted horizontal travel so repeated small diagonal moves can cross the threshold. - const { result, fire } = setup() - fire('onPointerDown', { clientX: 50, clientY: 50 }) - fire('onPointerMove', { clientX: 53, clientY: 55 }) - expect(result.current.dragAnimation).toBe(null) - fire('onPointerMove', { clientX: 56, clientY: 60 }) - expect(result.current.dragAnimation).toBe('running-right') - }) - - it('keeps the latest horizontal direction when two moves land in one commit', () => { - // Batched vertical motion must read the ref’s latest direction instead of resurrecting stale state. - const { result } = renderHook(() => usePetPointerInteraction({ x: 0, y: 0 }, vi.fn())) - const target = fakeTarget() - const ev = (clientX: number, clientY: number) => - ({ - button: 0, - pointerId: 1, - clientX, - clientY, - currentTarget: target, - preventDefault: () => {} - }) as never - - act(() => result.current.handlers.onPointerDown(ev(50, 50))) - act(() => { - result.current.handlers.onPointerMove(ev(40, 50)) - result.current.handlers.onPointerMove(ev(40, 90)) - }) - expect(result.current.dragAnimation).toBe('running-left') - }) - - it('scopes the drag to the owning pointer and ignores a second touch', () => { - const { result, fire, moveTo } = setup() - fire('onPointerDown', { clientX: 50, clientY: 50, pointerId: 1 }) - fire('onPointerDown', { clientX: 50, clientY: 50, pointerId: 2 }) - expect(result.current.dragGeneration).toBe(1) - fire('onPointerMove', { clientX: 90, clientY: 50, pointerId: 2 }) - expect(moveTo).not.toHaveBeenCalled() - fire('onPointerUp', { pointerId: 2 }) - expect(result.current.dragging).toBe(true) - fire('onPointerUp', { pointerId: 1 }) - expect(result.current.dragging).toBe(false) - expect(result.current.dragAnimation).toBe(null) - }) - - it('ends the drag when pointer capture is lost', () => { - const { result, fire } = setup() - fire('onPointerDown', { clientX: 50, clientY: 50 }) - fire('onLostPointerCapture', { pointerId: 1 }) - expect(result.current.dragging).toBe(false) - expect(result.current.dragAnimation).toBe(null) - }) -}) diff --git a/src/renderer/src/components/plugins/state/use-plugin-install-link.test.tsx b/src/renderer/src/components/plugins/state/use-plugin-install-link.test.tsx index 549b5c5fa2e..7da9149205e 100644 --- a/src/renderer/src/components/plugins/state/use-plugin-install-link.test.tsx +++ b/src/renderer/src/components/plugins/state/use-plugin-install-link.test.tsx @@ -63,22 +63,6 @@ afterEach(() => { root = null }) -describe('openPluginInstallLink', () => { - it('routes a valid link to Settings → Plugins and holds it for the catalog', () => { - openPluginInstallLink('orca://plugins/acme.dusk') - expect(storeState.openSettingsTarget).toHaveBeenCalledWith({ pane: 'plugins', repoId: null }) - expect(storeState.openSettingsPage).toHaveBeenCalled() - expect(usePluginPreviewRequestStore.getState().link?.pluginKey).toBe('acme.dusk') - }) - - it('shows only an error toast for a malformed link', () => { - openPluginInstallLink('orca://plugins/../evil') - expect(toastError).toHaveBeenCalledTimes(1) - expect(storeState.openSettingsPage).not.toHaveBeenCalled() - expect(usePluginPreviewRequestStore.getState().link).toBeNull() - }) -}) - describe('usePluginInstallLink', () => { it('keeps the link while plugins are off, then opens the page once the catalog loads', async () => { openPluginInstallLink('orca://plugins/acme.dusk') diff --git a/src/renderer/src/components/right-sidebar/ai-vault-session-account.test.ts b/src/renderer/src/components/right-sidebar/ai-vault-session-account.test.ts index 29b20a42ab7..0ac3c1e6184 100644 --- a/src/renderer/src/components/right-sidebar/ai-vault-session-account.test.ts +++ b/src/renderer/src/components/right-sidebar/ai-vault-session-account.test.ts @@ -117,18 +117,4 @@ describe('session account labels', () => { ) ).toBeNull() }) - - it('keeps explicit unmanaged data accounts as default and unsupported bindings unknown', () => { - expect( - resolveAiVaultSessionAccount( - { - ...session('opencode', '/unused'), - accountHome: { kind: 'opencode', locator: { kind: 'unmanaged' } } - }, - settings, - null - ) - ).toBe('System default') - expect(resolveAiVaultSessionAccount(session('pi', '/pi'), settings, null)).toBeNull() - }) }) diff --git a/src/renderer/src/components/right-sidebar/useFileExplorerWatch.broker.test.tsx b/src/renderer/src/components/right-sidebar/useFileExplorerWatch.broker.test.tsx index ab91a83a5ac..ed578671819 100644 --- a/src/renderer/src/components/right-sidebar/useFileExplorerWatch.broker.test.tsx +++ b/src/renderer/src/components/right-sidebar/useFileExplorerWatch.broker.test.tsx @@ -88,14 +88,6 @@ afterEach(() => { }) describe('remote file explorer using the recovered app watcher', () => { - it('refreshes from the app broker without opening an independent remote subscription', async () => { - renderWatch() - emit() - await settle() - expect(refreshDir).toHaveBeenCalledExactlyOnceWith('/repo') - expect(runtime.subscribe).not.toHaveBeenCalled() - }) - it('ignores other hosts and roots, including an identical local path', async () => { renderWatch() emit('host-b') diff --git a/src/renderer/src/components/settings/MachineNameField.test.tsx b/src/renderer/src/components/settings/MachineNameField.test.tsx index 8e902645236..fe1d68cbb09 100644 --- a/src/renderer/src/components/settings/MachineNameField.test.tsx +++ b/src/renderer/src/components/settings/MachineNameField.test.tsx @@ -46,22 +46,6 @@ describe('MachineNameField', () => { Reflect.deleteProperty(window, '__ORCA_WEB_CLIENT__') }) - it('shows the detected name as the blank default and lets the user set an override', async () => { - mocks.getStatus.mockResolvedValue({ machineName: 'm4airs-Air' }) - const { user } = renderField('') - - expect(await screen.findByPlaceholderText('m4airs-Air')).toBeVisible() - expect( - screen.getByText( - 'Other devices and hosts see “m4airs-Air”. Leave this blank to use the computer’s own name.' - ) - ).toBeVisible() - - await user.type(screen.getByRole('textbox', { name: 'Machine name' }), 'build-server') - await user.tab() - expect(mocks.updateSettings).toHaveBeenCalledWith({ machineName: 'build-server' }) - }) - it('captions a saved override without asking the runtime, so a stale read cannot show the old name', async () => { // Saved store names are already persisted; a stale runtime read must not override what peers see. mocks.getStatus.mockResolvedValue({ machineName: 'Brennan’s MacBook Pro' }) @@ -97,35 +81,4 @@ describe('MachineNameField', () => { unmount() expect(mocks.updateSettings).toHaveBeenCalledExactlyOnceWith({ machineName: 'build-server' }) }) - - it('keys the input, label, and caption off the mount id so two surfaces never collide', async () => { - mocks.getStatus.mockResolvedValue({ machineName: 'm4airs-Air' }) - renderField('', 'ssh-target-machine-name') - await act(async () => {}) - - const input = screen.getByRole('textbox', { name: 'Machine name' }) - expect(input).toHaveAttribute('id', 'ssh-target-machine-name') - expect(input).toHaveAccessibleDescription( - 'Other devices and hosts see “m4airs-Air”. Leave this blank to use the computer’s own name.' - ) - }) - - it('places a host class on its own root so a grid slot disappears with it', async () => { - mocks.getStatus.mockResolvedValue({ machineName: 'm4airs-Air' }) - mocks.holder.state = { settings: { machineName: '' }, updateSettings: mocks.updateSettings } - const { container } = render() - await act(async () => {}) - - expect(container.firstElementChild).toHaveClass('mp-pairing-machine', 'space-y-2') - }) - - it('renders nothing in the web client, which has no machine of its own to name', async () => { - Object.defineProperty(window, '__ORCA_WEB_CLIENT__', { configurable: true, value: true }) - mocks.getStatus.mockResolvedValue({ machineName: 'remote-host' }) - mocks.holder.state = { settings: { machineName: '' }, updateSettings: mocks.updateSettings } - const { container } = render() - await act(async () => {}) - - expect(container).toBeEmptyDOMElement() - }) }) diff --git a/src/renderer/src/components/settings/ShareSkillsSettingsPane.test.tsx b/src/renderer/src/components/settings/ShareSkillsSettingsPane.test.tsx deleted file mode 100644 index 06052b4caf3..00000000000 --- a/src/renderer/src/components/settings/ShareSkillsSettingsPane.test.tsx +++ /dev/null @@ -1,138 +0,0 @@ -// @vitest-environment happy-dom - -import '@testing-library/jest-dom/vitest' -import { cleanup, render, screen } from '@testing-library/react' -import userEvent from '@testing-library/user-event' -import { TooltipProvider } from '@/components/ui/tooltip' -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' - -const mocks = vi.hoisted(() => ({ - connect: vi.fn(), - fetchAuthStatus: vi.fn(), - openSkillsPage: vi.fn(), - updateSettings: vi.fn(), - state: { - orcaProfileAuthStatus: { configured: true, state: 'connected' } as Record< - string, - unknown - > | null, - isWebClient: false, - settings: { showSkillsButton: false, agentSkillSharingEnabled: false } - } -})) - -vi.mock('@/i18n/i18n', () => ({ - translate: (_key: string, fallback: string) => fallback -})) - -vi.mock('@/lib/web-client-location', () => ({ - isWebClientLocation: () => mocks.state.isWebClient -})) - -vi.mock('@/store', () => ({ - useAppStore: (selector: (state: Record) => unknown) => - selector({ - ...mocks.state, - connectCurrentOrcaProfile: mocks.connect, - fetchOrcaProfileAuthStatus: mocks.fetchAuthStatus, - openSkillsPage: mocks.openSkillsPage, - updateSettings: mocks.updateSettings - }) -})) - -import { ShareSkillsSettingsPane } from './ShareSkillsSettingsPane' - -describe('ShareSkillsSettingsPane', () => { - beforeEach(() => { - mocks.connect.mockReset() - mocks.fetchAuthStatus.mockReset() - mocks.openSkillsPage.mockReset() - mocks.updateSettings.mockReset() - mocks.state.orcaProfileAuthStatus = { configured: true, state: 'connected' } - mocks.state.isWebClient = false - Object.defineProperty(window, 'api', { - configurable: true, - value: { - skills: { - listOwnedShares: vi.fn().mockResolvedValue({ status: 'ok', value: [] }), - revokeShare: vi.fn() - } - } - }) - }) - - afterEach(() => { - cleanup() - Reflect.deleteProperty(window, 'api') - }) - - it('explains unlisted multi-skill links and opens Skills', async () => { - const user = userEvent.setup() - render( - - - - ) - - expect(screen.getByText('Unlisted skill links')).toBeInTheDocument() - expect(screen.getByText('Select one or more skills')).toBeInTheDocument() - expect( - screen.getByText( - 'Anyone with the link can inspect and install all or selected skills without signing in.' - ) - ).toBeInTheDocument() - expect(screen.getByText(/installed on another machine remain there/)).toBeInTheDocument() - await user.click(screen.getByRole('button', { name: /Open Skills/ })) - expect(mocks.openSkillsPage).toHaveBeenCalledOnce() - }) - - it('offers owner sign-in while explaining recipients stay signed out', async () => { - const user = userEvent.setup() - mocks.state.orcaProfileAuthStatus = { configured: true, state: 'local' } - render( - - - - ) - - expect(screen.getByText('Sign in to share skills')).toBeInTheDocument() - expect(screen.getByText(/Recipients do not need an account/)).toBeInTheDocument() - await user.click(screen.getByRole('button', { name: 'Sign in to Orca' })) - expect(mocks.connect).toHaveBeenCalledOnce() - }) - - it('requires an explicit desktop grant for agent publishing', async () => { - const user = userEvent.setup() - render( - - - - ) - - await user.click( - screen.getByRole('switch', { - name: 'Allow agents and the Orca CLI to publish skill links' - }) - ) - expect(mocks.updateSettings).toHaveBeenCalledWith({ agentSkillSharingEnabled: true }) - }) - - it('does not offer desktop publishing from the web client', () => { - mocks.state.isWebClient = true - mocks.state.orcaProfileAuthStatus = { configured: true, state: 'local' } - render( - - - - ) - - expect(screen.getByText(/available in the Orca desktop app/)).toBeInTheDocument() - expect(screen.queryByRole('button', { name: /Open Skills/ })).not.toBeInTheDocument() - expect(screen.queryByRole('button', { name: 'Sign in to Orca' })).not.toBeInTheDocument() - expect( - screen.getByRole('switch', { - name: 'Allow agents and the Orca CLI to publish skill links' - }) - ).toBeDisabled() - }) -}) diff --git a/src/renderer/src/components/setup-guide/use-setup-guide-telemetry.test.ts b/src/renderer/src/components/setup-guide/use-setup-guide-telemetry.test.ts deleted file mode 100644 index fd6e3c73705..00000000000 --- a/src/renderer/src/components/setup-guide/use-setup-guide-telemetry.test.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { afterEach, describe, expect, it, vi } from 'vitest' -import type { FeatureWallSetupProgress } from '../feature-wall/feature-wall-setup-progress' -import { - FEATURE_WALL_SETUP_STEP_IDS, - type FeatureWallSetupStepId -} from '../../../../shared/feature-wall-setup-steps' -import { readEmittedSetupGuideStepIds } from '@/lib/feature-education-telemetry' -import { - createSetupGuideStepCompletionTelemetryState, - getSetupGuideTelemetryFirstIncompleteStepId, - recordSetupGuideStepCompletionTelemetry -} from './use-setup-guide-telemetry' - -const trackMock = vi.hoisted(() => vi.fn()) - -vi.mock('@/lib/telemetry', () => ({ - track: trackMock -})) - -afterEach(() => { - trackMock.mockClear() - vi.restoreAllMocks() - vi.unstubAllGlobals() -}) - -describe('setup guide step completion telemetry', () => { - it('uses setup-first ordering for setup-guide open first-incomplete telemetry', () => { - expect(getSetupGuideTelemetryFirstIncompleteStepId(createProgress({}))).toBe('notifications') - expect( - getSetupGuideTelemetryFirstIncompleteStepId( - createProgress({ - notifications: true, - 'default-agent': true, - 'agent-capabilities': true, - 'task-sources': true, - 'setup-script': true, - 'add-two-repos': true - }) - ) - ).toBe('two-worktrees') - expect( - getSetupGuideTelemetryFirstIncompleteStepId( - createProgress( - Object.fromEntries(FEATURE_WALL_SETUP_STEP_IDS.map((stepId) => [stepId, true])) as Record< - FeatureWallSetupStepId, - boolean - > - ) - ) - ).toBe('none') - }) - - it('seeds startup-hydrated completed steps without backfilling completion events', () => { - vi.stubGlobal('localStorage', createMemoryStorage()) - const state = createSetupGuideStepCompletionTelemetryState() - - recordSetupGuideStepCompletionTelemetry({ - state, - progress: createProgress({}), - setupGuideVisible: false - }) - recordSetupGuideStepCompletionTelemetry({ - state, - progress: createProgress({ 'two-worktrees': true }), - setupGuideVisible: false - }) - - expect(trackMock).not.toHaveBeenCalled() - expect([...readEmittedSetupGuideStepIds()]).toEqual(['two-worktrees']) - - recordSetupGuideStepCompletionTelemetry({ - state, - progress: createProgress({ browser: true, 'two-worktrees': true }), - setupGuideVisible: false - }) - - expect(trackMock).not.toHaveBeenCalled() - expect([...readEmittedSetupGuideStepIds()].sort()).toEqual(['browser', 'two-worktrees']) - }) - - it('emits visible setup-guide completions during the startup baseline window', () => { - vi.stubGlobal('localStorage', createMemoryStorage()) - const state = createSetupGuideStepCompletionTelemetryState() - - recordSetupGuideStepCompletionTelemetry({ - state, - progress: createProgress({}), - setupGuideVisible: true - }) - recordSetupGuideStepCompletionTelemetry({ - state, - progress: createProgress({ notifications: true }), - setupGuideVisible: true - }) - - expect(trackMock).toHaveBeenCalledWith('setup_guide_step_completed', { - step_id: 'notifications', - section_id: 'setup', - completed_count: 1, - total_steps: 8, - setup_guide_visible: true - }) - }) -}) - -function createProgress( - doneOverrides: Partial> -): FeatureWallSetupProgress { - const stepDone = Object.fromEntries( - FEATURE_WALL_SETUP_STEP_IDS.map((stepId) => [stepId, doneOverrides[stepId] === true]) - ) as Record - return { - ready: true, - stepDone, - coreDoneCount: FEATURE_WALL_SETUP_STEP_IDS.filter((stepId) => stepDone[stepId]).length, - coreTotal: FEATURE_WALL_SETUP_STEP_IDS.length - } -} - -function createMemoryStorage(): Storage { - const values = new Map() - return { - get length() { - return values.size - }, - clear: () => values.clear(), - getItem: (key) => values.get(key) ?? null, - key: (index) => [...values.keys()][index] ?? null, - removeItem: (key) => values.delete(key), - setItem: (key, value) => { - values.set(key, value) - } - } -} diff --git a/src/renderer/src/components/sidebar/worktree-context-menu-delete-intent.test.ts b/src/renderer/src/components/sidebar/worktree-context-menu-delete-intent.test.ts deleted file mode 100644 index e83bad3f440..00000000000 --- a/src/renderer/src/components/sidebar/worktree-context-menu-delete-intent.test.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' - -const mocks = vi.hoisted(() => ({ runDelete: vi.fn(), runBatchDelete: vi.fn() })) - -vi.mock('@/store', () => ({ useAppStore: { getState: vi.fn() } })) -vi.mock('./delete-worktree-flow', () => ({ - runWorktreeDelete: mocks.runDelete, - runWorktreeBatchDelete: mocks.runBatchDelete -})) - -import { - createWorktreeContextMenuDeleteIntent, - deferWorktreeContextMenuDeleteIntent, - runWorktreeContextMenuDeleteIntent -} from './worktree-context-menu-delete-intent' - -describe('createWorktreeContextMenuDeleteIntent', () => { - it('routes a same-id row through the host that owns the context menu', () => { - const local = { id: 'shared', instanceId: 'local-instance', hostId: 'local' as const } - const ssh = { id: 'shared', instanceId: 'ssh-instance', hostId: 'ssh:box' as const } - const intent = createWorktreeContextMenuDeleteIntent({ - worktree: ssh, - batchDeleteWorktrees: [local, ssh], - isMultiContext: false - }) - - runWorktreeContextMenuDeleteIntent(intent) - - expect(mocks.runDelete).toHaveBeenCalledWith('shared', { - expectedInstanceId: 'ssh-instance', - expectedHostId: 'ssh:box' - }) - }) - - it('keeps every selected host in a colliding batch', () => { - const worktrees = [ - { id: 'shared', instanceId: 'local-instance', hostId: 'local' as const }, - { id: 'shared', instanceId: 'ssh-instance', hostId: 'ssh:box' as const } - ] - const intent = createWorktreeContextMenuDeleteIntent({ - worktree: worktrees[1], - batchDeleteWorktrees: worktrees, - isMultiContext: true - }) - - runWorktreeContextMenuDeleteIntent(intent) - - expect(mocks.runBatchDelete).toHaveBeenCalledWith(worktrees) - }) - - it('preserves the folder owner host in a context-menu delete intent', () => { - const intent = createWorktreeContextMenuDeleteIntent({ - worktree: { - id: 'folder:shared', - instanceId: 'runtime-instance', - hostId: 'runtime:env-owner' - }, - batchDeleteWorktrees: [], - isMultiContext: false, - folderWorkspaceId: 'shared' - }) - - expect(intent).toEqual({ - kind: 'folder', - folderWorkspaceId: 'shared', - executionHostId: 'runtime:env-owner' - }) - }) -}) - -describe('deferWorktreeContextMenuDeleteIntent', () => { - beforeEach(() => { - vi.clearAllMocks() - }) - - afterEach(() => { - vi.useRealTimers() - vi.unstubAllGlobals() - }) - - it('dispatches the selected workspace identity after the menu event completes', () => { - const defer = vi.fn<(callback: () => void) => void>() - const intent = { - kind: 'worktree' as const, - worktree: { id: 'repo::/work/wt', instanceId: 'instance-1' } - } - const onDispatched = vi.fn() - - deferWorktreeContextMenuDeleteIntent(intent, onDispatched, defer) - - expect(mocks.runDelete).not.toHaveBeenCalled() - expect(onDispatched).not.toHaveBeenCalled() - expect(defer).toHaveBeenCalledOnce() - - const [deferred] = defer.mock.calls[0] - deferred() - - expect(mocks.runDelete).toHaveBeenCalledWith('repo::/work/wt', { - expectedInstanceId: 'instance-1' - }) - expect(onDispatched).toHaveBeenCalledOnce() - }) - - it('preserves every selected workspace identity for batch validation', () => { - const intent = { - kind: 'batch' as const, - worktrees: [ - { id: 'wt-1', instanceId: 'instance-1' }, - { id: 'wt-2', instanceId: 'instance-2' } - ] - } - - deferWorktreeContextMenuDeleteIntent(intent, undefined, (callback) => callback()) - - expect(mocks.runBatchDelete).toHaveBeenCalledWith(intent.worktrees) - }) - - it('dispatches on the next macrotask by default', () => { - vi.useFakeTimers() - vi.stubGlobal('window', { setTimeout }) - const intent = { - kind: 'worktree' as const, - worktree: { id: 'wt-1', instanceId: 'instance-1' } - } - - deferWorktreeContextMenuDeleteIntent(intent) - - expect(mocks.runDelete).not.toHaveBeenCalled() - vi.runAllTimers() - expect(mocks.runDelete).toHaveBeenCalledWith('wt-1', { - expectedInstanceId: 'instance-1' - }) - }) -}) diff --git a/src/renderer/src/components/sidebar/worktree-list/listing/use-order-hold.test.ts b/src/renderer/src/components/sidebar/worktree-list/listing/use-order-hold.test.ts index 04480984983..fb722dc500b 100644 --- a/src/renderer/src/components/sidebar/worktree-list/listing/use-order-hold.test.ts +++ b/src/renderer/src/components/sidebar/worktree-list/listing/use-order-hold.test.ts @@ -82,20 +82,6 @@ describe('useOrderHeldWhileEngaged', () => { fire(row, 'dragend') expect(result.current).toEqual(['b', 'a']) }) - - it('never holds Manual or Name: your own drop or rename shows at once', () => { - const { row } = mountList() - const { result, rerender } = renderHook( - ({ ids, sortBy }: { ids: string[]; sortBy: SortBy }) => useOrderHeldWhileEngaged(ids, sortBy), - { initialProps: { ids: ['a', 'b'], sortBy: 'manual' } } - ) - fire(row, 'pointerover') - fire(row, 'dragstart') - rerender({ ids: ['b', 'a'], sortBy: 'manual' }) - expect(result.current).toEqual(['b', 'a']) - rerender({ ids: ['a', 'b'], sortBy: 'name' }) - expect(result.current).toEqual(['a', 'b']) - }) }) describe('useProjectRecencyHeldWhileEngaged', () => { diff --git a/src/renderer/src/components/skills/SkillFreshnessStatusPill.test.tsx b/src/renderer/src/components/skills/SkillFreshnessStatusPill.test.tsx deleted file mode 100644 index 401f9cb03b4..00000000000 --- a/src/renderer/src/components/skills/SkillFreshnessStatusPill.test.tsx +++ /dev/null @@ -1,135 +0,0 @@ -// @vitest-environment happy-dom - -import { act } from 'react' -import { createRoot, type Root } from 'react-dom/client' -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import type { BundledSkillPlan } from '../../../../shared/bundled-skill-plan' -import { SkillFreshnessStatusPill } from './SkillFreshnessStatusPill' -import { consumeSkillFreshnessUpdateDialogRequest } from './skill-freshness-update-dialog' -import { planEntry, planOf, planOp, sharedEntry } from './bundled-skill-plan-fixtures.test-support' - -const mocks = vi.hoisted(() => ({ - plan: ((): BundledSkillPlan | null => null)(), - loading: false, - error: null as string | null -})) - -vi.mock('@/hooks/useSkillFreshness', () => ({ - useSkillFreshness: () => ({ - plan: mocks.plan, - loading: mocks.loading, - error: mocks.error, - refresh: vi.fn() - }) -})) - -function detailsButton(container: HTMLDivElement): HTMLButtonElement | null { - return container.querySelector('[data-slot="button"]') -} - -function pillText(container: HTMLDivElement): string { - return (container.textContent ?? '').replace(detailsButton(container)?.textContent ?? '', '') -} - -let root: Root | null = null -let container: HTMLDivElement | null = null - -async function renderPill(skillName: string): Promise { - container = document.createElement('div') - document.body.appendChild(container) - root = createRoot(container) - await act(async () => { - root?.render() - }) - return container -} - -describe('SkillFreshnessStatusPill', () => { - beforeEach(() => { - mocks.plan = null - mocks.loading = false - mocks.error = null - // Why: the dialog request is module-level state shared across tests. - consumeSkillFreshnessUpdateDialogRequest() - }) - - afterEach(async () => { - if (root) { - await act(async () => root?.unmount()) - } - root = null - container?.remove() - container = null - }) - - it('shows Update available when the plan updates the skill', async () => { - mocks.plan = planOf([sharedEntry('orca-cli', 'update')]) - - const rendered = await renderPill('orca-cli') - expect(pillText(rendered)).toBe('Update available') - expect(detailsButton(rendered)?.textContent).toBe('Details') - }) - - it('shows Up to date when every location is current', async () => { - mocks.plan = planOf([sharedEntry('orca-cli', 'keep')]) - - const rendered = await renderPill('orca-cli') - expect(pillText(rendered)).toBe('Up to date') - expect(detailsButton(rendered)).toBeNull() - }) - - it('offers Details beside Installed when an agent still needs linking', async () => { - mocks.plan = planOf([ - planEntry('orca-cli', [ - planOp('keep', '/home/u/.agents/skills/orca-cli'), - planOp('link', '/home/u/.claude/skills/orca-cli') - ]) - ]) - - const rendered = await renderPill('orca-cli') - expect(pillText(rendered)).toBe('Installed') - expect(detailsButton(rendered)?.textContent).toBe('Details') - }) - - it('flags a copy the update leaves alone instead of reading as all-clear', async () => { - mocks.plan = planOf([sharedEntry('orca-cli', 'leave', { reason: 'edited' })]) - - const rendered = await renderPill('orca-cli') - // Why: a green pill over a copy the update cannot reach hides real drift. - expect(pillText(rendered)).toBe('Review skill') - expect(detailsButton(rendered)?.textContent).toBe('Details') - }) - - it('falls back to Installed before the plan loads', async () => { - const rendered = await renderPill('orca-cli') - expect(pillText(rendered)).toBe('Installed') - expect(detailsButton(rendered)).toBeNull() - }) - - it('shows a neutral verdict while freshness is being checked', async () => { - mocks.loading = true - - const rendered = await renderPill('orca-cli') - expect(pillText(rendered)).toBe('Checking...') - expect(detailsButton(rendered)).toBeNull() - }) - - it('does not report success after a freshness check fails', async () => { - mocks.error = 'Could not read skills.' - - const rendered = await renderPill('orca-cli') - expect(pillText(rendered)).toBe('Check failed') - expect(detailsButton(rendered)).toBeNull() - }) - - it('opens the freshness review dialog from Details', async () => { - mocks.plan = planOf([sharedEntry('orca-cli', 'update')]) - const rendered = await renderPill('orca-cli') - - await act(async () => { - detailsButton(rendered)?.click() - }) - - expect(consumeSkillFreshnessUpdateDialogRequest()).toBe(true) - }) -}) diff --git a/src/renderer/src/components/skills/SkillFreshnessUpdateDialog.target.test.tsx b/src/renderer/src/components/skills/SkillFreshnessUpdateDialog.target.test.tsx index f269271351b..bc5dfeeed5f 100644 --- a/src/renderer/src/components/skills/SkillFreshnessUpdateDialog.target.test.tsx +++ b/src/renderer/src/components/skills/SkillFreshnessUpdateDialog.target.test.tsx @@ -1,15 +1,14 @@ // @vitest-environment happy-dom -import { act, type ReactNode } from 'react' +import type { ReactNode } from 'react' + import { cleanup, fireEvent, render, screen, waitFor, within } from '@testing-library/react' import { afterEach, beforeEach, expect, it, vi } from 'vitest' import type { BundledSkillTarget } from '@/lib/bundled-skill-target' import { AgentSkillSetupPanel } from '../settings/AgentSkillSetupPanel' import { SkillFreshnessUpdateDialog } from './SkillFreshnessUpdateDialog' -import { - consumeSkillFreshnessUpdateDialogRequest, - requestSkillFreshnessUpdateDialog -} from './skill-freshness-update-dialog' +import { consumeSkillFreshnessUpdateDialogRequest } from './skill-freshness-update-dialog' + import { _resetSkillUpdateRunStore } from './skill-update-run-store' import { doneResult, @@ -118,15 +117,3 @@ it('reviews and replaces the setup panel host while a remote workspace is active }) ) }) - -it('uses the active workspace for requests without an originating target', async () => { - act(() => requestSkillFreshnessUpdateDialog()) - render() - const dialog = within(screen.getByRole('dialog')) - expect(dialog.getByText('orchestration')).toBeDefined() - expect(dialog.queryByText('orca-cli')).toBeNull() - fireEvent.click(dialog.getByRole('button', { name: 'Update 1 skill' })) - await waitFor(() => - expect(mocks.execute).toHaveBeenCalledWith(REMOTE, remotePlan.planDigest, { force: [] }) - ) -}) diff --git a/src/renderer/src/components/status-bar/usage-roster-row-state.test.ts b/src/renderer/src/components/status-bar/usage-roster-row-state.test.ts deleted file mode 100644 index 0b943525c2d..00000000000 --- a/src/renderer/src/components/status-bar/usage-roster-row-state.test.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { describe, expect, it, vi } from 'vitest' -import type { ProviderRateLimits } from '../../../../shared/rate-limit-types' - -vi.mock('@/i18n/i18n', () => ({ - translate: (_key: string, fallback: string, values?: Record) => - Object.entries(values ?? {}).reduce( - (text, [name, value]) => text.replace(`{{${name}}}`, value), - fallback - ) -})) - -import { getUsageRosterRowState } from './usage-roster-row-state' - -function provider(overrides: Partial = {}): ProviderRateLimits { - return { - provider: 'claude', - session: null, - weekly: null, - updatedAt: 0, - error: null, - status: 'ok', - ...overrides - } -} - -describe('getUsageRosterRowState', () => { - it('keeps fetching providers in a loading state instead of calling them signed out', () => { - expect(getUsageRosterRowState(provider({ status: 'fetching' }), false)).toEqual({ - kind: 'loading', - statusLabel: 'Loading usage…' - }) - }) - - it('preserves transient Claude failure copy instead of offering sign-in', () => { - expect( - getUsageRosterRowState( - provider({ - status: 'error', - error: 'OAuth token is stale', - usageMetadata: { failureKind: 'stale-token' } - }), - false - ) - ).toEqual({ kind: 'error', statusLabel: 'Updates when Claude runs' }) - expect( - getUsageRosterRowState( - provider({ - status: 'error', - error: 'network unavailable', - usageMetadata: { failureKind: 'network' } - }), - false - ) - ).toEqual({ kind: 'error', statusLabel: 'Network issue' }) - }) - - it('offers sign-in only for confirmed signed-out failures', () => { - expect( - getUsageRosterRowState( - provider({ status: 'error', usageMetadata: { failureKind: 'missing-credentials' } }), - false - ) - ).toEqual({ kind: 'sign-in', statusLabel: 'not signed in' }) - expect( - getUsageRosterRowState( - provider({ - provider: 'codex', - status: 'error', - error: 'ChatGPT authentication required to read rate limits' - }), - false - ) - ).toEqual({ kind: 'sign-in', statusLabel: 'not signed in' }) - }) - - it('does not turn an expired CLI-owned Kimi token into a sign-in action', () => { - expect( - getUsageRosterRowState( - provider({ - provider: 'kimi', - status: 'error', - error: 'Kimi token expired — open Kimi to refresh' - }), - false - ) - ).toEqual({ kind: 'error', statusLabel: 'Refresh failed' }) - }) - - it('distinguishes unavailable and empty successful responses', () => { - expect( - getUsageRosterRowState( - provider({ status: 'unavailable', error: 'Claude CLI not found' }), - false - ) - ).toEqual({ kind: 'unavailable', statusLabel: 'Usage unavailable' }) - expect(getUsageRosterRowState(provider(), false)).toEqual({ - kind: 'empty', - statusLabel: 'No usage data' - }) - }) - - it('lets real usage data win over a stale error status', () => { - expect(getUsageRosterRowState(provider({ status: 'error' }), true)).toEqual({ - kind: 'usage', - statusLabel: null - }) - }) - - it('names the host for a provider set up only on this computer, with the key note', () => { - expect( - getUsageRosterRowState( - provider({ - provider: 'minimax', - status: 'error', - error: 'Not configured on devbox', - usageMetadata: { - ownerNotSetUp: { - kind: 'not-configured', - ownerLabel: 'devbox', - signInSavedHereOnly: true - } - } - }), - false - ) - ).toEqual({ - kind: 'unavailable', - statusLabel: 'Not configured on devbox', - detail: 'Its sign-in is saved on this computer only.' - }) - }) -}) diff --git a/src/renderer/src/components/terminal-pane/remote-runtime-pty-snapshot-escape-tail.test.ts b/src/renderer/src/components/terminal-pane/remote-runtime-pty-snapshot-escape-tail.test.ts index 3565cc43094..a59ccd6ed3c 100644 --- a/src/renderer/src/components/terminal-pane/remote-runtime-pty-snapshot-escape-tail.test.ts +++ b/src/renderer/src/components/terminal-pane/remote-runtime-pty-snapshot-escape-tail.test.ts @@ -21,7 +21,7 @@ import { } from '../../../../shared/terminal-stream-protocol' import { stubRuntimeEnvironmentBridge } from '../../runtime/runtime-environment-bridge-fixture' -// Drive real wire frames through multiplexer and transport so SnapshotStart’s pending escape reaches replay; server counterpart: terminal-multiplex-escape-tail.test.ts (#7329). +// Drive real wire frames through multiplexer and transport so SnapshotStart’s pending escape reaches replay. describe('remote transport snapshot escape-tail threading (#7329)', () => { const runtimeCall = vi.fn() diff --git a/src/renderer/src/components/terminal-pane/terminal-captured-input-dispatch.test.ts b/src/renderer/src/components/terminal-pane/terminal-captured-input-dispatch.test.ts index 4dbd2eec471..9d8a16cebb5 100644 --- a/src/renderer/src/components/terminal-pane/terminal-captured-input-dispatch.test.ts +++ b/src/renderer/src/components/terminal-pane/terminal-captured-input-dispatch.test.ts @@ -1,9 +1,6 @@ import { describe, expect, it, vi } from 'vitest' import type { PtyTransport } from './pty-transport-types' -import { - requestCapturedTerminalReconfirmation, - sendCapturedTerminalInput -} from './terminal-captured-input-dispatch' +import { sendCapturedTerminalInput } from './terminal-captured-input-dispatch' function createTransport(ptyId: string | null, sendResult = true): PtyTransport { return { @@ -13,57 +10,6 @@ function createTransport(ptyId: string | null, sendResult = true): PtyTransport } describe('sendCapturedTerminalInput', () => { - it('sends on the captured route while its PTY still owns the mounted pane', () => { - const transport = createTransport('pty-original') - - expect( - sendCapturedTerminalInput({ - targetPaneMounted: true, - currentTransport: transport, - capturedTransport: transport, - capturedPtyId: 'pty-original', - data: '\r' - }) - ).toBe(true) - expect(transport.sendInput).toHaveBeenCalledWith('\r', 'driving') - }) - - it('runs the accepted callback only after a successful captured send', () => { - const transport = createTransport('pty-original') - const onAccepted = vi.fn() - - expect( - sendCapturedTerminalInput({ - targetPaneMounted: true, - currentTransport: transport, - capturedTransport: transport, - capturedPtyId: 'pty-original', - data: '\x1b[13;2u', - onAccepted - }) - ).toBe(true) - - expect(onAccepted).toHaveBeenCalledOnce() - }) - - it('does not run the accepted callback for a rejected captured send', () => { - const transport = createTransport('pty-original', false) - const onAccepted = vi.fn() - - expect( - sendCapturedTerminalInput({ - targetPaneMounted: true, - currentTransport: transport, - capturedTransport: transport, - capturedPtyId: 'pty-original', - data: '\x1b[13;2u', - onAccepted - }) - ).toBe(false) - - expect(onAccepted).not.toHaveBeenCalled() - }) - it('does not deliver to a replacement transport for a reused pane', () => { const original = createTransport('pty-original') const replacement = createTransport('pty-replacement') @@ -114,24 +60,3 @@ describe('sendCapturedTerminalInput', () => { expect(transport.sendInput).not.toHaveBeenCalled() }) }) - -describe('requestCapturedTerminalReconfirmation', () => { - it('reconfirms only through the still-current captured binding', () => { - const requestWindowsShiftEnterReconfirmation = vi.fn() - const binding = { requestWindowsShiftEnterReconfirmation } - - requestCapturedTerminalReconfirmation(binding, binding) - - expect(requestWindowsShiftEnterReconfirmation).toHaveBeenCalledOnce() - }) - - it('does not call a disposed binding or its replacement', () => { - const original = { requestWindowsShiftEnterReconfirmation: vi.fn() } - const replacement = { requestWindowsShiftEnterReconfirmation: vi.fn() } - - requestCapturedTerminalReconfirmation(replacement, original) - - expect(original.requestWindowsShiftEnterReconfirmation).not.toHaveBeenCalled() - expect(replacement.requestWindowsShiftEnterReconfirmation).not.toHaveBeenCalled() - }) -}) diff --git a/src/renderer/src/components/terminal-pane/terminal-pane-layout-owner-commands.test.ts b/src/renderer/src/components/terminal-pane/terminal-pane-layout-owner-commands.test.ts index a1169c652a0..c48d5a581cb 100644 --- a/src/renderer/src/components/terminal-pane/terminal-pane-layout-owner-commands.test.ts +++ b/src/renderer/src/components/terminal-pane/terminal-pane-layout-owner-commands.test.ts @@ -48,39 +48,6 @@ describe('equalizeTerminalPanes', () => { } } - it('a window-owned build equalizes at once, without asking main', () => { - const current = manager() - const then = vi.fn() - - equalizeTerminalPanes( - { worktreeId: 'worktree-1', tabId: 'tab-1', getManager: () => current }, - then - ) - - expect(current.equalizePaneSizes).toHaveBeenCalledOnce() - expect(then).toHaveBeenCalledWith(current) - expect(mocks.callRuntimeRpc).not.toHaveBeenCalled() - }) - - it('a layout-owner build leaves the sizes to main’s frame, then focuses', async () => { - mocks.layoutOwnerIsMain = true - beginLayoutFramePositions() - mocks.callRuntimeRpc.mockResolvedValue({ ok: true, result: {} }) - const current = manager() - const then = vi.fn() - - equalizeTerminalPanes( - { worktreeId: 'worktree-1', tabId: 'tab-1', getManager: () => current }, - then - ) - - expect(mocks.callRuntimeRpc).toHaveBeenCalledWith({ kind: 'local' }, 'layout.apply', { - command: { type: 'equalizePanes', tabId: 'tab-1', workspace: 'worktree-1' } - }) - await vi.waitFor(() => expect(then).toHaveBeenCalledWith(current)) - expect(current.equalizePaneSizes).not.toHaveBeenCalled() - }) - it('a layout-owner build equalizes itself when no frame is coming', async () => { mocks.layoutOwnerIsMain = true beginLayoutFramePositions() diff --git a/src/renderer/src/components/terminal-pane/terminal-parking-e2e-overrides.test.ts b/src/renderer/src/components/terminal-pane/terminal-parking-e2e-overrides.test.ts deleted file mode 100644 index b15b8712b45..00000000000 --- a/src/renderer/src/components/terminal-pane/terminal-parking-e2e-overrides.test.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' - -type MockE2EConfig = { - exposeStore: boolean - terminalParkingDelayMs: number | null - terminalRetentionLimit: number | null -} - -let mockE2EConfig: MockE2EConfig - -vi.mock('@/lib/e2e-config', () => ({ - get e2eConfig() { - return mockE2EConfig - } -})) - -vi.mock('./terminal-parked-tab-watchers', () => ({ - getParkedTerminalWatcherTabIds: () => ['tab-parked'] -})) - -const originalWindow = (globalThis as { window?: unknown }).window - -type TerminalParkingE2EOverridesModule = { - getTerminalParkingPolicyOverrides: () => { - coldParkDelayMs?: number - hotRetainMs?: number - hotRetainLimit?: number - retentionTtlMs?: number - retentionLimit?: number - } - registerTerminalParkingDebugHandle: () => void -} - -async function importOverridesModule(): Promise { - vi.resetModules() - return import('./terminal-parking-e2e-overrides') -} - -describe('getTerminalParkingPolicyOverrides', () => { - beforeEach(() => { - mockE2EConfig = { - exposeStore: false, - terminalParkingDelayMs: null, - terminalRetentionLimit: null - } - delete (globalThis as { window?: unknown }).window - }) - - afterEach(() => { - ;(globalThis as { window?: unknown }).window = originalWindow - }) - - it('ignores the delay override outside e2e (exposeStore off)', async () => { - mockE2EConfig = { - exposeStore: false, - terminalParkingDelayMs: 500, - terminalRetentionLimit: null - } - const { getTerminalParkingPolicyOverrides } = await importOverridesModule() - expect(getTerminalParkingPolicyOverrides()).toEqual({}) - }) - - it('maps the e2e delay to coldParkDelayMs and hotRetainMs but never the absolute retention TTL', async () => { - mockE2EConfig = { exposeStore: true, terminalParkingDelayMs: 500, terminalRetentionLimit: null } - const { getTerminalParkingPolicyOverrides } = await importOverridesModule() - expect(getTerminalParkingPolicyOverrides()).toEqual({ - coldParkDelayMs: 500, - hotRetainMs: 500 - }) - }) - - it('returns no overrides when no delay is configured', async () => { - mockE2EConfig = { - exposeStore: true, - terminalParkingDelayMs: null, - terminalRetentionLimit: null - } - const { getTerminalParkingPolicyOverrides } = await importOverridesModule() - expect(getTerminalParkingPolicyOverrides()).toEqual({}) - }) - - it('maps the e2e retention limit independently of the delay', async () => { - mockE2EConfig = { exposeStore: true, terminalParkingDelayMs: null, terminalRetentionLimit: 1 } - const { getTerminalParkingPolicyOverrides } = await importOverridesModule() - expect(getTerminalParkingPolicyOverrides()).toEqual({ retentionLimit: 1 }) - }) - - it('combines the delay overrides with the retention limit when both are set', async () => { - mockE2EConfig = { exposeStore: true, terminalParkingDelayMs: 500, terminalRetentionLimit: 1 } - const { getTerminalParkingPolicyOverrides } = await importOverridesModule() - expect(getTerminalParkingPolicyOverrides()).toEqual({ - coldParkDelayMs: 500, - hotRetainMs: 500, - retentionLimit: 1 - }) - }) - - it('ignores the retention limit outside e2e (exposeStore off)', async () => { - mockE2EConfig = { exposeStore: false, terminalParkingDelayMs: null, terminalRetentionLimit: 1 } - const { getTerminalParkingPolicyOverrides } = await importOverridesModule() - expect(getTerminalParkingPolicyOverrides()).toEqual({}) - }) - - it('rejects non-integer or non-positive retention limits', async () => { - mockE2EConfig = { exposeStore: true, terminalParkingDelayMs: null, terminalRetentionLimit: 1.5 } - const overridesModule = await importOverridesModule() - expect(overridesModule.getTerminalParkingPolicyOverrides()).toEqual({}) - mockE2EConfig = { exposeStore: true, terminalParkingDelayMs: null, terminalRetentionLimit: 0 } - expect(overridesModule.getTerminalParkingPolicyOverrides()).toEqual({}) - }) - - it('registers window.__terminalParkingDebug on import under exposeStore', async () => { - mockE2EConfig = { exposeStore: true, terminalParkingDelayMs: 500, terminalRetentionLimit: null } - const testWindow: { - __terminalParkingDebug?: { parkDelayMs: number; parkedTabIds: () => string[] } - } = {} - ;(globalThis as { window?: unknown }).window = testWindow - await importOverridesModule() - expect(testWindow.__terminalParkingDebug?.parkDelayMs).toBe(500) - expect(testWindow.__terminalParkingDebug?.parkedTabIds()).toEqual(['tab-parked']) - }) - - it('does not register the debug handle outside e2e', async () => { - mockE2EConfig = { - exposeStore: false, - terminalParkingDelayMs: null, - terminalRetentionLimit: null - } - const testWindow: { __terminalParkingDebug?: unknown } = {} - ;(globalThis as { window?: unknown }).window = testWindow - await importOverridesModule() - expect(testWindow.__terminalParkingDebug).toBeUndefined() - }) -}) diff --git a/src/renderer/src/components/terminal-pane/terminal-quick-command-dispatch.test.ts b/src/renderer/src/components/terminal-pane/terminal-quick-command-dispatch.test.ts deleted file mode 100644 index 11c0449bd96..00000000000 --- a/src/renderer/src/components/terminal-pane/terminal-quick-command-dispatch.test.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { beforeEach, describe, expect, it, vi } from 'vitest' - -const mocks = vi.hoisted(() => ({ - recordTerminalUserInputForLeaf: vi.fn() -})) - -vi.mock('./terminal-input-activity', () => ({ - recordTerminalUserInputForLeaf: mocks.recordTerminalUserInputForLeaf -})) -import { sendTerminalQuickCommandToPane } from './terminal-quick-command-dispatch' - -function createPane() { - return { - leafId: 'leaf-1', - terminal: { - focus: vi.fn() - } - } -} - -describe('sendTerminalQuickCommandToPane', () => { - beforeEach(() => { - vi.clearAllMocks() - }) - - it('writes the formatted command to the PTY transport and refocuses the terminal', () => { - const sendInput = vi.fn(() => true) - const pane = createPane() - - const sent = sendTerminalQuickCommandToPane({ - command: { - id: 'status', - label: 'Status', - command: 'git status', - appendEnter: true - }, - pane, - tabId: 'tab-1', - transport: { sendInput } - }) - - expect(sent).toBe(true) - expect(sendInput).toHaveBeenCalledWith('git status\r', 'driving') - expect(pane.terminal.focus).toHaveBeenCalledOnce() - expect(mocks.recordTerminalUserInputForLeaf).toHaveBeenCalledWith('tab-1', 'leaf-1') - }) - - it('does not focus the terminal when no connected transport accepts input', () => { - const sendInput = vi.fn(() => false) - const pane = createPane() - - const sent = sendTerminalQuickCommandToPane({ - command: { - id: 'draft', - label: 'Draft', - command: 'npm test', - appendEnter: false - }, - pane, - tabId: 'tab-1', - transport: { sendInput } - }) - - expect(sent).toBe(false) - expect(sendInput).toHaveBeenCalledWith('npm test', 'driving') - expect(pane.terminal.focus).not.toHaveBeenCalled() - expect(mocks.recordTerminalUserInputForLeaf).not.toHaveBeenCalled() - }) - - it('flattens multiline commands with semicolons before sending', () => { - const sendInput = vi.fn(() => true) - const pane = createPane() - const commandText = 'cd packages\nbun run build\ncd ..' - - const sent = sendTerminalQuickCommandToPane({ - command: { - id: 'build', - label: 'Build', - command: commandText, - appendEnter: true - }, - pane, - tabId: 'tab-1', - transport: { sendInput } - }) - - expect(sent).toBe(true) - expect(sendInput).toHaveBeenCalledWith('cd packages; bun run build; cd ..\r', 'driving') - expect(pane.terminal.focus).toHaveBeenCalledOnce() - }) - - it('flattens multiline insert-only commands without submitting', () => { - const sendInput = vi.fn(() => true) - const pane = createPane() - const commandText = 'echo one\necho two' - - const sent = sendTerminalQuickCommandToPane({ - command: { - id: 'insert', - label: 'Insert', - command: commandText, - appendEnter: false - }, - pane, - tabId: 'tab-1', - transport: { sendInput } - }) - - expect(sent).toBe(true) - expect(sendInput).toHaveBeenCalledWith('echo one; echo two', 'driving') - expect(pane.terminal.focus).toHaveBeenCalledOnce() - }) - - it('does not write agent prompt quick commands into the current pane', () => { - const sendInput = vi.fn(() => true) - const focus = vi.fn() - - const sent = sendTerminalQuickCommandToPane({ - command: { - id: 'agent', - label: 'Agent', - action: 'agent-prompt', - agent: 'codex', - prompt: 'Review this' - }, - pane: { leafId: 'leaf-1', terminal: { focus } }, - tabId: 'tab-1', - transport: { sendInput } - }) - - expect(sent).toBe(false) - expect(sendInput).not.toHaveBeenCalled() - expect(focus).not.toHaveBeenCalled() - expect(mocks.recordTerminalUserInputForLeaf).not.toHaveBeenCalled() - }) -}) diff --git a/src/renderer/src/hooks/composer-state/draft-target-sync.test.ts b/src/renderer/src/hooks/composer-state/draft-target-sync.test.ts deleted file mode 100644 index 858efa77385..00000000000 --- a/src/renderer/src/hooks/composer-state/draft-target-sync.test.ts +++ /dev/null @@ -1,131 +0,0 @@ -// @vitest-environment happy-dom - -import { renderHook } from '@testing-library/react' -import { describe, expect, it, vi } from 'vitest' -import { useDraftTargetSync, type DraftTargetSyncInput } from './draft-target-sync' - -function createRepo(id: string): DraftTargetSyncInput['eligibleRepos'][number] { - return { - id, - path: `/repos/${id}`, - displayName: id, - badgeColor: '#000000', - addedAt: 0 - } -} - -function createState(overrides: Partial = {}): DraftTargetSyncInput { - const defaults = { - agentPrompt: 'Fix the issue', - attachmentPaths: ['/tmp/context.txt'], - baseBranch: 'main', - baseBranchNamesWorkspace: true, - compareBaseRef: 'origin/main', - eligibleRepos: [], - fetchSparsePresets: vi.fn(), - folderSourceRepos: [], - isProjectGroupTarget: false, - linkedGitLabIssue: null, - linkedGitLabMR: null, - linkedIssue: '', - linkedPR: null, - linkedWorkItem: null, - name: 'workspace-name', - note: 'note', - persistDraft: true, - pendingInitialWorkspaceTarget: null, - repoId: '', - selectedProjectGroup: null, - selectedRepo: undefined, - selectedRepoIsGit: false, - selectedWorkspaceTarget: { - status: 'unavailable', - reason: 'no-eligible-repo' - }, - setNewWorkspaceDraft: vi.fn(), - setRepoId: vi.fn(), - sparsePresetsByRepo: {}, - taskSourceContext: null, - tuiAgent: 'claude' - } satisfies DraftTargetSyncInput - return { ...defaults, ...overrides } -} - -describe('useDraftTargetSync', () => { - it('persists the current external draft before repairing an empty repo target', () => { - const calls: string[] = [] - const setNewWorkspaceDraft = vi.fn(() => calls.push('persist')) - const setRepoId = vi.fn(() => calls.push('repair')) - const state = createState({ - eligibleRepos: [createRepo('repo-1')], - setNewWorkspaceDraft, - setRepoId - }) - - renderHook(() => useDraftTargetSync(state)) - - expect(calls).toEqual(['persist', 'repair']) - expect(setNewWorkspaceDraft).toHaveBeenCalledTimes(1) - expect(setRepoId).toHaveBeenCalledTimes(1) - expect(setNewWorkspaceDraft).toHaveBeenCalledWith( - expect.objectContaining({ - repoId: null, - name: 'workspace-name', - prompt: 'Fix the issue', - attachments: ['/tmp/context.txt'], - baseBranch: 'main', - compareBaseRef: 'origin/main' - }) - ) - expect(setRepoId).toHaveBeenCalledWith('repo-1') - }) - - it('persists whether the base ref also names the workspace', () => { - const setNewWorkspaceDraft = vi.fn() - const state = createState({ - eligibleRepos: [createRepo('repo-1')], - baseBranch: 'release/2.1', - baseBranchNamesWorkspace: false, - setNewWorkspaceDraft - }) - - renderHook(() => useDraftTargetSync(state)) - - expect(setNewWorkspaceDraft).toHaveBeenCalledWith( - expect.objectContaining({ - baseBranch: 'release/2.1', - baseBranchNamesWorkspace: false - }) - ) - }) - - it('does not persist or repair transient quick-composer state', () => { - const state = createState({ - persistDraft: false, - isProjectGroupTarget: true, - eligibleRepos: [createRepo('repo-1')] - }) - - renderHook(() => useDraftTargetSync(state)) - - expect(state.setNewWorkspaceDraft).not.toHaveBeenCalled() - expect(state.setRepoId).not.toHaveBeenCalled() - }) - - it('loads sparse presets only once for a local git repo', () => { - const fetchSparsePresets = vi.fn() - const state = createState({ - repoId: 'repo-1', - selectedRepoIsGit: true, - selectedRepo: createRepo('repo-1'), - fetchSparsePresets, - sparsePresetsByRepo: {} - }) - const hook = renderHook(() => useDraftTargetSync(state)) - - expect(fetchSparsePresets).toHaveBeenCalledWith('repo-1') - - hook.rerender() - expect(fetchSparsePresets).toHaveBeenCalledTimes(1) - }) -}) diff --git a/src/renderer/src/hooks/ipc-events/browser-request-ipc-bridge.split.test.ts b/src/renderer/src/hooks/ipc-events/browser-request-ipc-bridge.split.test.ts index 4fb2cb64906..9ad45ba5184 100644 --- a/src/renderer/src/hooks/ipc-events/browser-request-ipc-bridge.split.test.ts +++ b/src/renderer/src/hooks/ipc-events/browser-request-ipc-bridge.split.test.ts @@ -124,10 +124,4 @@ describe('browser tab create with a split pane', () => { expect.objectContaining({ split: expect.objectContaining({ sourceGroupId: 'g-terminal' }) }) ) }) - - it('adds a plain tab without --split', () => { - mocks.createListener?.({ requestId: 'r3', worktreeId: WT, url: 'about:blank' }) - - expect(mocks.createBrowserTab.mock.calls[0]?.[2]).not.toHaveProperty('split') - }) }) diff --git a/src/renderer/src/hooks/ipc-tab-switch-structured-tab-cycle.test.ts b/src/renderer/src/hooks/ipc-tab-switch-structured-tab-cycle.test.ts index cfda766ca33..8e2b75c3428 100644 --- a/src/renderer/src/hooks/ipc-tab-switch-structured-tab-cycle.test.ts +++ b/src/renderer/src/hooks/ipc-tab-switch-structured-tab-cycle.test.ts @@ -92,16 +92,6 @@ function storeWithStructuredTabActive({ describe('handleSwitchTerminalTab with a structured chat tab active', () => { beforeEach(() => vi.clearAllMocks()) - it('leaves activeTabId naming a live background terminal', () => { - // Require the stale ID to exist in the terminal list or the buggy path would pass. - mocks.store = storeWithStructuredTabActive({ - terminalIds: ['term-1', 'term-2', 'term-3'], - lastFocusedTerminalId: 'term-2' - }) - expect(mocks.store.activeTabType).toBe('agent-session') - expect(mocks.store.activeTabId).toBe('term-2') - }) - it('jumps to the first terminal instead of cycling from the background terminal', () => { mocks.store = storeWithStructuredTabActive({ terminalIds: ['term-1', 'term-2', 'term-3'], @@ -123,15 +113,4 @@ describe('handleSwitchTerminalTab with a structured chat tab active', () => { expect(handleSwitchTerminalTab(1)).toBe(true) expect(mocks.store.setActiveTab).toHaveBeenCalledWith('term-1') }) - - it('still cycles normally from a focused terminal tab', () => { - mocks.store = storeWithStructuredTabActive({ - terminalIds: ['term-1', 'term-2', 'term-3'], - lastFocusedTerminalId: 'term-2', - activeGroupTabId: 'unified-term-2' - }) - expect(mocks.store.activeTabType).toBe('terminal') - expect(handleSwitchTerminalTab(1)).toBe(true) - expect(mocks.store.setActiveTab).toHaveBeenCalledWith('term-3') - }) }) diff --git a/src/renderer/src/hooks/useIpcEvents-browser-certificate-failure.test.ts b/src/renderer/src/hooks/useIpcEvents-browser-certificate-failure.test.ts index e6a0bc3ac77..4a8368e86f2 100644 --- a/src/renderer/src/hooks/useIpcEvents-browser-certificate-failure.test.ts +++ b/src/renderer/src/hooks/useIpcEvents-browser-certificate-failure.test.ts @@ -51,22 +51,6 @@ describe('browser certificate failures while a runtime environment is active', ( expect(setBrowserPageCertificateFailure).not.toHaveBeenCalled() }) - - it('stores a local page failure when no runtime environment is active', async () => { - const setBrowserPageCertificateFailure = vi.fn() - const harness = await loadIpcEventsHarness( - createHarnessStoreState({ - tabsByWorktree: {}, - setBrowserPageCertificateFailure, - remoteBrowserPageHandlesByPageId: {} - }) - ) - harness.useIpcEvents() - - harness.certificateFailureChanged({ browserPageId: 'page-1', failure: FAILURE }) - - expect(setBrowserPageCertificateFailure).toHaveBeenCalledWith('page-1', FAILURE) - }) }) type AudioStateEvent = { browserPageId: string; audible: boolean } diff --git a/src/renderer/src/lib/pane-manager/pane-close-focus-successor.test.ts b/src/renderer/src/lib/pane-manager/pane-close-focus-successor.test.ts index 669eb55ec49..552bd893355 100644 --- a/src/renderer/src/lib/pane-manager/pane-close-focus-successor.test.ts +++ b/src/renderer/src/lib/pane-manager/pane-close-focus-successor.test.ts @@ -51,16 +51,6 @@ describe('PaneManager focus after a pane leaves a split', () => { vi.unstubAllGlobals() }) - it('focuses the neighbour that takes over the space when the last of four panes closes', () => { - const [, , c, d] = createFourColumns(manager) - const focus = vi.spyOn(c.terminal, 'focus') - - manager.closePane(d.id) - - expect(manager.getActivePane()?.id).toBe(c.id) - expect(focus).toHaveBeenCalled() - }) - it('focuses the adjacent pane of the subtree that takes over a closed middle pane', () => { const [, b, c] = createFourColumns(manager) manager.setActivePane(b.id) @@ -70,24 +60,6 @@ describe('PaneManager focus after a pane leaves a split', () => { expect(manager.getActivePane()?.id).toBe(c.id) }) - it('focuses the pane after a closed middle pane when that pane is its only sibling', () => { - const [, , c, d] = createFourColumns(manager) - manager.setActivePane(c.id) - - manager.closePane(c.id) - - expect(manager.getActivePane()?.id).toBe(d.id) - }) - - it('focuses the pane above when the lower half of a stacked split closes', () => { - const [, b] = createFourColumns(manager) - const below = split(manager, b, 'horizontal') - - manager.closePane(below.id) - - expect(manager.getActivePane()?.id).toBe(b.id) - }) - it('walks into the edge of an orthogonal split that takes over the space', () => { // [ a | b ] over [ c ], all left of d: closing d must land on b, which touches d's edge. const a = manager.createInitialPane() @@ -125,12 +97,4 @@ describe('PaneManager focus after a pane leaves a split', () => { expect(manager.getActivePane()?.id).toBe(d.id) }) - - it('leaves no active pane when the only pane closes', () => { - const a = manager.createInitialPane() - - manager.closePane(a.id) - - expect(manager.getActivePane()).toBeNull() - }) }) diff --git a/src/renderer/src/lib/pane-manager/pane-terminal-gpu-acceleration.test.ts b/src/renderer/src/lib/pane-manager/pane-terminal-gpu-acceleration.test.ts deleted file mode 100644 index bd287c62e2c..00000000000 --- a/src/renderer/src/lib/pane-manager/pane-terminal-gpu-acceleration.test.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import type { ManagedPaneInternal, PaneManagerOptions } from './pane-manager-types' -import { applyTerminalGpuAcceleration } from './pane-terminal-gpu-acceleration' - -function createPane(): ManagedPaneInternal { - const leafId = '11111111-1111-4111-8111-111111111111' as never - return { - id: 1, - leafId, - stablePaneId: leafId, - terminal: { - cols: 80, - rows: 24 - } as never, - container: {} as never, - xtermContainer: {} as never, - linkTooltip: {} as never, - terminalGpuAcceleration: 'auto', - gpuRenderingEnabled: true, - webglAttachmentDeferred: false, - webglDisabledAfterContextLoss: false, - hasComplexScriptOutput: false, - webglAddon: { - dispose: vi.fn() - } as never, - ligaturesAddon: null, - imageAddon: null, - fitResizeObserver: null, - pendingObservedFitRafId: null, - fitAddon: { - proposeDimensions: vi.fn(() => ({ cols: 80, rows: 23 })), - fit: vi.fn() - } as never, - searchAddon: {} as never, - serializeAddon: {} as never, - unicode11Addon: {} as never, - webLinksAddon: {} as never, - compositionHandler: null, - pendingSplitScrollState: null, - debugLabel: null - } -} - -describe('applyTerminalGpuAcceleration', () => { - beforeEach(() => { - vi.stubGlobal('requestAnimationFrame', (callback: FrameRequestCallback) => { - callback(16) - return 1 - }) - }) - - afterEach(() => { - vi.unstubAllGlobals() - }) - - it('refits after disabling WebGL so DOM renderer dimensions settle', () => { - const pane = createPane() - const options: PaneManagerOptions = { - linkOpenHint: () => '', - terminalGpuAcceleration: 'auto' - } - - applyTerminalGpuAcceleration([pane], options, 'off') - - expect(pane.webglAddon).toBeNull() - expect(pane.fitAddon.fit).toHaveBeenCalledTimes(1) - }) - - it('keeps complex-script panes on WebGL when switching from forced WebGL back to auto', () => { - vi.stubGlobal('navigator', { - platform: 'MacIntel', - userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0)' - }) - const pane = createPane() - pane.hasComplexScriptOutput = true - const options: PaneManagerOptions = { - linkOpenHint: () => '', - terminalGpuAcceleration: 'on' - } - - applyTerminalGpuAcceleration([pane], options, 'auto') - - expect(pane.webglAddon).not.toBeNull() - expect(pane.fitAddon.fit).not.toHaveBeenCalled() - }) - - it('clears context-loss latches when the acceleration mode changes', () => { - vi.stubGlobal('navigator', { - platform: 'MacIntel', - userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0)' - }) - const pane = createPane() - pane.webglDisabledAfterContextLoss = true - const options: PaneManagerOptions = { - linkOpenHint: () => '', - terminalGpuAcceleration: 'auto' - } - - applyTerminalGpuAcceleration([pane], options, 'on') - - expect(pane.webglDisabledAfterContextLoss).toBe(false) - }) - - it('keeps context-loss latches when the acceleration mode is unchanged', () => { - const pane = createPane() - pane.webglDisabledAfterContextLoss = true - const options: PaneManagerOptions = { - linkOpenHint: () => '', - terminalGpuAcceleration: 'on' - } - - applyTerminalGpuAcceleration([pane], options, 'on') - - expect(pane.webglDisabledAfterContextLoss).toBe(true) - }) - - it('returns Linux panes to DOM when switching from forced WebGL back to auto without a safe renderer', () => { - vi.stubGlobal('navigator', { - platform: 'Linux x86_64', - userAgent: 'Mozilla/5.0 (X11; Linux x86_64)' - }) - const pane = createPane() - const options: PaneManagerOptions = { - linkOpenHint: () => '', - terminalGpuAcceleration: 'on' - } - - applyTerminalGpuAcceleration([pane], options, 'auto') - - expect(pane.webglAddon).toBeNull() - expect(pane.fitAddon.fit).toHaveBeenCalledTimes(1) - }) -}) diff --git a/src/renderer/src/runtime/web-runtime-session-legacy-relay-bridged-activation.test.ts b/src/renderer/src/runtime/web-runtime-session-legacy-relay-bridged-activation.test.ts index 2b90baad4b4..abfc294f276 100644 --- a/src/renderer/src/runtime/web-runtime-session-legacy-relay-bridged-activation.test.ts +++ b/src/renderer/src/runtime/web-runtime-session-legacy-relay-bridged-activation.test.ts @@ -113,25 +113,4 @@ describe('activating a pane the legacy relay bridge serves', () => { }) ) }) - - it('still activates its sibling panes and every other tab on the server', async () => { - const call = vi.fn().mockResolvedValue({ id: 'activate', ok: true, result: {} }) - stubWindow(call) - - for (const hostTabId of ['relay-tab::orcad-leaf', 'orcad-tab::leaf']) { - await activateWebRuntimeSessionTab({ - worktreeId: WORKTREE_ID, - tabId: toWebTerminalSurfaceTabId(hostTabId), - environmentId: ENVIRONMENT_ID - }) - } - - expect(call).toHaveBeenCalledTimes(2) - expect(call).toHaveBeenCalledWith( - expect.objectContaining({ - method: 'session.tabs.activate', - params: expect.objectContaining({ tabId: 'orcad-tab::leaf' }) - }) - ) - }) }) diff --git a/src/renderer/src/store/slices/github-pr-refresh-host-guard.test.ts b/src/renderer/src/store/slices/github-pr-refresh-host-guard.test.ts index f90960acb25..f1070b75c95 100644 --- a/src/renderer/src/store/slices/github-pr-refresh-host-guard.test.ts +++ b/src/renderer/src/store/slices/github-pr-refresh-host-guard.test.ts @@ -3,7 +3,6 @@ import { create } from 'zustand' import { createGitHubSlice } from './github' import { createHostedReviewSlice } from './hosted-review' import type { AppState } from '../types' -import { LOCAL_EXECUTION_HOST_ID } from '../../../../shared/execution-host' // Route only eligible local repos to gh:enqueuePRRefresh; denied remote/SSH/runtime path floods previously grew renderer heap to OOM. const enqueuePRRefresh = vi.fn().mockResolvedValue(undefined) @@ -66,15 +65,6 @@ describe('enqueueGitHubPRRefresh host guard', () => { vi.clearAllMocks() }) - it('enqueues the local handler for a local-host repo', () => { - const store = createTestStore() - seed(store, { id: 'local-1', path: '/Users/me/code/local-1', name: 'local-1', kind: 'git' }) - - store.getState().enqueueGitHubPRRefresh('wt-1', 'active', 80) - - expect(enqueuePRRefresh).toHaveBeenCalledTimes(1) - }) - it('enqueues the local handler for a known local repo while a runtime is focused', () => { const store = createTestStore() seed(store, { id: 'local-1', path: '/Users/me/code/local-1', name: 'local-1', kind: 'git' }) @@ -86,21 +76,6 @@ describe('enqueueGitHubPRRefresh host guard', () => { expect(mockApi.runtimeEnvironments.call).not.toHaveBeenCalled() }) - it('enqueues the local handler for a repo with an explicit local executionHostId', () => { - const store = createTestStore() - seed(store, { - id: 'local-2', - path: '/Users/me/code/local-2', - name: 'local-2', - kind: 'git', - executionHostId: LOCAL_EXECUTION_HOST_ID - }) - - store.getState().enqueueGitHubPRRefresh('wt-1', 'active', 80) - - expect(enqueuePRRefresh).toHaveBeenCalledTimes(1) - }) - it('does NOT enqueue the local handler for a runtime-host repo (the OOM loop)', () => { const store = createTestStore() seed(store, { diff --git a/src/renderer/src/store/slices/runtime-managed-repair-keeps-workspaces.test.ts b/src/renderer/src/store/slices/runtime-managed-repair-keeps-workspaces.test.ts index 93742c402de..ee014893cc7 100644 --- a/src/renderer/src/store/slices/runtime-managed-repair-keeps-workspaces.test.ts +++ b/src/renderer/src/store/slices/runtime-managed-repair-keeps-workspaces.test.ts @@ -79,12 +79,6 @@ const keptWorkspaces = (store: ReturnType) => ({ afterEach(() => resetDeferredPeerChecksForTests()) describe('an on-connect update re-pairs a managed server', () => { - it('keeps the workspaces and tabs when the host proves the same key', () => { - const store = userOnServer() - store.getState().setRuntimeEnvironments([server(2, 'key-a')]) - expect(keptWorkspaces(store)).toEqual({ repos: 1, tabs: 1 }) - }) - it('keeps them when the re-read runs before the key is known, and once it arrives', () => { const store = userOnServer() store.getState().setRuntimeEnvironments([server(2)]) @@ -99,12 +93,6 @@ describe('an on-connect update re-pairs a managed server', () => { store.getState().setRuntimeEnvironments([server(2, 'key-reinstalled')]) expect(keptWorkspaces(store)).toEqual({ repos: 0, tabs: 0 }) }) - - it('retires them at once when the re-pair already proves a different host', () => { - const store = userOnServer() - store.getState().setRuntimeEnvironments([server(2, 'key-reinstalled')]) - expect(keptWorkspaces(store)).toEqual({ repos: 0, tabs: 0 }) - }) }) describe('Settings refreshes a hand-paired server with a new code for it', () => { diff --git a/src/renderer/src/store/slices/store-sleep-layout-owner.test.ts b/src/renderer/src/store/slices/store-sleep-layout-owner.test.ts index 7ea0a29d885..9efa4a82c73 100644 --- a/src/renderer/src/store/slices/store-sleep-layout-owner.test.ts +++ b/src/renderer/src/store/slices/store-sleep-layout-owner.test.ts @@ -76,29 +76,6 @@ describe('sleep through main in a layout-owner build', () => { shutdownBufferCaptures.clear() }) - it('sends the hibernated pane’s record to main once its terminal stopped', async () => { - const store = storeWithAgentPane() - - await store.getState().shutdownCompletedAgentPaneForHibernation(WT, { - paneKey: AGENT_PANE, - tabId: 'tab-1', - leafId: AGENT_LEAF, - ptyId: 'pty-agent' - }) - - const record = store.getState().sleepingAgentSessionsByPaneKey[AGENT_PANE] - expect(mocks.send).toHaveBeenCalledTimes(1) - expect(mocks.send.mock.calls[0]![2]).toEqual({ - type: 'sleep', - tabId: 'tab-1', - paneKeys: [AGENT_PANE], - records: [record] - }) - expect(mocks.send.mock.invocationCallOrder[0]).toBeGreaterThan( - mockApi.pty.kill.mock.invocationCallOrder[0]! - ) - }) - it('sends nothing when the hibernation stop fails', async () => { const store = storeWithAgentPane() mockApi.pty.kill.mockRejectedValueOnce(new Error('kill_failed')) diff --git a/src/renderer/src/store/slices/usage-snapshot-refresh.benchmark.test.ts b/src/renderer/src/store/slices/usage-snapshot-refresh.benchmark.test.ts deleted file mode 100644 index edfbf5175fe..00000000000 --- a/src/renderer/src/store/slices/usage-snapshot-refresh.benchmark.test.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { performance } from 'node:perf_hooks' -import { create } from 'zustand' -import { beforeEach, describe, expect, it, vi } from 'vitest' -import type { AppState } from '../types' -import type { - CodexUsageScanState, - CodexUsageSnapshot, - CodexUsageSummary -} from '../../../../shared/codex-usage-types' -import { createCodexUsageSlice } from './usage-provider-slices' - -type Deferred = { - promise: Promise - resolve: (value: T) => void -} - -function createDeferred(): Deferred { - let resolve!: (value: T) => void - const promise = new Promise((innerResolve) => { - resolve = innerResolve - }) - return { promise, resolve } -} - -async function flushImmediatePromises(): Promise { - for (let index = 0; index < 5; index++) { - await Promise.resolve() - } -} - -function createCodexOnlyStore() { - return create()((...args) => createCodexUsageSlice(...args) as AppState) -} - -function createScanState(overrides: Partial = {}): CodexUsageScanState { - return { - enabled: true, - isScanning: false, - lastScanStartedAt: 100, - lastScanCompletedAt: 200, - lastScanError: null, - hasAnyCodexData: true, - ...overrides - } -} - -function createSummary(totalTokens: number): CodexUsageSummary { - return { - scope: 'orca', - range: '30d', - sessions: totalTokens / 100, - events: totalTokens / 10, - inputTokens: totalTokens / 2, - cachedInputTokens: totalTokens / 10, - outputTokens: totalTokens / 2, - reasoningOutputTokens: 0, - totalTokens, - estimatedCostUsd: 1, - hasUnpricedModels: false, - topModel: 'gpt-5', - topProject: 'orca', - hasAnyCodexData: true - } -} - -function createSnapshot(totalTokens: number, scanState = createScanState()): CodexUsageSnapshot { - return { - scanState, - summary: createSummary(totalTokens), - daily: [ - { - day: '2026-04-10', - inputTokens: totalTokens / 2, - cachedInputTokens: totalTokens / 10, - outputTokens: totalTokens / 2, - reasoningOutputTokens: 0, - totalTokens - } - ], - modelBreakdown: [], - projectBreakdown: [], - recentSessions: [] - } -} - -describe('Codex usage cached snapshot benchmark', () => { - beforeEach(() => { - vi.clearAllMocks() - }) - - it('renders cached usage before a slow refresh completes', async () => { - const slowRefresh = createDeferred() - const getSnapshot = vi - .fn() - .mockResolvedValueOnce(createSnapshot(100)) - .mockResolvedValueOnce(createSnapshot(200, createScanState({ lastScanCompletedAt: 300 }))) - const refresh = vi.fn(() => slowRefresh.promise) - - vi.stubGlobal('window', { - api: { - codexUsage: { - getScanState: vi.fn(() => Promise.resolve(createScanState())), - getSnapshot, - refresh, - setEnabled: vi.fn(), - getSummary: vi.fn(), - getDaily: vi.fn(), - getBreakdown: vi.fn(), - getRecentSessions: vi.fn() - } - } - }) - - const store = createCodexOnlyStore() - const startedAt = performance.now() - const fetchPromise = store.getState().fetchCodexUsage() - - await flushImmediatePromises() - expect(store.getState().codexUsageSummary?.totalTokens).toBe(100) - const cachedRenderMs = performance.now() - startedAt - - expect(cachedRenderMs).toBeLessThan(10) - expect(refresh).toHaveBeenCalledTimes(1) - expect(getSnapshot).toHaveBeenCalledTimes(1) - - slowRefresh.resolve(createScanState({ lastScanCompletedAt: 300 })) - await fetchPromise - - expect(store.getState().codexUsageSummary?.totalTokens).toBe(200) - expect(getSnapshot).toHaveBeenCalledTimes(2) - expect(window.api.codexUsage.getSummary).not.toHaveBeenCalled() - expect(window.api.codexUsage.getDaily).not.toHaveBeenCalled() - expect(window.api.codexUsage.getBreakdown).not.toHaveBeenCalled() - expect(window.api.codexUsage.getRecentSessions).not.toHaveBeenCalled() - }) -}) diff --git a/src/renderer/src/store/slices/worktrees-runtime-connection-generation-fence.test.ts b/src/renderer/src/store/slices/worktrees-runtime-connection-generation-fence.test.ts index eb370e4717a..f6991733267 100644 --- a/src/renderer/src/store/slices/worktrees-runtime-connection-generation-fence.test.ts +++ b/src/renderer/src/store/slices/worktrees-runtime-connection-generation-fence.test.ts @@ -67,18 +67,6 @@ beforeEach(() => { }) describe('fetchAllWorktrees across a runtime connection-generation change', () => { - it('publishes every repo when nothing perturbs the connection', async () => { - const store = createTestStore() - seedRuntimeRepos(store) - runtimeEnvironmentCall.mockImplementation((args: RuntimeEnvironmentCallRequest) => - detectedListReply(repoOf(args)) - ) - - await store.getState().fetchAllWorktrees() - - expect(Object.keys(store.getState().worktreesByRepo).sort()).toEqual([...REPO_IDS]) - }) - it('re-reads instead of dropping the repos still in flight when the generation moves', async () => { // A host-wide generation bump discards every outstanding repo scan; retry rather than leave a stable sidebar subset (#19241). const store = createTestStore()