@@ -9,9 +9,12 @@ import path from 'node:path';
99import { afterEach , describe , it } from 'node:test' ;
1010import { pathToFileURL } from 'node:url' ;
1111
12+ import logger from 'debug' ;
13+ import puppeteer , { Locator } from 'puppeteer' ;
1214import type { Target } from 'puppeteer-core' ;
1315import sinon from 'sinon' ;
1416
17+ import { McpContext } from '../src/McpContext.js' ;
1518import { NetworkFormatter } from '../src/formatters/NetworkFormatter.js' ;
1619import { TextSnapshot } from '../src/TextSnapshot.js' ;
1720import type { HTTPResponse } from '../src/third_party/index.js' ;
@@ -283,4 +286,67 @@ describe('McpContext', () => {
283286 assert . ok ( pages . length > 0 , 'Should still enumerate healthy pages' ) ;
284287 } ) ;
285288 } ) ;
289+
290+ it ( 'should enumerate pages when a tab has a crashed renderer' , async ( ) => {
291+ const browser = await puppeteer . launch ( {
292+ headless : true ,
293+ args : [ '--remote-debugging-port=0' ] ,
294+ enableExtensions : true ,
295+ handleDevToolsAsPage : true ,
296+ executablePath : process . env . PUPPETEER_EXECUTABLE_PATH ,
297+ } ) ;
298+
299+ try {
300+ const wsEndpoint = browser . wsEndpoint ( ) ;
301+
302+ const activePage = await browser . newPage ( ) ;
303+ await activePage . goto ( 'data:text/html,<h1>Active</h1>' ) ;
304+
305+ const crashPage = await browser . newPage ( ) ;
306+ await crashPage . goto ( 'data:text/html,<h1>Will crash</h1>' ) ;
307+ try {
308+ await crashPage . goto ( 'chrome://crash' ) ;
309+ } catch { }
310+
311+ browser . disconnect ( ) ;
312+
313+ const reconnected = await puppeteer . connect ( {
314+ browserWSEndpoint : wsEndpoint ,
315+ handleDevToolsAsPage : true ,
316+ } ) ;
317+
318+ try {
319+ const start = Date . now ( ) ;
320+ const ctx = await McpContext . from (
321+ reconnected ,
322+ logger ( 'test' ) ,
323+ {
324+ experimentalDevToolsDebugging : false ,
325+ performanceCrux : false ,
326+ } ,
327+ Locator ,
328+ ) ;
329+ const elapsed = Date . now ( ) - start ;
330+
331+ assert . ok (
332+ elapsed < 20_000 ,
333+ `Took ${ elapsed } ms, expected < 20s` ,
334+ ) ;
335+ const pages = ctx . getPages ( ) ;
336+ assert . ok (
337+ pages . length >= 1 ,
338+ `Expected at least 1 page, got ${ pages . length } ` ,
339+ ) ;
340+
341+ ctx . dispose ( ) ;
342+ } finally {
343+ await reconnected . close ( ) ;
344+ }
345+ } catch ( e ) {
346+ if ( browser . connected ) {
347+ await browser . close ( ) ;
348+ }
349+ throw e ;
350+ }
351+ } ) ;
286352} ) ;
0 commit comments