@@ -143,8 +143,29 @@ export async function resetWarmNotebookPanel(page: Page): Promise<void> {
143143 }
144144 } ) ;
145145 // 3. Spawn a fresh Empty notebook and ensure it is the active tab.
146+ //
147+ // ``persistAndOpen`` (in ``NotebookPanel``) awaits a Pyodide round-trip
148+ // before it appends the new tab to the React state. Previous tests in
149+ // the warm worker may have left several stale ``Untitled`` tabs around,
150+ // and the *previously* active tab may also be titled ``Untitled``.
151+ // Asserting only that "the active tab is named Untitled" is therefore
152+ // racy: the assertion can match the prior active tab and return BEFORE
153+ // the new tab has been appended, leaving a deferred React state update
154+ // that pollutes the next test.
155+ //
156+ // To get a deterministic reset, snapshot the tab count first and wait
157+ // for it to grow by exactly one before continuing.
158+ const tabCountBefore = await page . locator ( ".nb-tab" ) . count ( ) ;
146159 await page . locator ( ".nb-tab-new" ) . click ( ) ;
147160 await page . getByRole ( "menuitem" , { name : / E m p t y n o t e b o o k / } ) . click ( ) ;
161+ await expect ( page . locator ( ".nb-tab" ) ) . toHaveCount ( tabCountBefore + 1 , {
162+ timeout : 10_000 ,
163+ } ) ;
164+ // The newly-appended tab is always the last one (``openOrFocusNotebook``
165+ // appends), and the panel activates it synchronously after the append.
166+ await expect ( page . locator ( ".nb-tab" ) . last ( ) ) . toHaveClass ( / a c t i v e / , {
167+ timeout : 10_000 ,
168+ } ) ;
148169 await expect ( page . locator ( ".nb-tab.active .nb-tab-title" ) ) . toHaveText (
149170 "Untitled" ,
150171 { timeout : 10_000 } ,
0 commit comments