@@ -14,9 +14,9 @@ import {
1414 sessionHref ,
1515} from "../utils/app"
1616import { openFileLauncher , reviewTabs } from "../utils/side-panel"
17- import { mockServers } from "../utils/mock-server"
17+ import { currentSession , mockServers } from "../utils/mock-server"
1818import { fixture , mockStressTimeline } from "../utils/session-fixture"
19- import { fileNode , mockWorkspace , openSession } from "../utils/workspace"
19+ import { fileNode , mockRemoteServer , mockWorkspace , openSession } from "../utils/workspace"
2020import { expectSessionTitle } from "../utils/waits"
2121
2222const a = { id : "ses_tab_a" , title : "Tab A session" }
@@ -128,6 +128,72 @@ test("recently closed fills remaining slots in Home order without open or duplic
128128 await expect ( items ) . toHaveText ( [ "OOther session 9" ] )
129129} )
130130
131+ for ( const server of [ SERVER , REMOTE_SERVER ] ) {
132+ test ( `session metadata failure does not follow navigation to another tab on ${ server } ` , async ( { page } ) => {
133+ await mockWorkspace ( page , {
134+ name : "Tabs" ,
135+ sessions : [ b ] ,
136+ seed : { tabs : [ a . id , { session : b . id , server } ] } ,
137+ } )
138+ if ( server === REMOTE_SERVER ) {
139+ await mockRemoteServer ( page , { sessions : [ session ( { ...b , directory : "/remote/project" } ) ] } )
140+ }
141+ await page . route (
142+ ( url ) => url . origin === SERVER && url . pathname === `/api/session/${ a . id } ` ,
143+ ( route ) => route . fulfill ( { status : 504 , json : { message : "Fixture metadata timeout" } } ) ,
144+ )
145+ await page . goto ( sessionHref ( a . id ) )
146+ await expect ( page . getByRole ( "heading" , { name : "Server request failed" } ) ) . toBeVisible ( )
147+ const document = await page . locator ( "html" ) . elementHandle ( )
148+
149+ await page . locator ( `a[data-titlebar-tab-link][href="${ sessionHref ( b . id , server ) } "]` ) . click ( )
150+
151+ await expectPath ( page , sessionHref ( b . id , server ) )
152+ await expectSessionTitle ( page , b . title )
153+ await expect ( page . locator ( '[data-component="composer-editor"]' ) ) . toBeEditable ( )
154+ await expect ( page . getByRole ( "heading" , { name : "Server request failed" } ) ) . toHaveCount ( 0 )
155+ expect ( await document ?. evaluate ( ( element ) => element . isConnected ) ) . toBe ( true )
156+ } )
157+ }
158+
159+ test ( "session metadata failure can be retried without reloading or looping" , async ( { page } , testInfo ) => {
160+ await page . setViewportSize ( { width : 1440 , height : 900 } )
161+ const workspace = await mockWorkspace ( page , { name : "Tabs" , sessions : [ b ] , seed : { tabs : [ a . id , b . id ] } } )
162+ const state = { fail : true , requests : 0 }
163+ await page . route (
164+ ( url ) => url . origin === SERVER && url . pathname === `/api/session/${ a . id } ` ,
165+ ( route ) => {
166+ state . requests ++
167+ return route . fulfill (
168+ state . fail
169+ ? { status : 504 , json : { message : "Fixture metadata timeout" } }
170+ : { json : { data : currentSession ( session ( { ...a , directory : workspace . directory } ) ) } } ,
171+ )
172+ } ,
173+ )
174+ await page . goto ( sessionHref ( a . id ) )
175+ const retry = page . getByRole ( "button" , { name : "Try again" , exact : true } )
176+ await expect ( retry ) . toBeVisible ( )
177+ const document = await page . locator ( "html" ) . elementHandle ( )
178+ const before = state . requests
179+ await retry . press ( "Enter" )
180+ await expect ( retry ) . toBeVisible ( )
181+ await expect . poll ( ( ) => state . requests ) . toBe ( before + 1 )
182+ await expect ( retry ) . toBeInViewport ( )
183+ await page . screenshot ( { path : testInfo . outputPath ( "retry-desktop.png" ) } )
184+ expect ( state . requests ) . toBe ( before + 1 )
185+ await page . setViewportSize ( { width : 390 , height : 720 } )
186+ await expect ( retry ) . toBeInViewport ( )
187+ await page . screenshot ( { path : testInfo . outputPath ( "retry-narrow.png" ) } )
188+
189+ state . fail = false
190+ await retry . click ( )
191+ await expectSessionTitle ( page , a . title )
192+ await expect ( page . locator ( '[data-component="composer-editor"]' ) ) . toBeEditable ( )
193+ await expect ( retry ) . toHaveCount ( 0 )
194+ expect ( await document ?. evaluate ( ( element ) => element . isConnected ) ) . toBe ( true )
195+ } )
196+
131197test ( "tab strip keeps draft tabs as wide as session tabs and navigates on mouse down" , async ( { page } ) => {
132198 const workspace = await mockWorkspace ( page , {
133199 name : "Tabs" ,
0 commit comments