@@ -8,6 +8,10 @@ import os from 'node:os';
88import path from 'node:path' ;
99
1010import type { Debugger } from 'debug' ;
11+
12+ import type { ListenerMap } from './PageCollector.js' ;
13+ import { NetworkCollector , PageCollector } from './PageCollector.js' ;
14+ import { Locator } from './third_party/puppeteer-core/index.js' ;
1115import type {
1216 Browser ,
1317 ConsoleMessage ,
@@ -17,10 +21,7 @@ import type {
1721 Page ,
1822 SerializedAXNode ,
1923 PredefinedNetworkConditions ,
20- } from 'puppeteer-core' ;
21-
22- import type { ListenerMap } from './PageCollector.js' ;
23- import { NetworkCollector , PageCollector } from './PageCollector.js' ;
24+ } from './third_party/puppeteer-core/index.js' ;
2425import { listPages } from './tools/pages.js' ;
2526import { takeSnapshot } from './tools/snapshot.js' ;
2627import { CLOSE_PAGE_ERROR } from './tools/ToolDefinition.js' ;
@@ -91,9 +92,16 @@ export class McpContext implements Context {
9192 #nextSnapshotId = 1 ;
9293 #traceResults: TraceResult [ ] = [ ] ;
9394
94- private constructor ( browser : Browser , logger : Debugger ) {
95+ #locatorClass: typeof Locator ;
96+
97+ private constructor (
98+ browser : Browser ,
99+ logger : Debugger ,
100+ locatorClass : typeof Locator ,
101+ ) {
95102 this . browser = browser ;
96103 this . logger = logger ;
104+ this . #locatorClass = locatorClass ;
97105
98106 this . #networkCollector = new NetworkCollector ( this . browser ) ;
99107
@@ -122,8 +130,13 @@ export class McpContext implements Context {
122130 await this . #consoleCollector. init ( ) ;
123131 }
124132
125- static async from ( browser : Browser , logger : Debugger ) {
126- const context = new McpContext ( browser , logger ) ;
133+ static async from (
134+ browser : Browser ,
135+ logger : Debugger ,
136+ /* Let tests use unbundled Locator class to avoid overly strict checks within puppeteer that fail when mixing bundled and unbundled class instances */
137+ locatorClass : typeof Locator = Locator ,
138+ ) {
139+ const context = new McpContext ( browser , logger , locatorClass ) ;
127140 await context . #init( ) ;
128141 return context ;
129142 }
@@ -428,4 +441,28 @@ export class McpContext implements Context {
428441 getNetworkRequestStableId ( request : HTTPRequest ) : number {
429442 return this . #networkCollector. getIdForResource ( request ) ;
430443 }
444+
445+ waitForTextOnPage ( {
446+ text,
447+ timeout,
448+ } : {
449+ text : string ;
450+ timeout ?: number | undefined ;
451+ } ) : Promise < Element > {
452+ const page = this . getSelectedPage ( ) ;
453+ const frames = page . frames ( ) ;
454+
455+ const locator = this . #locatorClass. race (
456+ frames . flatMap ( frame => [
457+ frame . locator ( `aria/${ text } ` ) ,
458+ frame . locator ( `text/${ text } ` ) ,
459+ ] ) ,
460+ ) ;
461+
462+ if ( timeout ) {
463+ locator . setTimeout ( timeout ) ;
464+ }
465+
466+ return locator . wait ( ) ;
467+ }
431468}
0 commit comments