Skip to content

test(e2e): keep nock suites off the real network - #525

Open
arabold wants to merge 1 commit into
mainfrom
test/nock-network-isolation
Open

arabold wants to merge 1 commit into
mainfrom
test/nock-network-isolation

Conversation

@arabold

@arabold arabold commented Oct 5, 2026

Copy link
Copy Markdown
Owner

Summary

The nock-based end-to-end suites could send a request to the real network, and they printed misleading MSW warnings for every request. This change makes nock the only thing that answers requests for each suite's test hosts.

nock 14 and the global MSW server (test/setup-e2e.ts) both use @mswjs/interceptors, and they share one interceptor instance, so every request reaches both of them. nock is applied when the test file imports it, so its listener always runs first and answers. MSW's listener runs after that and warns "intercepted a request without a matching request handler", even though nock already answered. When nock had no mock registered for a host at all, it let the request go, MSW passed it through, and it reached real DNS.

Changes

  • New helper mockOriginsWithNock() in test/nock-helpers.ts. It:
    • turns off real connections in nock (loopback is still allowed), so an unmocked request fails inside nock within a few milliseconds
    • registers an MSW passthrough handler for each origin, so MSW leaves these requests to nock whatever the listener order, and stops printing warnings
  • All five nock suites call it from beforeEach: unprocessable-content, scrape-progress, empty-page-refresh, markdown-identity and refresh-pipeline (including its allowlist hosts).
  • The llms.txt comments said unmocked probes wait on DNS. They actually fail as nock errors that the fetcher retries, so the comments now say that.
  • AGENTS.md has a short note for people writing new nock suites.

About the CI timeout in run 37244567007

This does not fix the 60-second timeout in "does not let an asset-heavy site trip the failure threshold", and I don't want this pull request to suggest it does. The MSW warnings in that log look like MSW took the requests, but they show up in passing runs too: 28 per run of this suite with --reporter=verbose. A request that really went to the network would have failed at once with ENOTFOUND, which the fetcher does not retry, and the crawl would have moved on to /two. Instead the log stops right after nock answered /one. The next step for that page is the Playwright render, because the scrape mode defaults to auto. Run 35456512541 (refresh-pipeline-e2e) stalled in the same way, right after /. I could not reproduce the stall locally, so the cause is still open.

Testing

  • npx vitest run test/unprocessable-content-e2e.test.ts: 20 runs in a row, all passed
  • The five nock suites: 44 tests pass, with zero MSW warnings in verbose output
  • A scratch test (not committed): without the helper, a request to an unmocked host reached real DNS (ENOTFOUND); with it, the request failed in nock in 2 to 3 ms, mocked requests still worked, and loopback was still reachable
  • npm test: 144 files, 2325 tests pass
  • rm -f .tsbuildinfo && npm run typecheck: clean

nock 14 and the global MSW server share one @mswjs/interceptors instance, so
every request reaches both listeners. nock applies on import and answers
first; MSW then warns about a request nock already served. A request nock has
no interceptor for at all fell through MSW's warn-and-passthrough to real DNS.

Add mockOriginsWithNock() and call it from every nock suite. It disables nock
net connect (loopback excepted), so an unmocked request fails inside nock in
milliseconds, and registers an MSW passthrough handler per origin, so MSW
defers to nock whichever listener runs first and stops printing warnings.

Correct the llms.txt comments: unmocked probes fail as nock errors and are
retried, they do not wait on DNS.
Copilot AI balanced review requested due to automatic review settings October 5, 2026 13:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The global Nock connection restriction is not restored during suite teardown and can leak into later test files.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
What changed in this PR

Adds shared network isolation for Nock-based E2E suites, preventing accidental external requests and suppressing misleading MSW warnings.

Changes:

  • Adds mockOriginsWithNock() for Nock isolation and MSW passthrough.
  • Applies the helper across five E2E suites.
  • Documents the testing convention and corrects retry comments.
File Description
test/​nock-helpers.ts Adds shared Nock/MSW setup.
test/​unprocessable-content-e2e.test.ts Enables isolated Nock networking.
test/​scrape-progress-e2e.test.ts Enables isolated Nock networking.
test/​refresh-pipeline-e2e.test.ts Covers standard and allowlist origins.
test/​markdown-identity-e2e.test.ts Enables isolated Nock networking.
test/​empty-page-refresh-e2e.test.ts Enables isolated Nock networking.
AGENTS.md Documents the Nock suite convention.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread test/nock-helpers.ts
Comment on lines +36 to +37
nock.disableNetConnect();
nock.enableNetConnect(LOOPBACK_HOST);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants