fix(startup): make CLAUDE logo D distinct (#986)

* fix(startup): make CLAUDE logo D distinct

Adjust the startup ASCII logo so the D in CLAUDE no longer reads as an O, and add a focused regression test for the rendered shape.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(startup): clear CI flag for logo rendering assertion

Ensure the startup logo regression test exercises the interactive render path under GitHub Actions, where CI is set by default.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
chioarub
2026-05-02 15:20:20 +03:00
committed by GitHub
parent dc3c065c4a
commit 35f86a9580
2 changed files with 40 additions and 5 deletions
+36 -1
View File
@@ -1,5 +1,6 @@
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
import { detectProvider } from './StartupScreen.js'
import stripAnsi from 'strip-ansi'
import { detectProvider, printStartupScreen } from './StartupScreen.js'
import { saveGlobalConfig } from '../utils/config.js'
import {
resetSettingsCache,
@@ -7,6 +8,7 @@ import {
} from '../utils/settings/settingsCache.js'
const ENV_KEYS = [
'CI',
'CLAUDE_CODE_USE_OPENAI',
'CLAUDE_CODE_USE_GEMINI',
'CLAUDE_CODE_USE_GITHUB',
@@ -25,6 +27,9 @@ const ENV_KEYS = [
]
const originalEnv: Record<string, string | undefined> = {}
const originalMacro = (globalThis as Record<string, unknown>).MACRO
const originalIsTTY = process.stdout.isTTY
const originalWrite = process.stdout.write
beforeEach(() => {
for (const key of ENV_KEYS) {
@@ -44,6 +49,12 @@ afterEach(() => {
...current,
model: undefined,
}))
;(globalThis as Record<string, unknown>).MACRO = originalMacro
Object.defineProperty(process.stdout, 'isTTY', {
configurable: true,
value: originalIsTTY,
})
process.stdout.write = originalWrite
for (const key of ENV_KEYS) {
if (originalEnv[key] === undefined) {
delete process.env[key]
@@ -60,6 +71,30 @@ function setupOpenAIMode(baseUrl: string, model: string): void {
process.env.OPENAI_API_KEY = 'test-key'
}
describe('printStartupScreen logo', () => {
test('renders CLAUDE with a D-shaped D instead of an O-shaped block', () => {
;(globalThis as Record<string, unknown>).MACRO = { VERSION: 'test-version' }
Object.defineProperty(process.stdout, 'isTTY', {
configurable: true,
value: true,
})
let output = ''
process.stdout.write = ((chunk: string | Uint8Array) => {
output += chunk.toString()
return true
}) as typeof process.stdout.write
printStartupScreen()
const plainOutput = stripAnsi(output)
expect(plainOutput).toContain('███████╗ ████████╗')
expect(plainOutput).toContain('██╔═══██╗ ██╔═════╝')
expect(plainOutput).toContain('███████╔╝ ████████╗')
expect(plainOutput).not.toContain('████████║ ████████╗')
})
})
// --- Issue #855: aggregator URL must win over vendor-prefixed model name ---
describe('detectProvider — aggregator URL authoritative over model-name substring (#855)', () => {
+4 -4
View File
@@ -78,12 +78,12 @@ const LOGO_OPEN = [
]
const LOGO_CLAUDE = [
` \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557`,
` \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u2550\u255d \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u2550\u255d`,
` \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557`,
` \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u2550\u255d \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557 \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u2550\u255d`,
` \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 `,
` \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u255d `,
` \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 \u255a\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255d \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557`,
` \u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d \u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\u255a\u2550\u255d \u255a\u2550\u255d \u255a\u2550\u2550\u2550\u2550\u2550\u255d \u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d \u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d`,
` \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 \u255a\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255d \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255d \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557`,
` \u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d \u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\u255a\u2550\u255d \u255a\u2550\u255d \u255a\u2550\u2550\u2550\u2550\u2550\u255d \u255a\u2550\u2550\u2550\u2550\u2550\u2550\u255d \u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d`,
]
// ─── Provider detection ───────────────────────────────────────────────────────