@@ -73,6 +73,10 @@ test.describe('ui', () => {
7373 await testPersistsAttemptInURL ( page )
7474 } )
7575
76+ test ( 'focused trace mode' , async ( { page } ) => {
77+ await testFocusedTraceMode ( page )
78+ } )
79+
7680 test ( 'persists resized trace panes across reloads' , async ( { page } ) => {
7781 await testPersistsResizedTracePanes ( page )
7882 } )
@@ -159,6 +163,10 @@ test.describe('html reporter', () => {
159163 await testPersistsAttemptInURL ( page )
160164 } )
161165
166+ test ( 'focused trace mode' , async ( { page } ) => {
167+ await testFocusedTraceMode ( page )
168+ } )
169+
162170 test ( 'persists resized trace panes across reloads' , async ( { page } ) => {
163171 await testPersistsResizedTracePanes ( page )
164172 } )
@@ -512,6 +520,58 @@ async function testPersistsAttemptInURL(page: Page) {
512520 await expect ( traceFrame . getByText ( 'retryCount: 1' ) ) . toBeVisible ( )
513521}
514522
523+ async function testFocusedTraceMode ( page : Page ) {
524+ // Opening the trace layout without a selection shows its empty state.
525+ const standardUrl = page . url ( )
526+ const emptyTraceUrl = new URL ( standardUrl )
527+ emptyTraceUrl . hash = '/?layout=trace'
528+ await page . goto ( emptyTraceUrl . href )
529+ await expect ( page . getByText ( 'No trace found' ) ) . toBeVisible ( )
530+
531+ // Select a trace step in the standard layout.
532+ await page . goto ( standardUrl )
533+ await openExplorerItem ( page , 'simple' )
534+ const traceView = page . getByTestId ( 'trace-view' )
535+ const traceSteps = traceView . getByTestId ( 'trace-step' )
536+ const traceFrame = traceView . frameLocator ( 'iframe' )
537+ await expect ( traceView . getByTestId ( 'trace-view-title' ) ) . toHaveText ( 'Trace Viewer' )
538+ await traceSteps . nth ( 1 ) . click ( )
539+ await expect ( traceFrame . getByRole ( 'button' , { name : 'Another' } ) ) . toBeVisible ( )
540+
541+ // Follow its new-tab URL in the current page to inspect the focused layout.
542+ const openFocusedTrace = traceView . getByRole ( 'link' , { name : 'Open Trace Viewer in New Tab' } )
543+ await expect ( openFocusedTrace ) . toHaveAttribute ( 'target' , '_blank' )
544+ const focusedUrl = await openFocusedTrace . getAttribute ( 'href' )
545+ if ( ! focusedUrl ) {
546+ throw new Error ( 'Focused trace URL is unavailable' )
547+ }
548+ await page . goto ( focusedUrl )
549+
550+ // The focused layout fills the viewport, preserves selection, and hides standard controls.
551+ const viewport = page . viewportSize ( )
552+ if ( ! viewport ) {
553+ throw new Error ( 'Viewport size is unavailable' )
554+ }
555+ await expect ( traceView ) . toBeVisible ( )
556+ await expect ( page . getByAltText ( 'Vitest logo' ) ) . toBeHidden ( )
557+ await expect ( traceView . getByTestId ( 'trace-view-title' ) . locator ( 'span' ) ) . toHaveText ( [ 'simple' , 'basic.test.ts' ] )
558+ await expect ( traceView . getByRole ( 'link' , { name : 'Open Trace Viewer in New Tab' } ) ) . toBeHidden ( )
559+ await expect ( traceView . getByRole ( 'button' , { name : 'Close Trace Viewer' } ) ) . toBeHidden ( )
560+ await expect ( traceSteps . nth ( 1 ) ) . toHaveAttribute ( 'aria-selected' , 'true' )
561+ await expect ( traceFrame . getByRole ( 'button' , { name : 'Another' } ) ) . toBeVisible ( )
562+ await expect . poll ( ( ) => traceView . boundingBox ( ) ) . toEqual ( {
563+ x : 0 ,
564+ y : 0 ,
565+ width : viewport . width ,
566+ height : viewport . height ,
567+ } )
568+
569+ // Reloading restores the selected trace step.
570+ await page . reload ( )
571+ await expect ( traceSteps . nth ( 1 ) ) . toHaveAttribute ( 'aria-selected' , 'true' )
572+ await expect ( traceFrame . getByRole ( 'button' , { name : 'Another' } ) ) . toBeVisible ( )
573+ }
574+
515575function getHashParams ( page : Page ) {
516576 const hash = new URL ( page . url ( ) ) . hash
517577 return Object . fromEntries ( new URLSearchParams ( hash . split ( '?' ) [ 1 ] ) )
0 commit comments