chromedevtools--chrome-devtools-mcp
345deac7e1
Bumps the bundled group with 1 update: [puppeteer](https://github.com/puppeteer/puppeteer). Updates `puppeteer` from 24.40.0 to 24.41.0 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/puppeteer/puppeteer/releases">puppeteer's releases</a>.</em></p> <blockquote> <h2>puppeteer-core: v24.41.0</h2> <h2><a href="https://github.com/puppeteer/puppeteer/compare/puppeteer-core-v24.40.0...puppeteer-core-v24.41.0">24.41.0</a> (2026-04-15)</h2> <h3>🎉 Features</h3> <ul> <li>add support for Issues (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14845">#14845</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/6e8dbe7a998a3619f089f549009ebcb860389fdd">6e8dbe7</a>)</li> <li>adds extension realms api (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14824">#14824</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/c14f4ae7ee65fd95a4a1f9d722e73f67c37da44b">c14f4ae</a>)</li> <li>API to list installed browser extensions and trigger extension actions (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14821">#14821</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/d6395ef88103a50cb2b2c43f61953ab6a495a8c3">d6395ef</a>)</li> <li>implement console event on web workers (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14784">#14784</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/fa6158a1dfa327df8dc8eea1eb22c49efefb3be5">fa6158a</a>)</li> <li>roll to Chrome 147.0.7727.24 (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14797">#14797</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/ee81786a8285e20afdee70e4fb8660df4d6748b0">ee81786</a>)</li> <li>roll to Firefox 149.0 (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14799">#14799</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/9fd5ceb054b0508bd8f4b14ed950a011a31f101a">9fd5ceb</a>)</li> <li><strong>webmcp:</strong> add hook for tool invocation (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14835">#14835</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/cf8169d5dee0bbff06118c211969eb94849f6bbd">cf8169d</a>)</li> <li><strong>webmcp:</strong> add hook for tool response (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14841">#14841</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/6fb05bc9e45fb2735a1c44b59ad868af2fb1ee9b">6fb05bc</a>)</li> <li><strong>webmcp:</strong> add initial API to inspect tool registrations (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14814">#14814</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/655c996fed21d4ac7f5df841aef0c6b246ba2e9d">655c996</a>)</li> <li><strong>webmcp:</strong> add WebMCPTool execute support (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14851">#14851</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/8f95117960af969ee31595406f985c924eb67bf1">8f95117</a>)</li> <li><strong>webmcp:</strong> expose WebMCPToolCall in WebMCPToolCallResult (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14848">#14848</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/242ac0b2d364e9463f2b0e37f26d8bd0cfdf4d3e">242ac0b</a>)</li> <li><strong>webmcp:</strong> Switch from WebMCPInvocationStatus Success to Completed (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14859">#14859</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/375e636beedaa5fef53d5f198fa70229d47155b5">375e636</a>)</li> </ul> <h3>🛠️ Fixes</h3> <ul> <li>add missing onRelease to Mutex and add tests (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14818">#14818</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/bf1e9722eef723c80250119d81fd9d9e0596c074">bf1e972</a>)</li> <li>make <code>Target.asPage</code> return the same Page instance (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14862">#14862</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/e484a918c432859efbf57a74b4957097b13f8575">e484a91</a>)</li> <li>remove RenderDocument from disabled Chrome features (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14745">#14745</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/a48eba24dcb2663da543bdf1f4597a2c1a56f0ff">a48eba2</a>)</li> <li>roll to Chrome 147.0.7727.50 (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14819">#14819</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/2be30023994ee2e7ebb15e43dc0e2804256f8ca2">2be3002</a>)</li> <li>roll to Chrome 147.0.7727.56 (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14842">#14842</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/fdb3c64f8bfcff367eab862c0309f9c4bf6d6f20">fdb3c64</a>)</li> <li>roll to Firefox 149.0.2 (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14838">#14838</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/55359a3d7383c03a9d9de7ff8e24b613655694e8">55359a3</a>)</li> <li>without azimuthAngle the altitudeAngle should no be specified (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14781">#14781</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/6f9d9752207d55be0e3b0d10ba9a416a81af4694">6f9d975</a>)</li> </ul> <h3>📄 Documentation</h3> <ul> <li>update extension and realm docs (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14867">#14867</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/080379bf24c6bd021d664bcf993457542cf76dcc">080379b</a>)</li> <li><strong>webmcp:</strong> Add JS example to WebMCP class (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14852">#14852</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/c514dba3316e742f2d2b428fd72a49890c0a2255">c514dba</a>)</li> <li><strong>webmcp:</strong> Add missing documentation (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14849">#14849</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/76b08d20305283b9a2a2ccd5cf9c2f5bad63e337">76b08d2</a>)</li> <li><strong>webmcp:</strong> tune tags and descriptions (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14844">#14844</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/578295815ca559790626b8aeeddeea9f9cef67be">5782958</a>)</li> </ul> <h2>puppeteer: v24.41.0</h2> <h2><a href="https://github.com/puppeteer/puppeteer/compare/puppeteer-v24.40.0...puppeteer-v24.41.0">24.41.0</a> (2026-04-15)</h2> <h3>🎉 Features</h3> <ul> <li>roll to Chrome 147.0.7727.24 (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14797">#14797</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/ee81786a8285e20afdee70e4fb8660df4d6748b0">ee81786</a>)</li> </ul> <h3>Dependencies</h3> <ul> <li>The following workspace dependencies were updated</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/puppeteer/puppeteer/blob/main/CHANGELOG.md">puppeteer's changelog</a>.</em></p> <blockquote> <h2><a href="https://github.com/puppeteer/puppeteer/compare/puppeteer-v24.40.0...puppeteer-v24.41.0">24.41.0</a> (2026-04-15)</h2> <h3>🎉 Features</h3> <ul> <li>add support for Issues (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14845">#14845</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/6e8dbe7a998a3619f089f549009ebcb860389fdd">6e8dbe7</a>)</li> <li>adds extension realms api (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14824">#14824</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/c14f4ae7ee65fd95a4a1f9d722e73f67c37da44b">c14f4ae</a>)</li> <li>API to list installed browser extensions and trigger extension actions (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14821">#14821</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/d6395ef88103a50cb2b2c43f61953ab6a495a8c3">d6395ef</a>)</li> <li>implement console event on web workers (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14784">#14784</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/fa6158a1dfa327df8dc8eea1eb22c49efefb3be5">fa6158a</a>)</li> <li>roll to Chrome 147.0.7727.24 (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14797">#14797</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/ee81786a8285e20afdee70e4fb8660df4d6748b0">ee81786</a>)</li> <li>roll to Firefox 149.0 (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14799">#14799</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/9fd5ceb054b0508bd8f4b14ed950a011a31f101a">9fd5ceb</a>)</li> <li><strong>webmcp:</strong> add hook for tool invocation (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14835">#14835</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/cf8169d5dee0bbff06118c211969eb94849f6bbd">cf8169d</a>)</li> <li><strong>webmcp:</strong> add hook for tool response (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14841">#14841</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/6fb05bc9e45fb2735a1c44b59ad868af2fb1ee9b">6fb05bc</a>)</li> <li><strong>webmcp:</strong> add initial API to inspect tool registrations (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14814">#14814</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/655c996fed21d4ac7f5df841aef0c6b246ba2e9d">655c996</a>)</li> <li><strong>webmcp:</strong> add WebMCPTool execute support (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14851">#14851</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/8f95117960af969ee31595406f985c924eb67bf1">8f95117</a>)</li> <li><strong>webmcp:</strong> expose WebMCPToolCall in WebMCPToolCallResult (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14848">#14848</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/242ac0b2d364e9463f2b0e37f26d8bd0cfdf4d3e">242ac0b</a>)</li> <li><strong>webmcp:</strong> Switch from WebMCPInvocationStatus Success to Completed (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14859">#14859</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/375e636beedaa5fef53d5f198fa70229d47155b5">375e636</a>)</li> </ul> <h3>Dependencies</h3> <ul> <li>The following workspace dependencies were updated <ul> <li>dependencies <ul> <li>puppeteer-core bumped from 24.40.0 to 24.41.0</li> </ul> </li> </ul> </li> </ul> <h3>🛠️ Fixes</h3> <ul> <li>add missing onRelease to Mutex and add tests (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14818">#14818</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/bf1e9722eef723c80250119d81fd9d9e0596c074">bf1e972</a>)</li> <li>make <code>Target.asPage</code> return the same Page instance (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14862">#14862</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/e484a918c432859efbf57a74b4957097b13f8575">e484a91</a>)</li> <li>remove RenderDocument from disabled Chrome features (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14745">#14745</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/a48eba24dcb2663da543bdf1f4597a2c1a56f0ff">a48eba2</a>)</li> <li>roll to Chrome 147.0.7727.50 (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14819">#14819</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/2be30023994ee2e7ebb15e43dc0e2804256f8ca2">2be3002</a>)</li> <li>roll to Chrome 147.0.7727.56 (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14842">#14842</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/fdb3c64f8bfcff367eab862c0309f9c4bf6d6f20">fdb3c64</a>)</li> <li>roll to Firefox 149.0.2 (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14838">#14838</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/55359a3d7383c03a9d9de7ff8e24b613655694e8">55359a3</a>)</li> <li>without azimuthAngle the altitudeAngle should no be specified (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14781">#14781</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/6f9d9752207d55be0e3b0d10ba9a416a81af4694">6f9d975</a>)</li> </ul> <h3>📄 Documentation</h3> <ul> <li>update extension and realm docs (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14867">#14867</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/080379bf24c6bd021d664bcf993457542cf76dcc">080379b</a>)</li> <li><strong>webmcp:</strong> Add JS example to WebMCP class (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14852">#14852</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/c514dba3316e742f2d2b428fd72a49890c0a2255">c514dba</a>)</li> <li><strong>webmcp:</strong> Add missing documentation (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14849">#14849</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/76b08d20305283b9a2a2ccd5cf9c2f5bad63e337">76b08d2</a>)</li> <li><strong>webmcp:</strong> tune tags and descriptions (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14844">#14844</a>) (<a href="https://github.com/puppeteer/puppeteer/commit/578295815ca559790626b8aeeddeea9f9cef67be">5782958</a>)</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/puppeteer/puppeteer/commit/2d05dfcfa321f7e6289e4658cd6f0cced3d62fe2"><code>2d05dfc</code></a> fix: bump node to 24 to avoid publishing bugs with npm (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14868">#14868</a>)</li> <li><a href="https://github.com/puppeteer/puppeteer/commit/20402bc0f9a7daeee2afc6a9859a55ff9bf0e391"><code>20402bc</code></a> chore: release main (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14866">#14866</a>)</li> <li><a href="https://github.com/puppeteer/puppeteer/commit/080379bf24c6bd021d664bcf993457542cf76dcc"><code>080379b</code></a> docs: update extension and realm docs (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14867">#14867</a>)</li> <li><a href="https://github.com/puppeteer/puppeteer/commit/1f9dc746565c818d59fff9e84c3c795ddd2ec32d"><code>1f9dc74</code></a> chore(deps): bump follow-redirects from 1.15.11 to 1.16.0 in /website (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14865">#14865</a>)</li> <li><a href="https://github.com/puppeteer/puppeteer/commit/4655500ac52c67c782a956ea66270dfcf5a38d91"><code>4655500</code></a> chore(deps-dev): bump the dev-dependencies group with 8 updates (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14855">#14855</a>)</li> <li><a href="https://github.com/puppeteer/puppeteer/commit/d5029415e2c3d83ed340cf29733662e9f0b58434"><code>d502941</code></a> test: fix extension test flakiness (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14864">#14864</a>)</li> <li><a href="https://github.com/puppeteer/puppeteer/commit/e484a918c432859efbf57a74b4957097b13f8575"><code>e484a91</code></a> fix: make <code>Target.asPage</code> return the same Page instance (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14862">#14862</a>)</li> <li><a href="https://github.com/puppeteer/puppeteer/commit/c14f4ae7ee65fd95a4a1f9d722e73f67c37da44b"><code>c14f4ae</code></a> feat: adds extension realms api (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14824">#14824</a>)</li> <li><a href="https://github.com/puppeteer/puppeteer/commit/5097b97d07eb0e3c68d99fce80efe899084a313d"><code>5097b97</code></a> test: fix flaky extension test (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14853">#14853</a>)</li> <li><a href="https://github.com/puppeteer/puppeteer/commit/8f95117960af969ee31595406f985c924eb67bf1"><code>8f95117</code></a> feat(webmcp): add WebMCPTool execute support (<a href="https://redirect.github.com/puppeteer/puppeteer/issues/14851">#14851</a>)</li> <li>Additional commits viewable in <a href="https://github.com/puppeteer/puppeteer/compare/puppeteer-v24.40.0...puppeteer-v24.41.0">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions </details> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alex Rudenko <alexrudenko@chromium.org>
417 行
12 KiB
TypeScript
417 行
12 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import assert from 'node:assert';
|
|
import {afterEach, beforeEach, describe, it} from 'node:test';
|
|
|
|
import type {Frame, HTTPRequest, Target, Protocol} from 'puppeteer-core';
|
|
import sinon from 'sinon';
|
|
|
|
import type {ListenerMap} from '../src/PageCollector.js';
|
|
import {
|
|
ConsoleCollector,
|
|
NetworkCollector,
|
|
PageCollector,
|
|
} from '../src/PageCollector.js';
|
|
import {DevTools} from '../src/third_party/index.js';
|
|
|
|
import {getMockRequest, getMockBrowser} from './utils.js';
|
|
|
|
describe('PageCollector', () => {
|
|
it('works', async () => {
|
|
const browser = getMockBrowser();
|
|
const page = (await browser.pages())[0];
|
|
const request = getMockRequest();
|
|
const collector = new PageCollector(browser, collect => {
|
|
return {
|
|
request: req => {
|
|
collect(req);
|
|
},
|
|
} as ListenerMap;
|
|
});
|
|
await collector.init([page]);
|
|
page.emit('request', request);
|
|
|
|
assert.equal(collector.getData(page)[0], request);
|
|
});
|
|
|
|
it('clean up after navigation', async () => {
|
|
const browser = getMockBrowser();
|
|
const page = (await browser.pages())[0];
|
|
const mainFrame = page.mainFrame();
|
|
const request = getMockRequest();
|
|
const collector = new PageCollector(browser, collect => {
|
|
return {
|
|
request: req => {
|
|
collect(req);
|
|
},
|
|
} as ListenerMap;
|
|
});
|
|
await collector.init([page]);
|
|
page.emit('request', request);
|
|
|
|
assert.equal(collector.getData(page)[0], request);
|
|
page.emit('framenavigated', mainFrame);
|
|
|
|
assert.equal(collector.getData(page).length, 0);
|
|
});
|
|
|
|
it('does not clean up after sub frame navigation', async () => {
|
|
const browser = getMockBrowser();
|
|
const page = (await browser.pages())[0];
|
|
const request = getMockRequest();
|
|
const collector = new PageCollector(browser, collect => {
|
|
return {
|
|
request: req => {
|
|
collect(req);
|
|
},
|
|
} as ListenerMap;
|
|
});
|
|
await collector.init([page]);
|
|
page.emit('request', request);
|
|
page.emit('framenavigated', {} as Frame);
|
|
|
|
assert.equal(collector.getData(page).length, 1);
|
|
});
|
|
|
|
it('clean up after navigation and be able to add data after', async () => {
|
|
const browser = getMockBrowser();
|
|
const page = (await browser.pages())[0];
|
|
const mainFrame = page.mainFrame();
|
|
const request = getMockRequest();
|
|
const collector = new PageCollector(browser, collect => {
|
|
return {
|
|
request: req => {
|
|
collect(req);
|
|
},
|
|
} as ListenerMap;
|
|
});
|
|
await collector.init([page]);
|
|
page.emit('request', request);
|
|
|
|
assert.equal(collector.getData(page)[0], request);
|
|
page.emit('framenavigated', mainFrame);
|
|
|
|
assert.equal(collector.getData(page).length, 0);
|
|
|
|
page.emit('request', request);
|
|
|
|
assert.equal(collector.getData(page).length, 1);
|
|
});
|
|
|
|
it('should only subscribe once', async () => {
|
|
const browser = getMockBrowser();
|
|
const page = (await browser.pages())[0];
|
|
const request = getMockRequest();
|
|
const collector = new PageCollector(browser, collect => {
|
|
return {
|
|
request: req => {
|
|
collect(req);
|
|
},
|
|
} as ListenerMap;
|
|
});
|
|
await collector.init([page]);
|
|
browser.emit('targetcreated', {
|
|
page() {
|
|
return Promise.resolve(page);
|
|
},
|
|
} as Target);
|
|
|
|
// The page inside part is async so we need to await some time
|
|
await new Promise<void>(res => res());
|
|
|
|
assert.equal(collector.getData(page).length, 0);
|
|
|
|
page.emit('request', request);
|
|
|
|
assert.equal(collector.getData(page).length, 1);
|
|
|
|
page.emit('request', request);
|
|
|
|
assert.equal(collector.getData(page).length, 2);
|
|
});
|
|
|
|
it('should clear data on page destroy', async () => {
|
|
const browser = getMockBrowser();
|
|
const page = (await browser.pages())[0];
|
|
const request = getMockRequest();
|
|
const collector = new PageCollector(browser, collect => {
|
|
return {
|
|
request: req => {
|
|
collect(req);
|
|
},
|
|
} as ListenerMap;
|
|
});
|
|
await collector.init([page]);
|
|
|
|
page.emit('request', request);
|
|
|
|
assert.equal(collector.getData(page).length, 1);
|
|
|
|
browser.emit('targetdestroyed', {
|
|
page() {
|
|
return Promise.resolve(page);
|
|
},
|
|
} as Target);
|
|
|
|
// The page inside part is async so we need to await some time
|
|
await new Promise<void>(res => res());
|
|
|
|
assert.equal(collector.getData(page).length, 0);
|
|
});
|
|
|
|
it('should assign ids to requests', async () => {
|
|
const browser = getMockBrowser();
|
|
const page = (await browser.pages())[0];
|
|
const request1 = getMockRequest();
|
|
const request2 = getMockRequest();
|
|
const collector = new PageCollector<HTTPRequest>(browser, collect => {
|
|
return {
|
|
request: req => {
|
|
collect(req);
|
|
},
|
|
} as ListenerMap;
|
|
});
|
|
await collector.init([page]);
|
|
|
|
page.emit('request', request1);
|
|
page.emit('request', request2);
|
|
|
|
assert.equal(collector.getData(page).length, 2);
|
|
|
|
assert.equal(collector.getIdForResource(request1), 1);
|
|
assert.equal(collector.getIdForResource(request2), 2);
|
|
});
|
|
});
|
|
|
|
describe('NetworkCollector', () => {
|
|
it('correctly picks up navigation requests to latest navigation', async () => {
|
|
const browser = getMockBrowser();
|
|
const page = (await browser.pages())[0];
|
|
const mainFrame = page.mainFrame();
|
|
const request = getMockRequest();
|
|
const navRequest = getMockRequest({
|
|
navigationRequest: true,
|
|
frame: page.mainFrame(),
|
|
});
|
|
const request2 = getMockRequest();
|
|
const collector = new NetworkCollector(browser);
|
|
await collector.init([page]);
|
|
page.emit('request', request);
|
|
page.emit('request', navRequest);
|
|
|
|
assert.equal(collector.getData(page)[0], request);
|
|
assert.equal(collector.getData(page)[1], navRequest);
|
|
page.emit('framenavigated', mainFrame);
|
|
|
|
assert.equal(collector.getData(page).length, 1);
|
|
assert.equal(collector.getData(page)[0], navRequest);
|
|
|
|
page.emit('request', request2);
|
|
|
|
assert.equal(collector.getData(page).length, 2);
|
|
assert.equal(collector.getData(page)[0], navRequest);
|
|
assert.equal(collector.getData(page)[1], request2);
|
|
});
|
|
|
|
it('correctly picks up after multiple back to back navigations', async () => {
|
|
const browser = getMockBrowser();
|
|
const page = (await browser.pages())[0];
|
|
const mainFrame = page.mainFrame();
|
|
const navRequest = getMockRequest({
|
|
navigationRequest: true,
|
|
frame: page.mainFrame(),
|
|
});
|
|
const navRequest2 = getMockRequest({
|
|
navigationRequest: true,
|
|
frame: page.mainFrame(),
|
|
});
|
|
const request = getMockRequest();
|
|
|
|
const collector = new NetworkCollector(browser);
|
|
await collector.init([page]);
|
|
page.emit('request', navRequest);
|
|
assert.equal(collector.getData(page)[0], navRequest);
|
|
|
|
page.emit('framenavigated', mainFrame);
|
|
assert.equal(collector.getData(page).length, 1);
|
|
assert.equal(collector.getData(page)[0], navRequest);
|
|
|
|
page.emit('request', navRequest2);
|
|
assert.equal(collector.getData(page).length, 2);
|
|
assert.equal(collector.getData(page)[0], navRequest);
|
|
assert.equal(collector.getData(page)[1], navRequest2);
|
|
|
|
page.emit('framenavigated', mainFrame);
|
|
assert.equal(collector.getData(page).length, 1);
|
|
assert.equal(collector.getData(page)[0], navRequest2);
|
|
|
|
page.emit('request', request);
|
|
assert.equal(collector.getData(page).length, 2);
|
|
});
|
|
|
|
it('works with previous navigations', async () => {
|
|
const browser = getMockBrowser();
|
|
const page = (await browser.pages())[0];
|
|
const mainFrame = page.mainFrame();
|
|
const navRequest = getMockRequest({
|
|
navigationRequest: true,
|
|
frame: page.mainFrame(),
|
|
});
|
|
const navRequest2 = getMockRequest({
|
|
navigationRequest: true,
|
|
frame: page.mainFrame(),
|
|
});
|
|
const request = getMockRequest();
|
|
|
|
const collector = new NetworkCollector(browser);
|
|
await collector.init([page]);
|
|
page.emit('request', navRequest);
|
|
assert.equal(collector.getData(page, true).length, 1);
|
|
|
|
page.emit('framenavigated', mainFrame);
|
|
assert.equal(collector.getData(page, true).length, 1);
|
|
|
|
page.emit('request', navRequest2);
|
|
assert.equal(collector.getData(page, true).length, 2);
|
|
|
|
page.emit('framenavigated', mainFrame);
|
|
assert.equal(collector.getData(page, true).length, 2);
|
|
|
|
page.emit('request', request);
|
|
assert.equal(collector.getData(page, true).length, 3);
|
|
});
|
|
|
|
it('should not grow beyond maxNavigationSaved', async () => {
|
|
const browser = getMockBrowser();
|
|
const page = (await browser.pages())[0];
|
|
const mainFrame = page.mainFrame();
|
|
const collector = new NetworkCollector(browser);
|
|
await collector.init([page]);
|
|
|
|
// Simulate 5 navigations (maxNavigationSaved is 3)
|
|
for (let i = 0; i < 5; i++) {
|
|
const req = getMockRequest({
|
|
url: `http://example.com/nav${i}`,
|
|
navigationRequest: true,
|
|
frame: mainFrame,
|
|
});
|
|
page.emit('request', req);
|
|
page.emit('framenavigated', mainFrame);
|
|
}
|
|
|
|
// We expect 3 arrays in navigations (current + 2 saved)
|
|
// Each navigation has 1 request, so total should be 3
|
|
assert.equal(collector.getData(page, true).length, 3);
|
|
});
|
|
});
|
|
|
|
describe('ConsoleCollector', () => {
|
|
let issue: Protocol.Audits.InspectorIssue;
|
|
|
|
beforeEach(() => {
|
|
issue = {
|
|
code: 'MixedContentIssue',
|
|
details: {
|
|
mixedContentIssueDetails: {
|
|
insecureURL: 'test.url',
|
|
resolutionStatus: 'MixedContentBlocked',
|
|
mainResourceURL: '',
|
|
},
|
|
},
|
|
};
|
|
});
|
|
|
|
afterEach(() => {
|
|
sinon.restore();
|
|
});
|
|
|
|
it('collects issues', async () => {
|
|
const browser = getMockBrowser();
|
|
const page = (await browser.pages())[0];
|
|
const collector = new ConsoleCollector(browser, collect => {
|
|
return {
|
|
devtoolsAggregatedIssue: issue => {
|
|
collect(issue);
|
|
},
|
|
} as ListenerMap;
|
|
});
|
|
await collector.init([page]);
|
|
|
|
const issue2 = {
|
|
code: 'ElementAccessibilityIssue' as const,
|
|
details: {
|
|
elementAccessibilityIssueDetails: {
|
|
nodeId: 1,
|
|
elementAccessibilityIssueReason: 'DisallowedSelectChild',
|
|
hasDisallowedAttributes: true,
|
|
},
|
|
},
|
|
} satisfies Protocol.Audits.InspectorIssue;
|
|
|
|
page.emit('issue', issue);
|
|
page.emit('issue', issue2);
|
|
const data = collector.getData(page);
|
|
assert.equal(data.length, 2);
|
|
});
|
|
|
|
it('filters duplicated issues', async () => {
|
|
const browser = getMockBrowser();
|
|
const page = (await browser.pages())[0];
|
|
|
|
const collector = new ConsoleCollector(browser, collect => {
|
|
return {
|
|
devtoolsAggregatedIssue: issue => {
|
|
collect(issue);
|
|
},
|
|
} as ListenerMap;
|
|
});
|
|
await collector.init([page]);
|
|
|
|
page.emit('issue', issue);
|
|
page.emit('issue', issue);
|
|
const data = collector.getData(page);
|
|
assert.equal(data.length, 1);
|
|
const collectedIssue = data[0];
|
|
assert(collectedIssue instanceof DevTools.AggregatedIssue);
|
|
assert.equal(collectedIssue.code(), 'MixedContentIssue');
|
|
assert.equal(collectedIssue.getAggregatedIssuesCount(), 1);
|
|
});
|
|
|
|
it('emits UncaughtErrors for Runtime.exceptionThrown CDP events', async () => {
|
|
const browser = getMockBrowser();
|
|
const page = (await browser.pages())[0];
|
|
// @ts-expect-error internal API.
|
|
const cdpSession = page._client();
|
|
const onUncaughtErrorListener = sinon.spy();
|
|
const collector = new ConsoleCollector(browser, () => {
|
|
return {
|
|
uncaughtError: onUncaughtErrorListener,
|
|
} as ListenerMap;
|
|
});
|
|
await collector.init([page]);
|
|
|
|
cdpSession.emit('Runtime.exceptionThrown', {
|
|
exceptionDetails: {
|
|
exception: {description: 'SyntaxError: Expected {'},
|
|
text: 'Uncaught',
|
|
stackTrace: {callFrames: []},
|
|
},
|
|
});
|
|
|
|
sinon.assert.calledOnceWithMatch(
|
|
onUncaughtErrorListener,
|
|
sinon.match(e => {
|
|
return (
|
|
e.details.exception.description === 'SyntaxError: Expected {',
|
|
e.details.text === 'Uncaught',
|
|
e.details.stackTrace.callFrames.length === 0
|
|
);
|
|
}),
|
|
);
|
|
});
|
|
});
|