From 456e5830bb4e4dfce0d00057e3f3df89df205157 Mon Sep 17 00:00:00 2001 From: OrcaWin Date: Thu, 22 Oct 2026 23:59:35 -0700 Subject: [PATCH] test: consolidate discovery coverage and replace copied oracles (#32211) Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> --- .../installed-agent-skill-discovery.test.ts | 20 ++ .../useInstalledAgentSkills.react.test.tsx | 8 +- .../src/hooks/useInstalledAgentSkills.test.ts | 253 +----------------- .../src/hooks/useInstalledAgentSkills.ts | 11 +- .../web/web-preload-api-composition.test.ts | 67 +---- .../src/web/web-preload-api-github.test.ts | 71 ----- .../src/web/web-preload-api-gitlab.test.ts | 18 -- src/shared/command-code-output-status.test.ts | 137 ++-------- src/shared/command-code-output-status.ts | 2 - 9 files changed, 53 insertions(+), 534 deletions(-) diff --git a/src/renderer/src/hooks/installed-agent-skill-discovery.test.ts b/src/renderer/src/hooks/installed-agent-skill-discovery.test.ts index 42dbb3c5ce3..6e8ca6dcf62 100644 --- a/src/renderer/src/hooks/installed-agent-skill-discovery.test.ts +++ b/src/renderer/src/hooks/installed-agent-skill-discovery.test.ts @@ -204,6 +204,26 @@ describe('installed agent skill discovery lifecycle', () => { expect(discover).toHaveBeenLastCalledWith(LOCAL, { projectRuntime: repairProjectRuntime }) }) + it('keeps host, WSL, project, and filtered results in separate cache entries', async () => { + const targets: (SkillDiscoveryTarget | undefined)[] = [ + undefined, + { runtime: 'wsl', wslDistro: null }, + { runtime: 'wsl', wslDistro: 'Ubuntu' }, + { projectRuntime: resolvedHostProjectRuntime }, + { projectRuntime: resolvedWslProjectRuntime }, + { names: ['orchestration'], sourceKinds: ['home'] }, + { names: ['computer-use'], sourceKinds: ['home'] } + ] + for (const [index, target] of targets.entries()) { + discoverSkillsForRuntimeTarget.mockResolvedValueOnce(result(index)) + await expect(discoverInstalledAgentSkills(false, target)).resolves.toEqual(result(index)) + } + for (const [index, target] of targets.entries()) { + await expect(discoverInstalledAgentSkills(false, target)).resolves.toEqual(result(index)) + } + expect(discoverSkillsForRuntimeTarget).toHaveBeenCalledTimes(targets.length) + }) + it('keys targets by runtime and project identity', () => { expect(getSkillDiscoveryTargetKey(undefined)).toBe('host') expect(getSkillDiscoveryTargetKey({ runtime: 'wsl', wslDistro: 'Ubuntu' })).toBe('wsl:Ubuntu') diff --git a/src/renderer/src/hooks/useInstalledAgentSkills.react.test.tsx b/src/renderer/src/hooks/useInstalledAgentSkills.react.test.tsx index 6a682fb0f1e..af14bbd9fae 100644 --- a/src/renderer/src/hooks/useInstalledAgentSkills.react.test.tsx +++ b/src/renderer/src/hooks/useInstalledAgentSkills.react.test.tsx @@ -15,11 +15,14 @@ import type { PublicKnownRuntimeEnvironment } from '../../../shared/runtime-envi import { createCompatibleRuntimeStatusResponseIfNeeded } from '@/runtime/runtime-compatibility-test-fixture' import { clearRuntimeCompatibilityCacheForTests } from '@/runtime/runtime-rpc-client' import { useAppStore } from '@/store' +import { + discoverInstalledAgentSkills, + resetSkillDiscoveryCacheForTests +} from './installed-agent-skill-discovery' import { INSTALLED_AGENT_SKILL_DISCOVERY_FRESH_MS } from './installed-agent-skill-discovery-cache' import { GLOBAL_AGENT_SKILL_SOURCE_KINDS, type InstalledAgentSkillState, - _installedAgentSkillDiscoveryInternalsForTests, notifyInstalledAgentSkillsChanged, notifyInstalledAgentSkillsRefreshed, useInstalledAgentSkillNames @@ -172,7 +175,7 @@ afterEach(async () => { latestState = null renderedStates.length = 0 suspendNextProbeRender = null - _installedAgentSkillDiscoveryInternalsForTests.reset() + resetSkillDiscoveryCacheForTests() clearRuntimeCompatibilityCacheForTests() useAppStore.setState({ settings: null, @@ -924,7 +927,6 @@ describe('useInstalledAgentSkill', () => { value: { skills: { discover } } }) - const { discoverInstalledAgentSkills } = _installedAgentSkillDiscoveryInternalsForTests await discoverInstalledAgentSkills(false, undefined) await expect(discoverInstalledAgentSkills(false, undefined)).resolves.toEqual( expect.objectContaining({ skills: [] }) diff --git a/src/renderer/src/hooks/useInstalledAgentSkills.test.ts b/src/renderer/src/hooks/useInstalledAgentSkills.test.ts index 6e82faab9a0..01a1ab49ac5 100644 --- a/src/renderer/src/hooks/useInstalledAgentSkills.test.ts +++ b/src/renderer/src/hooks/useInstalledAgentSkills.test.ts @@ -1,20 +1,11 @@ -import { afterEach, describe, expect, it, vi } from 'vitest' -import type { DiscoveredSkill, SkillDiscoveryResult } from '../../../shared/skills' -import type { ProjectExecutionRuntimeResolution } from '../../../shared/project-execution-runtime' +import { describe, expect, it } from 'vitest' +import type { DiscoveredSkill } from '../../../shared/skills' import { GLOBAL_AGENT_SKILL_SOURCE_KINDS, - _installedAgentSkillDiscoveryInternalsForTests, hasInstalledAgentSkill, - hasInstalledAgentSkillNamed, - notifyInstalledAgentSkillsRefreshed + hasInstalledAgentSkillNamed } from './useInstalledAgentSkills' -afterEach(() => { - _installedAgentSkillDiscoveryInternalsForTests.reset() - vi.restoreAllMocks() - vi.unstubAllGlobals() -}) - function skill(overrides: Partial): DiscoveredSkill { return { id: 'skill-1', @@ -32,28 +23,6 @@ function skill(overrides: Partial): DiscoveredSkill { } } -function discoveryResult(skills: DiscoveredSkill[] = []): SkillDiscoveryResult { - return { - skills, - sources: [], - scannedAt: Date.now() - } -} - -function deferred(): { - promise: Promise - resolve: (value: T) => void - reject: (reason?: unknown) => void -} { - let resolve!: (value: T) => void - let reject!: (reason?: unknown) => void - const promise = new Promise((resolvePromise, rejectPromise) => { - resolve = resolvePromise - reject = rejectPromise - }) - return { promise, resolve, reject } -} - describe('hasInstalledAgentSkill', () => { it('matches installed skills by summarized name', () => { expect(hasInstalledAgentSkill([skill({ name: 'orca-cli' })], 'orca-cli')).toBe(true) @@ -156,219 +125,3 @@ describe('hasInstalledAgentSkill', () => { expect(hasInstalledAgentSkill([skill({ name: 'linear-tickets' })], 'orca-linear')).toBe(false) }) }) - -describe('isOrchestrationSkillName', () => { - it('matches only the orchestration skill name', () => { - expect( - _installedAgentSkillDiscoveryInternalsForTests.isOrchestrationSkillName('orchestration') - ).toBe(true) - expect( - _installedAgentSkillDiscoveryInternalsForTests.isOrchestrationSkillName(' Orchestration ') - ).toBe(true) - expect( - _installedAgentSkillDiscoveryInternalsForTests.isOrchestrationSkillName('computer-use') - ).toBe(false) - }) -}) - -describe('discoverInstalledAgentSkills', () => { - const projectWslRuntime: ProjectExecutionRuntimeResolution = { - status: 'resolved', - runtime: { - kind: 'wsl', - hostPlatform: 'wsl', - projectId: 'repo-1', - distro: 'Ubuntu', - reason: 'project-override', - cacheKey: 'repo-1:wsl:Ubuntu' - } - } - - const projectHostRuntime: ProjectExecutionRuntimeResolution = { - status: 'resolved', - runtime: { - kind: 'windows-host', - hostPlatform: 'win32', - projectId: 'repo-1', - reason: 'project-override', - cacheKey: 'repo-1:windows-host' - } - } - - it('starts a fresh scan when a forced refresh arrives during a background scan', async () => { - const firstScan = deferred() - const secondScan = deferred() - const discover = vi.fn<() => Promise>() - discover.mockReturnValueOnce(firstScan.promise) - discover.mockReturnValueOnce(secondScan.promise) - vi.stubGlobal('window', { - api: { skills: { discover } } - }) - - const backgroundRefresh = - _installedAgentSkillDiscoveryInternalsForTests.discoverInstalledAgentSkills(false) - const forcedRefresh = - _installedAgentSkillDiscoveryInternalsForTests.discoverInstalledAgentSkills(true) - - expect(discover).toHaveBeenCalledTimes(1) - - const staleResult = discoveryResult([]) - firstScan.resolve(staleResult) - await expect(backgroundRefresh).resolves.toBe(staleResult) - - expect(discover).toHaveBeenCalledTimes(2) - - const freshResult = discoveryResult([skill({ name: 'orca-cli' })]) - secondScan.resolve(freshResult) - await expect(forcedRefresh).resolves.toBe(freshResult) - }) - - it('lets completed-scan broadcasts reuse the cached result', async () => { - const discover = vi - .fn<() => Promise>() - .mockResolvedValue(discoveryResult([skill({ name: 'orca-linear' })])) - vi.stubGlobal('window', { - api: { skills: { discover } }, - dispatchEvent: vi.fn(), - CustomEvent: class {} - }) - - await _installedAgentSkillDiscoveryInternalsForTests.discoverInstalledAgentSkills(true) - notifyInstalledAgentSkillsRefreshed() - const fromSubscribers = [1, 2, 3].map(() => - _installedAgentSkillDiscoveryInternalsForTests.discoverInstalledAgentSkills(false) - ) - - expect(discover).toHaveBeenCalledTimes(1) - for (const pending of fromSubscribers) { - await expect(pending).resolves.toMatchObject({ - skills: [expect.objectContaining({ name: 'orca-linear' })] - }) - } - expect(discover).toHaveBeenCalledTimes(1) - }) - - it('caches host and WSL discovery results separately', async () => { - const hostResult = discoveryResult([skill({ name: 'host-skill' })]) - const wslResult = discoveryResult([skill({ name: 'wsl-skill' })]) - const discover = vi - .fn< - (target?: { - runtime?: 'host' | 'wsl' - wslDistro?: string | null - }) => Promise - >() - .mockResolvedValueOnce(hostResult) - .mockResolvedValueOnce(wslResult) - vi.stubGlobal('window', { - api: { skills: { discover } } - }) - - await expect( - _installedAgentSkillDiscoveryInternalsForTests.discoverInstalledAgentSkills(false) - ).resolves.toBe(hostResult) - await expect( - _installedAgentSkillDiscoveryInternalsForTests.discoverInstalledAgentSkills(false, { - runtime: 'wsl' - }) - ).resolves.toBe(wslResult) - await expect( - _installedAgentSkillDiscoveryInternalsForTests.discoverInstalledAgentSkills(false) - ).resolves.toBe(hostResult) - - expect(discover).toHaveBeenCalledTimes(2) - expect(discover).toHaveBeenNthCalledWith(1, undefined) - expect(discover).toHaveBeenNthCalledWith(2, { runtime: 'wsl', wslDistro: null }) - }) - - it('forwards filters and isolates filtered discovery caches', async () => { - const orchestrationResult = discoveryResult([skill({ name: 'orchestration' })]) - const computerUseResult = discoveryResult([skill({ name: 'computer-use' })]) - const discover = vi - .fn() - .mockResolvedValueOnce(orchestrationResult) - .mockResolvedValueOnce(computerUseResult) - vi.stubGlobal('window', { api: { skills: { discover } } }) - - await _installedAgentSkillDiscoveryInternalsForTests.discoverInstalledAgentSkills( - false, - { runtime: 'wsl', wslDistro: 'Ubuntu' }, - undefined, - ['orchestration'], - GLOBAL_AGENT_SKILL_SOURCE_KINDS - ) - await _installedAgentSkillDiscoveryInternalsForTests.discoverInstalledAgentSkills( - false, - { runtime: 'wsl', wslDistro: 'Ubuntu' }, - undefined, - ['computer-use'], - GLOBAL_AGENT_SKILL_SOURCE_KINDS - ) - - expect(discover).toHaveBeenNthCalledWith(1, { - runtime: 'wsl', - wslDistro: 'Ubuntu', - names: ['orchestration'], - sourceKinds: ['home'] - }) - expect(discover).toHaveBeenNthCalledWith(2, { - runtime: 'wsl', - wslDistro: 'Ubuntu', - names: ['computer-use'], - sourceKinds: ['home'] - }) - }) - - it('forwards project runtime targets to skill discovery', async () => { - const wslResult = discoveryResult([skill({ name: 'wsl-skill' })]) - const discover = vi.fn().mockResolvedValueOnce(wslResult) - vi.stubGlobal('window', { - api: { skills: { discover } } - }) - - await expect( - _installedAgentSkillDiscoveryInternalsForTests.discoverInstalledAgentSkills(false, { - projectRuntime: projectWslRuntime - }) - ).resolves.toBe(wslResult) - - expect(discover).toHaveBeenCalledWith({ - runtime: 'wsl', - wslDistro: 'Ubuntu', - projectRuntime: projectWslRuntime - }) - }) - - it('caches project host runtime separately from generic host discovery', async () => { - const genericHostResult = discoveryResult([skill({ name: 'generic-host-skill' })]) - const projectHostResult = discoveryResult([skill({ name: 'project-host-skill' })]) - const discover = vi - .fn() - .mockResolvedValueOnce(genericHostResult) - .mockResolvedValueOnce(projectHostResult) - vi.stubGlobal('window', { - api: { skills: { discover } } - }) - - await expect( - _installedAgentSkillDiscoveryInternalsForTests.discoverInstalledAgentSkills(false) - ).resolves.toBe(genericHostResult) - await expect( - _installedAgentSkillDiscoveryInternalsForTests.discoverInstalledAgentSkills(false, { - projectRuntime: projectHostRuntime - }) - ).resolves.toBe(projectHostResult) - await expect( - _installedAgentSkillDiscoveryInternalsForTests.discoverInstalledAgentSkills(false, { - projectRuntime: projectHostRuntime - }) - ).resolves.toBe(projectHostResult) - - expect(discover).toHaveBeenCalledTimes(2) - expect(discover).toHaveBeenNthCalledWith(1, undefined) - expect(discover).toHaveBeenNthCalledWith(2, { - runtime: 'host', - projectRuntime: projectHostRuntime - }) - }) -}) diff --git a/src/renderer/src/hooks/useInstalledAgentSkills.ts b/src/renderer/src/hooks/useInstalledAgentSkills.ts index c5e8425edc7..248d65c3c9c 100644 --- a/src/renderer/src/hooks/useInstalledAgentSkills.ts +++ b/src/renderer/src/hooks/useInstalledAgentSkills.ts @@ -12,9 +12,7 @@ import { markOrchestrationSetupComplete } from '@/lib/orchestration-setup-state' import { discoverInstalledAgentSkills, getCachedSkillDiscovery, - getRuntimeScopedSkillDiscoveryKey, - getSkillDiscoveryTargetKey, - resetSkillDiscoveryCacheForTests + getRuntimeScopedSkillDiscoveryKey } from './installed-agent-skill-discovery' import { getInstalledAgentSkillVerdict, @@ -107,13 +105,6 @@ export function notifyInstalledAgentSkillsRefreshed(): void { } } -export const _installedAgentSkillDiscoveryInternalsForTests = { - discoverInstalledAgentSkills, - getSkillDiscoveryTargetKey, - isOrchestrationSkillName, - reset: resetSkillDiscoveryCacheForTests -} - export function useInstalledAgentSkill( skillName: string, options: InstalledAgentSkillOptions = {} diff --git a/src/renderer/src/web/web-preload-api-composition.test.ts b/src/renderer/src/web/web-preload-api-composition.test.ts index a33dd0413dd..f323755f4da 100644 --- a/src/renderer/src/web/web-preload-api-composition.test.ts +++ b/src/renderer/src/web/web-preload-api-composition.test.ts @@ -12,76 +12,11 @@ describe('web preload API composition', () => { vi.doUnmock('../../../shared/e2e-config') }) - it('installs the exact concrete surface without enumerating fallback namespaces', async () => { + it('keeps fallback namespaces non-enumerable and non-thenable', async () => { const globals = installBrowserGlobals('Linux') const { installWebPreloadApi } = await import('./web-preload-api') installWebPreloadApi() - expect(Object.keys(globals.window.api)).toEqual([ - 'app', - 'starNag', - 'platform', - 'workspacePorts', - 'orcaProfiles', - 'e2e', - 'settings', - 'agentAwake', - 'keybindings', - 'ui', - 'crashReports', - 'diagnostics', - 'session', - 'onboarding', - 'cache', - 'runtime', - 'nativeChat', - 'runtimeEnvironments', - 'repos', - 'worktrees', - 'fs', - 'git', - 'browser', - 'emulator', - 'gh', - 'gl', - 'hostedReview', - 'linear', - 'jira', - 'hooks', - 'stats', - 'memory', - 'aiVault', - 'preflight', - 'notifications', - 'rateLimits', - 'opencodeGoCredentials', - 'minimaxCredentials', - 'zcodePlanCredentials', - 'grokAccounts', - 'cursorAccounts', - 'codexAccounts', - 'claudeAccounts', - 'cli', - 'macosTccPrompts', - 'codexConfigSync', - 'developerPermissions', - 'computerUsePermissions', - 'updater', - 'shell', - 'skills', - 'pty', - 'ssh', - 'wsl', - 'wslMove', - 'pwsh', - 'gitBash', - 'agentStatus', - 'mobile', - 'telemetryTrack', - 'telemetrySetOptIn', - 'telemetryGetConsentState', - 'telemetryAcknowledgeBanner' - ]) expect('onFileDrop' in globals.window.api.ui).toBe(false) expect(Object.keys(globals.window.api.projects)).toEqual([]) const projects: Record = globals.window.api.projects diff --git a/src/renderer/src/web/web-preload-api-github.test.ts b/src/renderer/src/web/web-preload-api-github.test.ts index 2a89a27aed2..2c4cd7618c9 100644 --- a/src/renderer/src/web/web-preload-api-github.test.ts +++ b/src/renderer/src/web/web-preload-api-github.test.ts @@ -2,7 +2,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import type { PreloadApi } from '../../../preload/api-types' import type { RuntimeRpcResponse } from '../../../shared/runtime-rpc-envelope' import { - installApi, installBrowserGlobals, writeStoredRuntimeEnvironment } from './web-preload-api-test-harness' @@ -17,76 +16,6 @@ describe('web GitHub preload API', () => { vi.doUnmock('./web-runtime-client') }) - it('keeps the web GitHub preload key set in parity with the preload contract', async () => { - const { api } = await installApi('Linux') - - expect(Object.keys(api.gh).sort()).toEqual( - [ - 'addIssueComment', - 'addIssueCommentBySlug', - 'addPRReviewComment', - 'addPRReviewCommentReply', - 'checkOrcaStarred', - 'clearProjectItemField', - 'countWorkItems', - 'createIssue', - 'deleteIssueCommentBySlug', - 'diagnoseAuth', - 'enqueuePRRefresh', - 'getProjectViewTable', - 'issue', - 'listAccessibleProjects', - 'listAssignableUsers', - 'listAssignableUsersBySlug', - 'listBindableAccounts', - 'listIssueTypesBySlug', - 'listIssues', - 'listLabels', - 'listLabelsBySlug', - 'listProjectViews', - 'listWorkItems', - 'markPRReadyForReview', - 'mergePR', - 'notifyWorkItemMutated', - 'onPRRefreshEvent', - 'onWorkItemMutated', - 'prCheckDetails', - 'prChecks', - 'prComments', - 'prFileContents', - 'prForBranch', - 'projectWorkItemDetailsBySlug', - 'rateLimit', - 'refreshPRNow', - 'removePRReviewers', - 'repoSlug', - 'repoUpstream', - 'reportVisiblePRRefreshCandidates', - 'rerunPRChecks', - 'requestPRReviewers', - 'resolveProjectRef', - 'resolveReviewThread', - 'setPRAutoMerge', - 'setPRCommentReaction', - 'setPRFileViewed', - 'starOrca', - 'updateIssue', - 'updateIssueBySlug', - 'updateIssueCommentBySlug', - 'updateIssueTypeBySlug', - 'updatePRState', - 'updatePRTitle', - 'updateProjectItemField', - 'updatePullRequestBySlug', - 'validateAccountBinding', - 'viewer', - 'workItem', - 'workItemByOwnerRepo', - 'workItemDetails' - ].sort() - ) - }) - it('routes every runtime-backed GitHub method through the expected RPC method', async () => { type GitHubApi = NonNullable const runtimeCalls: { method: string; params: unknown }[] = [] diff --git a/src/renderer/src/web/web-preload-api-gitlab.test.ts b/src/renderer/src/web/web-preload-api-gitlab.test.ts index 7e6d63eeb6d..ba56926c370 100644 --- a/src/renderer/src/web/web-preload-api-gitlab.test.ts +++ b/src/renderer/src/web/web-preload-api-gitlab.test.ts @@ -15,24 +15,6 @@ describe('web GitLab preload API', () => { afterEach(() => { vi.unstubAllGlobals() vi.doUnmock('./web-runtime-client') - vi.doUnmock('electron') - }) - - it('keeps the web GitLab preload key set in parity with desktop preload', async () => { - vi.doMock('electron', () => ({ - ipcRenderer: { invoke: vi.fn() } - })) - const globals = installBrowserGlobals('Linux') - const { glApi } = (await import( - new URL('../../../preload/gitlab.ts', import.meta.url).href - )) as { - glApi: Record - } - const { installWebPreloadApi } = await import('./web-preload-api') - - installWebPreloadApi() - - expect(Object.keys(globals.window.api.gl).sort()).toEqual(Object.keys(glApi).sort()) }) it('routes every runtime-backed GitLab method through the expected RPC method', async () => { diff --git a/src/shared/command-code-output-status.test.ts b/src/shared/command-code-output-status.test.ts index 4ca0be25bbc..729909c3c7c 100644 --- a/src/shared/command-code-output-status.test.ts +++ b/src/shared/command-code-output-status.test.ts @@ -1,8 +1,6 @@ import { afterEach, describe, expect, it, vi } from 'vitest' -import { - createCommandCodeOutputStatusDetector, - stripTerminalControl -} from './command-code-output-status' +import { createCommandCodeOutputStatusDetector } from './command-code-output-status' +import { stripTerminalControl } from './terminal-control-stripping' afterEach(() => { vi.restoreAllMocks() @@ -389,44 +387,6 @@ function maxStringContextLength(contexts: unknown[]): number { } describe('terminal control stripping', () => { - const esc = String.fromCharCode(0x1b) - const bel = String.fromCharCode(0x07) - const ansiEscape = new RegExp( - `${esc}(?:[@-Z\\\\-_]|\\[[0-?]*[ -/]*[@-~]|\\][^${bel}]*(?:${bel}|${esc}\\\\))`, - 'g' - ) - const incompleteAnsiEscape = new RegExp( - `${esc}(?:\\[[0-?]*[ -/]*|\\][^${bel}${esc}]*|\\S?)?$`, - 'g' - ) - - function legacyStripTerminalControl(data: string): string { - const withoutAnsi = data.replace(ansiEscape, '').replace(incompleteAnsiEscape, '') - let output = '' - for (let index = 0; index < withoutAnsi.length; index += 1) { - const code = withoutAnsi.charCodeAt(index) - if ((code <= 0x1f && code !== 0x0a && code !== 0x0d) || (code >= 0x7f && code <= 0x9f)) { - continue - } - output += withoutAnsi[index] - } - return output - } - - function makeRandom(seed: number): () => number { - let state = seed >>> 0 - return () => { - state ^= state << 13 - state ^= state >>> 17 - state ^= state << 5 - return (state >>> 0) / 0x1_0000_0000 - } - } - - function expectLegacyEquivalent(data: string): void { - expect(stripTerminalControl(data)).toBe(legacyStripTerminalControl(data)) - } - function promptFrom(raw: string): string | null { let captured: string | null = null const detector = createCommandCodeOutputStatusDetector({ @@ -458,77 +418,26 @@ describe('terminal control stripping', () => { ) }) - it('matches the legacy filter across ANSI, C0/C1, line breaks, and Unicode', () => { - for (const data of [ - '', - 'plain text', - '\x1b[35mstyled\x1b[0m', - '\x1b[unterminated', - '\x00leading', - 'trailing\x9f', - '\x01\x02adjacent\x7f\x80', - 'keep\r\nline breaks', - '日本語 \u{1f389} \ud83d \ude00', - '\x1b]0;title\x07prompt', - '\x1b]0;title\x1b\\prompt' - ]) { - expectLegacyEquivalent(data) - } - }) - - it('matches legacy output at density thresholds and block resets', () => { - const control = '\x01' - const fixtures = [ - `${control.repeat(31)}${'a'.repeat(33)}`, - `${control.repeat(32)}${'a'.repeat(32)}`, - `${'a'.repeat(32)}${control.repeat(31)}a`, - `${control.repeat(31)}${'a'.repeat(33)}${control.repeat(31)}z`, - `${control.repeat(31)}${'a'.repeat(33)}${control.repeat(32)}z`, - `${'a'.repeat(64 * 3)}${control.repeat(32)}tail`, - `${'a\x01'.repeat(2048)}tail` - ] - for (const data of fixtures) { - expectLegacyEquivalent(data) - } - }) - - it('exhaustively matches short strings over control and Unicode code units', () => { - const alphabet = ['a', '\r', '\n', '\x01', '\x7f', '\x80', '\u20ac', '\ud83d'] - for (let encoded = 0; encoded < alphabet.length ** 4; encoded += 1) { - let cursor = encoded - let data = '' - for (let position = 0; position < 4; position += 1) { - data += alphabet[cursor % alphabet.length] - cursor = Math.floor(cursor / alphabet.length) - } - expectLegacyEquivalent(data) - } - }) - - it('matches seeded random terminal text', () => { - const random = makeRandom(0xc0de_0727) - const alphabet = [ - 'a', - 'Z', - '\r', - '\n', - '\x00', - '\x1f', - '\x7f', - '\x9f', - '\u00e9', - '\u20ac', - '\u{1f389}', - '\x1b[35m', - '\x1b[0m' - ] - for (let trial = 0; trial < 2_000; trial += 1) { - let data = '' - const parts = Math.floor(random() * 256) - for (let index = 0; index < parts; index += 1) { - data += alphabet[Math.floor(random() * alphabet.length)] - } - expectLegacyEquivalent(data) - } + it.each([ + { data: '', expected: '' }, + { data: 'plain text', expected: 'plain text' }, + { data: '\x1b[35mstyled\x1b[0m', expected: 'styled' }, + { data: 'prompt\x1b[35', expected: 'prompt' }, + { data: '\x00leading', expected: 'leading' }, + { data: 'trailing\x9f', expected: 'trailing' }, + { data: '\x01\x02adjacent\x7f\x80', expected: 'adjacent' }, + { data: 'keep\r\nline breaks', expected: 'keep\r\nline breaks' }, + { data: '日本語 🎉 \ud83d \ude00', expected: '日本語 🎉 \ud83d \ude00' }, + { data: '\x01'.repeat(31) + 'a'.repeat(33), expected: 'a'.repeat(33) }, + { data: '\x01'.repeat(32) + 'a'.repeat(32), expected: 'a'.repeat(32) }, + { data: `${'a'.repeat(32) + '\x01'.repeat(31)}a`, expected: 'a'.repeat(33) }, + { + data: `${'\x01'.repeat(31) + 'a'.repeat(33) + '\x01'.repeat(32)}z`, + expected: `${'a'.repeat(33)}z` + }, + { data: `${'a'.repeat(192) + '\x01'.repeat(32)}tail`, expected: `${'a'.repeat(192)}tail` }, + { data: `${'a\x01'.repeat(2048)}tail`, expected: `${'a'.repeat(2048)}tail` } + ])('strips controls while preserving printable text (case %#)', ({ data, expected }) => { + expect(stripTerminalControl(data)).toBe(expected) }) }) diff --git a/src/shared/command-code-output-status.ts b/src/shared/command-code-output-status.ts index 5c3761db32c..21ed5ae761d 100644 --- a/src/shared/command-code-output-status.ts +++ b/src/shared/command-code-output-status.ts @@ -13,8 +13,6 @@ import { stripTerminalControl } from './terminal-control-stripping' import { escapeRegex } from './string-utils' import { ownRetainedString } from './own-retained-string' -export { stripTerminalControl } from './terminal-control-stripping' - type CommandCodeOutputStatusDetector = { observe: (data: string) => boolean }