vitest-dev / vitest-dev/vitest

Cannot await `cdp.on()` rpc call to resolve

Open
#9,655 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feat: browser pending triage
Dominant language
TypeScript
Stars
17.1k
Forks
2k
Avg merge
1d 22h
Merged PRs (30d)
94

Description

Describe the bug

On client side the cdp.on() is a synchronous function that leaves the underlying rpc call floating. There is no way to wait for the call to resolve. This makes using the API racy on user side.

session.on("Fetch.requestPaused", async (event) => {
  console.log("Fetch.requestPaused", event.request.url);
  await session.send("Fetch.continueRequest", { requestId: event.requestId });
});

// This gets stuck
await session.send("Fetch.enable");

By adding explicit timeout after the event listener, this issue is resolved:

session.on("Fetch.requestPaused", async (event) => {});

+ await new Promise(resolve => setTimeout(resolve, 200))

- // This gets stuck
await session.send("Fetch.enable");

The rpc().trackCdpEvent() returns promise that's left floating:

https://github.com/vitest-dev/vitest/blob/7c103055cd2fa3b07039b0ab81a76ca90678c681/packages/browser/src/client/tester/state.ts#L73-L79

Tested quickly by returning the promise from on instead of whole cdp and it works. Though this would be breaking change, unless we make whole cdp a thennable.

- session.on("Fetch.requestPaused", async (event) => {
+ await session.on("Fetch.requestPaused", async (event) => {
  console.log("Fetch.requestPaused", event.request.url);
  await session.send("Fetch.continueRequest", { requestId: event.requestId });
});

// No longer stuck ✅ 
await session.send("Fetch.enable");
Reproduction

Add this in Vitest monorepo tests:

import { beforeAll, test } from "vitest";
import { cdp } from "vitest/browser";

beforeAll(async () => {
  const session = cdp();

  session.on("Fetch.requestPaused", async (event) => {
    console.log("Fetch.requestPaused", event.request.url);
    await session.send("Fetch.continueRequest", { requestId: event.requestId });
  });

  //   await new Promise((r) => setTimeout(r, 200));
  await session.send("Fetch.enable");
});

test("example test", async () => {
  await fetch("https://avatars.githubusercontent.com/u/95747107?s=200&v=4")
    .then((res) => res.blob())
    .then((blob) => console.log(blob.type, blob.size));
});
import { playwright } from "@vitest/browser-playwright";
import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {
    browser: {
      enabled: true,
      headless: true,
      provider: playwright(),
      instances: [{ browser: "chromium" }],
    },
  },
});
 RUN  v4.1.0-beta.3 /Users/ari/Git/examples

 ❯  chromium  test/example.test.ts (1 test | 1 failed) 15083ms
   × example test 15079ms

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

 FAIL   chromium  test/example.test.ts > example test
Error: Test timed out in 15000ms.
If this is a long-running test, pass a timeout value as the last argument or configure it globally with "testTimeout".

Failure screenshot:
  - test/__screenshots__/example.test.ts/example-test-1.png

 ❯ test/example.test.ts:16:0
     13|   await session.send("Fetch.enable");
     14| });
     15|
       | ^
     16| test("example test", async () => {
     17|   await fetch("https://avatars.githubusercontent.com/u/95747107?s=200&v=4")

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯


 Test Files  1 failed (1)
      Tests  1 failed (1)
   Start at  10:28:46
   Duration  15.87s (transform 0ms, setup 0ms, import 6ms, tests 15.08s, environment 0ms)

 ELIFECYCLE  Test failed. See above for more details.
System Info
System:
    OS: macOS 26.2
    CPU: (14) arm64 Apple M4 Pro
    Memory: 1.12 GB / 24.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.22.0 - /Users/ari/.nvm/versions/node/v22.22.0/bin/node
    npm: 10.9.4 - /Users/ari/.nvm/versions/node/v22.22.0/bin/npm
    pnpm: 10.29.2 - /Users/ari/.nvm/versions/node/v22.22.0/bin/pnpm
  Browsers:
    Safari: 26.2
  npmPackages:
    @vitest/browser-playwright: * => 4.1.0-beta.3 
    vitest: * => 4.1.0-beta.3
Used Package Manager

pnpm

Validations

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at packages/browser/src/client/tester/state.ts lines 73-79, where rpc().trackCdpEvent() is called, and reproduce the issue with the provided browser test using Fetch.requestPaused and Fetch.enable. Trace how cdp.on() exposes that call, then add a regression test showing that registration can be awaited without a timeout and that the Fetch flow completes.

Written by the indexing model from the issue text.

Assessment

Tech stack
playwright, typescript
Domain
api, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.