diff --git a/tests/unit/auth/resume-lane-warning.test.ts b/tests/unit/auth/resume-lane-warning.test.ts index 49eb3064..83205178 100644 --- a/tests/unit/auth/resume-lane-warning.test.ts +++ b/tests/unit/auth/resume-lane-warning.test.ts @@ -1,6 +1,10 @@ import { describe, expect, it } from 'bun:test'; import { maybeWarnAboutResumeLaneMismatch } from '../../../src/auth/resume-lane-warning'; +function stripAnsi(input: string): string { + return input.replace(/\u001b\[[0-9;]*m/g, ''); +} + describe('resume lane warning', () => { it('prints guidance when the plain ccs lane differs from the account lane', async () => { const logs: string[] = []; @@ -15,10 +19,12 @@ describe('resume lane warning', () => { }), }); - expect(logs[0]).toContain('Resume for account "work" will search that account lane'); - expect(logs).toContain('[i] Account lane: /tmp/account-lane'); - expect(logs).toContain('[i] Plain ccs lane: native Claude lane (/tmp/native-lane)'); - expect(logs).toContain('[i] Recover the original lane first: ccs -r'); + const plainLogs = logs.map((message) => stripAnsi(message)); + + expect(plainLogs[0]).toContain('Resume for account "work" will search that account lane'); + expect(plainLogs).toContain('[i] Account lane: /tmp/account-lane'); + expect(plainLogs).toContain('[i] Plain ccs lane: native Claude lane (/tmp/native-lane)'); + expect(plainLogs).toContain('[i] Recover the original lane first: ccs -r'); }); it('does not log anything when resume is not requested', async () => { diff --git a/tests/unit/commands/config-auth-command.test.ts b/tests/unit/commands/config-auth-command.test.ts index 5674b652..8fba6e33 100644 --- a/tests/unit/commands/config-auth-command.test.ts +++ b/tests/unit/commands/config-auth-command.test.ts @@ -1,5 +1,9 @@ import { afterEach, beforeEach, describe, expect, it, mock } from 'bun:test'; +function stripAnsi(input: string): string { + return input.replace(/\u001b\[[0-9;]*m/g, ''); +} + let calls: string[] = []; let logLines: string[] = []; let originalConsoleLog: typeof console.log; @@ -60,7 +64,7 @@ describe('config-auth command routing', () => { await handleConfigAuthCommand(['--help']); expect(calls).toEqual([]); - expect(logLines.join('\n')).toContain('Dashboard Auth Management'); + expect(stripAnsi(logLines.join('\n'))).toContain('Dashboard Auth Management'); }); it('rejects trailing arguments for zero-arg subcommands', async () => { diff --git a/tests/unit/utils/ui.test.js b/tests/unit/utils/ui.test.js index 24a04aee..daaaea17 100644 --- a/tests/unit/utils/ui.test.js +++ b/tests/unit/utils/ui.test.js @@ -6,6 +6,25 @@ const assert = require('assert'); +function stripAnsi(input) { + return input.replace(/\u001b\[[0-9;]*m/g, ''); +} + +function withoutForceColor(callback) { + const originalForceColor = process.env.FORCE_COLOR; + delete process.env.FORCE_COLOR; + + try { + callback(); + } finally { + if (originalForceColor === undefined) { + delete process.env.FORCE_COLOR; + } else { + process.env.FORCE_COLOR = originalForceColor; + } + } +} + describe('UI Module', function () { let ui; @@ -25,18 +44,21 @@ describe('UI Module', function () { }); it('should return plain text when NO_COLOR is set', function () { - const originalNoColor = process.env.NO_COLOR; - process.env.NO_COLOR = '1'; + withoutForceColor(() => { + const originalNoColor = process.env.NO_COLOR; + process.env.NO_COLOR = '1'; - const result = ui.color('test', 'success'); - assert.strictEqual(result, 'test', 'should return unmodified text'); - - // Restore - if (originalNoColor === undefined) { - delete process.env.NO_COLOR; - } else { - process.env.NO_COLOR = originalNoColor; - } + try { + const result = ui.color('test', 'success'); + assert.strictEqual(result, 'test', 'should return unmodified text'); + } finally { + if (originalNoColor === undefined) { + delete process.env.NO_COLOR; + } else { + process.env.NO_COLOR = originalNoColor; + } + } + }); }); it('should apply bold formatting', function () { @@ -51,7 +73,7 @@ describe('UI Module', function () { it('should apply gradient to text', function () { const result = ui.gradientText('gradient header'); - assert.ok(result.includes('gradient header'), 'should contain original text'); + assert.ok(stripAnsi(result).includes('gradient header'), 'should contain original text'); }); }); @@ -129,7 +151,7 @@ describe('UI Module', function () { describe('Headers', function () { it('should format section header', function () { const result = ui.header('Section Title'); - assert.ok(result.includes('Section Title'), 'should include title text'); + assert.ok(stripAnsi(result).includes('Section Title'), 'should include title text'); }); it('should format subsection header', function () { @@ -153,21 +175,24 @@ describe('UI Module', function () { describe('NO_COLOR Compliance', function () { it('should disable colors when NO_COLOR is set', function () { - const originalNoColor = process.env.NO_COLOR; - process.env.NO_COLOR = '1'; + withoutForceColor(() => { + const originalNoColor = process.env.NO_COLOR; + process.env.NO_COLOR = '1'; - // All color functions should return plain text - assert.strictEqual(ui.color('text', 'success'), 'text'); - assert.strictEqual(ui.bold('text'), 'text'); - assert.strictEqual(ui.dim('text'), 'text'); - assert.strictEqual(ui.gradientText('text'), 'text'); - - // Restore - if (originalNoColor === undefined) { - delete process.env.NO_COLOR; - } else { - process.env.NO_COLOR = originalNoColor; - } + try { + // All color functions should return plain text + assert.strictEqual(ui.color('text', 'success'), 'text'); + assert.strictEqual(ui.bold('text'), 'text'); + assert.strictEqual(ui.dim('text'), 'text'); + assert.strictEqual(ui.gradientText('text'), 'text'); + } finally { + if (originalNoColor === undefined) { + delete process.env.NO_COLOR; + } else { + process.env.NO_COLOR = originalNoColor; + } + } + }); }); }); });