@@ -212,6 +212,54 @@ test("closing the last New tab closes the side region, and only a New tab lists
212212 await expect ( review ) . toBeVisible ( )
213213} )
214214
215+ test ( "tabs in a narrow side strip shrink to keep their close buttons, and a tab's menu closes the others" , async ( {
216+ page,
217+ } ) => {
218+ await page . setViewportSize ( { width : 1000 , height : 700 } )
219+ const directory = "C:/OpenCode/NarrowStrip"
220+ const key = `local\u0000${ base64Encode ( directory ) } /ses_narrowstrip`
221+ const files = [ "a.md" , "a-file-name-long-enough-to-overflow-the-side-strip-by-itself.md" , "b.md" ]
222+
223+ await openSession ( page , {
224+ name : "NarrowStrip" ,
225+ fileList : ( ) => [ ] ,
226+ fileContent : ( path ) => ( { type : "text" , content : `contents:${ path } ` } ) ,
227+ seed : {
228+ panes : { ses_narrowstrip : { review : true , sessionWidth : 640 } } ,
229+ storage : {
230+ "opencode.global.dat:layout" : {
231+ sessionTabs : { [ key ] : { all : files . map ( ( file ) => `file://${ file } ` ) , active : `file://${ files [ 1 ] } ` } } ,
232+ } ,
233+ } ,
234+ } ,
235+ } )
236+
237+ const side = page . locator ( '[data-pane-content="side"]' )
238+ const add = side . getByRole ( "button" , { name : "Add tab" , exact : true } )
239+ await expect ( side . getByRole ( "tab" , { name : files [ 1 ] , exact : true } ) ) . toHaveAttribute ( "aria-selected" , "true" )
240+
241+ // Every tab's close button stays left of "+", instead of the strip scrolling it away under its edge fade.
242+ const end = ( await add . boundingBox ( ) ) ! . x
243+ const closes = side . locator ( '[data-pane-strip="side"] [data-slot="tabs-trigger-close-button"]' )
244+ await expect ( closes ) . toHaveCount ( files . length )
245+
246+ for ( const close of await closes . all ( ) ) {
247+ const box = ( await close . boundingBox ( ) ) !
248+ expect ( box . x + box . width ) . toBeLessThanOrEqual ( end )
249+ }
250+
251+ await side . getByRole ( "tab" , { name : "b.md" , exact : true } ) . click ( { button : "right" } )
252+ await page . getByRole ( "menuitem" , { name : "Close other tabs" , exact : true } ) . click ( )
253+ await expect ( side . getByRole ( "tab" ) ) . toHaveCount ( 1 )
254+ await expect ( side . getByRole ( "tab" , { name : "b.md" , exact : true } ) ) . toHaveAttribute ( "aria-selected" , "true" )
255+
256+ // With nothing else to close, the menu offers only the tab itself.
257+ await side . getByRole ( "tab" , { name : "b.md" , exact : true } ) . click ( { button : "right" } )
258+ await expect ( page . getByRole ( "menuitem" , { name : "Close other tabs" , exact : true } ) ) . toBeDisabled ( )
259+ await page . getByRole ( "menuitem" , { name : "Close tab" , exact : true } ) . click ( )
260+ await expect ( side . getByRole ( "tab" , { name : "b.md" , exact : true } ) ) . toHaveCount ( 0 )
261+ } )
262+
215263// A DOM mark survives only while the same node stays mounted.
216264function mark ( locator : Locator ) {
217265 return locator . evaluate ( ( element ) => element . setAttribute ( "data-e2e-mounted" , "original" ) )
0 commit comments