Repository navigation
Conversation
Proof-of-concept for issue ChromeDevTools#2639 (optimize tests). Adds two files: tests/testMocks.ts Sinon-based factory helpers for the three objects that every tool-handler test depends on: createMockMcpPage, createMockMcpContext, and createMockMcpResponse. The McpPage stub's emulate() mirrors the real McpPage.emulate() clear/set semantics without touching a real browser. tests/tools/emulation.unit.test.ts 27 unit tests for the emulate tool handler covering all emulation axes: networkConditions, cpuThrottlingRate, geolocation, userAgent, colorScheme, viewport, and extraHttpHeaders (set and clear paths). No real browser is required; the suite completes in ~100 ms vs several seconds for the existing real-browser suite.
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
…s, snapshot tools Extends the proof-of-concept from the first commit to cover four more tool handlers — all without a real browser. tests/testMocks.ts Extended createMockMcpResponse with stubs for all response methods used by tool handlers: setIncludeConsoleData, attachConsoleMessage, setIncludeNetworkRequests, attachNetworkRequest, setIncludePages, setListThirdPartyDeveloperTools, setListWebMcpTools, includeSnapshot, attachDevToolsData. Extended createMockMcpContext with getPageById, selectPage, closePage, newPage stubs. tests/tools/console.unit.test.ts (8 tests) listConsoleMessages: verifies setIncludeConsoleData is called with correct value and all option fields (pageSize, pageIdx, types, includeStackTraces, serviceWorkerId, includePreservedMessages). getConsoleMessage: verifies attachConsoleMessage is called with the correct msgid. tests/tools/network.unit.test.ts (6 tests) listNetworkRequests: verifies setIncludeNetworkRequests and all option fields (pageSize, pageIdx, resourceTypes, includePreservedRequests). getNetworkRequest: verifies attachNetworkRequest with reqid, requestFilePath, responseFilePath. tests/tools/pages.unit.test.ts (8 tests) listPages: verifies setIncludePages, setListThirdPartyDeveloperTools, setListWebMcpTools. selectPage: verifies getPageById lookup, selectPage call, setIncludePages. closePage: verifies closePage call, setIncludePages, and CLOSE_PAGE_ERROR handling. tests/tools/snapshot.unit.test.ts (5 tests) takeSnapshot: verifies includeSnapshot is called with verbose default, verbose override, filePath pass-through.
|
Updated this PR with a second commit that extends the proof-of-concept to cover four more tool handlers. Now includes:
67/67 tests pass, no browser required, ~200ms total. Formatter tests were audited and are already clean — no real Let me know if you'd like any adjustments to the pattern before I continue with item (3). |
…files Per @OrKoN feedback on ChromeDevTools#2641: remove separate *.unit.test.ts files and instead migrate tests directly inside the existing test files. tests/testMocks.ts Fully implements ContextPage, Context and Response interfaces via sinon stubs so mock objects satisfy the handler signatures without any casts. tests/tools/emulation.test.ts Converted the 'network' and 'cpu' describe blocks from withMcpContext to createMockMcpPage/createMockMcpContext/createMockMcpResponse. The 'Slow 11G' predefined-options test is kept as a real-browser test since it exercises McpPage internal validation logic.
Addresses two review comments from @OrKoN on ChromeDevTools#2641: 1. Use sinon.createStubInstance(McpPage/McpContext/McpResponse) instead of hand-rolled mock interfaces. The stubs are derived directly from the real class prototypes so no shadow type definitions are needed. 2. Remove the mock implementation of emulate(). Tool handler tests now assert that page.emulate() was called with the correct arguments rather than simulating emulate()'s internal clear/set logic. The actual emulate() behaviour (clear/set semantics, predefined conditions validation) is covered by new tests in McpPage.test.ts which run against the real McpPage class. tests/testMocks.ts Reduced to three one-liner factory functions using createStubInstance. tests/tools/emulation.test.ts network/cpu mock tests now assert on page.emulate.firstCall.args[0] instead of page.networkConditions / page.cpuThrottlingRate. tests/McpPage.test.ts New McpPage.emulate() describe block with 9 real-browser tests covering networkConditions (set/clear/unknown), cpuThrottlingRate (set/reset), userAgent (set/clear), colorScheme (set/reset via auto).
Per @OrKoN review: drop withMcpContext from McpPage.emulate() tests. Instead, construct a real McpPage wrapping a fake Puppeteer page built on top of the existing getMockPage() helper from utils.ts, extended with the specific Puppeteer methods that emulate() calls internally: emulateNetworkConditions, emulateCPUThrottling, setGeolocation, setUserAgent, emulateMediaFeatures, setViewport, setExtraHTTPHeaders, setDefaultTimeout, setDefaultNavigationTimeout. This exercises the real emulate() code path without starting a browser.
Per @OrKoN review: - Rename tests/testMocks.ts to tests/mocks.ts (already in tests folder) - Move getMockPage() from tests/utils.ts into tests/mocks.ts - tests/utils.ts re-exports getMockPage from mocks.ts for backwards compat - Update emulation.test.ts and McpPage.test.ts imports accordingly
|
Hi @OrKoN Renamed testMocks.ts → mocks.ts Regarding createStubInstance for getMockPage() — Page is an abstract class in Puppeteer, so createStubInstance can't be used directly on it. Kept the existing satisfies Page pattern but moved it into mocks.ts as requested. Happy to explore a different approach if you have one in mind. |
… comments Addresses three review comments from @OrKoN: Thread 1 — McpPage.test.ts emulate() tests now assert on the underlying Puppeteer method calls (emulateNetworkConditions, emulateCPUThrottling, setUserAgent, emulateMediaFeatures) via sinon.assert.calledWith, not just on McpPage's internal emulationSettings state. Thread 2 — Removed redundant section divider comments from mocks.ts. Thread 3 — Added a JSDoc note to getMockPage() explaining why createStubInstance cannot be used: Puppeteer's Page is declared as 'abstract class', which sinon.createStubInstance() cannot stub.
- Add createHandlerMocks() to mocks.ts returning {page, context, response}
so tests don't repeat the same three setup lines
- Use createHandlerMocks() across all network/cpu tests in emulation.test.ts
- Rename createFakePuppeteerPage -> createMockPuppeteerPage and
fakePage -> pptrPage in McpPage.test.ts per @OrKoN review
…nstance Per @OrKoN: getMockPage should be a generic stub not tuned for emulation. - mocks.ts: rename getMockPage -> createMockPuppeteerPage, replace the hand-rolled object literal with sinon.createStubInstance(Page) using puppeteer-core's abstract Page class - utils.ts: update import and re-export to createMockPuppeteerPage - McpPage.test.ts: remove the local createMockPuppeteerPage wrapper, import the generic stub from mocks.ts, and configure the emulation- specific methods (emulateNetworkConditions, emulateCPUThrottling, etc.) inline in createMcpPage() via Object.assign since those methods live on CdpPage (concrete subclass) rather than the abstract Page class
|
hi @OrKoN Clean rebuild: 0 build errors This is ready for another look whenever you get a chance. |
|
in #2660 I updated agents.md to capture the learnings from this PR's review. As the next step, we could migrate tests/tools/emulation.test.ts off the withMcpContext helper while ensuring appropriate test coverage on the McpPage / McpContext level. |
Head branch was pushed to by a user without write access
775ad21 to
da16207
Compare
|
@maheshsingh20 please do not rebase or merge the main branch into this branch unnecessarily. |
|
Hi @OrKoN, |
086299a
|
Thanks for merging, @OrKoN! I saw the updates in #2660 and AGENTS.md — that's super helpful. Should I go ahead and open a new PR to migrate the remaining withMcpContext tests in tests/tools/emulation.test.ts to unit tests and add the corresponding coverage in McpPage / McpContext? Or is there another area/issue you'd prefer to tackle next? |
|
Yeah let's finish emulation.test.ts and then go over other tool tests on by one. |
…eDevTools#2665) Relates to ChromeDevTools#2639. Follow-up to ChromeDevTools#2641 and feedback in ChromeDevTools#2660 (`AGENTS.md`). ### Summary of Changes 1. **`tests/tools/emulation.test.ts`**: - Completely migrated off `withMcpContext`, removing all real-browser launches, `serverHooks`, and HTTP fixtures. - All tool handler test suites (`geolocation`, `viewport`, `userAgent`, `extraHttpHeaders`, `colorScheme`, `network`, `cpu`) now use `createHandlerMocks()` from `tests/mocks.ts` and verify `page.emulate()` is invoked with exact expected arguments. 2. **`tests/McpPage.test.ts`**: - Added unit test coverage for `McpPage.emulate()` using `createMockPuppeteerPage()`: - Offline network throttling settings and network blocking guard. - Secondary DevTools session CPU throttling delegation. - Geolocation set/clear behavior. - Viewport set/clear with default parameter merging. - Extra HTTP headers set/clear behavior. ### Verification - `npm run check-format`: Passed (clean ESLint + Prettier) - `npm run build`: Compiled with exit code 0 - `node scripts/test.js tests/tools/emulation.test.ts`: 50/50 tests passed - `node scripts/test.js tests/McpPage.test.ts`: 32/32 tests passed
…meDevTools#2683) This PR migrates `tests/tools/screencast.test.ts` from real-browser tests (`withMcpContext`) to mock-based unit tests using the established Sinon mock infrastructure. ### Summary - References ChromeDevTools#2639 (item 1) - Follow-up building on ChromeDevTools#2641 and ChromeDevTools#2665 - Rewrites `tests/tools/screencast.test.ts` to use `createHandlerMocks()` instead of `withMcpContext()`, eliminating real browser launches. - Adds `createMockScreenRecorder()` helper and wires `getScreenRecorder`/`setScreenRecorder` and `ensureExtension` in `tests/mocks.ts`. - Re-exports `ScreenRecorder` from `src/third_party/index.ts` to comply with internal import boundaries.
… tests to McpPage (ChromeDevTools#2698) This PR migrates tests in `tests/tools/snapshot.test.ts` to mock-based unit tests using the established Sinon mock infrastructure and relocates the real-browser integration tests to `tests/McpPage.test.ts`. ### Summary - References ChromeDevTools#2639 (item 1). - Follow-up building on ChromeDevTools#2641, ChromeDevTools#2665, and ChromeDevTools#2683. - Relocated the 6 real-browser `waitFor` integration tests to a dedicated `waitForTextOnPage()` suite in `tests/McpPage.test.ts` to directly cover the `mcpPage.waitForTextOnPage` method. - Converted all tool handler tests in `tests/tools/snapshot.test.ts` (`take_snapshot` and `wait_for`) to mock unit tests using `createHandlerMocks()`, completely removing `withMcpContext` from the file. - Asserted exact method calls on `response` and `page` using `sinon.assert.calledOnceWithExactly()`. - Maintained `afterEach(() => sinon.restore())` cleanup per `AGENTS.md`. ### Verification - `npm run test tests/tools/snapshot.test.ts` (4 passed, 0 failed, exit code: 0) - `npm run test tests/McpPage.test.ts` (39 passed, 0 failed, exit code: 0) - `npm run check-format` (exit code: 0) - `npm run docs:generate` (exit code: 0) - `git status` (clean working tree, exit code: 0)
This PR migrates the mock-eligible test in `tests/tools/extensions.test.ts` from a real-browser test (`withMcpContext`) to a mock-based unit test using the established Sinon mock infrastructure. ### Architectural Principle (Category 1 vs. Category 2 Split) This PR continues issue ChromeDevTools#2639 (item 1), applying the core architectural separation of concerns established across ChromeDevTools#2641, ChromeDevTools#2665, ChromeDevTools#2683, and ChromeDevTools#2698: - **Category 1 (Handler wiring & response verification -> Mock unit tests)**: Tests that only verify tool parameter parsing and response manipulation should not launch real browsers. Launching Chrome just to assert that a tool invoked `response.setListExtensions()` introduces unnecessary startup latency and lifecycle flakiness without providing real integration coverage. These are converted to deterministic unit tests using `createHandlerMocks()`. - **Category 2 (Genuine browser, extension, and protocol behavior -> Retained real-browser tests)**: Tests that depend on genuine browser mechanics must remain in `withMcpContext`. Mocking them would require simulating Chrome's internal extension loader, V8 script execution, or Puppeteer's target lifecycle inside mocks, creating brittle and artificial tests that do not validate real behavior. ### Summary of Changes - **Converted to mocks (Category 1)**: - `lists installed extensions`: Converted to `createHandlerMocks()`. Asserts `response.setListExtensions` was invoked with `sinon.assert.calledOnceWithExactly(response.setListExtensions)`. - **Intentionally retained as real-browser tests (Category 2)**: - `installs and uninstalls an extension and verifies it in chrome://extensions`: Genuinely installs an unpacked extension into Chrome and verifies real extension lifecycle and management. - `reloads an extension`: Verifies Chrome's live extension reload mechanics and registry reappearance. - `triggers an extension action`: Validates asynchronous Puppeteer `Target` creation when an extension action fires. - `verifies that content script console logs are received`: Tests real content script execution in a live navigated page and CDP console capture. ### Verification - `powershell -Command "Remove-Item -Recurse -Force build -ErrorAction SilentlyContinue"; npm run build` (exit code: 0) - `node scripts/test.js tests/tools/extensions.test.ts` (6 passed, 0 failed, exit code: 0) - `npm run check-format` (exit code: 0) - `npm run docs:generate` (exit code: 0) - `git status` (clean working tree, exit code: 0)
test: mock-based unit tests for emulation, no real browser needed
Relates to #2639.
Summary
Adds tests/mocks.ts — sinon createStubInstance-based factories for McpPage, McpContext, McpResponse, and Puppeteer's Page (via the concrete CdpPage subclass)
createHandlerMocks() helper returns {page, context, response} together for handler tests
Converts the network and cpu describe blocks in emulation.test.ts from real-browser (withMcpContext) to the sinon mocks
Converts emulate() behavior tests in McpPage.test.ts to use a real McpPage instance wrapping a mocked Puppeteer page (createMockPuppeteerPage()), instead of a real browser
No new test files — all changes are in-place edits to existing test files, per review feedback
Remaining emulate()-related tests that need real browser behavior (predefined-condition validation, secondary DevTools session) are intentionally left as real-browser tests
Verification
npm run format
npm run test