From be1fceb69dbf596cc44eb8d3a6f23117143ff149 Mon Sep 17 00:00:00 2001 From: OrcaWin Date: Fri, 30 Oct 2026 17:20:27 -0700 Subject: [PATCH] test: remove 39 low-value suites from audit batch 849 (#36491) * test: remove 39 low-value suites from audit batch 849 * test: remove obsolete shell-contract trigger for deleted suite --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> --- .github/workflows/pr.yml | 1 - config/flaky-test-pattern-baseline.txt | 1 - config/scripts/ci-shard-timings.json | 31 ------ config/scripts/ci-unit-files.mjs | 1 - config/scripts/pr-shell-contract-prefixes.mjs | 1 - ...owser-extension-background-wrapper.test.ts | 92 ----------------- .../browser-extension-webstore-events.test.ts | 83 ---------------- .../claude-profile-shell-composition.test.ts | 94 ------------------ .../codex-configured-launch-defaults.test.ts | 99 ------------------- src/main/git/status-wsl-pathspecs.test.ts | 91 ----------------- .../worktree-create-admission-tier.test.ts | 83 ---------------- ...tlab-known-host-probe-wsl-fallback.test.ts | 86 ---------------- ...nted-cold-restore-ack-layout-owner.test.ts | 86 ---------------- ...sparse-checkout-cache-invalidation.test.ts | 85 ---------------- ...sl-host-handlers-startup-reconcile.test.ts | 97 ------------------ .../session-file-resolver-codex-roots.test.ts | 91 ----------------- .../shell-ready-framework-example.test.ts | 87 ---------------- .../rpc/methods/automatic-work.test.ts | 82 --------------- ...e-worktree-removal-process-cleanup.test.ts | 87 ---------------- ...rca-runtime-workspace-review-facts.test.ts | 87 ---------------- .../startup/windows-isolated-spawner.test.ts | 84 ---------------- .../wsl/wsl-host-e2e-fake-connector.test.ts | 96 ------------------ .../combined-diff-file-tree-row-drag.test.tsx | 86 ---------------- .../AiVaultShowMoreSessionsRow.test.tsx | 85 ---------------- .../use-status-refresh.local-ignore.test.tsx | 86 ---------------- .../settings/AppearanceThemeControl.test.tsx | 98 ------------------ ...SettingsFormControls.number-field.test.tsx | 85 ---------------- .../chat-settings-unsaved-guard.test.tsx | 84 ---------------- .../sidebar/OrcaYamlTrustDialog.test.tsx | 92 ----------------- .../sidebar/WslMovedProjectsSection.test.tsx | 92 ----------------- .../open-standalone-terminal.test.ts | 86 ---------------- .../status-bar-cursor-segment.test.tsx | 92 ----------------- .../task-page-jira-workspace-actions.test.tsx | 85 ---------------- .../task-page-repo-source-divergence.test.ts | 92 ----------------- ...minal-pane-bootstrap-split-in-main.test.ts | 86 ---------------- ...t-workspace-surfaces-startup-hold.test.tsx | 86 ---------------- ...erminal-window-lifecycle.lazy-ref.test.tsx | 82 --------------- ...space-cleanup-confirm-stop-agents.test.tsx | 91 ----------------- .../hooks/composer-native-file-drop.test.ts | 82 --------------- ...-agent-session-launch-layout-owner.test.ts | 86 ---------------- ...t-wsl-filesystem-boundary-advisory.test.ts | 95 ------------------ .../purge-stale-runtime-host-groups.test.ts | 82 --------------- ...tatus-restored-browser-host-attach.test.ts | 86 ---------------- .../slices/tabs/preview-tab-promotion.test.ts | 86 ---------------- 44 files changed, 3470 deletions(-) delete mode 100644 src/main/browser/extensions/browser-extension-background-wrapper.test.ts delete mode 100644 src/main/browser/extensions/browser-extension-webstore-events.test.ts delete mode 100644 src/main/claude-accounts/claude-profile-shell-composition.test.ts delete mode 100644 src/main/codex/codex-configured-launch-defaults.test.ts delete mode 100644 src/main/git/status-wsl-pathspecs.test.ts delete mode 100644 src/main/git/worktree-create-admission-tier.test.ts delete mode 100644 src/main/gitlab/gitlab-known-host-probe-wsl-fallback.test.ts delete mode 100644 src/main/ipc/pty-painted-cold-restore-ack-layout-owner.test.ts delete mode 100644 src/main/ipc/worktrees/listing/register-sparse-checkout-cache-invalidation.test.ts delete mode 100644 src/main/ipc/wsl-host-handlers-startup-reconcile.test.ts delete mode 100644 src/main/native-chat/session-file-resolver-codex-roots.test.ts delete mode 100644 src/main/providers/__tests__/shell-ready-framework-example.test.ts delete mode 100644 src/main/runtime/rpc/methods/automatic-work.test.ts delete mode 100644 src/main/runtime/runtime-worktree-removal-process-cleanup.test.ts delete mode 100644 src/main/runtime/sidebar-inputs/orca-runtime-workspace-review-facts.test.ts delete mode 100644 src/main/startup/windows-isolated-spawner.test.ts delete mode 100644 src/main/wsl/wsl-host-e2e-fake-connector.test.ts delete mode 100644 src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree-row-drag.test.tsx delete mode 100644 src/renderer/src/components/right-sidebar/AiVaultShowMoreSessionsRow.test.tsx delete mode 100644 src/renderer/src/components/right-sidebar/source-control/sync/use-status-refresh.local-ignore.test.tsx delete mode 100644 src/renderer/src/components/settings/AppearanceThemeControl.test.tsx delete mode 100644 src/renderer/src/components/settings/SettingsFormControls.number-field.test.tsx delete mode 100644 src/renderer/src/components/settings/chat-settings-unsaved-guard.test.tsx delete mode 100644 src/renderer/src/components/sidebar/OrcaYamlTrustDialog.test.tsx delete mode 100644 src/renderer/src/components/sidebar/WslMovedProjectsSection.test.tsx delete mode 100644 src/renderer/src/components/standalone-terminal/open-standalone-terminal.test.ts delete mode 100644 src/renderer/src/components/status-bar/status-bar-cursor-segment.test.tsx delete mode 100644 src/renderer/src/components/task-page/jira/task-page-jira-workspace-actions.test.tsx delete mode 100644 src/renderer/src/components/task-page/task-page-repo-source-divergence.test.ts delete mode 100644 src/renderer/src/components/terminal-pane/terminal-pane-bootstrap-split-in-main.test.ts delete mode 100644 src/renderer/src/components/terminal-split-workspace-surfaces-startup-hold.test.tsx delete mode 100644 src/renderer/src/components/use-terminal-window-lifecycle.lazy-ref.test.tsx delete mode 100644 src/renderer/src/components/workspace-cleanup/workspace-cleanup-confirm-stop-agents.test.tsx delete mode 100644 src/renderer/src/hooks/composer-native-file-drop.test.ts delete mode 100644 src/renderer/src/lib/sleeping-agent-session-launch-layout-owner.test.ts delete mode 100644 src/renderer/src/store/projects/project-wsl-filesystem-boundary-advisory.test.ts delete mode 100644 src/renderer/src/store/slices/purge-stale-runtime-host-groups.test.ts delete mode 100644 src/renderer/src/store/slices/runtime-status-restored-browser-host-attach.test.ts delete mode 100644 src/renderer/src/store/slices/tabs/preview-tab-promotion.test.ts diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 4a0d4769ad5..62d0c4716b1 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -831,7 +831,6 @@ jobs: src/main/daemon/shell-ready.test.ts \ src/main/daemon/node-pty-fd-leak.test.ts \ src/main/providers/local-pty-shell-ready-zsh-launch-environment.test.ts \ - src/main/providers/__tests__/shell-ready-framework-example.test.ts \ src/main/pty/codex-shell-launch-preflight.test.ts \ src/main/pty/codex-shell-no-daemon.test.ts \ src/main/pty/omp-shell-wrapper-alias-safety.test.ts \ diff --git a/config/flaky-test-pattern-baseline.txt b/config/flaky-test-pattern-baseline.txt index 3701da56da4..c1fae52bbde 100644 --- a/config/flaky-test-pattern-baseline.txt +++ b/config/flaky-test-pattern-baseline.txt @@ -1118,7 +1118,6 @@ 5 test-no-wall-clock:src/renderer/src/components/status-bar/inline-usage-bars.test.tsx 4 test-no-wall-clock:src/renderer/src/components/status-bar/provider-segment-balance.test.tsx 2 test-no-wall-clock:src/renderer/src/components/status-bar/status-bar-antigravity-segment.test.tsx -1 test-no-wall-clock:src/renderer/src/components/status-bar/status-bar-cursor-segment.test.tsx 3 test-no-wall-clock:src/renderer/src/components/status-bar/status-bar-provider-menu-focus.test.tsx 1 test-no-wall-clock:src/renderer/src/components/status-bar/workspace-space-worktree-row.test.tsx 1 test-no-wall-clock:src/renderer/src/components/tab-bar/TabBarCreateEntry.history.test.tsx diff --git a/config/scripts/ci-shard-timings.json b/config/scripts/ci-shard-timings.json index 5f0df4fb03e..de4bbebcd52 100644 --- a/config/scripts/ci-shard-timings.json +++ b/config/scripts/ci-shard-timings.json @@ -1431,7 +1431,6 @@ "src/main/claude-accounts/claude-profile-router.test.ts": 864, "src/main/claude-accounts/claude-profile-setup-worker.test.ts": 331, "src/main/claude-accounts/claude-profile-setup.test.ts": 243, - "src/main/claude-accounts/claude-profile-shell-composition.test.ts": 70, "src/main/claude-accounts/claude-profile-wsl-router.test.ts": 821, "src/main/claude-accounts/claude-sign-in-browser.test.ts": 288, "src/main/claude-accounts/claude-structured-auth-policy.test.ts": 57, @@ -1760,7 +1759,6 @@ "src/main/codex/codex-config-mirror-mcp-ownership.test.ts": 114, "src/main/codex/codex-config-mirror.test.ts": 247, "src/main/codex/codex-config-settings-removal.test.ts": 36, - "src/main/codex/codex-configured-launch-defaults.test.ts": 62, "src/main/codex/codex-daemon-socket-path-guard.test.ts": 101, "src/main/codex/codex-default-mode-subagents.test.ts": 574, "src/main/codex/codex-goal-journal-rows.test.ts": 74, @@ -2499,7 +2497,6 @@ "src/main/git/status-upstream-negative-cache.test.ts": 839, "src/main/git/status-upstream-probe-churn.test.ts": 147, "src/main/git/status-upstream-ref.test.ts": 42, - "src/main/git/status-wsl-pathspecs.test.ts": 161, "src/main/git/status.test.ts": 184, "src/main/git/upstream-deferred-fork-remote-real.test.ts": 195, "src/main/git/upstream.test.ts": 371, @@ -2518,7 +2515,6 @@ "src/main/git/worktree-checkout-progress-real-git.test.ts": 631, "src/main/git/worktree-common-dir-comparison.test.ts": 178, "src/main/git/worktree-configured-paths-concurrency.test.ts": 67, - "src/main/git/worktree-create-admission-tier.test.ts": 249, "src/main/git/worktree-create-git-executor-real-git.test.ts": 540, "src/main/git/worktree-create-preparation-real-git.test.ts": 2248, "src/main/git/worktree-create-preparation-real-wsl.test.ts": 209, @@ -2685,7 +2681,6 @@ "src/main/gitlab/client-work-items.test.ts": 539, "src/main/gitlab/client.test.ts": 395, "src/main/gitlab/gitlab-known-host-backoff.test.ts": 349, - "src/main/gitlab/gitlab-known-host-probe-wsl-fallback.test.ts": 457, "src/main/gitlab/gitlab-known-host-probe.test.ts": 420, "src/main/gitlab/gitlab-known-host-retirement.test.ts": 420, "src/main/gitlab/gl-utils.test.ts": 437, @@ -2945,7 +2940,6 @@ "src/main/ipc/preflight-wsl-command.test.ts": 48, "src/main/ipc/pty-attach-view-joins-main-start.test.ts": 3883, "src/main/ipc/pty-claude-agent-view-readiness.test.ts": 3531, - "src/main/ipc/pty-painted-cold-restore-ack-layout-owner.test.ts": 2928, "src/main/ipc/pty-spawn-saved-resume-admission.test.ts": 6908, "src/main/ipc/pty/daemon-late-exit.test.ts": 6475, "src/main/ipc/pty/delivery/attached-pty-size.test.ts": 68, @@ -3279,7 +3273,6 @@ "src/main/ipc/worktrees/listing/detected-worktree-scan-hygiene-gate.test.ts": 79, "src/main/ipc/worktrees/listing/detected-worktree-scan-listing-distro.test.ts": 677, "src/main/ipc/worktrees/listing/detected-worktree-scan-superseded.test.ts": 46, - "src/main/ipc/worktrees/listing/register-sparse-checkout-cache-invalidation.test.ts": 122, "src/main/ipc/wsl-guest-windows-drive-path.test.ts": 58, "src/main/ipc/wsl-host-gate-off.test.ts": 3774, "src/main/ipc/wsl-move-handlers.test.ts": 399, @@ -3775,7 +3768,6 @@ "src/main/native-chat/native-chat-visuals-delivery.test.ts": 653, "src/main/native-chat/native-chat-visuals-sweep.test.ts": 150, "src/main/native-chat/session-file-resolver-claude-roots.test.ts": 157, - "src/main/native-chat/session-file-resolver-codex-roots.test.ts": 164, "src/main/native-chat/session-file-resolver-wsl-scan-gate.test.ts": 138, "src/main/native-chat/session-file-resolver-wsl.test.ts": 107, "src/main/native-chat/session-file-resolver.test.ts": 150, @@ -5237,7 +5229,6 @@ "src/main/runtime/rpc/methods/ai-vault-structured-ownership.test.ts": 1351, "src/main/runtime/rpc/methods/ai-vault.test.ts": 2715, "src/main/runtime/rpc/methods/artifacts.test.ts": 241, - "src/main/runtime/rpc/methods/automatic-work.test.ts": 2248, "src/main/runtime/rpc/methods/automation-scoped-list-methods.test.ts": 526, "src/main/runtime/rpc/methods/automations.test.ts": 527, "src/main/runtime/rpc/methods/browser-client-host-attach-adoption.test.ts": 621, @@ -5719,7 +5710,6 @@ "src/main/runtime/runtime-worktree-default-tabs-layout-owner.test.ts": 36, "src/main/runtime/runtime-worktree-ps-summaries.test.ts": 83, "src/main/runtime/runtime-worktree-ps-unverifiable-terminals.test.ts": 35, - "src/main/runtime/runtime-worktree-removal-process-cleanup.test.ts": 3713, "src/main/runtime/runtime-worktree-selection.test.ts": 36, "src/main/runtime/runtime-worktree-startup-readiness.test.ts": 215, "src/main/runtime/runtime-worktree-structured-agent-rows-liveness.test.ts": 762, @@ -5760,7 +5750,6 @@ "src/main/runtime/sidebar-inputs/orca-runtime-sort-stamps.test.ts": 4086, "src/main/runtime/sidebar-inputs/orca-runtime-terminal-use.test.ts": 2341, "src/main/runtime/sidebar-inputs/orca-runtime-workspace-activity-facts.test.ts": 3455, - "src/main/runtime/sidebar-inputs/orca-runtime-workspace-review-facts.test.ts": 3885, "src/main/runtime/sidebar-inputs/orca-runtime-workspace-unread.test.ts": 3997, "src/main/runtime/sidebar-inputs/paired-server-rows-producer.test.ts": 265, "src/main/runtime/sidebar-inputs/repo-icon-data-urls.test.ts": 191, @@ -7283,7 +7272,6 @@ "src/renderer/src/components/editor/combined-diff-on-demand-load.test.ts": 94, "src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree-collapsed-work.test.tsx": 742, "src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree-render.test.tsx": 737, - "src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree-row-drag.test.tsx": 305, "src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree-windowing.test.tsx": 577, "src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree.test.ts": 77, "src/renderer/src/components/editor/combined-diff/browse-files/use-combined-diff-file-tree-resize.test.tsx": 248, @@ -8151,7 +8139,6 @@ "src/renderer/src/components/right-sidebar/AiVaultSessionSubagents.test.tsx": 1926, "src/renderer/src/components/right-sidebar/AiVaultSessionVirtualList.keyboard.test.tsx": 2036, "src/renderer/src/components/right-sidebar/AiVaultSessionVirtualList.measurement.test.tsx": 2554, - "src/renderer/src/components/right-sidebar/AiVaultShowMoreSessionsRow.test.tsx": 369, "src/renderer/src/components/right-sidebar/AiVaultVirtualRow.test.tsx": 2253, "src/renderer/src/components/right-sidebar/ChecksPanel.updated-at-metadata.test.tsx": 243, "src/renderer/src/components/right-sidebar/CommitArea.chevron-spinner.test.tsx": 1564, @@ -8376,7 +8363,6 @@ "src/renderer/src/components/right-sidebar/source-control/review/use-review-push-target.test.tsx": 255, "src/renderer/src/components/right-sidebar/source-control/sync/git-history-format.test.ts": 47, "src/renderer/src/components/right-sidebar/source-control/sync/git-history-graph-svg.test.tsx": 102, - "src/renderer/src/components/right-sidebar/source-control/sync/use-status-refresh.local-ignore.test.tsx": 272, "src/renderer/src/components/right-sidebar/use-ai-vault-search-focus-request.test.tsx": 1566, "src/renderer/src/components/right-sidebar/use-ai-vault-search.test.tsx": 485, "src/renderer/src/components/right-sidebar/use-checks-panel-terminal-worktree.test.ts": 1574, @@ -8512,7 +8498,6 @@ "src/renderer/src/components/settings/SessionHistorySettingsPane.test.tsx": 903, "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.number-field.test.tsx": 753, "src/renderer/src/components/settings/SettingsFormControls.segmented-control.test.tsx": 548, "src/renderer/src/components/settings/SettingsSidebar.test.tsx": 2169, "src/renderer/src/components/settings/ShareSkillsSettingsPane.test.tsx": 601, @@ -8557,7 +8542,6 @@ "src/renderer/src/components/settings/browser-session-host-selection.test.ts": 43, "src/renderer/src/components/settings/bundled-skill-setup-result-copy.test.ts": 304, "src/renderer/src/components/settings/chat-naming-persistence.test.tsx": 3654, - "src/renderer/src/components/settings/chat-settings-unsaved-guard.test.tsx": 1560, "src/renderer/src/components/settings/cli-install-failure.test.ts": 34, "src/renderer/src/components/settings/codex-config-sync-warning.test.ts": 34, "src/renderer/src/components/settings/codex-session-source-home-control.test.tsx": 154, @@ -8665,7 +8649,6 @@ "src/renderer/src/components/sidebar/NewExternalWorktreesInboxLine.test.tsx": 1735, "src/renderer/src/components/sidebar/NonGitFolderDialog.test.tsx": 1097, "src/renderer/src/components/sidebar/NoticeHostGlyph.test.tsx": 2211, - "src/renderer/src/components/sidebar/OrcaYamlTrustDialog.test.tsx": 54, "src/renderer/src/components/sidebar/PendingWorktreeRow.test.tsx": 1397, "src/renderer/src/components/sidebar/ProjectAddedDialog.test.tsx": 187, "src/renderer/src/components/sidebar/ProjectGroupDeleteDialog.test.tsx": 2252, @@ -9017,7 +9000,6 @@ "src/renderer/src/components/sparse/SparsePresetChooser.test.tsx": 510, "src/renderer/src/components/sparse/sparse-directory-browse.test.ts": 45, "src/renderer/src/components/sparse/sparse-directory-entry-input.test.ts": 107, - "src/renderer/src/components/standalone-terminal/open-standalone-terminal.test.ts": 1321, "src/renderer/src/components/star-nag/StarNagAgentValueMomentObserver.test.tsx": 1534, "src/renderer/src/components/star-nag/StarNagToastHost.test.tsx": 344, "src/renderer/src/components/stats/CodexUsagePane.test.tsx": 753, @@ -9070,7 +9052,6 @@ "src/renderer/src/components/status-bar/ssh-status-menu-rows.test.ts": 48, "src/renderer/src/components/status-bar/status-bar-antigravity-segment.test.tsx": 968, "src/renderer/src/components/status-bar/status-bar-copy-localization.test.tsx": 885, - "src/renderer/src/components/status-bar/status-bar-cursor-segment.test.tsx": 1503, "src/renderer/src/components/status-bar/status-bar-density.test.ts": 57, "src/renderer/src/components/status-bar/status-bar-pool-countdown.test.tsx": 389, "src/renderer/src/components/status-bar/status-bar-provider-menu-focus.test.tsx": 941, @@ -9230,11 +9211,9 @@ "src/renderer/src/components/task-page-jira-status-catalog.test.ts": 60, "src/renderer/src/components/task-page/jira/task-page-jira-status-order-session.test.tsx": 2111, "src/renderer/src/components/task-page/jira/task-page-jira-text-fallback-notice.test.tsx": 375, - "src/renderer/src/components/task-page/jira/task-page-jira-workspace-actions.test.tsx": 1971, "src/renderer/src/components/task-page/task-page-list-chrome-visibility.test.ts": 33, "src/renderer/src/components/task-page/task-page-mutation-page-allocation.test.ts": 128, "src/renderer/src/components/task-page/task-page-new-issue-draft.test.ts": 76, - "src/renderer/src/components/task-page/task-page-repo-source-divergence.test.ts": 1043, "src/renderer/src/components/task-page/task-page-task-source-host-availability.test.ts": 401, "src/renderer/src/components/task-page/task-page-work-item-pagination.test.ts": 56, "src/renderer/src/components/task-page/github/rows-twin-host-routing.test.tsx": 1521, @@ -9700,7 +9679,6 @@ "src/renderer/src/components/terminal-pane/terminal-option-punctuation.test.ts": 65, "src/renderer/src/components/terminal-pane/terminal-output-visibility.test.ts": 39, "src/renderer/src/components/terminal-pane/terminal-pane-attention-subscriptions.test.ts": 42, - "src/renderer/src/components/terminal-pane/terminal-pane-bootstrap-split-in-main.test.ts": 1119, "src/renderer/src/components/terminal-pane/terminal-pane-close-identity.test.ts": 26, "src/renderer/src/components/terminal-pane/terminal-pane-detach-layout-owner.test.ts": 1521, "src/renderer/src/components/terminal-pane/terminal-pane-element-file-drop.test.tsx": 1853, @@ -9830,7 +9808,6 @@ "src/renderer/src/components/terminal-search-decoration-leak.test.ts": 1946, "src/renderer/src/components/terminal-search-long-wrapped-line.test.ts": 3017, "src/renderer/src/components/terminal-search-safe-find.test.ts": 48, - "src/renderer/src/components/terminal-split-workspace-surfaces-startup-hold.test.tsx": 1949, "src/renderer/src/components/terminal-startup-hold-placeholder.test.tsx": 559, "src/renderer/src/components/terminal-workspace-keydown.test.ts": 646, "src/renderer/src/components/terminal-workspace-surface-ids.test.tsx": 1948, @@ -9886,7 +9863,6 @@ "src/renderer/src/components/use-terminal-editor-close-foundation.window-close.test.tsx": 1766, "src/renderer/src/components/use-terminal-editor-close-queue.reveal.test.tsx": 581, "src/renderer/src/components/use-terminal-parking-pass.test.tsx": 1759, - "src/renderer/src/components/use-terminal-window-lifecycle.lazy-ref.test.tsx": 170, "src/renderer/src/components/use-terminal-workspace-foundation.runtime-status.test.tsx": 1503, "src/renderer/src/components/use-worktree-jump-palette-browser-ownership.test.ts": 1477, "src/renderer/src/components/use-worktree-jump-palette-task-search.test.tsx": 1933, @@ -9905,7 +9881,6 @@ "src/renderer/src/components/workspace-cleanup/workspace-cleanup-candidate-row-data.test.ts": 279, "src/renderer/src/components/workspace-cleanup/workspace-cleanup-candidate-row.test.tsx": 2141, "src/renderer/src/components/workspace-cleanup/workspace-cleanup-confirm-remove.test.tsx": 658, - "src/renderer/src/components/workspace-cleanup/workspace-cleanup-confirm-stop-agents.test.tsx": 343, "src/renderer/src/components/workspace-cleanup/workspace-cleanup-facet-controls.test.tsx": 601, "src/renderer/src/components/workspace-cleanup/workspace-cleanup-facet-filter.test.ts": 107, "src/renderer/src/components/workspace-cleanup/workspace-cleanup-facet-sort.test.ts": 127, @@ -9941,7 +9916,6 @@ "src/renderer/src/hooks/client-workspace-view-report.test.ts": 42, "src/renderer/src/hooks/composer-branch-selection.test.ts": 50, "src/renderer/src/hooks/composer-drop-result.test.ts": 25, - "src/renderer/src/hooks/composer-native-file-drop.test.ts": 62, "src/renderer/src/hooks/composer-state/attachment-drop-failure.test.tsx": 547, "src/renderer/src/hooks/composer-state/attachment-drop-lifetime.test.tsx": 741, "src/renderer/src/hooks/composer-state/branch-start-point-actions.test.ts": 231, @@ -10619,7 +10593,6 @@ "src/renderer/src/lib/simulator-tab-palette-activation.test.ts": 1304, "src/renderer/src/lib/skill-freshness-display-status.test.ts": 109, "src/renderer/src/lib/sleeping-agent-pane-ownership.test.ts": 45, - "src/renderer/src/lib/sleeping-agent-session-launch-layout-owner.test.ts": 536, "src/renderer/src/lib/sleeping-agent-session-launch-windows-quoting.test.ts": 533, "src/renderer/src/lib/smart-github-submit.test.ts": 75, "src/renderer/src/lib/source-control-agent-action-launch-check.test.ts": 1325, @@ -11162,7 +11135,6 @@ "src/renderer/src/store/plugin-panels.test.ts": 122, "src/renderer/src/store/project-host-setup-selector.test.ts": 47, "src/renderer/src/store/projects/project-catalog-null-field-ingest.test.ts": 143, - "src/renderer/src/store/projects/project-wsl-filesystem-boundary-advisory.test.ts": 72, "src/renderer/src/store/react-commit-cascade-write-probe.test.ts": 169, "src/renderer/src/store/repos/converted-ssh-browser-pages.test.ts": 489, "src/renderer/src/store/repos/converted-ssh-host-rows.test.ts": 33, @@ -11354,7 +11326,6 @@ "src/renderer/src/store/slices/project-removal-owner-host.test.ts": 1455, "src/renderer/src/store/slices/project-removal-runtime-terminal-order.test.ts": 1801, "src/renderer/src/store/slices/pull-request-generation-jira-title.test.ts": 76, - "src/renderer/src/store/slices/purge-stale-runtime-host-groups.test.ts": 1390, "src/renderer/src/store/slices/purge-stale-runtime-host-ownership.test.ts": 1529, "src/renderer/src/store/slices/purge-stale-runtime-host-state.test.ts": 1678, "src/renderer/src/store/slices/readopted-ssh-worktree-rows.test.ts": 47, @@ -11399,7 +11370,6 @@ "src/renderer/src/store/slices/runtime-status-catalog-identity.test.ts": 286, "src/renderer/src/store/slices/runtime-status-first-publication.test.ts": 329, "src/renderer/src/store/slices/runtime-status-reconnect-connection-generation.test.ts": 1219, - "src/renderer/src/store/slices/runtime-status-restored-browser-host-attach.test.ts": 376, "src/renderer/src/store/slices/runtime-status-skill-cache-eviction.test.ts": 269, "src/renderer/src/store/slices/runtime-status-snapshot.test.ts": 378, "src/renderer/src/store/slices/runtime-status.test.ts": 576, @@ -11459,7 +11429,6 @@ "src/renderer/src/store/slices/tabs-unread-and-focus.test.ts": 1556, "src/renderer/src/store/slices/tabs/hydrated-workspace-reconciliation-batch.test.ts": 1774, "src/renderer/src/store/slices/tabs/layout-owner-shared-path-gates.test.ts": 2018, - "src/renderer/src/store/slices/tabs/preview-tab-promotion.test.ts": 33, "src/renderer/src/store/slices/tabs/structured-chat-close-owner.test.ts": 1418, "src/renderer/src/store/slices/tabs/tab-selection-contract.test.ts": 237, "src/renderer/src/store/slices/tabs/tabs-layout-owner-groups-order.test.ts": 1456, diff --git a/config/scripts/ci-unit-files.mjs b/config/scripts/ci-unit-files.mjs index 8802da83ed6..8f89dc1b6e9 100644 --- a/config/scripts/ci-unit-files.mjs +++ b/config/scripts/ci-unit-files.mjs @@ -29,7 +29,6 @@ export const UNIT_EXCLUDE = [ 'src/main/daemon/shell-ready.test.ts', 'src/main/daemon/node-pty-fd-leak.test.ts', 'src/main/providers/local-pty-shell-ready-zsh-launch-environment.test.ts', - 'src/main/providers/__tests__/shell-ready-framework-example.test.ts', 'src/main/pty/omp-shell-wrapper-alias-safety.test.ts', 'src/main/pty/omp-shell-wrapper.node-pty.test.ts', 'src/main/shell-startup-feature-channel.test.ts', diff --git a/config/scripts/pr-shell-contract-prefixes.mjs b/config/scripts/pr-shell-contract-prefixes.mjs index 26783c1a240..7402851f616 100644 --- a/config/scripts/pr-shell-contract-prefixes.mjs +++ b/config/scripts/pr-shell-contract-prefixes.mjs @@ -6,7 +6,6 @@ export const SHELL_PREFIXES = [ 'src/main/daemon/daemon-shell-ready-wrapper', 'src/main/daemon/node-pty-fd-leak', 'src/main/providers/local-pty-shell-ready', - 'src/main/providers/__tests__/shell-ready-framework-example', 'src/main/pty/', 'src/main/shell-templates', 'src/main/shell-startup-', diff --git a/src/main/browser/extensions/browser-extension-background-wrapper.test.ts b/src/main/browser/extensions/browser-extension-background-wrapper.test.ts deleted file mode 100644 index 0c496cb4424..00000000000 --- a/src/main/browser/extensions/browser-extension-background-wrapper.test.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { - buildBrowserExtensionBackgroundWrapper, - withBrowserExtensionApiConnectSource -} from './browser-extension-background-wrapper' - -const base = { manifest_version: 3, name: 'Vault', version: '1.0' } - -describe('background wrapper', () => { - it('loads the shim, then the classic worker, through importScripts', () => { - const wrapper = buildBrowserExtensionBackgroundWrapper({ - ...base, - background: { service_worker: 'background.js' } - }) - expect(wrapper?.wrapperPath).toBe('orca-background.js') - expect(wrapper?.wrapperSource).toContain( - 'importScripts("/orca-extension-api.js", "/background.js");' - ) - expect(wrapper?.manifest.background).toEqual({ service_worker: 'orca-background.js' }) - }) - - it('imports the shim, then the module worker, from beside the original', () => { - const wrapper = buildBrowserExtensionBackgroundWrapper({ - ...base, - background: { service_worker: './build/service worker.js', type: 'module' } - }) - expect(wrapper?.wrapperPath).toBe('build/orca-background.js') - expect(wrapper?.wrapperSource).toContain( - 'import "/orca-extension-api.js";\nimport "/build/service%20worker.js";' - ) - expect(wrapper?.manifest.background).toEqual({ - service_worker: 'build/orca-background.js', - type: 'module' - }) - }) - - it('drops the Firefox background.scripts key that Chromium warns about in MV3', () => { - const wrapper = buildBrowserExtensionBackgroundWrapper({ - ...base, - background: { - service_worker: 'assets/background.js', - type: 'module', - scripts: ['assets/background.js'] - } - }) - expect(wrapper?.manifest.background).toEqual({ - service_worker: 'assets/orca-background.js', - type: 'module' - }) - }) - - it('leaves extensions without a background worker alone', () => { - expect(buildBrowserExtensionBackgroundWrapper(base)).toBeNull() - expect(buildBrowserExtensionBackgroundWrapper({ ...base, background: {} })).toBeNull() - }) - - it('rejects Manifest V2 and workers outside the folder', () => { - expect(() => - buildBrowserExtensionBackgroundWrapper({ - ...base, - manifest_version: 2, - background: { scripts: ['bg.js'] } - }) - ).toThrow('Manifest V3') - expect(() => - buildBrowserExtensionBackgroundWrapper({ - ...base, - background: { service_worker: '../outside.js' } - }) - ).toThrow('inside the extension folder') - }) - - it('lets a restrictive extension-pages policy reach the API', () => { - const wrapper = buildBrowserExtensionBackgroundWrapper({ - ...base, - background: { service_worker: 'bg.js' }, - content_security_policy: { - extension_pages: "script-src 'self'; connect-src https://vault.example", - sandbox: 'sandbox allow-scripts' - } - }) - expect(wrapper?.manifest.content_security_policy).toEqual({ - extension_pages: - "script-src 'self'; connect-src https://vault.example 'self' orca-extension-api:", - sandbox: 'sandbox allow-scripts' - }) - expect(withBrowserExtensionApiConnectSource("default-src 'none'; script-src 'self'")).toBe( - "default-src 'none'; script-src 'self'; connect-src 'self' orca-extension-api:" - ) - expect(withBrowserExtensionApiConnectSource("script-src 'self'")).toBe("script-src 'self'") - }) -}) diff --git a/src/main/browser/extensions/browser-extension-webstore-events.test.ts b/src/main/browser/extensions/browser-extension-webstore-events.test.ts deleted file mode 100644 index 41de24cd984..00000000000 --- a/src/main/browser/extensions/browser-extension-webstore-events.test.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { beforeEach, describe, expect, it, vi } from 'vitest' -import type { InstalledBrowserExtension } from '../../../shared/browser-extension-types' - -const state = vi.hoisted(() => { - const contents: unknown[] = [] - return { contents, enabled: new Map() } -}) - -vi.mock('electron', () => ({ - webContents: { getAllWebContents: () => state.contents } -})) -vi.mock('./browser-extension-api-host', () => ({ - getBrowserExtensionProfileIdForSession: (session: { profileId: string }) => session.profileId -})) -vi.mock('../browser-session-registry', () => ({ - browserSessionRegistry: { - getEnabledExtensionIds: (profileId: string) => state.enabled.get(profileId) ?? [] - } -})) - -const { notifyChromeWebStoreInstalled, notifyChromeWebStoreUninstalled } = - await import('./browser-extension-webstore-events') - -const extension: InstalledBrowserExtension = { - id: 'a'.repeat(32), - name: 'Example', - version: '1', - source: 'webstore', - path: '/extensions/example', - iconPath: null, - permissions: [], - hostPermissions: [], - optionsPage: null -} - -function storePage(profileId: string, url = 'https://chromewebstore.google.com/') { - const send = vi.fn() - const contents = { - isDestroyed: () => false, - getType: () => 'webview', - session: { profileId }, - mainFrame: { url, send } - } - state.contents.push(contents) - return send -} - -beforeEach(() => { - state.contents = [] - state.enabled.clear() -}) - -describe('Chrome Web Store profile events', () => { - it('reports an installation only to profiles where the extension is enabled', () => { - const enabledPage = storePage('personal') - const disabledPage = storePage('work') - const unrelatedPage = storePage('personal', 'https://example.com/') - state.enabled.set('personal', [extension.id]) - - notifyChromeWebStoreInstalled(extension) - - expect(enabledPage).toHaveBeenCalledWith(expect.any(String), { - event: 'onInstalled', - args: [expect.objectContaining({ id: extension.id, enabled: true })] - }) - expect(disabledPage).not.toHaveBeenCalled() - expect(unrelatedPage).not.toHaveBeenCalled() - }) - - it('reports a global uninstall to store pages in every profile', () => { - const personal = storePage('personal') - const work = storePage('work') - - notifyChromeWebStoreUninstalled(extension.id) - - for (const send of [personal, work]) { - expect(send).toHaveBeenCalledWith(expect.any(String), { - event: 'onUninstalled', - args: [extension.id] - }) - } - }) -}) diff --git a/src/main/claude-accounts/claude-profile-shell-composition.test.ts b/src/main/claude-accounts/claude-profile-shell-composition.test.ts deleted file mode 100644 index fb4ed6255e1..00000000000 --- a/src/main/claude-accounts/claude-profile-shell-composition.test.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { spawnSync } from 'node:child_process' -import { chmodSync, existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs' -import { tmpdir } from 'node:os' -import { join } from 'node:path' -import { afterEach, expect, it } from 'vitest' -const FISH = - ['/opt/homebrew/bin/fish', '/usr/local/bin/fish', '/usr/bin/fish'].find(existsSync) ?? - '/usr/bin/fish' -const roots: string[] = [] -afterEach(() => { - roots.splice(0).forEach((root) => rmSync(root, { recursive: true, force: true })) -}) -function fishInit({ args }: { args: string[] | null }): string { - const init = args?.[2] - if (!init) { - throw new Error('fish launch was not wrapped') - } - return init -} -async function composed() { - const local = await import('../providers/local-pty-shell-ready') - const daemon = await import('../daemon/shell-ready') - const powershell = await import('../powershell-osc133-bootstrap') - const localBash = await import('../providers/local-pty-shell-ready-bash-rcfile') - const daemonBash = await import('../daemon/daemon-bash-shell-ready-rcfile') - const zsh = await import('../zsh-startup-wrapper-builder') - const localZsh = await import('../providers/local-pty-shell-ready-wrapper-fileset') - const daemonZsh = await import('../daemon/daemon-zsh-shell-ready-wrapper-spec') - return { - zsh: [ - zsh.buildZshStartupHook(localZsh.getLocalZshWrapperSpec()), - zsh.buildZshStartupHook(daemonZsh.getDaemonZshWrapperSpec()) - ], - bash: [ - localBash.getBashShellReadyRcfileContent(), - daemonBash.getDaemonBashShellReadyRcfileContent() - ], - fish: [ - fishInit(local.getShellLaunchConfig(FISH, ['ready'])), - fishInit(daemon.getShellLaunchConfig(FISH, ['ready'])) - ], - powershell: powershell.getPowerShellOsc133Bootstrap() - } -} - -it('gives every composed shell startup and the plain fish vendor snippet the claude function', async () => { - const on = await composed() - for (const text of [...on.bash, ...on.zsh]) { - expect(text).toContain('ORCA_CLAUDE_INJECTED_CONFIG_DIR') - } - const { getFishVendorConfSnippet } = await import('../fish-xdg-data-dirs-handoff') - const { getFishClaudeShellFunction } = await import('../../shared/claude-shell-function') - expect(getFishClaudeShellFunction()).toContain('function claude') - expect(getFishVendorConfSnippet()).toContain(getFishClaudeShellFunction()) -}) - -it('starts the PowerShell claude function on its own line after the codex fragment', async () => { - const on = await composed() - expect(on.powershell).toContain( - 'Remove-Variable orcaCodexCommand -ErrorAction SilentlyContinue\n$orcaClaudeCommand' - ) -}) - -it.skipIf(!existsSync(FISH))( - 'defines both the ready hook and the claude function from the composed fish init', - async () => { - const root = mkdtempSync(join(tmpdir(), 'claude-fish-compose-')) - roots.push(root) - mkdirSync(join(root, 'bin')) - writeFileSync(join(root, 'bin', 'claude'), '#!/bin/sh\nexit 0\n') - chmodSync(join(root, 'bin', 'claude'), 0o700) - const on = await composed() - for (const init of on.fish) { - const result = spawnSync( - '/usr/bin/env', - [ - '-i', - `HOME=${root}`, - `PATH=${join(root, 'bin')}:/usr/bin:/bin`, - `ORCA_CLAUDE_PROFILE_POINTER=${join(root, 'selected')}`, - FISH, - '--no-config', - '-c', - `test (command -s claude) = '${join(root, 'bin', 'claude')}'; or exit 97\n${init}\nfunctions -q claude; and echo CLAUDE-FN\nfunctions -q __orca_shell_ready_marker; and echo READY-HOOK` - ], - { encoding: 'utf8' } - ) - expect(result.status).not.toBe(97) - expect(result.stderr).toBe('') - expect(result.stdout).toContain('CLAUDE-FN') - expect(result.stdout).toContain('READY-HOOK') - } - } -) diff --git a/src/main/codex/codex-configured-launch-defaults.test.ts b/src/main/codex/codex-configured-launch-defaults.test.ts deleted file mode 100644 index 722e5295841..00000000000 --- a/src/main/codex/codex-configured-launch-defaults.test.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { describe, expect, it, vi } from 'vitest' -import type { CodexAppServerConnection } from './app-server/codex-app-server-connection-types' -import { fetchCodexModelCatalogListing } from './codex-structured-model-catalog' - -function modelRow(id: string, isDefault = false): Record { - return { - model: id, - displayName: id.toUpperCase(), - hidden: false, - supportedReasoningEfforts: [ - { reasoningEffort: 'medium' }, - { reasoningEffort: 'high' }, - { reasoningEffort: 'xhigh' } - ], - defaultReasoningEffort: 'medium', - isDefault - } -} - -function connection( - configRead: { answer: unknown } | { error: Error } -): Pick & { request: ReturnType } { - return { - request: vi.fn(async (method: string) => { - if (method === 'model/list') { - return { data: [modelRow('gpt-6-astra', true), modelRow('gpt-5.5')], nextCursor: null } - } - if (method === 'config/read') { - if ('error' in configRead) { - throw configRead.error - } - return configRead.answer - } - throw new Error(`unexpected ${method}`) - }) - } -} - -function defaults(models: { id: string; isDefault: boolean; defaultEffort?: string }[]) { - return models.map(({ id, isDefault, defaultEffort }) => ({ id, isDefault, defaultEffort })) -} - -describe('Codex listing default follows the configured launch model', () => { - it('marks the configured model and effort as what a launch runs', async () => { - const listing = await fetchCodexModelCatalogListing({ - connection: connection({ - answer: { config: { model: 'gpt-5.5', model_reasoning_effort: 'xhigh' } } - }) - }) - expect(defaults(listing.models)).toEqual([ - { id: 'gpt-6-astra', isDefault: false, defaultEffort: 'medium' }, - { id: 'gpt-5.5', isDefault: true, defaultEffort: 'xhigh' } - ]) - }) - - it('applies a configured effort to the listed default when no model is configured', async () => { - const listing = await fetchCodexModelCatalogListing({ - connection: connection({ - answer: { config: { model: null, model_reasoning_effort: 'high' } } - }) - }) - expect(defaults(listing.models)).toEqual([ - { id: 'gpt-6-astra', isDefault: true, defaultEffort: 'high' }, - { id: 'gpt-5.5', isDefault: false, defaultEffort: 'medium' } - ]) - }) - - it('names no default when the configured model is one the listing does not offer', async () => { - const listing = await fetchCodexModelCatalogListing({ - connection: connection({ - answer: { config: { model: 'gpt-oss:20b', model_reasoning_effort: 'high' } } - }) - }) - expect(defaults(listing.models)).toEqual([ - { id: 'gpt-6-astra', isDefault: false, defaultEffort: 'medium' }, - { id: 'gpt-5.5', isDefault: false, defaultEffort: 'medium' } - ]) - }) - - it('ignores a configured effort the listed default cannot run', async () => { - const listing = await fetchCodexModelCatalogListing({ - connection: connection({ answer: { config: { model: null, model_reasoning_effort: 'max' } } }) - }) - expect(defaults(listing.models)).toEqual([ - { id: 'gpt-6-astra', isDefault: true, defaultEffort: 'medium' }, - { id: 'gpt-5.5', isDefault: false, defaultEffort: 'medium' } - ]) - }) - - it('keeps the listing as Codex sent it when config/read is unavailable', async () => { - const rpc = connection({ error: new Error('Method not found: config/read') }) - const listing = await fetchCodexModelCatalogListing({ connection: rpc }) - expect(rpc.request.mock.calls.map(([method]) => method)).toEqual(['model/list', 'config/read']) - expect(defaults(listing.models)).toEqual([ - { id: 'gpt-6-astra', isDefault: true, defaultEffort: 'medium' }, - { id: 'gpt-5.5', isDefault: false, defaultEffort: 'medium' } - ]) - }) -}) diff --git a/src/main/git/status-wsl-pathspecs.test.ts b/src/main/git/status-wsl-pathspecs.test.ts deleted file mode 100644 index c735bb42493..00000000000 --- a/src/main/git/status-wsl-pathspecs.test.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' -import { tmpdir } from 'node:os' -import path from 'node:path' -import { beforeEach, describe, expect, it, vi } from 'vitest' - -const { gitExecFileAsyncMock } = vi.hoisted(() => ({ - gitExecFileAsyncMock: vi.fn() -})) - -vi.mock('./runner', () => ({ - gitExecFileAsync: gitExecFileAsyncMock, - gitExecFileAsyncBuffer: vi.fn(), - gitOptionalLocksDisabledEnv: (env: NodeJS.ProcessEnv = process.env) => env, - gitStreamStdout: vi.fn() -})) - -import { - bulkDiscardChanges, - bulkStageFiles, - bulkUnstageFiles, - discardChanges, - stageFile, - unstageFile -} from './status' - -const worktreePath = path.resolve('repo') -const windowsRelativePath = 'tests\\breakgit' -const wslOptions = { wslDistro: 'Ubuntu' } - -describe('WSL git pathspecs', () => { - beforeEach(() => { - gitExecFileAsyncMock.mockReset() - gitExecFileAsyncMock.mockResolvedValue({ stdout: 'tests/breakgit\0', stderr: '' }) - }) - - it('uses POSIX separators for tracked file mutations executed inside WSL', async () => { - await stageFile(worktreePath, windowsRelativePath, wslOptions) - await unstageFile(worktreePath, windowsRelativePath, wslOptions) - await bulkStageFiles(worktreePath, [windowsRelativePath], wslOptions) - await bulkUnstageFiles(worktreePath, [windowsRelativePath], wslOptions) - await discardChanges(worktreePath, windowsRelativePath, wslOptions) - await bulkDiscardChanges(worktreePath, [windowsRelativePath], wslOptions) - - const pathspecs = gitExecFileAsyncMock.mock.calls.flatMap(([args]) => - (args as string[]).filter((arg) => arg.startsWith(':(literal)')) - ) - expect(pathspecs).toEqual(Array(5).fill(':(literal)tests/breakgit')) - const inputs = gitExecFileAsyncMock.mock.calls - .map(([, options]) => options.stdin) - .filter((input) => input !== undefined) - expect(inputs).toEqual(Array(3).fill(':(literal)tests/breakgit\0')) - }) - - it('uses POSIX separators when discarding untracked files inside WSL', async () => { - const repo = await mkdtemp(path.join(tmpdir(), 'orca-wsl-pathspec-')) - const targetPath = path.resolve(repo, windowsRelativePath) - await mkdir(path.dirname(targetPath), { recursive: true }) - await writeFile(targetPath, 'untracked') - - try { - gitExecFileAsyncMock - .mockRejectedValueOnce(new Error('not tracked')) - .mockResolvedValue({ stdout: '', stderr: '' }) - await discardChanges(repo, windowsRelativePath, wslOptions) - - expect(gitExecFileAsyncMock.mock.calls.map(([args]) => args)).toEqual([ - ['ls-files', '--error-unmatch', '--', ':(literal)tests/breakgit'], - ['clean', '-ffdx', '--', ':(literal)tests/breakgit'] - ]) - - gitExecFileAsyncMock.mockReset() - gitExecFileAsyncMock.mockResolvedValue({ stdout: '', stderr: '' }) - await bulkDiscardChanges(repo, [windowsRelativePath], wslOptions) - - expect(gitExecFileAsyncMock.mock.calls.map(([args]) => args)).toEqual([ - ['ls-files', '-z', '--', ':(literal)tests/breakgit'], - ['clean', '-ffdx', '--', ':(literal)tests/breakgit'] - ]) - } finally { - await rm(repo, { recursive: true, force: true }) - } - }) - - it('preserves backslashes for host Git where they can be literal filename characters', async () => { - await stageFile(worktreePath, windowsRelativePath) - - expect(gitExecFileAsyncMock).toHaveBeenCalledWith(['add', '--', ':(literal)tests\\breakgit'], { - cwd: worktreePath - }) - }) -}) diff --git a/src/main/git/worktree-create-admission-tier.test.ts b/src/main/git/worktree-create-admission-tier.test.ts deleted file mode 100644 index 8289689dc89..00000000000 --- a/src/main/git/worktree-create-admission-tier.test.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { beforeEach, describe, expect, it, vi } from 'vitest' -import type * as WorktreePreparationLock from './worktree-preparation-lock' - -type GitExec = ( - args: string[], - options: Record -) => Promise<{ stdout: string; stderr: string }> - -const gitExecFileAsyncMock = vi.hoisted(() => vi.fn()) - -vi.mock('./runner', () => ({ gitExecFileAsync: gitExecFileAsyncMock })) -vi.mock('./worktree-preparation-lock', async (importOriginal) => ({ - ...(await importOriginal()), - verifyWorktreePreparationLock: vi.fn(async () => '/owned-lock'), - verifyWorktreePreparationLockAtPath: vi.fn(), - unlockWorktreePreparationAtPath: vi.fn() -})) - -import { addWorktree } from './worktree-add' -import { listWorktreesSharedStrict } from './worktree-scan-cache' -import { finalizePreparedWorktree } from './worktree-create-preparation' - -const HEAD = 'a'.repeat(40) - -function optionsForCommand(match: string): Record[] { - return gitExecFileAsyncMock.mock.calls - .filter((call) => call[0].join(' ').includes(match)) - .map((call) => call[1]) -} - -describe('worktree create admission tier', () => { - beforeEach(() => { - gitExecFileAsyncMock.mockReset().mockResolvedValue({ stdout: HEAD, stderr: '' }) - }) - - it('runs the create add at the tier the caller asked for', async () => { - await addWorktree('/repo', '/repo-wt', 'feature', 'main', false, false, { - admissionTier: 'interactive' - }) - - const addOptions = optionsForCommand('worktree add') - expect(addOptions).toHaveLength(1) - expect(addOptions[0]).toMatchObject({ - cwd: '/repo', - admissionTier: 'interactive' - }) - }) - - it('runs the post-add listing at the tier the caller asked for', async () => { - await listWorktreesSharedStrict('/repo', { admissionTier: 'interactive' }) - - const listOptions = optionsForCommand('worktree list') - expect(listOptions.length).toBeGreaterThan(0) - for (const options of listOptions) { - expect(options).toMatchObject({ admissionTier: 'interactive' }) - } - }) - - it('runs the prepared-checkout finalize at the tier the caller asked for', async () => { - await finalizePreparedWorktree( - '/repo', - '/prepared', - '/repo-wt', - 'feature', - 'main', - false, - { admissionTier: 'interactive' }, - 'owner' - ) - - for (const match of ['worktree move', 'checkout --no-track']) { - const options = optionsForCommand(match) - expect(options, match).toHaveLength(1) - expect(options[0], match).toMatchObject({ admissionTier: 'interactive' }) - } - }) - - it('leaves a command with no tier at the scheduler default', async () => { - await addWorktree('/repo', '/repo-wt', 'feature', 'main') - - expect(optionsForCommand('worktree add')[0]).not.toHaveProperty('admissionTier') - }) -}) diff --git a/src/main/gitlab/gitlab-known-host-probe-wsl-fallback.test.ts b/src/main/gitlab/gitlab-known-host-probe-wsl-fallback.test.ts deleted file mode 100644 index 0c22f1576b2..00000000000 --- a/src/main/gitlab/gitlab-known-host-probe-wsl-fallback.test.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import type * as BackgroundDistroGate from '../wsl-background-distro-gate' -import { fakeSpawnDispatch } from '../../shared/__fixtures__/fake-spawned-child' -import type * as WslModule from '../wsl' - -const { execFileSyncMock, spawnMock, getDefaultWslDistroMock } = vi.hoisted(() => ({ - execFileSyncMock: vi.fn(), - spawnMock: vi.fn(), - getDefaultWslDistroMock: vi.fn() -})) - -// The default-distro fallback asks whether the distro runs before it may start it (E9). -vi.mock('../wsl-background-distro-gate', async (importOriginal) => ({ - ...(await importOriginal()), - readWslDistroRunningState: vi.fn(async () => 'running') -})) - -vi.mock('child_process', () => ({ - execFile: vi.fn(), - execFileSync: execFileSyncMock, - spawn: spawnMock -})) - -vi.mock('../wsl', async (importOriginal) => ({ - ...(await importOriginal()), - getDefaultWslDistro: getDefaultWslDistroMock -})) - -import { setDefaultWslDistroOverride } from '../git/runner' -import { _resetKnownHostsCache, getGlabKnownHosts } from './gitlab-known-host-probe' - -describe('glab known-hosts probe on Windows', () => { - const originalPlatform = process.platform - - const hostGlabMissingWslLoggedIn = (): void => { - spawnMock.mockImplementation( - fakeSpawnDispatch((program) => - program === 'wsl.exe' - ? { stdout: 'Logged in to gitlab.wsl.test as user' } - : { spawnError: Object.assign(new Error('spawn glab ENOENT'), { code: 'ENOENT' }) } - ) - ) - } - - beforeEach(() => { - spawnMock.mockReset() - getDefaultWslDistroMock.mockReset() - getDefaultWslDistroMock.mockReturnValue('Ubuntu') - setDefaultWslDistroOverride(null) - _resetKnownHostsCache() - Object.defineProperty(process, 'platform', { configurable: true, value: 'win32' }) - }) - - afterEach(() => { - setDefaultWslDistroOverride(null) - _resetKnownHostsCache() - Object.defineProperty(process, 'platform', { configurable: true, value: originalPlatform }) - }) - - it('does not wake the default WSL distro for the native execution key', async () => { - hostGlabMissingWslLoggedIn() - - await expect(getGlabKnownHosts()).resolves.toEqual(['gitlab.com']) - - expect(spawnMock).toHaveBeenCalledTimes(1) - expect(spawnMock).toHaveBeenCalledWith( - 'glab', - ['auth', 'status'], - expect.objectContaining({ cwd: undefined }) - ) - }) - - // Connection-keyed auth and API calls both use local glab, including its default-distro fallback. - it('keeps the default-distro fallback for a connection execution key', async () => { - hostGlabMissingWslLoggedIn() - - await expect(getGlabKnownHosts('conn-1')).resolves.toEqual(['gitlab.com', 'gitlab.wsl.test']) - - expect(spawnMock).toHaveBeenCalledWith( - 'wsl.exe', - ['-d', 'Ubuntu', '--exec', 'bash', '-c', "'glab' 'auth' 'status'"], - // A concrete safe cwd avoids inheriting a deletable worktree's UNC directory during Windows spawn. - expect.objectContaining({ cwd: expect.any(String) }) - ) - }) -}) diff --git a/src/main/ipc/pty-painted-cold-restore-ack-layout-owner.test.ts b/src/main/ipc/pty-painted-cold-restore-ack-layout-owner.test.ts deleted file mode 100644 index 0019b21825b..00000000000 --- a/src/main/ipc/pty-painted-cold-restore-ack-layout-owner.test.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { describe, expect, it, vi } from 'vitest' -import { onMock } from './pty/pty-ipc-mock-registry' -import { setupPtyIpcSuite } from './pty/pty-ipc-test-harness' -import { registerPtyHandlers } from './pty/register-handlers' -import { setLocalPtyProvider } from './pty/provider/registry' -vi.mock('electron', () => import('./pty/pty-ipc-mock-registry').then((m) => m.electronModuleMock())) -vi.mock('fs', () => import('./pty/pty-ipc-mock-registry').then((m) => m.fsModuleMock())) -vi.mock('node-pty', () => import('./pty/pty-ipc-mock-registry').then((m) => m.nodePtyModuleMock())) -vi.mock('node:child_process', async (importOriginal) => - (await import('./pty/pty-ipc-mock-registry')).childProcessModuleMock(await importOriginal()) -) -vi.mock('../opencode/hook-service', () => - import('./pty/pty-ipc-mock-registry').then((m) => m.openCodeHookServiceModuleMock()) -) -vi.mock('../mimo/hook-service', () => - import('./pty/pty-ipc-mock-registry').then((m) => m.mimoHookServiceModuleMock()) -) -vi.mock('../agent-hooks/server', () => - import('./pty/pty-ipc-mock-registry').then((m) => m.agentHookServerModuleMock()) -) -vi.mock('../pi/titlebar-extension-service', () => - import('./pty/pty-ipc-mock-registry').then((m) => m.piTitlebarExtensionModuleMock()) -) -vi.mock('../pwsh', () => import('./pty/pty-ipc-mock-registry').then((m) => m.pwshModuleMock())) -vi.mock('../wsl', async (importOriginal) => - (await import('./pty/pty-ipc-mock-registry')).wslModuleMock(await importOriginal()) -) -vi.mock('../telemetry/client', () => - import('./pty/pty-ipc-mock-registry').then((m) => m.telemetryClientModuleMock()) -) -vi.mock('../telemetry/classify-error', () => - import('./pty/pty-ipc-mock-registry').then((m) => m.classifyErrorModuleMock()) -) -vi.mock('../cli/linux-terminal-orca-cli-shim', () => - import('./pty/pty-ipc-mock-registry').then((m) => m.linuxCliShimModuleMock()) -) -vi.mock('../memory/pty-registry', () => - import('./pty/pty-ipc-mock-registry').then((m) => m.ptyRegistryModuleMock()) -) -vi.mock('../agent-hooks/migration-unsupported-pty-state', () => - import('./pty/pty-ipc-mock-registry').then((m) => m.migrationUnsupportedPtyModuleMock()) -) -vi.mock('../codex/codex-pane-account-registry', () => - import('./pty/pty-ipc-mock-registry').then((m) => m.codexPaneAccountRegistryModuleMock()) -) -vi.mock('../codex/codex-state-db-backfill-recovery', () => - import('./pty/pty-ipc-mock-registry').then((m) => m.codexBackfillRecoveryModuleMock()) -) -vi.mock('../../shared/layout-owner-switch', () => ({ ORCA_LAYOUT_OWNER_IS_MAIN: true })) - -const PANE = { worktreeId: 'repo::/wt', tabId: 'tab-1', leafId: 'leaf-1' } - -describe('a painted cold-restore ack in the layout-owner build', () => { - const { mainWindow } = setupPtyIpcSuite() - - function ackWith(boundPtyId: string, args: unknown): ReturnType { - const ackColdRestore = vi.fn() - const isRestoredPaneBoundTo = (_pane: unknown, ptyId: string): boolean => ptyId === boundPtyId - // Only the binding read matters here; every other runtime hook the handlers install is inert. - const runtime = new Proxy( - {}, - { get: (_target, key) => (key === 'isRestoredPaneBoundTo' ? isRestoredPaneBoundTo : vi.fn()) } - ) - // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the Proxy answers every runtime hook the handlers install. - registerPtyHandlers(mainWindow, runtime as never) - // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the ack listener calls only ackColdRestore. - setLocalPtyProvider({ ackColdRestore } as never) - const call = onMock.mock.calls.findLast((entry: unknown[]) => entry[0] === 'pty:ackColdRestore') - // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: ipcMain.on registered this channel with an (event, args) listener. - const listener = call?.[1] as (event: unknown, args: unknown) => void - listener(null, args) - return ackColdRestore - } - - it('releases the terminal service copy for the pane’s current terminal', () => { - expect(ackWith('pty-1', { id: 'pty-1', pane: PANE })).toHaveBeenCalledWith('pty-1') - }) - - it('keeps it when a stale view acks a terminal the pane no longer binds', () => { - expect(ackWith('pty-new', { id: 'pty-old', pane: PANE })).not.toHaveBeenCalled() - }) - - it('keeps it for an ack that names no pane', () => { - expect(ackWith('pty-1', { id: 'pty-1' })).not.toHaveBeenCalled() - }) -}) diff --git a/src/main/ipc/worktrees/listing/register-sparse-checkout-cache-invalidation.test.ts b/src/main/ipc/worktrees/listing/register-sparse-checkout-cache-invalidation.test.ts deleted file mode 100644 index 760fa2801e4..00000000000 --- a/src/main/ipc/worktrees/listing/register-sparse-checkout-cache-invalidation.test.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { beforeEach, describe, expect, it, vi } from 'vitest' -import type { Repo } from '../../../../shared/repo-types' -import type { Store } from '../../../persistence/loading-store/store' -import { runWorktreeChangeInvalidators } from '../../worktree-change-invalidators' -import { registerSparseCheckoutCacheInvalidation } from './register-sparse-checkout-cache-invalidation' - -const { - clearSparseCheckoutStateCacheMock, - clearSparseCheckoutStateCacheForRepoMock, - onSparseCheckoutStateChangedMock, - notifyWorktreesChangedMock -} = vi.hoisted(() => ({ - clearSparseCheckoutStateCacheMock: vi.fn(), - clearSparseCheckoutStateCacheForRepoMock: vi.fn(), - onSparseCheckoutStateChangedMock: vi.fn(), - notifyWorktreesChangedMock: vi.fn() -})) - -vi.mock('../../../git/worktree-sparse-checkout-cache', () => ({ - clearSparseCheckoutStateCache: clearSparseCheckoutStateCacheMock, - clearSparseCheckoutStateCacheForRepo: clearSparseCheckoutStateCacheForRepoMock, - onSparseCheckoutStateChanged: onSparseCheckoutStateChangedMock -})) - -vi.mock('../../worktree-remote', () => ({ - notifyWorktreesChanged: notifyWorktreesChangedMock -})) - -function makeStore(repos: Repo[]): Store { - return { - getRepo: (id: string) => repos.find((repo) => repo.id === id), - getRepos: () => repos - } as unknown as Store -} - -const mainWindow = {} as never - -beforeEach(() => { - vi.clearAllMocks() -}) - -describe('registerSparseCheckoutCacheInvalidation', () => { - it('clears only the resolved repo`s cache when the invalidator registry fires', () => { - const store = makeStore([{ id: 'repo-1', path: '/repo-1' } as Repo]) - const dispose = registerSparseCheckoutCacheInvalidation(mainWindow, store) - try { - runWorktreeChangeInvalidators('repo-1') - expect(clearSparseCheckoutStateCacheForRepoMock).toHaveBeenCalledWith('/repo-1') - expect(clearSparseCheckoutStateCacheMock).not.toHaveBeenCalled() - } finally { - dispose() - } - }) - - it('falls back to a full clear when the repo cannot be resolved', () => { - const store = makeStore([]) - const dispose = registerSparseCheckoutCacheInvalidation(mainWindow, store) - try { - runWorktreeChangeInvalidators('unknown-repo') - expect(clearSparseCheckoutStateCacheMock).toHaveBeenCalledTimes(1) - expect(clearSparseCheckoutStateCacheForRepoMock).not.toHaveBeenCalled() - } finally { - dispose() - } - }) - - it('forwards a background stale-while-revalidate flip to the shared worktrees-changed notification', () => { - const store = makeStore([{ id: 'repo-1', path: '/repo-1' } as Repo]) - const dispose = registerSparseCheckoutCacheInvalidation(mainWindow, store) - try { - const listener = onSparseCheckoutStateChangedMock.mock.calls.at(-1)?.[0] - listener?.('/repo-1', '/repo-1/wt-a', true) - expect(notifyWorktreesChangedMock).toHaveBeenCalledWith(mainWindow, 'repo-1') - } finally { - dispose() - } - }) - - it('drops the change listener on disposal so a stale window/store stops receiving flips', () => { - const store = makeStore([{ id: 'repo-1', path: '/repo-1' } as Repo]) - const dispose = registerSparseCheckoutCacheInvalidation(mainWindow, store) - dispose() - expect(onSparseCheckoutStateChangedMock).toHaveBeenLastCalledWith(undefined) - }) -}) diff --git a/src/main/ipc/wsl-host-handlers-startup-reconcile.test.ts b/src/main/ipc/wsl-host-handlers-startup-reconcile.test.ts deleted file mode 100644 index edd6fecebdf..00000000000 --- a/src/main/ipc/wsl-host-handlers-startup-reconcile.test.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { afterEach, describe, expect, it, vi } from 'vitest' - -const order = vi.hoisted(() => ({ calls: new Array(), serving: true })) -vi.mock('electron', () => ({ - BrowserWindow: { getAllWindows: () => [] }, - ipcMain: { removeHandler: vi.fn(), handle: vi.fn() } -})) -vi.mock('../wsl/wsl-host-gate', async (importOriginal) => ({ - ...(await importOriginal>()), - wslHostsServing: () => order.serving -})) -vi.mock('../../shared/runtime-environment-wsl-host-store', async (importOriginal) => ({ - ...(await importOriginal>()), - reconcileWslHostBridgePorts: () => { - order.calls.push('reconcile') - return [] - } -})) -vi.mock('../wsl/wsl-host-connector', () => ({ createWslHostConnector: vi.fn() })) -vi.mock('../wsl/wsl-host-e2e-fake-connector', () => ({ - readFakeWslHostsConfig: () => ({ serverFiles: 'present' }), - createFakeWslHostConnector: () => { - order.calls.push('connector') - return { - connect: async () => { - order.calls.push('connect') - } - } - } -})) -vi.mock('../wsl/wsl-orphan-holder-release', () => ({ - releaseUnwantedWslHolders: async () => {}, - wslHolderKeepPolicy: () => () => true -})) -vi.mock('./wsl-host-automation-wake-wiring', () => ({ createWslHostAutomationWake: () => null })) -vi.mock('../wsl/wsl-host-service', () => ({ - WslHostService: class { - connector: { connect: (distro: string) => Promise } | null = null - attach(connector: { connect: (distro: string) => Promise }): void { - this.connector = connector - } - handleConnectionChange(): void {} - isKnownDistro(): boolean { - return true - } - hasUserVisibleWork(): boolean { - return false - } - // Startup's first bridge work: adopting holders, then any reconnect. - async start(): Promise { - order.calls.push('start') - await this.connector?.connect('Ubuntu') - } - } -})) -const instance = vi.hoisted((): { service: unknown } => ({ service: null })) -vi.mock('../wsl/wsl-host-service-instance', () => ({ - getWslHostService: () => instance.service, - setWslHostService: (service: unknown) => { - instance.service = service - }, - // The phone's gate is built beside the service; startup order is all this suite checks. - setWslHostPhoneGate: () => {} -})) - -import { registerWslHostHandlers } from './wsl-host-handlers' - -function register(): void { - registerWslHostHandlers({ - // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: startup reads settings only through onSettingsChanged. - store: { getSettings: () => ({}), onSettingsChanged: vi.fn() } as never, - getUserDataPath: () => '/user-data', - invalidateTransport: vi.fn() - }) -} - -// A crash between a pairing save's two writes hides the host unless its record is realigned first. -describe('WSL host startup: the bridge-port reconcile', () => { - afterEach(() => { - order.calls = [] - order.serving = true - instance.service = null - }) - - it('realigns saved records before the connector exists or any bridge connects', async () => { - register() - await vi.waitFor(() => expect(order.calls).toContain('connect')) - expect(order.calls).toEqual(['reconcile', 'connector', 'start', 'connect']) - }) - - it('reads and writes no record while WSL hosts are not serving', () => { - order.serving = false - register() - expect(order.calls).toEqual([]) - expect(instance.service).toBeNull() - }) -}) diff --git a/src/main/native-chat/session-file-resolver-codex-roots.test.ts b/src/main/native-chat/session-file-resolver-codex-roots.test.ts deleted file mode 100644 index 5dcdf66f179..00000000000 --- a/src/main/native-chat/session-file-resolver-codex-roots.test.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { beforeEach, describe, expect, it, vi } from 'vitest' -import type * as WslModule from '../wsl' -import type * as WslRunningPathFilterModule from '../wsl-running-path-filter' - -const MANAGED_HOME = '/tmp/orca-user-data/codex-runtime-home/home' - -// Polling may read paths only; the launch-time getter mkdirSyncs and would block every tick. -vi.mock('../codex/codex-home-paths', () => ({ - getOrcaManagedCodexHomePath: vi.fn(() => MANAGED_HOME), - resolveOrcaManagedCodexHomePath: vi.fn(() => MANAGED_HOME) -})) - -// Disable WSL fallback so the host-roots test behaves identically on every platform. -vi.mock('../wsl', async (importOriginal) => ({ - ...(await importOriginal()), - listRunningWslHomeDirsAsync: vi.fn(async () => []) -})) -vi.mock('../wsl-running-path-filter', async (importOriginal) => ({ - ...(await importOriginal()), - filterPathsToRunningWslDistrosAsync: vi.fn(async (paths: readonly string[]) => [...paths]) -})) - -const scanned = vi.hoisted(() => ({ dirs: [] as string[] })) -vi.mock('../ai-vault/session-scanner-discovery', () => ({ - walkSessionFiles: async (dir: string) => { - scanned.dirs.push(dir) - return [] - } -})) - -import { join } from 'node:path' -import { getOrcaManagedCodexHomePath } from '../codex/codex-home-paths' -import { - configureHostReadableTranscriptPathSources, - resetHostReadableTranscriptPathCacheForTests -} from './host-readable-transcript-path' -import { resolveSessionFilePath } from './session-file-resolver' - -beforeEach(() => { - resetHostReadableTranscriptPathCacheForTests() - vi.mocked(getOrcaManagedCodexHomePath).mockClear() - scanned.dirs = [] -}) - -describe('codex sessions roots', () => { - it('scans the managed home without materializing it', async () => { - await resolveSessionFilePath('codex', 'sess-1') - - expect(scanned.dirs).toContain(join(MANAGED_HOME, 'sessions')) - expect(vi.mocked(getOrcaManagedCodexHomePath)).not.toHaveBeenCalled() - }) - - it('scans per-account homes after the default roots, leaving WSL shares to their tier', async () => { - const accountHome = '/home/u/.local/share/orca/codex-accounts/a1/home' - configureHostReadableTranscriptPathSources({ - getAdditionalCodexHomePaths: () => [accountHome, '\\\\wsl.localhost\\Ubuntu\\home\\u\\.codex'] - }) - - await resolveSessionFilePath('codex', 'sess-1') - - const accountDir = join(accountHome, 'sessions') - expect(scanned.dirs).toContain(accountDir) - expect(scanned.dirs.indexOf(accountDir)).toBeGreaterThan( - scanned.dirs.indexOf(join(MANAGED_HOME, 'sessions')) - ) - expect(scanned.dirs.some((dir) => dir.startsWith('\\\\'))).toBe(false) - }) - - it('leaves per-account homes out when the caller names the roots', async () => { - const getAdditionalCodexHomePaths = vi.fn(() => ['/home/u/acct/home']) - configureHostReadableTranscriptPathSources({ getAdditionalCodexHomePaths }) - - await resolveSessionFilePath('codex', 'sess-1', { codexSessionsDirs: ['/pinned/sessions'] }) - - expect(scanned.dirs).toEqual(['/pinned/sessions']) - expect(getAdditionalCodexHomePaths).not.toHaveBeenCalled() - }) - - it('still answers when the account homes cannot be listed', async () => { - const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}) - configureHostReadableTranscriptPathSources({ - getAdditionalCodexHomePaths: () => { - throw new Error('EACCES') - } - }) - - await expect(resolveSessionFilePath('codex', 'sess-1')).resolves.toBe(null) - expect(scanned.dirs).toContain(join(MANAGED_HOME, 'sessions')) - warn.mockRestore() - }) -}) diff --git a/src/main/providers/__tests__/shell-ready-framework-example.test.ts b/src/main/providers/__tests__/shell-ready-framework-example.test.ts deleted file mode 100644 index 0a807bfc657..00000000000 --- a/src/main/providers/__tests__/shell-ready-framework-example.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' -import { tmpdir } from 'node:os' -import { join } from 'node:path' -import { mkdtempSync, rmSync } from 'node:fs' -import { spawnSync } from 'node:child_process' -import { shellScriptTest } from './shell-ready-framework/shell-script-test' - -const { getUserDataPathMock } = vi.hoisted(() => ({ - getUserDataPathMock: vi.fn<() => string>() -})) - -vi.mock('electron', () => ({ - app: { - getPath: (name: string) => { - if (name === 'userData') { - return getUserDataPathMock() - } - throw new Error(`unexpected app.getPath(${name})`) - } - } -})) - -const hasZsh = process.platform !== 'win32' && spawnSync('which', ['zsh']).status === 0 -const describeIfZsh = hasZsh ? describe : describe.skip - -describeIfZsh('shell-script-literal framework example', () => { - let userDataPath: string - - beforeEach(() => { - userDataPath = mkdtempSync(join(tmpdir(), 'shell-test-userdata-')) - getUserDataPathMock.mockReturnValue(userDataPath) - }) - - afterEach(() => { - rmSync(userDataPath, { recursive: true, force: true }) - }) - - it('discovers ZDOTDIR when .zshenv sources another file', async () => { - const { stdout } = await shellScriptTest( - ` - # Setup multi-file config - mkdir -p ~/.config/zsh - cat > ~/.config/zsh/env <<'EOF' -export ZDOTDIR="$HOME/.config/zsh" -EOF - - cat > ~/.zshenv <<'EOF' -source "$HOME/.config/zsh/env" -EOF - - # Run: check discovered ZDOTDIR - zsh -c 'env | grep -E "^(ORCA_|ZDOTDIR|HOME)=" | sort' - `, - { userDataPath } - ) - - expect(stdout).toMatchInlineSnapshot(` - "HOME= - ZDOTDIR=/.config/zsh - " - `) - }) - - it('handles conditional ZDOTDIR based on SSH_CONNECTION', async () => { - const { stdout } = await shellScriptTest( - ` - mkdir -p ~/.config/zsh-local ~/.config/zsh-remote - cat > ~/.zshenv <<'EOF' -if [[ -n "$SSH_CONNECTION" ]]; then - export ZDOTDIR="$HOME/.config/zsh-remote" -else - export ZDOTDIR="$HOME/.config/zsh-local" -fi -EOF - - # Run with SSH_CONNECTION set - SSH_CONNECTION='192.168.1.100 52100 192.168.1.1 22' zsh -c 'env | grep ZDOTDIR | sort' - `, - { userDataPath } - ) - - expect(stdout).toMatchInlineSnapshot(` - "ZDOTDIR=/.config/zsh-remote - " - `) - }) -}) diff --git a/src/main/runtime/rpc/methods/automatic-work.test.ts b/src/main/runtime/rpc/methods/automatic-work.test.ts deleted file mode 100644 index 09f345aee38..00000000000 --- a/src/main/runtime/rpc/methods/automatic-work.test.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { describe, expect, it, vi } from 'vitest' -import { OrcaRuntimeService } from '../../orca-runtime' -import { denyRpcMethodForCaller } from '../rpc-caller-scope' -import { eraseRpcMethods } from '../core' -import { AUTOMATIC_WORK_METHODS } from './automatic-work' -import type { RpcContext } from '../core' -import type { RuntimePtyController } from '../../runtime-pty-controller-contract' - -function context(runtime: OrcaRuntimeService): RpcContext { - return { runtime } -} - -function method(name: string) { - const found = eraseRpcMethods(AUTOMATIC_WORK_METHODS).find((candidate) => candidate.name === name) - if (!found) { - throw new Error(`Missing method ${name}`) - } - return found -} - -function runtimeWithController( - controller: Pick -): OrcaRuntimeService { - const runtime = new OrcaRuntimeService(null) - runtime.setPtyController({ - spawn: vi.fn(), - write: () => true, - kill: () => true, - getForegroundProcess: async () => null, - ...controller - }) - return runtime -} - -describe('runtime.automaticWork RPC methods', () => { - it('resumes through the local terminal owner and reports what it cleared', async () => { - const cleared = { kind: 'paused' as const, reason: 'unclean_host_death' as const, since: 5 } - const resumeAutomaticWork = vi.fn(async () => ({ - admission: 'enforce' as const, - mode: { kind: 'normal' as const }, - cleared - })) - const runtime = runtimeWithController({ resumeAutomaticWork }) - - await expect( - method('runtime.automaticWork.resume').handler(undefined, context(runtime)) - ).resolves.toEqual({ - automaticWork: { admission: 'enforce', mode: { kind: 'normal' }, cleared } - }) - expect(resumeAutomaticWork).toHaveBeenCalledOnce() - }) - - it('answers null when the local owner has no gate', async () => { - const runtime = runtimeWithController({}) - await expect( - method('runtime.automaticWork.status').handler(undefined, context(runtime)) - ).resolves.toEqual({ automaticWork: null }) - await expect( - method('runtime.automaticWork.resume').handler(undefined, context(runtime)) - ).resolves.toEqual({ automaticWork: null }) - }) - - it('says when the running terminal host predates resume instead of claiming no gate', async () => { - const runtime = runtimeWithController({ - resumeAutomaticWork: async () => 'terminal-host-predates-resume' as const - }) - await expect( - method('runtime.automaticWork.resume').handler(undefined, context(runtime)) - ).resolves.toEqual({ automaticWork: null, terminalHostPredatesResume: true }) - }) - - it('lets a paired desktop resume but never a phone', () => { - const resume = method('runtime.automaticWork.resume') - expect(resume.permission).toBe('host-admin') - expect( - denyRpcMethodForCaller({ kind: 'runtime-paired', grants: [] }, resume.name, resume.permission) - ).toBeNull() - expect( - denyRpcMethodForCaller({ kind: 'mobile' }, resume.name, resume.permission) - ).not.toBeNull() - }) -}) diff --git a/src/main/runtime/runtime-worktree-removal-process-cleanup.test.ts b/src/main/runtime/runtime-worktree-removal-process-cleanup.test.ts deleted file mode 100644 index 703142f02dc..00000000000 --- a/src/main/runtime/runtime-worktree-removal-process-cleanup.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -/** Runtime removals must clear the same per-id process state and persisted scan snapshots as desktop IPC removals. */ -import { beforeEach, describe, expect, it, vi } from 'vitest' - -const mocks = vi.hoisted(() => ({ - unregisterWorktree: vi.fn(), - pruneCleanupScan: vi.fn(async () => {}), - pruneSpaceAnalysis: vi.fn(async () => {}) -})) - -vi.mock('../localhost-worktree-label-proxy', () => ({ - localhostWorktreeLabelProxy: { unregisterWorktree: mocks.unregisterWorktree } -})) -vi.mock('../workspace-cleanup-scan-snapshot', () => ({ - pruneWorkspaceCleanupScanSnapshot: mocks.pruneCleanupScan -})) -vi.mock('../workspace-space-analysis-snapshot', () => ({ - pruneWorkspaceSpaceAnalysisSnapshot: mocks.pruneSpaceAnalysis -})) - -import type { Repo } from '../../shared/repo-types' -import { OrcaRuntimeService } from './orca-runtime' - -const WT = 'repo-1::/tmp/worktree-a' - -function repo(overrides: Partial = {}): Repo { - return { - id: 'repo-1', - path: '/tmp/repo', - displayName: 'repo', - badgeColor: 'blue', - addedAt: 1, - ...overrides - } -} - -function createRuntime(repos: Repo[]) { - const store = { - getRepo: () => repos[0], - getRepos: () => repos, - addRepo: () => {}, - updateRepo: () => undefined, - getAllWorktreeMeta: () => ({}), - getWorktreeMeta: () => undefined, - removeWorktreeMeta: () => {}, - getGitHubCache: () => ({ pr: {}, issue: {} }), - setWorktreeMeta: () => undefined, - getRetiredWorktreeNameRegistry: () => ({ exhaustedTiers: 0, names: [] }), - addRetiredWorktreeName: () => {}, - mergeRetiredWorktreeNames: () => false, - getProfileStorageDirectory: () => '/tmp/profile', - getSettings: () => ({ - workspaceDir: '/tmp/workspaces', - nestWorkspaces: false, - refreshLocalBaseRefOnWorktreeCreate: false, - branchPrefix: 'none', - branchPrefixCustom: '' - }) - } - // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: a partial store covering every method this removal path reads. - const runtimeStore = store as never - return { runtime: new OrcaRuntimeService(runtimeStore), store: runtimeStore } -} - -beforeEach(() => { - vi.clearAllMocks() -}) - -describe('runtime worktree removal cleanup', () => { - it('drops label routes and persisted scan snapshots', () => { - const { runtime, store } = createRuntime([repo()]) - - runtime.removeWorktreeMetadataAndHistory(store, WT, 'local') - - expect(mocks.unregisterWorktree).toHaveBeenCalledWith(WT) - expect(mocks.pruneCleanupScan).toHaveBeenCalledWith('/tmp/profile', WT, 'local') - expect(mocks.pruneSpaceAnalysis).toHaveBeenCalledWith('/tmp/profile', WT, 'local') - }) - - it('keeps a surviving same-id twin its process state but prunes only this host snapshot', () => { - const { runtime, store } = createRuntime([repo(), repo({ connectionId: 'box' })]) - - runtime.removeWorktreeMetadataAndHistory(store, WT, 'local') - - expect(mocks.unregisterWorktree).not.toHaveBeenCalled() - expect(mocks.pruneCleanupScan).toHaveBeenCalledWith('/tmp/profile', WT, 'local') - }) -}) diff --git a/src/main/runtime/sidebar-inputs/orca-runtime-workspace-review-facts.test.ts b/src/main/runtime/sidebar-inputs/orca-runtime-workspace-review-facts.test.ts deleted file mode 100644 index d0b0b6e156d..00000000000 --- a/src/main/runtime/sidebar-inputs/orca-runtime-workspace-review-facts.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -// Runs on plain Node, as orcad does: facts come from the host's persisted PR cache. -import { describe, expect, it, vi } from 'vitest' -import { OrcaRuntimeService } from '../orca-runtime' -import type { PRInfo } from '../../../shared/github/pull-request-types' -import type { RuntimeStore } from '../runtime-store-contract' -import type { ResolvedWorktreeSnapshot } from '../runtime-resolved-worktree-cache' -import type { ResolvedWorktree } from '../runtime-worktree-path-identity' - -vi.mock('../../../shared/sidebar-inputs-switch', () => ({ ORCA_SIDEBAR_INPUTS_IS_MAIN: true })) - -function withSidebarFacts(runtime: OrcaRuntimeService) { - const facts = runtime.sidebarFacts - if (!facts) { - throw new Error('built without the sidebar facts layer') - } - return facts -} - -const repo = { id: 'repo-1', path: '/r', displayName: 'r', badgeColor: 'blue', addedAt: 1 } - -function worktree(id: string, branch: string): ResolvedWorktree { - return { - id, - repoId: repo.id, - path: id, - branch, - head: '', - isBare: false, - isMainWorktree: false, - displayName: id, - comment: '', - linkedIssue: null, - linkedPR: null, - linkedLinearIssue: null, - linkedGitLabMR: null, - linkedGitLabIssue: null, - isArchived: false, - isUnread: false, - isPinned: false, - sortOrder: 0, - lastActivityAt: 0, - parentWorktreeId: null, - childWorktreeIds: [], - lineage: null, - git: { path: id, head: '', branch, isBare: false, isMainWorktree: false } - } -} - -describe('getWorkspaceReviewFacts', () => { - it('keys the persisted PR cache by workspace row', async () => { - const merged: PRInfo = { - number: 3, - title: 'Ship it', - state: 'merged', - url: 'https://github.com/o/r/pull/3', - checksStatus: 'success', - updatedAt: '2026-10-17T00:00:00Z', - mergeable: 'UNKNOWN' - } - const pr = { 'repo-1::a': { data: merged, fetchedAt: 1 } } - const store: Pick = { - getRepos: () => [repo], - getGitHubCache: () => ({ pr, issue: {} }) - } - class Probe extends OrcaRuntimeService { - protected override async listResolvedWorktreeSnapshot(): Promise { - return { - worktrees: [worktree('repo-1::/r/a', 'refs/heads/a'), worktree('repo-1::/r/b', 'b')], - platformByRepoId: new Map() - } - } - } - // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the read touches only repos and the GitHub cache. - const runtime = withSidebarFacts(new Probe(store as RuntimeStore)) - await expect(runtime.getWorkspaceReviewFacts()).resolves.toEqual({ - facts: { '|repo-1::/r/a': { provider: 'github', reviewState: 'merged' } } - }) - }) - - it('publishes nothing without a store', async () => { - await expect( - withSidebarFacts(new OrcaRuntimeService()).getWorkspaceReviewFacts() - ).resolves.toEqual({ - facts: {} - }) - }) -}) diff --git a/src/main/startup/windows-isolated-spawner.test.ts b/src/main/startup/windows-isolated-spawner.test.ts deleted file mode 100644 index 5fc8468e1a5..00000000000 --- a/src/main/startup/windows-isolated-spawner.test.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { afterEach, describe, expect, it, vi } from 'vitest' - -const { loadWindowsSecurity, setIsolatedSpawner } = vi.hoisted(() => ({ - loadWindowsSecurity: vi.fn(), - setIsolatedSpawner: vi.fn() -})) -vi.mock('../../shared/windows-security-addon', () => ({ loadWindowsSecurity })) -vi.mock('@orca/process-host/isolated-detached-spawn', () => ({ setIsolatedSpawner })) - -import { installWindowsIsolatedSpawner } from './windows-isolated-spawner' - -function addonWith(hasNativeExport: (name: string) => boolean) { - const spawnDetachedIsolated = vi.fn() - return { - spawnDetachedIsolated, - security: { userSid: 'S-1-5-18', addon: { hasNativeExport, spawnDetachedIsolated } } - } -} - -describe('installWindowsIsolatedSpawner', () => { - afterEach(() => { - vi.restoreAllMocks() - loadWindowsSecurity.mockReset() - setIsolatedSpawner.mockReset() - }) - - it('is a no-op off Windows', () => { - installWindowsIsolatedSpawner('darwin') - - expect(loadWindowsSecurity).not.toHaveBeenCalled() - expect(setIsolatedSpawner).not.toHaveBeenCalled() - }) - - it('installs the native spawner when the binary exports it', () => { - const { security, spawnDetachedIsolated } = addonWith(() => true) - loadWindowsSecurity.mockReturnValue(security) - const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}) - - installWindowsIsolatedSpawner('win32') - - expect(setIsolatedSpawner).toHaveBeenCalledWith(spawnDetachedIsolated) - expect(warn).not.toHaveBeenCalled() - }) - - it('still installs a pre-breakaway spawner for its handle isolation, and logs it', () => { - const { security, spawnDetachedIsolated } = addonWith( - (name) => name === 'spawnDetachedIsolated' - ) - loadWindowsSecurity.mockReturnValue(security) - const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}) - - installWindowsIsolatedSpawner('win32') - - expect(setIsolatedSpawner).toHaveBeenCalledWith(spawnDetachedIsolated) - expect(warn).toHaveBeenCalledWith( - '[startup] detached spawns stay in our jobs; the addon build predates breakaway' - ) - }) - - it('keeps libuv and logs when the binary is stale', () => { - loadWindowsSecurity.mockReturnValue(addonWith(() => false).security) - const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}) - - installWindowsIsolatedSpawner('win32') - - expect(setIsolatedSpawner).not.toHaveBeenCalled() - expect(warn).toHaveBeenCalledWith( - '[startup] detached spawns inherit handles; the addon build is stale' - ) - }) - - it('keeps libuv and logs when the addon is unavailable or throws', () => { - const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}) - loadWindowsSecurity.mockReturnValueOnce({ error: 'missing binary' }) - loadWindowsSecurity.mockImplementationOnce(() => { - throw new Error('boom') - }) - - expect(() => installWindowsIsolatedSpawner('win32')).not.toThrow() - expect(() => installWindowsIsolatedSpawner('win32')).not.toThrow() - expect(setIsolatedSpawner).not.toHaveBeenCalled() - expect(warn).toHaveBeenCalledTimes(2) - }) -}) diff --git a/src/main/wsl/wsl-host-e2e-fake-connector.test.ts b/src/main/wsl/wsl-host-e2e-fake-connector.test.ts deleted file mode 100644 index 9bf9637869d..00000000000 --- a/src/main/wsl/wsl-host-e2e-fake-connector.test.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs' -import { tmpdir } from 'node:os' -import { join } from 'node:path' -import { afterEach, beforeEach, expect, it, vi } from 'vitest' -import { UNVERIFIABLE_ORCAD_TERMINAL_CENSUS } from '../../shared/orcad-terminal-census' -import { encodePairingOffer } from '../../shared/pairing' -import { createFakeWslHostConnector } from './wsl-host-e2e-fake-connector' - -const pairingCode = encodePairingOffer({ - v: 2, - endpoint: 'ws://127.0.0.1:42000', - deviceToken: 'fake-token', - publicKeyB64: Buffer.alloc(32, 7).toString('base64') -}) -const runtime = { - call: async () => ({}), - census: async () => UNVERIFIABLE_ORCAD_TERMINAL_CENSUS -} - -let dir: string -let distrosFile: string - -function writeState(state: 'running' | 'stopped'): void { - writeFileSync(distrosFile, JSON.stringify([{ name: 'Ubuntu', state, version: 2 }])) -} - -function connector(onChange = vi.fn(), stopSilently = false) { - const fake = createFakeWslHostConnector( - { distros: [], distrosFile, pairingCode, stopSilently }, - onChange, - { isKnownDistro: () => true, runtime } - ) - return { fake, onChange } -} - -beforeEach(() => { - dir = mkdtempSync(join(tmpdir(), 'orca-fake-wsl-')) - distrosFile = join(dir, 'distros.json') - writeState('running') -}) - -afterEach(() => { - rmSync(dir, { recursive: true, force: true }) -}) - -it('drops the bridge of a distro the test stops and refuses a no-boot reconnect', async () => { - const { fake, onChange } = connector() - await fake.connect('Ubuntu') - expect(await fake.reachability('Ubuntu', 'wsl:ubuntu')).toBe('available') - writeState('stopped') - expect(await fake.reachability('Ubuntu', 'wsl:ubuntu')).toBe('stopped') - expect(fake.get('Ubuntu')).toBeNull() - // Matches production liveness, which reports the stop rather than a plain close. - expect(onChange).toHaveBeenLastCalledWith('Ubuntu', null, { - state: 'distro-stopped', - terminals: 'exited', - recovering: false - }) - await expect(fake.connect('Ubuntu', { noBoot: true })).rejects.toThrow('Ubuntu is not running.') -}) - -it('leaves a silent stop for a runtime call to report, as when liveness saw only a quick reboot', async () => { - const { fake, onChange } = connector(vi.fn(), true) - await fake.connect('Ubuntu') - writeState('stopped') - expect(await fake.reachability('Ubuntu', 'wsl:ubuntu')).toBe('stopped') - expect(onChange).toHaveBeenLastCalledWith('Ubuntu', null, { state: 'closed' }) -}) - -it('still reports a plain close for an explicit disconnect of a running distro', async () => { - const { fake, onChange } = connector() - await fake.connect('Ubuntu') - await fake.disconnect('Ubuntu') - expect(onChange).toHaveBeenLastCalledWith('Ubuntu', null, { state: 'closed' }) -}) - -it('boots a stopped distro on a plain connect', async () => { - const { fake } = connector() - writeState('stopped') - await fake.connect('Ubuntu') - expect(JSON.parse(readFileSync(distrosFile, 'utf8'))).toEqual([ - { name: 'Ubuntu', state: 'running', version: 2 } - ]) - expect(await fake.reachability('Ubuntu', 'wsl:ubuntu')).toBe('available') -}) - -it('keeps a fixed listing always running', async () => { - const fake = createFakeWslHostConnector( - { distros: [{ name: 'Legacy', state: 'stopped', version: 1 }], pairingCode }, - vi.fn(), - { isKnownDistro: () => true, runtime } - ) - expect(await fake.reachability('Legacy', 'wsl:legacy')).toBe('unreachable') - await fake.connect('Legacy', { noBoot: true }) - expect(await fake.reachability('Legacy', 'wsl:legacy')).toBe('available') -}) diff --git a/src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree-row-drag.test.tsx b/src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree-row-drag.test.tsx deleted file mode 100644 index 9f8fca7fe44..00000000000 --- a/src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree-row-drag.test.tsx +++ /dev/null @@ -1,86 +0,0 @@ -// @vitest-environment happy-dom - -import { act } from 'react' -import { createRoot, type Root } from 'react-dom/client' -import { afterEach, describe, expect, it, vi } from 'vitest' -import type { ExecutionHostId } from '../../../../../../shared/execution-host' - -const testState: { executionHostId: ExecutionHostId } = vi.hoisted(() => ({ - executionHostId: 'local' -})) - -vi.mock('@/store', () => ({ useAppStore: { getState: () => ({}) } })) -vi.mock('@/lib/worktree-runtime-owner', () => ({ - getKnownExecutionHostIdForWorktree: () => testState.executionHostId -})) - -const { CombinedDiffFileTreeRow } = await import('./combined-diff-file-tree-row') -const { readWorkspaceFileDragSource } = await import('@/lib/workspace-file-drag') - -globalThis.IS_REACT_ACT_ENVIRONMENT = true - -const roots: Root[] = [] -afterEach(() => { - roots.splice(0).forEach((root) => act(() => root.unmount())) - document.body.replaceChildren() - testState.executionHostId = 'local' -}) - -function renderRow(sourceWorkspaceId?: string): HTMLDivElement { - const container = document.createElement('div') - document.body.appendChild(container) - const root = createRoot(container) - roots.push(root) - act(() => { - root.render( - {}} - onNavigate={() => {}} - /> - ) - }) - return container -} - -function dragRow(container: HTMLDivElement): DataTransfer { - const transfer = new DataTransfer() - const event = new Event('dragstart', { bubbles: true, cancelable: true }) - Object.defineProperty(event, 'dataTransfer', { value: transfer }) - act(() => { - container.querySelector('[draggable="true"]')?.dispatchEvent(event) - }) - return transfer -} - -describe('combined diff rows stamp their drag source', () => { - // Entry lists are snapshots; drag paths must use the workspace’s live owner, matching source-control rows. - it('stamps the live owner of the workspace the diff belongs to', () => { - testState.executionHostId = 'runtime:env-1' - expect(readWorkspaceFileDragSource(dragRow(renderRow('wt-1')))).toEqual({ - executionHostId: 'runtime:env-1', - workspaceId: 'wt-1' - }) - }) - - it('leaves the drag unstamped when the owner or the workspace is unknown', () => { - expect(readWorkspaceFileDragSource(dragRow(renderRow(undefined)))).toBeNull() - testState.executionHostId = 'runtime:unresolved-owner' - expect(readWorkspaceFileDragSource(dragRow(renderRow('wt-1')))).toBeNull() - }) -}) diff --git a/src/renderer/src/components/right-sidebar/AiVaultShowMoreSessionsRow.test.tsx b/src/renderer/src/components/right-sidebar/AiVaultShowMoreSessionsRow.test.tsx deleted file mode 100644 index 8bfa1489695..00000000000 --- a/src/renderer/src/components/right-sidebar/AiVaultShowMoreSessionsRow.test.tsx +++ /dev/null @@ -1,85 +0,0 @@ -// @vitest-environment happy-dom -import { cleanup, render, screen } from '@testing-library/react' -import userEvent from '@testing-library/user-event' -import { afterEach, expect, it, vi } from 'vitest' -import { AiVaultShowMoreSessionsRow } from './AiVaultShowMoreSessionsRow' - -afterEach(cleanup) - -it('steps the history depth up by one page once the scan filled it', async () => { - const onSessionLimitChange = vi.fn() - render( - - ) - await userEvent.setup().click(screen.getByRole('button', { name: 'Show more sessions' })) - expect(onSessionLimitChange).toHaveBeenCalledWith(750) -}) - -it('stays put in a loading state while the deeper rescan runs', () => { - render( - - ) - const button = screen.getByRole('button', { name: 'Loading more sessions…' }) - expect(button.hasAttribute('disabled')).toBe(true) -}) - -// Depth-minus-page is zero at the default, falsely claiming every foreground rescan loads deeper history. -it('stays hidden during a foreground rescan the scan had room for', () => { - render( - - ) - expect(screen.queryByRole('button')).toBeNull() -}) - -it('stays hidden while the scan has room or is already unlimited', () => { - render( - - ) - render( - - ) - expect(screen.queryByRole('button')).toBeNull() -}) - -it('stays hidden until the first scan reports the depth it ran at', () => { - render( - - ) - expect(screen.queryByRole('button')).toBeNull() -}) diff --git a/src/renderer/src/components/right-sidebar/source-control/sync/use-status-refresh.local-ignore.test.tsx b/src/renderer/src/components/right-sidebar/source-control/sync/use-status-refresh.local-ignore.test.tsx deleted file mode 100644 index 62b84c90c6b..00000000000 --- a/src/renderer/src/components/right-sidebar/source-control/sync/use-status-refresh.local-ignore.test.tsx +++ /dev/null @@ -1,86 +0,0 @@ -/** @vitest-environment happy-dom */ -import { act } from 'react' -import { runtimeTargetForOwnerEnvironment } from '@/runtime/runtime-client-target' -import { createRoot, type Root } from 'react-dom/client' -import { afterEach, beforeEach, expect, it, vi } from 'vitest' -import { clearHugeRepoWarningDismissalsForTests } from '@/lib/source-control-huge-repo-warning-dismissals' -import { useSourceControlStatusRefresh } from './use-status-refresh' - -globalThis.IS_REACT_ACT_ENVIRONMENT = true - -const actions = vi.hoisted(() => ({ - setGitStatus: vi.fn(), - updateWorktreeGitIdentity: vi.fn(), - setUpstreamStatus: vi.fn(), - fetchUpstreamStatus: vi.fn() -})) -const warning = vi.hoisted(() => vi.fn()) -vi.mock('@/store', () => ({ - useAppStore: (select: (state: typeof actions) => unknown) => select(actions) -})) -vi.mock('sonner', () => ({ toast: { warning } })) -vi.mock('@/lib/connection-context', () => ({ getConnectionId: () => null })) -vi.mock('../../git-status-refresh', () => ({ refreshGitStatusForWorktree: vi.fn() })) -vi.mock('@/i18n/i18n', () => ({ translate: (_key: string, fallback: string) => fallback })) - -const findHugeFoldersToIgnore = vi.fn() -const appendGitignore = vi.fn() -let root: Root | null = null -let container: HTMLDivElement | null = null - -beforeEach(() => { - findHugeFoldersToIgnore.mockReset().mockResolvedValue(['dist']) - appendGitignore.mockReset().mockResolvedValue(true) - warning.mockReset() - vi.stubGlobal('window', { - ...window, - api: { git: { findHugeFoldersToIgnore, appendGitignore } } - }) - container = document.createElement('div') - root = createRoot(container) -}) - -afterEach(() => { - act(() => root?.unmount()) - root = null - container = null - vi.unstubAllGlobals() - clearHugeRepoWarningDismissalsForTests() -}) - -async function renderOwner( - runtimeEnvironmentId: string | null, - connectionId: string | null = null -) { - function Probe() { - useSourceControlStatusRefresh({ - activeRepoTarget: runtimeTargetForOwnerEnvironment(runtimeEnvironmentId), - activeWorktreeId: 'repo::/same/path', - worktreePath: '/same/path', - isFolder: false, - repositoryHuge: { limit: 1000 }, - activeConnectionId: connectionId - }) - return null - } - await act(async () => root?.render()) -} - -it('does not probe or offer a desktop ignore action for a managed owner without a legacy SSH ID', async () => { - await renderOwner('managed-owner') - expect(findHugeFoldersToIgnore).not.toHaveBeenCalled() - expect(warning).not.toHaveBeenCalled() - expect(appendGitignore).not.toHaveBeenCalled() -}) - -it('keeps the existing local suggestion', async () => { - await renderOwner(null) - expect(findHugeFoldersToIgnore).toHaveBeenCalledExactlyOnceWith({ worktreePath: '/same/path' }) - expect(warning).toHaveBeenCalledTimes(1) -}) - -it('keeps direct SSH targets out of the desktop helper', async () => { - await renderOwner(null, 'ssh-owner') - expect(findHugeFoldersToIgnore).not.toHaveBeenCalled() - expect(warning).not.toHaveBeenCalled() -}) diff --git a/src/renderer/src/components/settings/AppearanceThemeControl.test.tsx b/src/renderer/src/components/settings/AppearanceThemeControl.test.tsx deleted file mode 100644 index daf254f23e5..00000000000 --- a/src/renderer/src/components/settings/AppearanceThemeControl.test.tsx +++ /dev/null @@ -1,98 +0,0 @@ -// @vitest-environment happy-dom -import { cleanup, render, screen } from '@testing-library/react' -import { afterEach, expect, it, vi } from 'vitest' -import { getDefaultSettings } from '../../../../shared/constants' -import { AppearanceThemeSlotSelect } from './AppearanceThemeControl' - -const themes = vi.hoisted((): { app: unknown[]; terminal: unknown[] } => ({ - app: [], - terminal: [] -})) -vi.mock('@/store/plugin-themes', () => ({ - usePluginThemes: () => themes.app, - usePluginTerminalThemes: () => themes.terminal -})) - -afterEach(() => { - cleanup() - themes.app = [] - themes.terminal = [] -}) - -const dusk = { - id: 'plugin:samples.dusk/dusk', - pluginKey: 'samples.dusk', - revision: 'r1', - pluginName: 'Dusk', - label: 'Dusk', - base: 'dark', - tokens: { '--background': '#1b1430', '--foreground': '#e8e0ff' } -} - -it('lists only themes of its mode, grouped by plugin, and offers the plugin terminal colors', async () => { - themes.app = [ - dusk, - { ...dusk, id: 'plugin:samples.dusk/dawn', label: 'Dawn', base: 'light' }, - { - ...dusk, - id: 'plugin:acme.night/night', - pluginKey: 'acme.night', - pluginName: 'Acme', - label: 'Night' - } - ] - themes.terminal = [ - { - ...dusk, - mode: 'dark', - terminal: { background: '#1b1430', foreground: '#e8e0ff', red: '#f00' } - } - ] - const updateSettings = vi.fn() - render( - - ) - expect(screen.getByRole('combobox', { name: 'Dark theme' }).textContent).toContain('Dusk') - screen.getByRole('button', { name: 'Use its terminal colors' }).click() - expect(updateSettings).toHaveBeenCalledWith({ - terminalThemeDark: 'plugin:samples.dusk/dusk', - terminalPluginPalettes: [ - { - id: 'plugin:samples.dusk/dusk', - colors: { background: '#1b1430', foreground: '#e8e0ff', red: '#f00' } - } - ] - }) - // Overrides would otherwise mask the palette the user just chose. - expect(updateSettings.mock.calls[0]?.[0]).toHaveProperty('terminalColorOverrides', undefined) - screen.getByRole('combobox', { name: 'Dark theme' }).click() - expect(await screen.findByText('Acme')).toBeDefined() - expect(screen.queryByRole('option', { name: 'Dawn' })).toBeNull() - screen.getByRole('option', { name: 'Night' }).click() - expect(updateSettings).toHaveBeenLastCalledWith({ pluginAppThemeDark: 'plugin:acme.night/night' }) -}) - -it('returns a slot to the built-in colors', async () => { - themes.app = [dusk] - const updateSettings = vi.fn() - render( - - ) - screen.getByRole('combobox', { name: 'Dark theme' }).click() - ;(await screen.findByRole('option', { name: 'Built-in' })).click() - expect(updateSettings).toHaveBeenCalledWith({ pluginAppThemeDark: null }) -}) diff --git a/src/renderer/src/components/settings/SettingsFormControls.number-field.test.tsx b/src/renderer/src/components/settings/SettingsFormControls.number-field.test.tsx deleted file mode 100644 index 75c8e27d082..00000000000 --- a/src/renderer/src/components/settings/SettingsFormControls.number-field.test.tsx +++ /dev/null @@ -1,85 +0,0 @@ -// @vitest-environment happy-dom -import { cleanup, fireEvent, render, screen } from '@testing-library/react' -import { afterEach, describe, expect, it, vi } from 'vitest' -import { NumberField } from './SettingsFormControls' - -afterEach(cleanup) - -// Optional settings need a clear path back to automatic behavior (#10754). -describe('NumberField clearable fields', () => { - it('renders the placeholder and commits nothing while the value is unset', () => { - render( - - ) - - const input = screen.getByLabelText('Minimum Contrast Ratio') as HTMLInputElement - expect(input.value).toBe('') - expect(input.getAttribute('placeholder')).toBe('Auto') - }) - - it('clears the setting when the field is emptied', () => { - const onChange = vi.fn() - const onClear = vi.fn() - render( - - ) - - const input = screen.getByLabelText('Minimum Contrast Ratio') - fireEvent.change(input, { target: { value: '' } }) - fireEvent.blur(input) - - expect(onClear).toHaveBeenCalledTimes(1) - expect(onChange).not.toHaveBeenCalled() - }) - - it('still snaps back to the current value when the field is not clearable', () => { - const onChange = vi.fn() - render() - - const input = screen.getByLabelText('Font Size') as HTMLInputElement - fireEvent.change(input, { target: { value: '' } }) - fireEvent.blur(input) - - expect(onChange).not.toHaveBeenCalled() - expect(input.value).toBe('14') - }) - - it('clamps a committed value into the min/max window', () => { - const onChange = vi.fn() - render( - - ) - - const input = screen.getByLabelText('Minimum Contrast Ratio') - fireEvent.change(input, { target: { value: '99' } }) - fireEvent.blur(input) - - expect(onChange).toHaveBeenCalledWith(21) - }) -}) diff --git a/src/renderer/src/components/settings/chat-settings-unsaved-guard.test.tsx b/src/renderer/src/components/settings/chat-settings-unsaved-guard.test.tsx deleted file mode 100644 index ef4c370aff1..00000000000 --- a/src/renderer/src/components/settings/chat-settings-unsaved-guard.test.tsx +++ /dev/null @@ -1,84 +0,0 @@ -// @vitest-environment happy-dom -import { act, cleanup, renderHook } from '@testing-library/react' -import { afterEach, describe, expect, it, vi } from 'vitest' -import { getDefaultSettings } from '../../../../shared/constants' -import { - useSettingsInteractionController, - type SettingsInteractionModel -} from './use-settings-interaction-controller' -import { useSettingsNavigationActions } from './settings-view-model' - -afterEach(cleanup) - -function createModel(shouldDiscard = false, dirty = true) { - return { - closeSettingsPage: vi.fn(), - confirm: vi.fn(async () => shouldDiscard), - hasUnsavedBranchPromptChanges: false, - hasUnsavedCommitPromptChanges: false, - hasUnsavedChatPromptChanges: dirty, - highlightedSettingsTargetId: null, - setFontSuggestions: vi.fn(), - setHasUnsavedBranchPromptChanges: vi.fn(), - setHasUnsavedCommitPromptChanges: vi.fn(), - setHasUnsavedChatPromptChanges: vi.fn(), - setHighlightedSettingsTargetId: vi.fn(), - setSettingsSearchQuery: vi.fn(), - setSourceControlAiPromptDiscardSignal: vi.fn(), - settings: getDefaultSettings('/tmp'), - updateSettingsOrThrow: vi.fn(async () => {}), - activeSectionId: 'chat', - setActiveSectionId: vi.fn(), - setPendingNavRequestTick: vi.fn(), - settingsSearchQuery: '' - } satisfies SettingsInteractionModel & Parameters[0] -} - -function renderController(model: ReturnType) { - return renderHook(() => { - const interactions = useSettingsInteractionController(model) - const navigation = useSettingsNavigationActions(model, interactions) - return { ...interactions, ...navigation } - }) -} - -describe('Chat settings unsaved guard', () => { - it('asks before closing with a dirty chat recipe and keeps the page open when cancelled', async () => { - const model = createModel() - const { result } = renderController(model) - await act(async () => result.current.closeSettingsPageWithPromptGuard()) - expect(model.confirm).toHaveBeenCalledWith( - expect.objectContaining({ title: 'Discard unsaved AI settings?' }) - ) - expect(model.closeSettingsPage).not.toHaveBeenCalled() - expect(model.setHasUnsavedChatPromptChanges).not.toHaveBeenCalled() - expect(model.setSourceControlAiPromptDiscardSignal).not.toHaveBeenCalled() - }) - - it('clears the chat draft through the existing discard signal before closing', async () => { - const model = createModel(true) - const { result } = renderController(model) - await act(async () => result.current.closeSettingsPageWithPromptGuard()) - expect(model.confirm).toHaveBeenCalledOnce() - expect(model.setSourceControlAiPromptDiscardSignal).toHaveBeenCalledOnce() - expect(model.setHasUnsavedChatPromptChanges).toHaveBeenCalledWith(false) - expect(model.closeSettingsPage).toHaveBeenCalledOnce() - }) - - it('guards settings navigation with the same dirty chat recipe', async () => { - const model = createModel() - const { result } = renderController(model) - await act(async () => result.current.scrollToSection('git')) - expect(model.confirm).toHaveBeenCalledOnce() - expect(model.setActiveSectionId).not.toHaveBeenCalled() - expect(model.setSourceControlAiPromptDiscardSignal).not.toHaveBeenCalled() - }) - - it('closes without asking when the recipe is clean', async () => { - const model = createModel(false, false) - const { result } = renderController(model) - await act(async () => result.current.closeSettingsPageWithPromptGuard()) - expect(model.confirm).not.toHaveBeenCalled() - expect(model.closeSettingsPage).toHaveBeenCalledOnce() - }) -}) diff --git a/src/renderer/src/components/sidebar/OrcaYamlTrustDialog.test.tsx b/src/renderer/src/components/sidebar/OrcaYamlTrustDialog.test.tsx deleted file mode 100644 index 0b8b638a52c..00000000000 --- a/src/renderer/src/components/sidebar/OrcaYamlTrustDialog.test.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import { renderToStaticMarkup } from 'react-dom/server' -import type { ButtonHTMLAttributes, ReactNode } from 'react' -import { beforeEach, describe, expect, it, vi } from 'vitest' - -const mocks = vi.hoisted(() => ({ - state: { - activeModal: 'confirm-orca-yaml-hooks' as string | null, - modalData: {} as Record, - closeModal: vi.fn(), - markOrcaHookScriptConfirmed: vi.fn(), - markOrcaHookRepoAlwaysTrusted: vi.fn() - } -})) - -vi.mock('@/store', () => ({ - useAppStore: Object.assign( - (selector: (state: typeof mocks.state) => unknown) => selector(mocks.state), - { - getState: () => mocks.state - } - ) -})) - -vi.mock('@/components/ui/dialog', () => ({ - Dialog: ({ open, children }: { open: boolean; children: ReactNode }) => - open ?
{children}
: null, - DialogContent: ({ children }: { children: ReactNode }) =>
{children}
, - DialogDescription: ({ children }: { children: ReactNode }) =>
{children}
, - DialogFooter: ({ children }: { children: ReactNode }) =>
{children}
, - DialogHeader: ({ children }: { children: ReactNode }) =>
{children}
, - DialogTitle: ({ children }: { children: ReactNode }) =>
{children}
-})) - -vi.mock('@/components/ui/button', () => ({ - Button: ({ - children, - ...props - }: ButtonHTMLAttributes & { children: ReactNode }) => ( - - ) -})) - -function decodeHtml(html: string): string { - return html - .replace(/'/g, "'") - .replace(/"/g, '"') - .replace(/&/g, '&') - .replace(/</g, '<') - .replace(/>/g, '>') -} - -describe('OrcaYamlTrustDialog', () => { - beforeEach(() => { - vi.clearAllMocks() - mocks.state.activeModal = 'confirm-orca-yaml-hooks' - mocks.state.modalData = { - repoId: 'repo-1', - repoName: 'orca', - scriptKind: 'setup', - scriptContent: 'node config/scripts/run-internal-dev-setup.mjs\npnpm install', - contentHash: 'hash-1', - previouslyApproved: false - } - }) - - it('keeps spaces around orca.yaml and the repo name in the first-run copy', async () => { - const { default: OrcaYamlTrustDialog } = await import('./OrcaYamlTrustDialog') - const text = decodeHtml(renderToStaticMarkup()).replace(/<[^>]+>/g, '') - - expect(text).toContain("This repository's orca.yaml runs on your machine") - expect(text).toContain('Only run if you trust orca.') - expect(text).toContain('Always trust orca.yaml in orca') - expect(text).not.toContain("repository'sorca.yaml") - expect(text).not.toContain('trustorca') - expect(text).not.toContain('trustorca.yaml') - expect(text).not.toContain('inorca') - }) - - it('keeps spaces around orca.yaml when the script changed since last approval', async () => { - mocks.state.modalData = { - ...mocks.state.modalData, - previouslyApproved: true - } - const { default: OrcaYamlTrustDialog } = await import('./OrcaYamlTrustDialog') - const text = decodeHtml(renderToStaticMarkup()).replace(/<[^>]+>/g, '') - - expect(text).toContain('orca.yaml changed since you last approved') - expect(text).toContain('Always trust orca.yaml in orca') - expect(text).not.toContain('Always trustorca.yaml') - expect(text).not.toContain('inorca') - }) -}) diff --git a/src/renderer/src/components/sidebar/WslMovedProjectsSection.test.tsx b/src/renderer/src/components/sidebar/WslMovedProjectsSection.test.tsx deleted file mode 100644 index e5ac1321802..00000000000 --- a/src/renderer/src/components/sidebar/WslMovedProjectsSection.test.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import { renderToStaticMarkup } from 'react-dom/server' -import { beforeEach, describe, expect, it, vi } from 'vitest' -import type { Tab } from '../../../../shared/tab-types' -import type { WslMovedProject } from '../../../../shared/wsl-move/wsl-moved-project' - -type MockState = { - wslMovedProjects: WslMovedProject[] - worktreesByRepo: Record - folderWorkspaces: { id: string }[] - unifiedTabsByWorktree: Record[]> - activeWorktreeId: string | null - activeGroupIdByWorktree: Record - groupsByWorktree: Record -} - -let mockState: MockState - -vi.mock('@/store', () => ({ - useAppStore: (selector: (state: MockState) => unknown) => selector(mockState) -})) -vi.mock('@/lib/wsl-moved-chat-activation', () => ({ activateWslMovedWorkspace: vi.fn() })) -vi.mock('@/lib/wsl-moved-project-use-here', () => ({ bringWslMovedProjectBack: vi.fn() })) -vi.mock('@/components/confirmation-dialog-context', () => ({ - useConfirmationDialog: () => vi.fn() -})) - -const { default: WslMovedProjectsSection } = await import('./WslMovedProjectsSection') -const { TooltipProvider } = await import('@/components/ui/tooltip') - -// The app shell provides the tooltip context the sidebar renders in. -const render = (): string => - renderToStaticMarkup( - - - - ) - -const MOVED = 'repo1::\\\\wsl.localhost\\Ubuntu\\home\\dev\\repo1' -const chat = (id: string, label: string): Partial => ({ - id, - entityId: id, - worktreeId: MOVED, - contentType: 'agent-session', - label, - customLabel: null -}) - -describe('WslMovedProjectsSection', () => { - beforeEach(() => { - mockState = { - wslMovedProjects: [ - { kind: 'repo', id: 'repo1', displayName: 'Repo 1', path: MOVED, distro: 'Ubuntu' } - ], - worktreesByRepo: {}, - folderWorkspaces: [], - unifiedTabsByWorktree: { - [MOVED]: [chat('agent-session:a', 'Fix the parser'), chat('agent-session:b', 'Plan')] - }, - activeWorktreeId: MOVED, - activeGroupIdByWorktree: { [MOVED]: 'group-1' }, - groupsByWorktree: { [MOVED]: [{ id: 'group-1', activeTabId: 'agent-session:b' }] } - } - }) - - it('lists the moved project read-only, labeled with its host, with only its chats', () => { - const markup = render() - expect(markup).toContain('Repo 1') - expect(markup).toContain('Moved to Ubuntu host') - expect(markup).toContain('Fix the parser') - // One button per chat plus "use here again": no new terminal, new chat, rename or menu. - expect(markup.match(/