diff --git a/config/scripts/dev-rolldown-runtime-env.test.mjs b/config/scripts/dev-rolldown-runtime-env.test.mjs deleted file mode 100644 index 881e4a824cc..00000000000 --- a/config/scripts/dev-rolldown-runtime-env.test.mjs +++ /dev/null @@ -1,25 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { - removeDevRolldownRuntimeEnv, - withDevRolldownRuntimeEnv -} from './dev-rolldown-runtime-env.mjs' - -describe('dev Rolldown runtime env', () => { - it('removes only the keys it added, keeping caller choices', () => { - const env = withDevRolldownRuntimeEnv({ RAYON_NUM_THREADS: '2', PATH: '/bin' }, 24) - expect(env).toMatchObject({ - MIMALLOC_PURGE_DELAY: '0', - ROLLDOWN_WORKER_THREADS: '4', - RAYON_NUM_THREADS: '2' - }) - removeDevRolldownRuntimeEnv(env) - expect(env).toEqual({ RAYON_NUM_THREADS: '2', PATH: '/bin' }) - }) - - it('keeps Rolldown thread defaults on small hosts', () => { - expect(withDevRolldownRuntimeEnv({}, 4)).toEqual({ - MIMALLOC_PURGE_DELAY: '0', - ORCA_DEV_RUNTIME_ENV_KEYS: 'MIMALLOC_PURGE_DELAY' - }) - }) -}) diff --git a/config/scripts/rolldown-thread-limit.test.mjs b/config/scripts/rolldown-thread-limit.test.mjs deleted file mode 100644 index 77bbe26edd8..00000000000 --- a/config/scripts/rolldown-thread-limit.test.mjs +++ /dev/null @@ -1,17 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { withRolldownThreadLimit } from './rolldown-thread-limit.mjs' - -describe('withRolldownThreadLimit', () => { - it('caps both pools on large hosts', () => { - expect(withRolldownThreadLimit({ A: '1' }, 24)).toEqual({ - A: '1', - ROLLDOWN_WORKER_THREADS: '8', - RAYON_NUM_THREADS: '8' - }) - }) - - it('keeps Rolldown defaults on small hosts and explicit sizes everywhere', () => { - expect(withRolldownThreadLimit({}, 8)).toEqual({}) - expect(withRolldownThreadLimit({ RAYON_NUM_THREADS: '2' }, 24).RAYON_NUM_THREADS).toBe('2') - }) -}) diff --git a/config/scripts/vitest-run-temp-directory.test.mjs b/config/scripts/vitest-run-temp-directory.test.mjs index 75b4d27328d..b0d91a1a181 100644 --- a/config/scripts/vitest-run-temp-directory.test.mjs +++ b/config/scripts/vitest-run-temp-directory.test.mjs @@ -2,11 +2,7 @@ import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node: import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, expect, it } from 'vitest' -import { - createRunTempDirectory, - resolveRunTempBase, - sweepStaleRunDirectories -} from './vitest-run-temp-directory.mjs' +import { createRunTempDirectory, sweepStaleRunDirectories } from './vitest-run-temp-directory.mjs' const bases = [] @@ -51,12 +47,3 @@ it('removes the run directory and leaves an unmarked one with the same name alon runDirectory(base, 105, false) expect(createRunTempDirectory({ base, pid: 105 })).toBeNull() }) - -it('keeps POSIX run roots no longer than the default macOS temp root', () => { - const macTemp = '/var/folders/zz/zyxvpxvq6csfxvn_n0000000000000gn/T' - expect(resolveRunTempBase(macTemp, 'ov255r', 'darwin')).toBe('/tmp') - expect(resolveRunTempBase('/tmp', 'ov255r', 'linux')).toBe('/tmp') - expect(resolveRunTempBase('C:\\Users\\a\\AppData\\Local\\Temp', 'ov255r', 'win32')).toBe( - 'C:\\Users\\a\\AppData\\Local\\Temp' - ) -}) diff --git a/config/scripts/windows-signing-rehearsal-orcad-template.test.mjs b/config/scripts/windows-signing-rehearsal-orcad-template.test.mjs deleted file mode 100644 index e1328094cfd..00000000000 --- a/config/scripts/windows-signing-rehearsal-orcad-template.test.mjs +++ /dev/null @@ -1,45 +0,0 @@ -import { readFileSync } from 'node:fs' -import { describe, expect, it } from 'vitest' -import { parse } from 'yaml' - -// The rehearsal must sign and reseal the same template payload release-cut ships, or Windows reseal regressions only surface in a real release. -function readWorkflow(name) { - return parse(readFileSync(new URL(`../../.github/workflows/${name}`, import.meta.url), 'utf8')) -} - -const RESEAL_STEP = 'Reseal the orcad template over its signed binaries' -const release = readWorkflow('release-cut.yml').jobs.build -const { jobs } = readWorkflow('windows-signing-rehearsal.yml') -const rehearse = jobs.rehearse -const stepIndex = (name) => rehearse.steps.findIndex((step) => step.name === name) - -describe('Windows signing rehearsal ships the orcad template', () => { - it('packages the qualified template built from the dispatched commit', () => { - expect(jobs['orcad-template'].uses).toBe('./.github/workflows/qualified-orcad-template.yml') - expect(jobs['orcad-template'].with).toEqual({ ref: '${{ github.sha }}', fast_runners: false }) - expect(rehearse.needs).toBe('orcad-template') - expect(rehearse.env.ORCA_REQUIRE_ORCAD_TEMPLATE).toBe('1') - const download = stepIndex('Download the orcad deployment template') - expect(download).toBeGreaterThan(stepIndex('Build app')) - expect(download).toBeLessThan(stepIndex('Package Windows app and export the NSIS uninstaller')) - expect(rehearse.steps[download].with).toEqual({ - name: 'orcad-template', - path: 'out/orcad-template' - }) - }) - - it('reseals the signed template exactly like release-cut, before the installer rebuild', () => { - const releaseReseal = release.steps.find((step) => step.name === RESEAL_STEP) - const reseal = stepIndex(RESEAL_STEP) - expect(rehearse.steps[reseal].run).toBe(releaseReseal.run) - expect(reseal).toBeGreaterThan(stepIndex('Restore signed inner binaries into unpacked app')) - expect(reseal).toBeLessThan(stepIndex('Build NSIS installer from signed unpacked app')) - }) - - it('keeps non-Windows template addons out of SignPath staging', () => { - const filter = "'^resources[\\\\/]orcad-template[\\\\/]targets[\\\\/](?!win32-)'" - const staging = (job) => job.steps.find((step) => step.id === 'stage-inner').run - expect(staging(release)).toContain(filter) - expect(staging(rehearse)).toContain(filter) - }) -}) diff --git a/src/renderer/src/lib/monaco-languages/textmate-token-provider.test.ts b/src/renderer/src/lib/monaco-languages/textmate-token-provider.test.ts index 37e09729238..3ea99a920e1 100644 --- a/src/renderer/src/lib/monaco-languages/textmate-token-provider.test.ts +++ b/src/renderer/src/lib/monaco-languages/textmate-token-provider.test.ts @@ -35,36 +35,6 @@ describe('createTextMateTokensProvider', () => { expect(after.tokens.length).toBeGreaterThan(1) }) - it('tokenizes Nim with the vendored TextMate grammar', async () => { - const provider = await createTextMateTokensProvider({ loadGrammar: loadNimTextMateGrammar }) - - const procLine = provider.tokenize('proc greet(name: string) =', provider.getInitialState()) - const procScopes = procLine.tokens.map((token) => token.scopes) - expect(procScopes).toContain('keyword.other') - expect(procScopes).toContain('entity.name.function.nim') - expect(procScopes).toContain('storage.type.concrete.nim') - - const commentLine = provider.tokenize('# hello', provider.getInitialState()) - expect(commentLine.tokens.map((token) => token.scopes)).toContain( - 'comment.line.number-sign.nim' - ) - }) - - it('tokenizes Typst markup, code, and math through the lazy grammar loader', async () => { - const provider = await createTextMateTokensProvider({ loadGrammar: loadTypstTextMateGrammar }) - const scopesOf = (line: string) => - provider.tokenize(line, provider.getInitialState()).tokens.map((token) => token.scopes) - - expect(scopesOf('#let width = 12pt')).toEqual( - expect.arrayContaining(['keyword.other.typst', 'constant.numeric.length.typst']) - ) - expect(scopesOf('#set text(font: "Inter")')).toEqual( - expect.arrayContaining(['entity.name.function.typst', 'string.quoted.double.typst']) - ) - expect(scopesOf('// note')).toContain('comment.line.double-slash.typst') - expect(scopesOf('$ sum_(k=0)^n k $')).toContain('string.other.math.typst') - }) - it.each([ ['```rust', 'let x = 1', '```', '#let y = 2'], ['````', '```', '````', '#let y = 2'] diff --git a/src/renderer/src/lib/syntax-highlighting/syntax-highlighter.test.ts b/src/renderer/src/lib/syntax-highlighting/syntax-highlighter.test.ts index 8f4e642ffc2..1b659b05c6e 100644 --- a/src/renderer/src/lib/syntax-highlighting/syntax-highlighter.test.ts +++ b/src/renderer/src/lib/syntax-highlighting/syntax-highlighter.test.ts @@ -95,31 +95,6 @@ describe('highlightSyntax', () => { expect(find(result, 'total')).toMatchObject({ dark: '#9CDCFE' }) }) - it('leaves a line too long to color plain, along with every line after it', async () => { - const typescript = await highlighterFor('typescript') - const code = ['const a = 1', `const long = "${'x'.repeat(2000)}"`, 'const b = 2'].join('\n') - - const result = typescript(code) - - expect(result.outcome).toBe('degraded') - expect(find(result, 'const')).toMatchObject({ dark: '#569CD6' }) - expect(result.lines[1]).toEqual([expect.objectContaining({ dark: undefined })]) - expect(result.lines[2]).toEqual([ - { - content: 'const b = 2', - offset: code.lastIndexOf('const b'), - light: undefined, - dark: undefined, - lightFontStyle: 0, - darkFontStyle: 0 - } - ]) - expect(typescript('const c = 3', result.state)).toMatchObject({ - outcome: 'degraded', - lines: [[expect.objectContaining({ content: 'const c = 3', dark: undefined })]] - }) - }) - it('leaves a line that runs out of time plain instead of guessing the rest', async () => { const typescript = await highlighterFor('typescript') let now = 0 @@ -143,16 +118,6 @@ describe('highlightSyntax', () => { }) describe('loadSyntaxLanguage', () => { - it('reports a language without a grammar as unsupported', async () => { - await expect(loadSyntaxLanguage('not-a-real-language')).resolves.toBe('unsupported') - expect(loadedSyntaxHighlighter('not-a-real-language')).toBeNull() - }) - - it('accepts aliases and any letter case', async () => { - await expect(loadSyntaxLanguage('PS1')).resolves.toBe('ready') - expect(loadedSyntaxHighlighter('ps1')).not.toBeNull() - }) - it('retries a failed load after a pause', async () => { const { loadSyntaxLanguage, loadedSyntaxHighlighter } = await freshHighlighterModule() let now = 0 diff --git a/src/shared/mermaid-flowchart-contrast.test.ts b/src/shared/mermaid-flowchart-contrast.test.ts index 6f10748cab6..fd40ed73c29 100644 --- a/src/shared/mermaid-flowchart-contrast.test.ts +++ b/src/shared/mermaid-flowchart-contrast.test.ts @@ -31,9 +31,4 @@ describe('readableMermaidFlowchartSvg', () => { ) expect(labelFill(readableMermaidFlowchartSvg(stadium, '#e0e0e0', '#111111'))).toBe('#e0e0e0') }) - - it('leaves a label that already reads on its fill', () => { - const svg = readableMermaidFlowchartSvg(flowchart('#1e3a8a', '#e0e0e0'), '#e0e0e0', '#111111') - expect(labelFill(svg)).toBe('#e0e0e0') - }) }) diff --git a/src/shared/native-chat-availability.test.ts b/src/shared/native-chat-availability.test.ts deleted file mode 100644 index 30bbc90d0e5..00000000000 --- a/src/shared/native-chat-availability.test.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { describe, it, expect } from 'vitest' -import { canToggleNativeChat } from './native-chat-availability' -import { isNativeChatTranscriptLocalReadable } from './native-chat-transcript-readability' - -describe('canToggleNativeChat', () => { - // omp exposes no hook transcript path; its session file requires readable agent storage. - it('rejects Model-A SSH omp but accepts it local and runtime-owned', () => { - const forConnection = (connectionId: string | null): boolean => - canToggleNativeChat({ - contentType: 'terminal', - launchAgent: 'omp', - nativeChatTranscriptIsLocalReadable: isNativeChatTranscriptLocalReadable(connectionId) - }) - expect(forConnection('ssh-target-1')).toBe(false) - expect(forConnection(null)).toBe(true) - expect(forConnection('runtime-ssh-env-1')).toBe(true) - }) - - it('lets an existing Model-A SSH Grok chat toggle back to terminal', () => { - expect( - canToggleNativeChat({ - contentType: 'terminal', - launchAgent: 'grok', - nativeChatTranscriptIsLocalReadable: false, - isChatViewMode: true - }) - ).toBe(true) - }) - - it('rejects a stale supported title when live detection found an unsupported agent', () => { - expect( - canToggleNativeChat({ - contentType: 'terminal', - launchAgent: null, - detectedAgent: 'gemini', - resolvedAgent: 'codex' - }) - ).toBe(false) - }) - - it('rejects stale launch metadata when live detection found an unsupported agent', () => { - expect( - canToggleNativeChat({ - contentType: 'terminal', - launchAgent: 'codex', - detectedAgent: 'gemini' - }) - ).toBe(false) - }) - - it('rejects a stale supported title when launch metadata names an unsupported agent', () => { - expect( - canToggleNativeChat({ - contentType: 'terminal', - launchAgent: 'gemini', - resolvedAgent: 'claude' - }) - ).toBe(false) - }) -}) diff --git a/src/shared/native-chat-message-copy-text.test.ts b/src/shared/native-chat-message-copy-text.test.ts index 4057cca0460..1542dc1cef1 100644 --- a/src/shared/native-chat-message-copy-text.test.ts +++ b/src/shared/native-chat-message-copy-text.test.ts @@ -1,9 +1,6 @@ import { describe, expect, it } from 'vitest' import { nativeChatMessageCopyText } from './native-chat-message-copy-text' -import { - NATIVE_CHAT_STOPPED_BEFORE_START_PRESENTATION, - NATIVE_CHAT_STOPPED_BEFORE_START_TEXT -} from './native-chat-stopped-before-start' + import { subagentGroupFallbackText } from './native-chat-subagent-summary' import type { NativeChatSubagentEntry } from './native-chat-types' @@ -29,15 +26,4 @@ describe('nativeChatMessageCopyText', () => { ) expect(nativeChatMessageCopyText({ role: 'user', blocks: [{ type: 'text', text }] })).toBe(text) }) - - it('copies the stopped-before-start notice in the caller’s words', () => { - const blocks = [ - { - type: 'text' as const, - text: NATIVE_CHAT_STOPPED_BEFORE_START_TEXT, - presentation: NATIVE_CHAT_STOPPED_BEFORE_START_PRESENTATION - } - ] - expect(nativeChatMessageCopyText({ role: 'assistant', blocks }, 'Arrêté')).toBe('Arrêté') - }) }) diff --git a/src/shared/native-chat-session-option-labels.test.ts b/src/shared/native-chat-session-option-labels.test.ts deleted file mode 100644 index 46a6eb6725f..00000000000 --- a/src/shared/native-chat-session-option-labels.test.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { - nativeChatModelPillLabel, - sayNativeChatSessionOptionEnglish as say -} from './native-chat-session-option-labels' -import type { SessionOptionDescriptor } from './native-chat/input/native-chat-session-options' - -function modelDescriptor( - valueSource: SessionOptionDescriptor['valueSource'], - currentValue?: string -): SessionOptionDescriptor { - return { - id: 'model', - label: 'Model', - valueSource, - transport: 'catalog', - settable: true, - kind: { - type: 'select', - ...(currentValue ? { currentValue } : {}), - choices: [{ value: 'grok-4.5', label: 'Grok 4.5' }] - } - } -} - -describe('nativeChatModelPillLabel', () => { - it('withholds a value it has no evidence for', () => { - expect(nativeChatModelPillLabel(modelDescriptor('unknown', 'grok-4.5'), say)).toBe('Model') - expect(nativeChatModelPillLabel(modelDescriptor('default'), say)).toBe('Model') - }) - - it('falls back to the raw id when the list no longer offers it', () => { - // Keep naming a tracked model after discovery drops it; the running selection is still known. - expect(nativeChatModelPillLabel(modelDescriptor('reported', 'grok-build'), say)).toBe( - 'grok-build' - ) - }) -}) diff --git a/src/shared/native-chat-skill-visibility.test.ts b/src/shared/native-chat-skill-visibility.test.ts index 942fb3a1749..01942b4674f 100644 --- a/src/shared/native-chat-skill-visibility.test.ts +++ b/src/shared/native-chat-skill-visibility.test.ts @@ -36,34 +36,6 @@ function discovery(owner: string | null, rootPath = '/Users/test/.agents/skills' } describe('isNativeChatSkillForAgent', () => { - it('shows Codex-native and generic agent skills for Codex chat', () => { - expect(isNativeChatSkillForAgent('codex', skill({ providers: ['codex'] }))).toBe(true) - expect(isNativeChatSkillForAgent('codex', skill({ providers: ['agent-skills'] }))).toBe(true) - }) - - it('keeps Claude skills out of the Codex skill picker', () => { - expect(isNativeChatSkillForAgent('codex', skill({ providers: ['claude'] }))).toBe(false) - }) - - it('does not enable skill autocomplete for other agents yet', () => { - expect(isNativeChatSkillForAgent('claude', skill({ providers: ['agent-skills'] }))).toBe(false) - }) - - it('uses explicit source ownership and keeps shared roots visible', () => { - const shared = discovery(null) - expect(isNativeChatSkillForAgent('codex', skill({}), shared)).toBe(true) - expect(isNativeChatSkillForAgent('claude', skill({}), shared)).toBe(true) - expect(isNativeChatSkillForAgent('grok', skill({}), shared)).toBe(true) - }) - - it('aliases OpenClaude to Claude roots without exposing them to other agents', () => { - const claude = discovery('claude') - expect(isNativeChatSkillForAgent('claude', skill({}), claude)).toBe(true) - expect(isNativeChatSkillForAgent('openclaude', skill({}), claude)).toBe(true) - expect(isNativeChatSkillForAgent('codex', skill({}), claude)).toBe(false) - expect(isNativeChatSkillForAgent('grok', skill({}), claude)).toBe(false) - }) - it('shows OpenCode the Claude skill folders it reads, and not Claude plugins', () => { const claude = discovery('claude') expect(isNativeChatSkillForAgent('opencode', skill({}), claude)).toBe(true) diff --git a/src/shared/structured-agent-session-option-pick-book.test.ts b/src/shared/structured-agent-session-option-pick-book.test.ts index efd36839761..7d46809677d 100644 --- a/src/shared/structured-agent-session-option-pick-book.test.ts +++ b/src/shared/structured-agent-session-option-pick-book.test.ts @@ -7,15 +7,6 @@ import { } from './structured-agent-session-option-pick-book' describe('structured option pick commits', () => { - it('commits all returned values for the latest write', () => { - const book = createStructuredOptionPickBook() - const pick = beginStructuredOptionPick(book, 'model', 'opus', false) - expect(structuredOptionPickCommit(book, pick, { model: 'opus', effort: 'high' })).toEqual({ - model: 'opus', - effort: 'high' - }) - }) - it('commits only its own option when another option was picked since', () => { const book = createStructuredOptionPickBook() const model = beginStructuredOptionPick(book, 'model', 'opus', false) diff --git a/src/shared/structured-agent-session-options.test.ts b/src/shared/structured-agent-session-options.test.ts index 6f59d42be59..e9dd24bb814 100644 --- a/src/shared/structured-agent-session-options.test.ts +++ b/src/shared/structured-agent-session-options.test.ts @@ -125,33 +125,6 @@ describe('structured agent session options', () => { expect(model.kind.type === 'select' ? model.kind.currentValue : null).toBe('persisted-unknown') }) - it('projects live options as directly settable descriptors', () => { - const state = applyStructuredAgentSessionOptions( - createStructuredAgentSessionOptionState('codex'), - CODEX_SESSION_OPTION_CATALOG, - { - models: [ - { - id: 'account-model', - label: 'Account Model', - isDefault: true, - defaultEffort: 'medium', - efforts: [ - { value: 'medium', label: 'Medium' }, - { value: 'high', label: 'High' } - ] - } - ], - current: { model: 'account-model', effort: 'medium' } - } - ) - - const snapshot = structuredAgentSessionOptionSnapshot(state) - expect(snapshot.map((descriptor) => descriptor.id)).toEqual(['model', 'effort']) - expect(snapshot.every((descriptor) => descriptor.settable)).toBe(true) - expect(snapshot.every((descriptor) => descriptor.action === undefined)).toBe(true) - }) - it('projects Fast mode only from positive session and model capability', () => { const supported = applyStructuredAgentSessionOptions( createStructuredAgentSessionOptionState('codex'), diff --git a/src/shared/structured-agent-session-permission-option.test.ts b/src/shared/structured-agent-session-permission-option.test.ts index b9b226d7f05..d1bf193d00d 100644 --- a/src/shared/structured-agent-session-permission-option.test.ts +++ b/src/shared/structured-agent-session-permission-option.test.ts @@ -3,8 +3,6 @@ import type { AgentSessionOptionsResult } from './agent-session-wire' import { sortNativeChatSessionOptions } from './native-chat/input/native-chat-session-option-snapshot' import { applyStructuredAgentSessionOptions, - commitStructuredAgentSessionOption, - commitStructuredAgentSessionOptionValues, createStructuredAgentSessionOptionState, structuredAgentSessionOptionPicks, structuredAgentSessionOptionSnapshot @@ -75,45 +73,6 @@ describe('the permission mode picker', () => { }) }) - it('shows nothing for a host that states no mode, or an agent with none', () => { - expect(permission(live('codex', {}))).toBeUndefined() - expect(permission(live('pi', { permissionMode: 'ask' }))).toBeUndefined() - }) - - it("offers Codex's three modes with its own descriptions", () => { - const descriptor = permission(live('codex', { permissionMode: 'ask' })) - expect(descriptor?.kind.type === 'select' && descriptor.kind.choices).toEqual([ - { - value: 'ask', - label: 'Ask for approval', - description: "Asks before edits or commands it isn't already allowed to make" - }, - { value: 'auto', label: 'Approve for me', description: 'Reviews approval requests for you' }, - { - value: 'full-access', - label: 'Full access', - description: 'Never asks; can edit any file and use the network' - } - ]) - }) - - it('offers all Claude modes regardless of catalog support, and shows the host mode as stated', () => { - const unsupported = permission(live('claude', { permissionMode: 'ask' }, false)) - expect( - unsupported?.kind.type === 'select' && unsupported.kind.choices.map((c) => c.value) - ).toEqual(['ask', 'accept-edits', 'auto', 'full-access']) - expect(permission(live('claude', { permissionMode: 'auto' }, false))).toMatchObject({ - kind: { currentValue: 'auto' } - }) - const state = createStructuredAgentSessionOptionState('claude') - const descriptor = permission( - structuredAgentSessionOptionView(state, { permissionMode: 'ask' }, {}) - ) - expect( - descriptor?.kind.type === 'select' && descriptor.kind.choices.map((c) => c.value) - ).toContain('auto') - }) - it("shows a held pick over the host's value, and the host's over the seed", () => { const state = live('codex', { permissionMode: 'auto' }) const seed = { permissionMode: 'ask' } @@ -125,19 +84,6 @@ describe('the permission mode picker', () => { ).toMatchObject({ kind: { currentValue: 'full-access' } }) }) - it('takes a settled pick, and the record a write answers with', () => { - const state = live('codex', { permissionMode: 'ask' }) - expect(commitStructuredAgentSessionOption(state, 'permissionMode', 'auto').permissionMode).toBe( - 'auto' - ) - expect( - commitStructuredAgentSessionOptionValues(state, { - model: 'model-a', - permissionMode: 'full-access' - }).permissionMode - ).toBe('full-access') - }) - it('stays out of the per-model option pill and out of the saved selection', () => { const state = live('codex', { permissionMode: 'ask' }) expect( diff --git a/src/shared/structured-conversation-command-hold.test.ts b/src/shared/structured-conversation-command-hold.test.ts deleted file mode 100644 index 1a91f8a62b6..00000000000 --- a/src/shared/structured-conversation-command-hold.test.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { structuredConversationCommandHold } from './structured-conversation-command-hold' - -describe('a conversation command held on this side', () => { - const idle = { - waitsInLine: false, - agentWorking: false, - promptPending: false, - backgroundTasksRunning: false, - sendPending: false - } - - it('is held here only by a message the host does not have yet, or background work', () => { - const inLine = { ...idle, waitsInLine: true } - expect( - structuredConversationCommandHold({ - ...inLine, - agentWorking: true, - promptPending: true - }) - ).toBeNull() - expect(structuredConversationCommandHold({ ...inLine, sendPending: true })).toBe('ahead') - expect(structuredConversationCommandHold({ ...inLine, backgroundTasksRunning: true })).toBe( - 'background' - ) - }) - - it('against a host that cannot hold it, and for /clear, keeps every check in true words', () => { - expect(structuredConversationCommandHold(idle)).toBeNull() - expect(structuredConversationCommandHold({ ...idle, agentWorking: true })).toBe('working') - expect(structuredConversationCommandHold({ ...idle, sendPending: true })).toBe('sending') - expect( - structuredConversationCommandHold({ ...idle, agentWorking: true, sendPending: true }) - ).toBe('working') - expect(structuredConversationCommandHold({ ...idle, promptPending: true })).toBe('prompt') - }) -}) diff --git a/src/shared/tab-agent-identity-decision-table.test.ts b/src/shared/tab-agent-identity-decision-table.test.ts deleted file mode 100644 index db68fd46d49..00000000000 --- a/src/shared/tab-agent-identity-decision-table.test.ts +++ /dev/null @@ -1,196 +0,0 @@ -import { writeFileSync } from 'node:fs' -import { tmpdir } from 'node:os' -import { join } from 'node:path' -import { describe, expect, it } from 'vitest' -import { - resolveCanonicalPaneAgentIdentity, - type CanonicalPaneAgentIdentity -} from './pane-agent-identity-adapter' -import { resolveTabAgentFromSignals } from './tab-agent-from-signals' -import type { TuiAgent } from './tui-agent' - -const AGENTS: readonly TuiAgent[] = ['claude', 'codex'] -const SLOT_COUNT = 7 -const COMBINATION_COUNT = 3 ** SLOT_COUNT * 4 * 2 -const TITLES: readonly string[] = ['', 'zsh', 'Task - claude', 'Task - codex'] - -type Breakdown = Record< - 'launch' | 'completed-hook' | 'sleeping-session' | 'process' | 'sibling' | 'title', - number -> - -function slotValues(mask: number): (TuiAgent | null)[] { - let remaining = mask - return Array.from({ length: SLOT_COUNT }, () => { - const value = remaining % 3 - remaining = Math.floor(remaining / 3) - return value === 0 ? null : AGENTS[value - 1] - }) -} - -function canonicalResult( - values: readonly (TuiAgent | null)[], - title: string, - withProof: boolean -): CanonicalPaneAgentIdentity { - const [hook, siblingHook, completed, siblingCompleted, process, sleeping, launch] = values - return resolveCanonicalPaneAgentIdentity({ - hookAgent: hook, - hookIsLive: hook !== null, - completedHookAgent: completed, - launchAgent: launch, - foregroundAgent: process, - processProof: - withProof && process - ? { - agent: process, - processIncarnation: 'fixture-process', - authorityId: 'fixture-authority', - capturedAgeMs: 10, - validForMs: 1_000 - } - : undefined, - sleepingSessionAgent: sleeping, - siblingAgents: [siblingHook, siblingCompleted].filter( - (agent): agent is TuiAgent => agent !== null - ), - allowSibling: true, - title - }) -} - -function realResult(values: readonly (TuiAgent | null)[], title: string, remote: boolean) { - const [hook, siblingHook, completed, siblingCompleted, process, sleeping, launch] = values - // Hold the runtime memory bit true; the approved 17,496 steady-state shapes cover seven other slots. - return resolveTabAgentFromSignals({ - hasObservedAgentSignal: true, - isRemote: remote, - title, - hookAgent: hook, - siblingHookAgent: siblingHook, - focusedCompletedHookAgent: completed, - siblingCompletedHookAgent: siblingCompleted, - processAgent: process, - processShellForeground: false, - sleepingSessionAgent: sleeping, - launchAgent: launch ?? undefined - }) -} - -function runDecisionTable(withProof: boolean) { - let disagreements = 0 - let flipped = 0 - const breakdown: Breakdown = { - launch: 0, - 'completed-hook': 0, - 'sleeping-session': 0, - process: 0, - sibling: 0, - title: 0 - } - for (let mask = 0; mask < 3 ** SLOT_COUNT; mask += 1) { - const values = slotValues(mask) - for (const title of TITLES) { - for (const remote of [false, true]) { - const real = realResult(values, title, remote) - const canonical = canonicalResult(values, title, withProof) - if (real !== canonical.agent) { - disagreements += 1 - if (canonical.source !== null) { - breakdown[canonical.source] += 1 - } - } - if (!withProof) { - const proven = canonicalResult(values, title, true) - if ( - canonical.agent !== proven.agent && - proven.source === 'process' && - (canonical.source === 'launch' || - canonical.source === 'completed-hook' || - canonical.source === 'sleeping-session') - ) { - flipped += 1 - } - } - } - } - } - return { disagreements, flipped, breakdown } -} - -describe('renderer ladder decision table', () => { - it('replays the real shipping ladder and records all rung disagreements', () => { - const proofFree = runDecisionTable(false) - const freshProof = runDecisionTable(true) - const result = { - combinations: COMBINATION_COUNT, - proofOmitted: proofFree, - freshProof, - flippedByAddingProof: proofFree.flipped - } - writeFileSync( - join(tmpdir(), 'orca-pane-agent-identity-decision-table-real.json'), - `${JSON.stringify(result, null, 2)}\n` - ) - // Re-derived against resolveTabAgentFromSignals (not a hand-written model). - expect(proofFree).toEqual({ - disagreements: 2_622, - flipped: 1_872, - breakdown: { - launch: 1_884, - 'completed-hook': 478, - 'sleeping-session': 144, - process: 0, - sibling: 54, - title: 6 - } - }) - expect(freshProof).toEqual({ - disagreements: 658, - flipped: 0, - breakdown: { - launch: 588, - 'completed-hook': 46, - 'sleeping-session': 0, - process: 0, - sibling: 6, - title: 2 - } - }) - expect(proofFree.flipped).toBe(1_872) - }) - - it('requires both freshness fields before process evidence can change the no-proof result', () => { - const values = [null, null, null, null, 'codex', null, 'claude'] as const - expect(canonicalResult(values, '', false)).toMatchObject({ - agent: 'claude', - source: 'launch' - }) - expect( - resolveCanonicalPaneAgentIdentity({ - foregroundAgent: 'codex', - processProof: { - agent: 'codex', - processIncarnation: 'fixture-process', - authorityId: 'fixture-authority', - capturedAgeMs: undefined as unknown as number, - validForMs: 1_000 - }, - launchAgent: 'claude' - }) - ).toMatchObject({ agent: 'claude', source: 'launch' }) - expect( - resolveCanonicalPaneAgentIdentity({ - foregroundAgent: 'codex', - processProof: { - agent: 'codex', - processIncarnation: 'fixture-process', - authorityId: 'fixture-authority', - capturedAgeMs: 10, - validForMs: undefined as unknown as number - }, - launchAgent: 'claude' - }) - ).toMatchObject({ agent: 'claude', source: 'launch' }) - }) -}) diff --git a/src/shared/terminal-title-agent-type.test.ts b/src/shared/terminal-title-agent-type.test.ts index bc577b713f0..d021ab21814 100644 --- a/src/shared/terminal-title-agent-type.test.ts +++ b/src/shared/terminal-title-agent-type.test.ts @@ -2,7 +2,6 @@ import { describe, expect, it } from 'vitest' import { getAgentLabel as getSharedAgentLabel } from './agent-title-identity' import { isOpenCodeNativeTitle } from './opencode-terminal-title' import { - isClaudeAgent, isClaudeIdentityFrameTitle, isGrokRotatingWorkingTitle, resolveExplicitTerminalTitleAgentType, @@ -37,20 +36,6 @@ describe('isGrokRotatingWorkingTitle', () => { }) describe('resolveExplicitTerminalTitleAgentType', () => { - it('maps explicit product-name titles to their TuiAgent id', () => { - expect(resolveExplicitTerminalTitleAgentType('✳ Claude Code')).toBe('claude') - expect(resolveExplicitTerminalTitleAgentType('⠋ Codex')).toBe('codex') - expect(resolveExplicitTerminalTitleAgentType('✦ Gemini CLI')).toBe('gemini') - expect(resolveExplicitTerminalTitleAgentType('MiMo Code')).toBe('mimo-code') - expect(resolveExplicitTerminalTitleAgentType('⠋ OpenClaude')).toBe('openclaude') - expect(resolveExplicitTerminalTitleAgentType('OMP')).toBe('omp') - }) - - it('reads Pi/OMP identity only from the leading brand', () => { - expect(resolveExplicitTerminalTitleAgentType('⠂ OMP: fix title detection')).toBeNull() - expect(resolveExplicitTerminalTitleAgentType('Fix Pi > OMP routing - grok')).toBe('grok') - }) - it('treats Claude generic status prefixes as activity-only, not identity', () => { expect(resolveExplicitTerminalTitleAgentType('✳ investigating startup')).toBeNull() expect(resolveExplicitTerminalTitleAgentType('⠸ investigating startup')).toBeNull() @@ -77,22 +62,6 @@ describe('resolveExplicitTerminalTitleAgentType', () => { expect(resolveExplicitTerminalTitleAgentType('⠋ Fix foo | OC | bar')).toBeNull() }) - it('keeps other agents classified correctly alongside OpenCode native titles', () => { - expect(resolveExplicitTerminalTitleAgentType('✳ Claude Code')).toBe('claude') - expect(resolveExplicitTerminalTitleAgentType('⠋ Codex')).toBe('codex') - expect(resolveExplicitTerminalTitleAgentType('✦ Gemini CLI')).toBe('gemini') - expect(resolveExplicitTerminalTitleAgentType('Cursor Agent')).toBe('cursor') - expect(resolveExplicitTerminalTitleAgentType('Pi ready')).toBe('pi') - expect(resolveExplicitTerminalTitleAgentType('OpenCode ready')).toBe('opencode') - expect(resolveTerminalTitleAgentType('OC | ⠋ implementing the feature')).toBe('opencode') - expect(isClaudeAgent('OC | ⠋ implementing the feature')).toBe(false) - expect(isClaudeAgent('OC | Understand about the plugin')).toBe(false) - }) - - it('still resolves Claude when the title explicitly names Claude', () => { - expect(resolveExplicitTerminalTitleAgentType('. Claude Code compare Opencode')).toBe('claude') - }) - // Only explicit Claude identity may replace the owner; task-text mentions do not prove identity (#8940). it('separates Claude identity frames from an incidental claude token', () => { for (const title of [ @@ -123,11 +92,6 @@ describe('resolveExplicitTerminalTitleAgentType', () => { } }) - it('returns null for plain shell and unknown titles', () => { - expect(resolveExplicitTerminalTitleAgentType('Terminal 1')).toBeNull() - expect(resolveExplicitTerminalTitleAgentType('zsh')).toBeNull() - }) - // cursor is ordinary task vocabulary; only Cursor’s identity frames can claim the pane. it('resolves Cursor by its identity titles, never a bare cursor token', () => { expect(resolveExplicitTerminalTitleAgentType('Cursor Agent')).toBe('cursor') @@ -155,13 +119,3 @@ describe('resolveTerminalTitleAgentType', () => { expect(resolveTerminalTitleAgentType('⠋ Codex: fix cursor offsets')).toBe('codex') }) }) - -// Pin this module’s parallel isClaudeAgent guard directly so it cannot drift from agent-title-identity.ts. -describe('isClaudeAgent', () => { - it('excludes real Cursor identity titles, keeps cursor-mentioning Claude braille titles', () => { - expect(isClaudeAgent('⠋ Cursor Agent')).toBe(false) - expect(isClaudeAgent('Cursor ready')).toBe(false) - expect(isClaudeAgent('⠋ preserve cursor visibility across replays')).toBe(true) - expect(isClaudeAgent('⠋ OpenClaude')).toBe(false) - }) -}) diff --git a/src/shared/window-shortcut-policy.test.ts b/src/shared/window-shortcut-policy.test.ts index 25569161f42..758bce2929a 100644 --- a/src/shared/window-shortcut-policy.test.ts +++ b/src/shared/window-shortcut-policy.test.ts @@ -1,7 +1,6 @@ import { describe, expect, it } from 'vitest' import { isRecentTabSwitcherCommitRelease, - isWindowShortcutModifierChord, matchesRecentTabSwitcherChord, resolveWindowShortcutAction, type WindowShortcutAction, @@ -59,59 +58,6 @@ describe('resolveWindowShortcutAction', () => { } ) - it('resolves the explicit window shortcut allowlist on macOS', () => { - expect( - resolveWindowShortcutAction( - { code: 'KeyJ', key: 'j', meta: true, control: false, alt: false, shift: false }, - 'darwin' - ) - ).toEqual({ type: 'toggleWorktreePalette' }) - - expect( - resolveWindowShortcutAction( - { code: 'KeyP', key: 'p', meta: true, control: false, alt: false, shift: false }, - 'darwin' - ) - ).toEqual({ type: 'openQuickOpen' }) - - expect( - resolveWindowShortcutAction( - { code: 'Digit3', key: '3', meta: true, control: false, alt: false, shift: false }, - 'darwin' - ) - ).toEqual({ type: 'jumpToWorktreeIndex', index: 2 }) - - expect( - resolveWindowShortcutAction( - { code: 'Digit3', key: '3', meta: false, control: true, alt: false, shift: false }, - 'darwin' - ) - ).toEqual({ type: 'jumpToTabIndex', index: 2 }) - }) - - it('uses Alt+number for tab jumps on Windows/Linux without stealing workspace jumps', () => { - expect( - resolveWindowShortcutAction( - { code: 'Digit4', key: '4', meta: false, control: true, alt: false, shift: false }, - 'linux' - ) - ).toEqual({ type: 'jumpToWorktreeIndex', index: 3 }) - - expect( - resolveWindowShortcutAction( - { code: 'Digit4', key: '4', meta: false, control: false, alt: true, shift: false }, - 'linux' - ) - ).toEqual({ type: 'jumpToTabIndex', index: 3 }) - - expect( - resolveWindowShortcutAction( - { code: 'Digit4', key: '4', meta: false, control: false, alt: true, shift: true }, - 'win32' - ) - ).toBeNull() - }) - it('resolves customized quick-command menu shortcuts with terminal policy gating', () => { const input: WindowShortcutInput = { code: 'KeyQ', @@ -273,82 +219,6 @@ describe('resolveWindowShortcutAction', () => { ).toEqual({ type: 'jumpToTabIndex', index: 2 }) }) - it('does not resolve the removed PDF export shortcut globally', () => { - expect( - resolveWindowShortcutAction( - { code: 'KeyE', key: 'e', meta: true, control: false, alt: false, shift: true }, - 'darwin' - ) - ).toBeNull() - }) - - it('routes menu-backed actions through the same window shortcut policy', () => { - expect( - resolveWindowShortcutAction( - { code: 'KeyR', key: 'r', meta: false, control: true, alt: false, shift: true }, - 'linux' - ) - ).toEqual({ type: 'forceReload' }) - expect( - resolveWindowShortcutAction( - { code: 'KeyR', key: 'r', meta: false, control: true, alt: false, shift: true }, - 'linux', - undefined, - { context: 'terminal', terminalShortcutPolicy: 'terminal-first' } - ) - ).toBeNull() - }) - - it('requires shift for the non-mac worktree palette shortcut', () => { - expect( - resolveWindowShortcutAction( - { code: 'KeyJ', key: 'j', meta: false, control: true, alt: false, shift: false }, - 'win32' - ) - ).toBeNull() - - expect( - resolveWindowShortcutAction( - { code: 'KeyJ', key: 'j', meta: false, control: true, alt: false, shift: true }, - 'win32' - ) - ).toEqual({ type: 'toggleWorktreePalette' }) - }) - - it('resolves dictation using the layout-aware key value', () => { - expect( - resolveWindowShortcutAction( - { code: 'KeyD', key: 'e', meta: true, control: false, alt: false, shift: false }, - 'darwin' - ) - ).toEqual({ type: 'dictationKeyDown' }) - - expect( - resolveWindowShortcutAction( - { code: 'KeyE', key: 'd', meta: true, control: false, alt: false, shift: false }, - 'darwin' - ) - ).toBeNull() - }) - - it('applies custom keybinding overrides to dictation and main-process shortcuts', () => { - expect( - resolveWindowShortcutAction( - { code: 'KeyE', key: 'e', meta: false, control: true, alt: false, shift: false }, - 'linux', - { 'voice.dictation': [] } - ) - ).toBeNull() - - expect( - resolveWindowShortcutAction( - { code: 'KeyY', key: 'y', meta: false, control: true, alt: false, shift: true }, - 'linux', - { 'voice.dictation': ['Mod+Shift+Y'] } - ) - ).toEqual({ type: 'dictationKeyDown' }) - }) - it('applies custom keybinding overrides to main-process shortcuts', () => { const overrides: KeybindingOverrides = { 'worktree.quickOpen': ['Mod+Shift+O'], @@ -413,15 +283,6 @@ describe('resolveWindowShortcutAction', () => { ).toEqual({ type: 'deleteCurrentWorkspace' }) }) - it('resolves the MRU tab quick-toggle chord', () => { - expect( - resolveWindowShortcutAction( - { code: 'Tab', key: 'Tab', meta: false, control: true, alt: false, shift: false }, - 'linux' - ) - ).toEqual({ type: 'switchRecentTab' }) - }) - it('gates the held Ctrl+Tab switcher on the configurable binding', () => { const input = { code: 'Tab', key: 'Tab', meta: false, control: true, alt: false, shift: true } const domInput = { @@ -540,80 +401,6 @@ describe('resolveWindowShortcutAction', () => { ).toBeNull() }) - it('resolves the worktree-history chord despite carrying Alt', () => { - expect( - resolveWindowShortcutAction( - { - code: 'ArrowLeft', - key: 'ArrowLeft', - meta: true, - control: false, - alt: true, - shift: false - }, - 'darwin' - ) - ).toEqual({ type: 'worktreeHistoryNavigate', direction: 'back' }) - - expect( - resolveWindowShortcutAction( - { - code: 'ArrowRight', - key: 'ArrowRight', - meta: true, - control: false, - alt: true, - shift: false - }, - 'darwin' - ) - ).toEqual({ type: 'worktreeHistoryNavigate', direction: 'forward' }) - - expect( - resolveWindowShortcutAction( - { - code: 'ArrowLeft', - key: 'ArrowLeft', - meta: false, - control: true, - alt: true, - shift: false - }, - 'linux' - ) - ).toEqual({ type: 'worktreeHistoryNavigate', direction: 'back' }) - }) - - it('resolves the floating terminal chord despite carrying Alt', () => { - expect( - resolveWindowShortcutAction( - { - code: 'KeyA', - key: 'a', - meta: true, - control: false, - alt: true, - shift: false - }, - 'darwin' - ) - ).toEqual({ type: 'toggleFloatingTerminal' }) - - expect( - resolveWindowShortcutAction( - { - code: 'KeyA', - key: 'a', - meta: false, - control: true, - alt: true, - shift: false - }, - 'linux' - ) - ).toEqual({ type: 'toggleFloatingTerminal' }) - }) - it('resolves the floating terminal chord when macOS Option composes the letter', () => { expect( resolveWindowShortcutAction( @@ -630,172 +417,6 @@ describe('resolveWindowShortcutAction', () => { ).toEqual({ type: 'toggleFloatingTerminal' }) }) - it('rejects floating terminal chord variants with Shift or opposite primary modifier', () => { - expect( - resolveWindowShortcutAction( - { - code: 'KeyA', - key: 'a', - meta: true, - control: false, - alt: true, - shift: true - }, - 'darwin' - ) - ).toBeNull() - - expect( - resolveWindowShortcutAction( - { - code: 'KeyA', - key: 'a', - meta: true, - control: true, - alt: true, - shift: false - }, - 'linux' - ) - ).toBeNull() - }) - - it('rejects the history chord when Shift is also held', () => { - expect( - resolveWindowShortcutAction( - { - code: 'ArrowLeft', - key: 'ArrowLeft', - meta: true, - control: false, - alt: true, - shift: true - }, - 'darwin' - ) - ).toBeNull() - }) - - it('leaves Alt+Arrow without a primary modifier untouched (word-nav territory)', () => { - expect( - resolveWindowShortcutAction( - { - code: 'ArrowLeft', - key: 'ArrowLeft', - meta: false, - control: false, - alt: true, - shift: false - }, - 'darwin' - ) - ).toBeNull() - }) - - it('ignores Cmd/Ctrl+Alt combined with ArrowUp or ArrowDown', () => { - // Leave primary+Alt+Up/Down to renderer/PTTY shell handling; history claims only Left/Right. - expect( - resolveWindowShortcutAction( - { - code: 'ArrowUp', - key: 'ArrowUp', - meta: true, - control: false, - alt: true, - shift: false - }, - 'darwin' - ) - ).toBeNull() - - expect( - resolveWindowShortcutAction( - { - code: 'ArrowDown', - key: 'ArrowDown', - meta: false, - control: true, - alt: true, - shift: false - }, - 'linux' - ) - ).toBeNull() - }) - - it('rejects the history chord when the opposite primary modifier is also held', () => { - // Do not intercept Cmd+Ctrl+Alt on macOS or Ctrl+Meta+Alt on Linux: they collide with OS workspace switching. - expect( - resolveWindowShortcutAction( - { - code: 'ArrowLeft', - key: 'ArrowLeft', - meta: true, - control: true, - alt: true, - shift: false - }, - 'darwin' - ) - ).toBeNull() - - expect( - resolveWindowShortcutAction( - { - code: 'ArrowRight', - key: 'ArrowRight', - meta: true, - control: true, - alt: true, - shift: false - }, - 'linux' - ) - ).toBeNull() - }) - - it('still returns null for other Cmd/Ctrl+Alt combos (not an allowlist escape)', () => { - // History’s special branch must not claim unrelated primary+Alt chords without an explicit new action. - expect( - resolveWindowShortcutAction( - { - code: 'KeyY', - key: 'y', - meta: true, - control: false, - alt: true, - shift: false - }, - 'darwin' - ) - ).toBeNull() - }) - - it('routes Cmd/Ctrl+Shift+N to the unified new-workspace composer', () => { - // Preserve the old Create-from chord; the unified composer now switches sources in its name field. - expect( - resolveWindowShortcutAction( - { code: 'KeyN', key: 'n', meta: true, control: false, alt: false, shift: true }, - 'darwin' - ) - ).toEqual({ type: 'openNewWorkspace' }) - - expect( - resolveWindowShortcutAction( - { code: 'KeyN', key: 'n', meta: false, control: true, alt: false, shift: true }, - 'linux' - ) - ).toEqual({ type: 'openNewWorkspace' }) - - // Keep Alt chords unclaimed for future actions. - expect( - resolveWindowShortcutAction( - { code: 'KeyN', key: 'n', meta: true, control: false, alt: true, shift: true }, - 'darwin' - ) - ).toBeNull() - }) - it('resolves letter shortcuts by layout-aware key, with code as fallback', () => { // Prefer layout-aware letter keys over physical QWERTY codes; only empty/nonletter IME/dead-key values need code fallback. @@ -848,18 +469,6 @@ describe('resolveWindowShortcutAction', () => { } }) - it('exposes the shared platform modifier gate used by browser guests', () => { - expect( - isWindowShortcutModifierChord({ meta: true, control: false, alt: false }, 'darwin') - ).toBe(true) - expect(isWindowShortcutModifierChord({ meta: false, control: true, alt: false }, 'linux')).toBe( - true - ) - expect(isWindowShortcutModifierChord({ meta: false, control: true, alt: true }, 'linux')).toBe( - false - ) - }) - it('resolves an allowlisted action from a synthetic double-tap input', () => { const overrides: KeybindingOverrides = { 'worktree.quickOpen': ['DoubleTap+Shift'] } expect( diff --git a/src/shared/workspace-statuses.test.ts b/src/shared/workspace-statuses.test.ts index b08ab890389..3fe834c070c 100644 --- a/src/shared/workspace-statuses.test.ts +++ b/src/shared/workspace-statuses.test.ts @@ -1,9 +1,5 @@ import { describe, expect, it } from 'vitest' import { - WORKSPACE_BOARD_COLUMN_WIDTH_DEFAULT, - WORKSPACE_BOARD_COLUMN_WIDTH_MAX, - WORKSPACE_BOARD_COLUMN_WIDTH_MIN, - clampWorkspaceBoardColumnWidth, cloneDefaultWorkspaceStatuses, normalizePersistedWorkspaceStatuses, normalizeWorkspaceStatuses @@ -21,17 +17,6 @@ describe('workspace status visuals', () => { ) }) - it('keeps the default workflow order', () => { - expect(cloneDefaultWorkspaceStatuses().map((status) => status.id)).toEqual([ - 'todo', - 'in-progress', - 'in-review', - 'completed' - ]) - expect(cloneDefaultWorkspaceStatuses()[0]).toMatchObject({ id: 'todo', label: 'Todo' }) - expect(cloneDefaultWorkspaceStatuses().at(-1)).toMatchObject({ id: 'completed', label: 'Done' }) - }) - it('migrates legacy default statuses to the default workflow order', () => { const statuses = normalizePersistedWorkspaceStatuses( [ @@ -56,31 +41,6 @@ describe('workspace status visuals', () => { expect(statuses).toEqual(cloneDefaultWorkspaceStatuses()) }) - it('migrates the old default status visuals without reordering the board', () => { - const statuses = normalizePersistedWorkspaceStatuses( - [ - { id: 'todo', label: 'Todo', color: 'neutral', icon: 'circle' }, - { id: 'in-progress', label: 'In progress', color: 'blue', icon: 'circle-dot' }, - { id: 'in-review', label: 'In review', color: 'violet', icon: 'git-pull-request' }, - { id: 'completed', label: 'Completed', color: 'emerald', icon: 'circle-check' } - ], - { migrateLegacyDefaultStatusVisuals: true } - ) - - expect(statuses.map((status) => status.id)).toEqual([ - 'todo', - 'in-progress', - 'in-review', - 'completed' - ]) - expect(statuses.map((status) => status.color)).toEqual([ - 'neutral', - 'conductor-progress', - 'conductor-review', - 'conductor-done' - ]) - }) - it('preserves explicit status order while migrating default visuals', () => { const statuses = normalizePersistedWorkspaceStatuses( [ @@ -104,27 +64,6 @@ describe('workspace status visuals', () => { }) }) - it('preserves default-label reordered statuses unless a default migration is requested', () => { - const statuses = normalizePersistedWorkspaceStatuses([ - { id: 'completed', label: 'Completed', color: 'conductor-done', icon: 'conductor-done' }, - { id: 'in-review', label: 'In review', color: 'conductor-review', icon: 'conductor-review' }, - { - id: 'in-progress', - label: 'In progress', - color: 'conductor-progress', - icon: 'conductor-progress' - }, - { id: 'todo', label: 'Todo', color: 'neutral', icon: 'circle' } - ]) - - expect(statuses.map((status) => status.id)).toEqual([ - 'completed', - 'in-review', - 'in-progress', - 'todo' - ]) - }) - it('migrates exact reordered default statuses to the new Done label when requested', () => { const statuses = normalizePersistedWorkspaceStatuses( [ @@ -173,30 +112,6 @@ describe('workspace status visuals', () => { expect(statuses).toEqual(cloneDefaultWorkspaceStatuses()) }) - it('repairs the exact reordered default status payload with the Done label', () => { - const statuses = normalizePersistedWorkspaceStatuses( - [ - { id: 'completed', label: 'Done', color: 'conductor-done', icon: 'conductor-done' }, - { - id: 'in-review', - label: 'In review', - color: 'conductor-review', - icon: 'conductor-review' - }, - { - id: 'in-progress', - label: 'In progress', - color: 'conductor-progress', - icon: 'conductor-progress' - }, - { id: 'todo', label: 'Todo', color: 'neutral', icon: 'circle' } - ], - { repairReorderedDefaultStatuses: true } - ) - - expect(statuses).toEqual(cloneDefaultWorkspaceStatuses()) - }) - it('does not repair reordered default-label statuses with a different raw shape', () => { const statuses = normalizePersistedWorkspaceStatuses( [ @@ -216,47 +131,6 @@ describe('workspace status visuals', () => { ]) }) - it('leaves custom persisted status layouts in their saved order', () => { - const statuses = normalizePersistedWorkspaceStatuses([ - { id: 'completed', label: 'Shipped', color: 'conductor-done', icon: 'conductor-done' }, - { id: 'todo', label: 'Todo', color: 'neutral', icon: 'circle' } - ]) - - expect(statuses.map((status) => status.id)).toEqual(['completed', 'todo']) - }) - - it('uses Conductor-style visuals for the default status icons', () => { - const statuses = cloneDefaultWorkspaceStatuses() - const inProgress = statuses.find((status) => status.id === 'in-progress') - const inReview = statuses.find((status) => status.id === 'in-review') - const completed = statuses.find((status) => status.id === 'completed') - - expect(inProgress).toMatchObject({ - color: 'conductor-progress', - icon: 'conductor-progress' - }) - expect(inReview).toMatchObject({ - color: 'conductor-review', - icon: 'conductor-review' - }) - expect(completed).toMatchObject({ - color: 'conductor-done', - icon: 'conductor-done' - }) - }) - - it('migrates the old in-progress blue dot default only when requested', () => { - const statuses = normalizePersistedWorkspaceStatuses( - [{ id: 'in-progress', label: 'In progress', color: 'blue', icon: 'circle-dot' }], - { migrateLegacyDefaultStatusVisuals: true } - ) - - expect(statuses[0]).toMatchObject({ - color: 'conductor-progress', - icon: 'conductor-progress' - }) - }) - it('preserves valid legacy visuals for default-label statuses at runtime', () => { const statuses = normalizeWorkspaceStatuses([ { id: 'in-progress', label: 'In progress', color: 'blue', icon: 'circle-dot' } @@ -275,11 +149,4 @@ describe('workspace status visuals', () => { expect(status.label).toBe('a'.repeat(31)) }) - - it('clamps workspace board column widths to resizable bounds', () => { - expect(clampWorkspaceBoardColumnWidth(undefined)).toBe(WORKSPACE_BOARD_COLUMN_WIDTH_DEFAULT) - expect(clampWorkspaceBoardColumnWidth(100)).toBe(WORKSPACE_BOARD_COLUMN_WIDTH_MIN) - expect(clampWorkspaceBoardColumnWidth(321.6)).toBe(322) - expect(clampWorkspaceBoardColumnWidth(900)).toBe(WORKSPACE_BOARD_COLUMN_WIDTH_MAX) - }) })