// Terminal styling is for people only: piped, CI, NO_COLOR, TERM=dumb, MCP and serve children get the plain lines. import { describe, expect, test } from 'bun:test'; import { emojiFor, fancy } from '../cli/lib/log'; describe('fancy terminal output', () => { test('only on a TTY with nothing asking for plain text', () => { expect(fancy({}, true)).toBe(true); expect(fancy({}, false)).toBe(false); for (const env of [{ NO_COLOR: '1' }, { CI: 'true' }, { TERM: 'dumb' }, { STOREBOUND_MCP: '1' }, { STOREBOUND_MACHINE: '1' }]) expect(fancy(env, true)).toBe(false); }); test('emoji by level and message', () => { expect(emojiFor('anything', 'done')).toBe('โœ…'); expect(emojiFor('anything', 'warn')).toBe('โš ๏ธ '); expect(emojiFor('upload failed: 409', 'log')).toBe('โŒ'); expect(emojiFor('uploading 3 files', 'log')).toBe('๐Ÿ“ฆ'); expect(emojiFor('submitted for review', 'log')).toBe('๐Ÿš€'); expect(emojiFor('dry run: nothing changed', 'log')).toBe('๐Ÿงช'); }); test('a piped run prints the plain line, no ANSI', () => { const r = Bun.spawnSync(['bun', '-e', "const { log, warn, done } = await import('./cli/lib/log.ts'); log('t', 'waiting for x'); warn('t', 'careful'); done('t', 'ok');"], { cwd: `${import.meta.dir}/..`, stdout: 'pipe', stderr: 'pipe' }); const out = r.stdout.toString() + r.stderr.toString(); expect(out).not.toMatch(/\x1b\[/); expect(out).toMatch(/\[t\] waiting for x/); expect(out).toMatch(/\[t\] WARN careful/); }); });