Files
orca/config/scripts/pr-e2e-route-contracts.test.mjs
T

543 lines
24 KiB
JavaScript

import { describe, expect, it } from 'vitest'
import { existsSync, readdirSync, readFileSync } from 'node:fs'
import { join, resolve } from 'node:path'
import { parse } from 'yaml'
import {
classifyE2eJobs,
DEDICATED_E2E_SPECS,
MANAGED_SSH_E2E_SPEC_PREFIX,
ORCAD_SERVE_MODE_SWITCH_E2E_SPEC,
WINDOWS_COPY_FILE_E2E_SPEC,
WINDOWS_MISSING_APPDATA_E2E_SPEC,
selectGeneralE2eSpecs
} from './ci-e2e-job-selection.mjs'
import { classifyPrJobs } from './pr-code-change-scope.mjs'
import { testImportClosure } from './e2e-test-import-closure.mjs'
import { isLayoutOracleSource, LAYOUT_ORACLE_E2E_SPECS } from './pr-layout-oracle-route.mjs'
import {
hasNativeImeSourceChange,
MANUAL_ONLY_E2E_SPECS,
PR_E2E_SOURCE_ROUTES,
selectPrE2eSpecs,
shouldRunReusablePrE2e
} from './pr-e2e-source-routing.mjs'
const projectDir = resolve(import.meta.dirname, '../..')
const prWorkflow = parse(readFileSync(join(projectDir, '.github/workflows/pr.yml'), 'utf8'))
const e2eWorkflow = parse(readFileSync(join(projectDir, '.github/workflows/e2e.yml'), 'utf8'))
describe('pr-e2e-native-only-routing', () => {
const workflow = prWorkflow
const filterStep = workflow.jobs.code_paths.steps.find((step) => step.id === 'e2e_filter')
describe('native-only PR E2E routing', () => {
it('avoids generic E2E allocation for native-only changes while preserving its IME lane', () => {
for (const file of [
'tests/e2e/terminal-ibus-hangul-native.spec.ts',
'config/scripts/run-terminal-ibus-hangul-e2e.mjs'
]) {
expect(hasNativeImeSourceChange([file])).toBe(true)
expect(shouldRunReusablePrE2e([file])).toBe(false)
}
expect(shouldRunReusablePrE2e([])).toBe(false)
for (const spec of [
'tests/e2e/paired-startup-exec-readiness.spec.ts',
'tests/e2e/terminal-ime-exact-byte.spec.ts',
'tests/e2e/future.spec.ts'
]) {
expect(shouldRunReusablePrE2e([spec])).toBe(true)
expect(
shouldRunReusablePrE2e(['tests/e2e/terminal-ibus-hangul-native.spec.ts', spec])
).toBe(true)
}
expect(filterStep.run).toContain('pr-e2e-source-routing.mjs --reusable-workflow')
expect(filterStep.run).toContain('if [ "$SHOULD_RUN" = true ]; then')
})
})
})
describe('pr-e2e-pane-close-routing', () => {
/**
* The product paths of #21005, "retire captured remote handles when pending panes close". It
* changed the pane close and retirement lifecycle across three transports and matched no route
* at all, so it merged with E2E skipped outright. The routes named every module that BINDS a
* pane and none that unbinds one.
*/
const PENDING_PANE_CLOSE_CHANGE = [
'src/renderer/src/components/terminal-pane/retire-unbound-ipc-terminal-pane.ts',
'src/renderer/src/components/terminal-pane/retire-unbound-runtime-terminal-pane.ts',
'src/renderer/src/components/terminal-pane/terminal-pane-close-admission.ts',
'src/renderer/src/components/terminal-pane/terminal-pane-retirement-ownership.ts',
'src/renderer/src/components/terminal-pane/use-terminal-pane-close-actions.ts',
'src/renderer/src/store/terminals/terminal-tab-close-providers.ts'
]
const CLOSE_ROUTE = PR_E2E_SOURCE_ROUTES.find(
(route) => route.id === 'terminal-pane.close-and-retirement'
)
describe('pane close and retirement PR E2E routing', () => {
it('selects the close specs for a pane close lifecycle change', () => {
expect(selectPrE2eSpecs(PENDING_PANE_CLOSE_CHANGE)).toEqual([
'tests/e2e/paired-remote-split-pane-host-retired-ghost.spec.ts',
'tests/e2e/terminal-pane-close-layout-consistency.spec.ts',
'tests/e2e/terminal-parked-close-retirement.spec.ts'
])
expect(shouldRunReusablePrE2e(PENDING_PANE_CLOSE_CHANGE)).toBe(true)
})
it('routes each unbind authority on its own, not just as a group', () => {
expect(CLOSE_ROUTE, 'the close route was renamed or removed').toBeDefined()
// A single-file change is the shape that slipped through; assert per path rather than only
// on the union, where one matching path would hide five that do not.
for (const file of PENDING_PANE_CLOSE_CHANGE) {
expect(selectPrE2eSpecs([file]), file).toEqual(CLOSE_ROUTE.specs.toSorted())
}
})
it('keeps every routed spec and authority a real file', () => {
for (const spec of CLOSE_ROUTE.specs) {
expect(existsSync(join(projectDir, spec)), spec).toBe(true)
}
for (const file of PENDING_PANE_CLOSE_CHANGE) {
expect(existsSync(join(projectDir, file)), file).toBe(true)
}
})
it('leaves unrelated changes alone', () => {
// Neighbours in the same directories that this route must not claim.
for (const file of [
'src/renderer/src/components/terminal-pane/CloseTerminalDialog.tsx',
'src/renderer/src/components/terminal-pane/terminal-hidden-view-parking.ts',
'src/renderer/src/runtime/runtime-rpc-client.ts',
'src/renderer/src/store/terminals/terminal-tab-close-providers.test.ts'
]) {
expect(CLOSE_ROUTE.matches(file), file).toBe(false)
}
})
})
})
describe('pr-e2e-layout-oracle-routing', () => {
/** One product file per layout writer family; each alone must run the oracle. */
const LAYOUT_AUTHORITIES = [
'src/shared/workspace-layout/workspace-layout-pane-commands.ts',
'src/shared/workspace-layout/old-client/old-client-session-tab-rows.ts',
'src/main/persistence/terminal-topology/terminal-topology-commit.ts',
'src/main/persistence/restoring-sessions/session-owner-fields.ts',
'src/main/persistence/loading-store/pty-binding-persistence.ts',
'src/main/remote-layout-snapshot/remote-layout-snapshot-recorder.ts',
'src/main/runtime/terminal/launch/terminal-split-surface.ts',
'src/main/runtime/terminal/adoption/adopt-terminal-orphans-from-inventory.ts',
'src/main/runtime/runtime-terminal-orphan-adoption.ts',
'src/main/runtime/session-tabs/headless-tab-group-moves.ts',
'src/main/runtime/terminal/launch/terminal-create.ts',
'src/main/runtime/terminal/stop/worktree-terminal-stop.ts',
'src/renderer/src/runtime/mobile-session-tab-close.ts',
'src/renderer/src/runtime/runtime-layout-client.ts',
'src/renderer/src/store/slices/tabs.ts',
'src/renderer/src/store/slices/tabs/tabs-move-actions.ts',
'tests/e2e/workspace-layout-oracle-known-on-main.ts',
'tests/e2e/helpers/workspace-layout-oracle-compare.ts',
...LAYOUT_ORACLE_E2E_SPECS
]
/** Widened while the layout-holder stack is open: these still write layout. */
const STACK_WRITERS = [
'src/renderer/src/store/slices/terminals.ts',
'src/renderer/src/components/terminal-pane/TerminalPane.tsx',
'src/renderer/src/runtime/sync-runtime-graph.ts',
'src/renderer/src/runtime/web-session-tabs-sync/store-patch.ts',
'src/main/runtime/terminal/launch/terminal-split.ts',
'src/main/runtime/workspaces/workspace-file-session-targets.ts',
'src/main/runtime/session-graph/session-window-graph.ts',
'src/main/runtime/session-tabs/mobile-session-hydration.ts',
'src/main/runtime/session-tabs/mobile-session-reconciliation.ts',
'src/main/runtime/session-tabs/mobile-session-preservation.ts',
'src/main/runtime/workspaces/session-hosts/get-runtime-id.ts',
'src/main/runtime/mobile-session-layout-projection.ts',
'src/main/runtime/headless-runtime-graph.ts',
'src/main/persistence/loading-store/session-host-partitions.ts',
'src/main/persistence/loading-store/workspace-session-snapshot-publication.ts',
'src/renderer/src/store/slices/tab-group-reference-repair.ts',
'src/renderer/src/store/slices/terminal-session-row-hydration.ts',
'src/renderer/src/store/workspace-layout-cache.ts',
'src/renderer/src/app-shell/use-runtime-graph-sync.ts',
'src/renderer/src/components/tab-group/tab-drag-drop-commit.ts',
'src/shared/remote-layout-snapshot.ts',
'src/shared/terminal-leaf-move.ts',
'src/main/ipc/pty/ipc/leaf-move.ts',
'src/main/persistence/closed-terminal-tab-write-fence.ts',
'src/main/runtime/runtime-workspace-session-controller.ts',
'src/main/runtime/workspaces/persisted-surfaces/has-exact-persisted-terminal-surface-identity.ts',
'src/main/runtime/terminal-surface-close.ts',
'src/main/runtime/terminal/output/terminal-derived-agent-facts.ts',
'src/main/runtime/terminal/output/terminal-output-generation.ts',
'src/main/runtime/session-tabs/mobile-session-membership.ts',
'src/main/runtime/session-tabs/pty-backed-session-publication.ts',
'src/renderer/src/components/terminal/terminal-tab-actions.ts',
'src/renderer/src/components/tab-bar/web-runtime-tab-move-mirror.ts',
'src/shared/rpc-contract/workspace-layout-params.ts',
'src/renderer/src/store/slices/recently-closed-tabs.ts'
]
/** Every test file the oracle specs import, transitively: a change there can break the gate. */
const oracleHarnessFiles = () => testImportClosure(projectDir, LAYOUT_ORACLE_E2E_SPECS)
describe('workspace layout oracle merge gate', () => {
it('routes each layout authority and stack writer on its own', () => {
for (const file of [...LAYOUT_AUTHORITIES, ...STACK_WRITERS]) {
expect(isLayoutOracleSource(file), file).toBe(true)
expect(classifyPrJobs([file]).layout_oracle, file).toBe(true)
expect(existsSync(join(projectDir, file)), file).toBe(true)
}
})
it('routes every test file the oracle specs import', () => {
const harness = oracleHarnessFiles()
expect(harness.length).toBeGreaterThan(LAYOUT_ORACLE_E2E_SPECS.length)
expect(harness.filter((file) => !isLayoutOracleSource(file))).toEqual([])
})
it('leaves tests, fixtures, harnesses and unrelated runtime modules alone', () => {
for (const file of [
'src/main/persistence/terminal-topology/terminal-topology-commit.test.ts',
'src/main/persistence/terminal-topology/terminal-leaf-move-fixture.ts',
'src/main/runtime/orca-runtime-tests/mobile-session-tabs-part-03.spec.ts',
'src/main/runtime/session-tabs/headless-tab-group-moves.test.ts',
'src/main/runtime/session-tabs/headless-tab-group-moves-fixture.ts',
'src/main/runtime/session-tabs/session-tabs-inventory-test-fixture.ts',
'src/main/runtime/terminal/stop/worktree-terminal-stop.test.ts',
'src/main/runtime/terminal/stop/worktree-terminal-stop-fixture.ts',
'src/main/runtime/terminal/stop/worktree-terminal-stop.ts.backup',
'src/main/runtime/terminal/stop/worktree-terminal-stop-extra.ts',
'src/main/runtime/runtime-durable-store-fixture.ts',
'src/main/runtime/orchestration/db/worker-terminal/worker-terminal-store.ts',
'src/main/runtime/rpc/methods/terminal/terminal-create.ts',
'src/main/runtime/runtime-rpc-database.ts',
'src/main/runtime/orca-runtime-files.ts',
'src/main/runtime/workspaces/persisted-surfaces/automation-operations.ts',
'src/main/runtime/workspaces/persisted-surfaces/has-exact-persisted-terminal-surface-identity.test.ts',
'src/renderer/src/runtime/remote-runtime-terminal-multiplexer.ts',
'src/renderer/src/runtime/web-session-tabs-sync-test-harness.ts',
'src/renderer/src/runtime/sync-runtime-graph-test-harness.ts',
'src/renderer/src/runtime/sync-runtime-graph.test.ts',
'tests/e2e/workspace-layout-oracle-latency.spec.ts'
]) {
expect(isLayoutOracleSource(file), file).toBe(false)
}
expect(classifyPrJobs(['src/main/runtime/orca-runtime-files.ts']).layout_oracle).toBe(false)
})
it('keeps the oracle specs out of the advisory e2e job', () => {
expect(selectPrE2eSpecs(LAYOUT_AUTHORITIES)).toEqual([])
expect(shouldRunReusablePrE2e(LAYOUT_AUTHORITIES)).toBe(false)
})
it('runs exactly the oracle specs, each in the lane that can run it', () => {
const job = prWorkflow.jobs.layout_oracle
expect(job.uses).toBe('./.github/workflows/e2e.yml')
// The merge commit, so a stale-base PR cannot pass on an old main.
expect(job.with.ref).toBe('${{ github.sha }}')
const specs = JSON.parse(job.with.test_files)
expect(specs.toSorted()).toEqual(LAYOUT_ORACLE_E2E_SPECS.toSorted())
// Window spec runs in the changed-spec lane; headless runs in the orcad lane.
expect(selectGeneralE2eSpecs(specs)).toEqual(['tests/e2e/workspace-layout-oracle.spec.ts'])
expect(classifyE2eJobs(job.with.test_files)).toEqual({
e2e_run_changed: true,
e2e_needs_build: true
})
})
it('blocks the merge on the oracle and passes when it is skipped', () => {
const verify = prWorkflow.jobs.verify
const gate = verify.steps.find((step) => step.name === 'Require successful checks')
expect(verify.needs).toContain('layout_oracle')
expect(gate.run).toContain(
'check_job layout_oracle "$LAYOUT_ORACLE" "$LAYOUT_ORACLE_SHOULD_RUN"'
)
// Two calls of the reusable workflow in one run must not share artifact names.
expect(prWorkflow.jobs.layout_oracle.with.artifact_suffix).toBeTruthy()
expect(prWorkflow.jobs.e2e.with.artifact_suffix).toBeUndefined()
})
})
})
describe('ssh-browser-e2e-routing', () => {
const workflow = e2eWorkflow
it('executes both Docker network routes in a Node job with their opt-in enabled', () => {
const spec = 'tests/e2e/ssh-browser-network-execution-route.docker.unit.test.ts'
const job = workflow.jobs['ssh-browser-network-route']
const install = job.steps.find(
(step) => step.uses === './.github/actions/install-node-dependencies'
)
const run = job.steps.find(
(step) => step.name === 'Run Docker SSH browser network route journeys'
)
expect(job['runs-on']).toBe('blacksmith-4vcpu-ubuntu-2404')
expect(job.if).toContain("inputs.test_files == ''")
expect(job.if).toContain(spec)
expect(install.with['native-runtime']).toBe('node')
expect(run.env.ORCA_RUN_DOCKER_SSH_BROWSER_E2E).toBe('1')
expect(run.run).toContain(`vitest run --config config/vitest.config.ts ${spec}`)
expect(run['continue-on-error']).toBeUndefined()
expect(DEDICATED_E2E_SPECS).toContain(spec)
for (const changed of [
spec,
'src/main/browser/ssh-browser-network-execution-route.ts',
'src/main/browser/browser-network-deferred-socket.ts',
'src/main/browser/browser-network-execution-route.ts',
'src/main/browser/system-ssh-socks-client-socket.ts',
'src/main/ssh/system-transport/system-ssh-dynamic-forward-process.ts',
'tests/e2e/helpers/docker-ssh-host-target.ts',
'tests/e2e/helpers/docker-ssh-host-image.ts'
]) {
expect(selectPrE2eSpecs([changed])).toContain(spec)
}
expect(selectPrE2eSpecs(['src/renderer/src/components/Unrelated.tsx'])).not.toContain(spec)
expect(selectPrE2eSpecs(['tests/e2e/helpers/docker-ssh-host-terminal-tabs.ts'])).not.toContain(
spec
)
})
})
describe('orcad-e2e-routing', () => {
const root = projectDir
const jobs = e2eWorkflow.jobs
const ORCAD_AUTO_CONVERT_E2E_SPEC = 'tests/e2e/ssh-orcad-auto-convert.spec.ts'
const ORCAD_IDLE_EXIT_E2E_SPEC = 'tests/e2e/ssh-orcad-idle-exit.spec.ts'
const ORCAD_OPEN_IN_OWNER_E2E_SPEC = 'tests/e2e/ssh-orcad-open-in-owner.spec.ts'
const ORCAD_JOURNEY_E2E_SPECS = [
'tests/e2e/ssh-orcad-terminal-journeys.spec.ts',
'tests/e2e/ssh-orcad-workspace-tools.spec.ts',
'tests/e2e/ssh-orcad-vm-provisioned-root.spec.ts'
]
function expectRouted(files, spec) {
for (const file of files) {
expect(existsSync(resolve(root, file)), file).toBe(true)
expect(selectPrE2eSpecs([file]), file).toContain(spec)
expect(shouldRunReusablePrE2e([file]), file).toBe(true)
}
}
it('routes the mode-switch spec from its serve sources and harness', () => {
expectRouted(
[
'src/main/orcad/orcad-lifecycle.ts',
'src/main/daemon/daemon-spawner.ts',
'tests/e2e/helpers/orca-serve-cli-host.ts',
'tests/e2e/helpers/headless-paired-runtime-host.ts'
],
ORCAD_SERVE_MODE_SWITCH_E2E_SPEC
)
})
it('routes the missing-AppData spec from its startup sources and harness', () => {
expectRouted(
['src/main/startup/windows-app-data-path.ts', 'tests/e2e/helpers/orca-serve-cli-host.ts'],
WINDOWS_MISSING_APPDATA_E2E_SPEC
)
})
it('routes the Windows file-copy spec from its clipboard sources', () => {
expectRouted(
[
'src/main/window/clipboard-file-copy.ts',
'src/main/window/clipboard-ipc-handlers.ts',
'src/renderer/src/components/right-sidebar/file-explorer-row-file-transfer.ts'
],
WINDOWS_COPY_FILE_E2E_SPEC
)
})
it('routes the auto-convert spec from its conversion sources and harness', () => {
expectRouted(
[
'src/main/managed-server/lifecycle/orcad-runtime-conversion.ts',
'tests/e2e/helpers/orcad-convert-flow.ts',
'tests/e2e/helpers/orcad-convert-host.ts',
'tests/e2e/helpers/orcad-template-variant.ts',
'tests/e2e/helpers/orcad-upgrade-profile.ts'
],
ORCAD_AUTO_CONVERT_E2E_SPEC
)
expect(
selectPrE2eSpecs(['src/main/managed-server/lifecycle/orcad-runtime-conversion.test.ts'])
).not.toContain(ORCAD_AUTO_CONVERT_E2E_SPEC)
})
it('routes the idle-exit spec from its idle sources and the shared convert harness', () => {
expectRouted(
[
'src/shared/orcad-idle-exit.ts',
'src/main/managed-server/install/orcad-remote-runtime-control.ts',
'src/main/managed-server/lifecycle/orcad-managed-serving.ts',
'tests/e2e/helpers/orcad-convert-flow.ts',
'tests/e2e/helpers/orcad-convert-host.ts'
],
ORCAD_IDLE_EXIT_E2E_SPEC
)
})
it('builds the e2e app when only a build-dependent orcad spec is requested', () => {
for (const spec of [
ORCAD_SERVE_MODE_SWITCH_E2E_SPEC,
ORCAD_AUTO_CONVERT_E2E_SPEC,
ORCAD_IDLE_EXIT_E2E_SPEC,
ORCAD_OPEN_IN_OWNER_E2E_SPEC
]) {
expect(classifyE2eJobs(JSON.stringify([spec])), spec).toEqual({
e2e_run_changed: false,
e2e_needs_build: true
})
}
expect(jobs['orcad-ssh-docker'].needs).toEqual(['build'])
})
it('passes the requested managed-SSH specs to the sharded lane', () => {
const lane = jobs['orcad-ssh-docker']
expect(lane.if).toBe(
`inputs.test_files == '' || contains(inputs.test_files, '${MANAGED_SSH_E2E_SPEC_PREFIX}')`
)
expect(lane.strategy.matrix.shard).toBe(
`\${{ fromJSON(inputs.managed_ssh_shards || '["1/2","2/2"]') }}`
)
const run = lane.steps.find((step) => step.env?.ORCA_E2E_SSH_DOCKER === '1').run
expect(run).toContain('"${TEST_FILES[@]}"')
expect(run).toContain('--shard="$SHARD"')
for (const spec of [
ORCAD_AUTO_CONVERT_E2E_SPEC,
ORCAD_IDLE_EXIT_E2E_SPEC,
ORCAD_OPEN_IN_OWNER_E2E_SPEC,
...ORCAD_JOURNEY_E2E_SPECS
]) {
expect(existsSync(resolve(root, spec)), spec).toBe(true)
expect(spec.startsWith(MANAGED_SSH_E2E_SPEC_PREFIX), spec).toBe(true)
}
})
it('runs the Windows-only specs on one runner, each only when requested', () => {
expect(jobs['windows-missing-appdata-startup']).toBeUndefined()
const job = jobs['orcad-serve-mode-switch-windows']
for (const spec of [
ORCAD_SERVE_MODE_SWITCH_E2E_SPEC,
WINDOWS_MISSING_APPDATA_E2E_SPEC,
WINDOWS_COPY_FILE_E2E_SPEC
]) {
expect(job.if, spec).toContain(`contains(inputs.test_files, '${spec}')`)
const step = job.steps.find((candidate) => candidate.run?.includes(spec))
expect(step.if, spec).toContain(`contains(inputs.test_files, '${spec}')`)
expect(step.env.ORCA_STARTUP_DIAGNOSTICS, spec).toBeUndefined()
}
})
it('routes managed target-owner guards and menus to the real launch regression', () => {
expectRouted(
[
'src/renderer/src/lib/local-path-open-guard.ts',
'src/renderer/src/lib/external-editor-open-capability.ts',
'src/renderer/src/lib/worktree-runtime-owner.ts',
'src/renderer/src/components/sidebar/WorktreeOpenInMenu.tsx',
'src/renderer/src/components/sidebar/WorktreeContextMenuView.tsx',
'src/renderer/src/components/right-sidebar/FileExplorer.tsx',
'src/renderer/src/components/right-sidebar/FileExplorerToolbar.tsx',
'src/renderer/src/components/right-sidebar/source-control/listing/entry-context-menu.tsx',
'tests/e2e/helpers/orcad-convert-flow.ts',
'tests/e2e/helpers/orcad-convert-host.ts',
'tests/e2e/helpers/orcad-upgrade-profile.ts',
'tests/e2e/helpers/docker-ssh-host-target.ts'
],
ORCAD_OPEN_IN_OWNER_E2E_SPEC
)
expect(selectPrE2eSpecs(['src/renderer/src/lib/local-path-open-guard.test.ts'])).not.toContain(
ORCAD_OPEN_IN_OWNER_E2E_SPEC
)
})
it('routes the managed-host journey specs from their harness and sources', () => {
for (const spec of ORCAD_JOURNEY_E2E_SPECS) {
expectRouted(
[
'tests/e2e/helpers/orcad-managed-workspace.ts',
'src/renderer/src/components/terminal-pane/terminal-host-workspace-file.ts',
'src/renderer/src/components/terminal-pane/terminal-host-file-link-existence.ts',
'src/renderer/src/runtime/runtime-terminal-artifact-read.ts',
// #30130's Disconnect sources merged with this lane skipped.
'src/main/ipc/ssh/ssh-host-user-disconnect.ts',
'src/main/ipc/ssh/ssh-connect-flow.ts',
'src/main/ipc/ssh/ssh-connection-handlers.ts',
'src/main/ipc/runtime-environments/runtime-environment-connectivity-handlers.ts',
'src/main/ipc/runtime-environments/runtime-environment-manual-disconnect.ts',
'src/main/ssh/connection/ssh-connection-manager.ts',
'src/main/ssh/ssh-user-disconnect.ts',
'src/renderer/src/runtime/web-session-close-intent.ts',
'src/renderer/src/runtime/web-session-close-replay.ts'
],
spec
)
expect(classifyE2eJobs(JSON.stringify([spec])), spec).toEqual({
e2e_run_changed: false,
e2e_needs_build: true
})
}
})
})
function selectsManagedSshLane(file) {
return selectPrE2eSpecs([file]).some((spec) => spec.startsWith(MANAGED_SSH_E2E_SPEC_PREFIX))
}
describe('managed-SSH remote sources routing', () => {
it('gives every managed-SSH spec a source route', () => {
const routed = new Set(PR_E2E_SOURCE_ROUTES.flatMap((route) => route.specs))
const specs = readdirSync(join(projectDir, 'tests/e2e'))
.filter((name) => /^ssh-orcad-.*\.spec\.ts$/.test(name))
.map((name) => `tests/e2e/${name}`)
expect(specs.length).toBeGreaterThan(0)
expect(
specs.filter((spec) => !routed.has(spec) && !MANUAL_ONLY_E2E_SPECS.includes(spec))
).toEqual([])
})
it('starts the lane for remote product sources no hand-kept route names', () => {
for (const file of [
// #30130 and #30120 merged with the lane skipped.
'src/main/ipc/ssh/ssh.ts',
'src/cli/runtime/serve-orcad-launch.ts',
'src/main/orcad/orcad-entry.ts',
'src/main/ssh/connection/ssh-connection.ts',
'src/main/ipc/runtime-environments/runtime-environment-status-probe.ts',
'src/main/ipc/runtime-environments/orcad-runtime-lifecycle-handlers.ts',
'src/shared/protocol-version.ts',
'src/shared/remote-runtime/remote-runtime-client-error-classification.ts',
// #30047 and #30060: sidebar sleep and project removal.
'src/renderer/src/components/sidebar/sleep-worktree-flow.ts',
'src/renderer/src/components/sidebar/ssh-host-remove-resolution.ts',
'src/renderer/src/store/repos/repo-removal.ts',
// #30775: the pane banner for a managed server that refused this desktop.
'src/renderer/src/components/terminal-pane/TerminalRemoteRuntimeReconnectBanner.tsx',
'src/renderer/src/components/terminal-pane/use-managed-pairing-refused.ts',
'src/renderer/src/components/terminal-pane/TerminalPaneRuntimePortals.tsx'
]) {
expect(existsSync(join(projectDir, file)), file).toBe(true)
expect(selectsManagedSshLane(file), file).toBe(true)
}
})
it('leaves unit tests and local-only sources alone', () => {
for (const file of [
'src/main/ssh/connection/ssh-connection.test.ts',
'src/main/ipc/ssh/ssh.test.ts',
'src/main/daemon/daemon-server.ts',
'src/main/runtime/rpc/methods/accounts.ts',
'src/renderer/src/components/sidebar/WorktreeCard.tsx',
'src/renderer/src/store/repos/repo-ordering.ts',
'docs/STYLEGUIDE.md'
]) {
expect(selectsManagedSshLane(file), file).toBe(false)
}
})
})