chromedevtools--chrome-devtools-mcp
53483bc637
This should reduce the flakiness and issue with finding open DevTools tabs for the corresponding pages. Currently we do multiple loops over all the targets, so this should have a nice performance improvement when multiple pages are opened. With a fallback for older versions.
90 行
2.6 KiB
TypeScript
90 行
2.6 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import assert from 'node:assert';
|
|
import {afterEach, describe, it} from 'node:test';
|
|
|
|
import sinon from 'sinon';
|
|
|
|
import {UniverseManager} from '../src/DevtoolsUtils.js';
|
|
import {DevTools} from '../src/third_party/index.js';
|
|
import type {Browser, Target} from '../src/third_party/index.js';
|
|
|
|
import {
|
|
getMockBrowser,
|
|
getMockPage,
|
|
mockListener,
|
|
withBrowser,
|
|
} from './utils.js';
|
|
|
|
describe('UniverseManager', () => {
|
|
afterEach(() => {
|
|
sinon.restore();
|
|
});
|
|
|
|
it('calls the factory for existing pages', async () => {
|
|
const browser = getMockBrowser();
|
|
const factory = sinon.stub().resolves({});
|
|
const manager = new UniverseManager(browser, factory);
|
|
await manager.init(await browser.pages());
|
|
|
|
const page = (await browser.pages())[0];
|
|
sinon.assert.calledOnceWithExactly(factory, page);
|
|
});
|
|
|
|
it('calls the factory only once for the same page', async () => {
|
|
const browser = {
|
|
...mockListener(),
|
|
} as unknown as Browser;
|
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
const factory = sinon.stub().returns(new Promise(() => {})); // Don't resolve.
|
|
const manager = new UniverseManager(browser, factory);
|
|
await manager.init([]);
|
|
|
|
sinon.assert.notCalled(factory);
|
|
|
|
const page = getMockPage();
|
|
browser.emit('targetcreated', {
|
|
page: () => Promise.resolve(page),
|
|
} as Target);
|
|
browser.emit('targetcreated', {
|
|
page: () => Promise.resolve(page),
|
|
} as Target);
|
|
|
|
await new Promise(r => setTimeout(r, 0)); // One event loop tick for the micro task queue to run.
|
|
|
|
sinon.assert.calledOnceWithExactly(factory, page);
|
|
});
|
|
|
|
it('works with a real browser', async () => {
|
|
await withBrowser(async (browser, page) => {
|
|
const manager = new UniverseManager(browser);
|
|
await manager.init([page]);
|
|
|
|
assert.notStrictEqual(manager.get(page), null);
|
|
});
|
|
});
|
|
|
|
it('ignores pauses', async () => {
|
|
await withBrowser(async (browser, page) => {
|
|
const manager = new UniverseManager(browser);
|
|
await manager.init([page]);
|
|
const targetUniverse = manager.get(page);
|
|
assert.ok(targetUniverse);
|
|
const model = targetUniverse.target.model(DevTools.DebuggerModel);
|
|
assert.ok(model);
|
|
|
|
const pausedSpy = sinon.stub();
|
|
model.addEventListener('DebuggerPaused' as any, pausedSpy); // eslint-disable-line
|
|
|
|
const result = await page.evaluate('debugger; 1 + 1');
|
|
assert.strictEqual(result, 2);
|
|
|
|
sinon.assert.notCalled(pausedSpy);
|
|
});
|
|
});
|
|
});
|