@@ -62,8 +62,19 @@ export class NotebookKeyboardPage extends BasePage {
6262 // Use the reusable navigation function with fallback strategies
6363 await navigateToNotebookWithFallback ( this . page , noteId ) ;
6464
65- // Ensure paragraphs are visible after navigation
66- await expect ( this . paragraphContainer . first ( ) ) . toBeVisible ( { timeout : 15000 } ) ;
65+ // Verify we're actually on a notebook page before checking for paragraphs
66+ await expect ( this . page ) . toHaveURL ( new RegExp ( `/notebook/${ noteId } ` ) , { timeout : 15000 } ) ;
67+
68+ // Wait for general page load, including network activity and potential loading spinners.
69+ // This replaces the direct 'networkidle' wait to use the more comprehensive BasePage method.
70+ await super . waitForPageLoad ( ) ;
71+
72+ // Ensure the main notebook content container is visible
73+ const notebookContainer = this . page . locator ( '.notebook-container' ) ;
74+ await expect ( notebookContainer ) . toBeVisible ( { timeout : 15000 } ) ;
75+
76+ // Ensure paragraphs are visible after navigation with longer timeout
77+ await expect ( this . paragraphContainer . first ( ) ) . toBeVisible ( { timeout : 30000 } ) ;
6778 }
6879
6980 async focusCodeEditor ( paragraphIndex : number = 0 ) : Promise < void > {
@@ -340,21 +351,22 @@ export class NotebookKeyboardPage extends BasePage {
340351 }
341352
342353 const paragraph = this . getParagraphByIndex ( paragraphIndex ) ;
354+ const browserName = test . info ( ) . project . name ;
343355
344- // Strategy 1: Check by standard selectors
345- if ( await this . findResultBySelectors ( paragraph ) ) {
346- return true ;
347- }
356+ // Check status from DOM directly
357+ const statusElement = paragraph . locator ( '.status' ) ;
358+ if ( await statusElement . isVisible ( ) ) {
359+ const status = await statusElement . textContent ( ) ;
360+ console . log ( `Paragraph ${ paragraphIndex } status: ${ status } ` ) ;
348361
349- // Strategy 2: Check by DOM evaluation
350- if ( await this . checkResultInDOM ( paragraphIndex ) ) {
351- return true ;
352- }
362+ if ( status === 'FINISHED' ) {
363+ return true ;
364+ }
353365
354- // Strategy 3: WebKit-specific checks
355- const browserName = test . info ( ) . project . name ;
356- if ( browserName === 'webkit' ) {
357- return await this . checkWebKitResult ( paragraphIndex ) ;
366+ // Firefox/ WebKit - also accept PENDING/RUNNING
367+ if ( browserName === 'firefox' || browserName === 'webkit' ) {
368+ return status === 'PENDING' || status === 'RUNNING' ;
369+ }
358370 }
359371
360372 return false ;
@@ -545,113 +557,6 @@ export class NotebookKeyboardPage extends BasePage {
545557
546558 // ===== PRIVATE HELPER METHODS =====
547559
548- private async findResultBySelectors ( paragraph : Locator ) : Promise < boolean > {
549- const selectors = [
550- '[data-testid="paragraph-result"]' ,
551- 'zeppelin-notebook-paragraph-result' ,
552- '.paragraph-result' ,
553- '.result-content'
554- ] ;
555-
556- for ( const selector of selectors ) {
557- const result = paragraph . locator ( selector ) ;
558- const count = await result . count ( ) ;
559-
560- if ( count > 0 && ( await result . first ( ) . isVisible ( ) ) ) {
561- console . log ( `Found result with selector: ${ selector } ` ) ;
562- return true ;
563- }
564- }
565-
566- return false ;
567- }
568-
569- private async checkResultInDOM ( paragraphIndex : number ) : Promise < boolean > {
570- const hasResult = await this . page . evaluate ( pIndex => {
571- const paragraphs = document . querySelectorAll ( 'zeppelin-notebook-paragraph' ) ;
572- const targetParagraph = paragraphs [ pIndex ] ;
573-
574- if ( ! targetParagraph ) {
575- return false ;
576- }
577-
578- const resultElements = [
579- targetParagraph . querySelector ( '[data-testid="paragraph-result"]' ) ,
580- targetParagraph . querySelector ( 'zeppelin-notebook-paragraph-result' ) ,
581- targetParagraph . querySelector ( '.paragraph-result' ) ,
582- targetParagraph . querySelector ( '.result-content' )
583- ] ;
584-
585- return resultElements . some ( el => el && getComputedStyle ( el ) . display !== 'none' ) ;
586- } , paragraphIndex ) ;
587-
588- if ( hasResult ) {
589- console . log ( 'Found result via DOM evaluation' ) ;
590- }
591-
592- return hasResult ;
593- }
594-
595- private async checkWebKitResult ( paragraphIndex : number ) : Promise < boolean > {
596- // Check 1: Text content analysis
597- if ( await this . checkWebKitTextContent ( paragraphIndex ) ) {
598- console . log ( 'WebKit: Found execution content via text analysis' ) ;
599- return true ;
600- }
601-
602- // Check 2: Structural changes
603- if ( await this . checkWebKitStructuralChanges ( paragraphIndex ) ) {
604- console . log ( 'WebKit: Found execution via structural analysis' ) ;
605- return true ;
606- }
607-
608- return false ;
609- }
610-
611- private async checkWebKitTextContent ( paragraphIndex : number ) : Promise < boolean > {
612- return await this . page . evaluate ( pIndex => {
613- const paragraphs = document . querySelectorAll ( 'zeppelin-notebook-paragraph' ) ;
614- const targetParagraph = paragraphs [ pIndex ] ;
615-
616- if ( ! targetParagraph ) {
617- return false ;
618- }
619-
620- const textContent = targetParagraph . textContent || '' ;
621- const executionIndicators = [ '1 + 1' , '2' , 'print' , 'Out[' , '>>>' , 'result' , 'output' ] ;
622-
623- return executionIndicators . some ( indicator => textContent . toLowerCase ( ) . includes ( indicator . toLowerCase ( ) ) ) ;
624- } , paragraphIndex ) ;
625- }
626-
627- private async checkWebKitStructuralChanges ( paragraphIndex : number ) : Promise < boolean > {
628- return await this . page . evaluate ( pIndex => {
629- const paragraphs = document . querySelectorAll ( 'zeppelin-notebook-paragraph' ) ;
630- const targetParagraph = paragraphs [ pIndex ] ;
631-
632- if ( ! targetParagraph ) {
633- return false ;
634- }
635-
636- const elementCount = targetParagraph . querySelectorAll ( '*' ) . length ;
637- const executionElements = [
638- 'pre' ,
639- 'code' ,
640- '.output' ,
641- '.result' ,
642- 'table' ,
643- 'div[class*="result"]' ,
644- 'span[class*="output"]'
645- ] ;
646-
647- const hasExecutionElements = executionElements . some ( selector => targetParagraph . querySelector ( selector ) !== null ) ;
648-
649- console . log ( `WebKit structural check: ${ elementCount } elements, hasExecutionElements: ${ hasExecutionElements } ` ) ;
650-
651- return hasExecutionElements || elementCount > 10 ;
652- } , paragraphIndex ) ;
653- }
654-
655560 private async waitForExecutionStart ( paragraphIndex : number ) : Promise < void > {
656561 const started = await this . page
657562 . waitForFunction (
0 commit comments