@@ -3,7 +3,8 @@ import assert from "node:assert/strict";
33import * as os from "os" ;
44import * as path from "path" ;
55import React from "react" ;
6- import { renderToString } from "ink" ;
6+ import { Box , Static , renderToString } from "ink" ;
7+ import stringWidth from "string-width" ;
78import { resolveSettingsSources } from "../../../core/src/settings" ;
89import { buildWelcomeTips , formatHomeRelativePath } from "../ui" ;
910import { AsciiLogo } from "../ui/ascii-art" ;
@@ -27,6 +28,57 @@ test("welcome logo clips its right edge without wrapping in narrow terminals", (
2728 }
2829} ) ;
2930
31+ test ( "static welcome output stays within the terminal width and keeps the settings panel aligned" , ( ) => {
32+ const settings = resolveSettingsSources ( { } , { } , { model : "deepseek-flash" , baseURL : "https://example.com" } , { } ) ;
33+ for ( const width of [ 40 , 60 , 62 , 70 , 72 , 73 , 74 , 80 , 111 , 112 , 120 ] ) {
34+ const output = stripTerminalControls (
35+ renderToString (
36+ React . createElement (
37+ Box ,
38+ { flexDirection : "column" , width } ,
39+ React . createElement ( Static < string > , {
40+ items : [ "welcome" ] ,
41+ children : ( key ) =>
42+ React . createElement ( WelcomeScreen , { key, projectRoot : "/private/tmp" , settings, skills : [ ] , width } ) ,
43+ } )
44+ ) ,
45+ { columns : width }
46+ )
47+ ) ;
48+ const lines = output . split ( "\n" ) ;
49+ for ( const line of lines ) {
50+ assert . ok ( stringWidth ( line ) <= width , `terminal width: ${ width } , line: ${ line } ` ) ;
51+ }
52+
53+ const panelWidth = width < 112 ? width : 72 ;
54+ const panelTop = lines . findIndex ( ( line ) => line . startsWith ( " ╭─" ) ) ;
55+ assert . deepEqual (
56+ lines . slice ( 0 , panelTop ) . filter ( ( line ) => line . trim ( ) ) ,
57+ AsciiLogo . split ( "\n" ) . map ( ( line ) => ` ${ line . slice ( 0 , panelWidth - 3 ) } ` . trimEnd ( ) ) ,
58+ `logo at terminal width: ${ width } `
59+ ) ;
60+ assert . equal ( lines [ panelTop ] , ` ╭${ "─" . repeat ( panelWidth - 4 ) } ╮` ) ;
61+ const panelBottom = lines . findIndex ( ( line ) => line . startsWith ( " ╰─" ) ) ;
62+ assert . ok ( panelBottom > panelTop ) ;
63+ assert . equal ( lines [ panelBottom ] , ` ╰${ "─" . repeat ( panelWidth - 4 ) } ╯` ) ;
64+ for ( const line of lines . slice ( panelTop + 1 , panelBottom ) ) {
65+ assert . ok ( line . startsWith ( " │ " ) && line . endsWith ( " │" ) , line ) ;
66+ assert . equal ( stringWidth ( line ) , panelWidth - 1 , line ) ;
67+ }
68+ for ( const [ label , value ] of [
69+ [ "Model" , settings . model ] ,
70+ [ "Thinking Enabled" , String ( settings . thinkingEnabled ) ] ,
71+ [ "Reasoning Effort" , settings . reasoningEffort ] ,
72+ [ "CWD" , "/private/tmp" ] ,
73+ ] ) {
74+ assert . ok (
75+ lines . some ( ( line ) => line . includes ( label ) && line . includes ( value ) ) ,
76+ `${ label } and its value should share a row at terminal width: ${ width } `
77+ ) ;
78+ }
79+ }
80+ } ) ;
81+
3082test ( "formatHomeRelativePath returns tilde for the home directory" , ( ) => {
3183 const home = path . resolve ( "/Users/example" ) ;
3284 assert . equal ( formatHomeRelativePath ( home , home ) , "~" ) ;
0 commit comments