Skip to content

feat(test-runner): add httpCache config option#41687

Open
pavelfeldman wants to merge 1 commit into
microsoft:mainfrom
pavelfeldman:http-cache-proxy
Open

feat(test-runner): add httpCache config option#41687
pavelfeldman wants to merge 1 commit into
microsoft:mainfrom
pavelfeldman:http-cache-proxy

Conversation

@pavelfeldman

@pavelfeldman pavelfeldman commented Jul 8, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds a top-level httpCache: { dir, match } test config option. When set, the runner starts a single caching MITM proxy and routes every browser through it: matching responses are recorded to dir on the first run and replayed from disk on later runs.
  • One proxy owns the cache for the whole run, so all workers share it and concurrent identical misses coalesce into one upstream fetch. match (glob/RegExp) selects which request URLs are cached; https is intercepted with a self-signed cert.

Fixes: #22865

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@Skn0tt Skn0tt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm not seeing typical caching headers like Vary or Accept-Encoding be mentioned, which seems fishy. Am I misunderstanding something?

@pavelfeldman

Copy link
Copy Markdown
Member Author

I'm not seeing typical caching headers like Vary or Accept-Encoding be mentioned, which seems fishy. Am I misunderstanding something?

This is intentional, typical caching headers in dev / testing flow are not aggressive enough. We might want to have some finer grained controls for that though.

Comment thread packages/playwright/src/plugins/cacheProxyPlugin.ts
hasTouch: [({ contextOptions }, use) => use(contextOptions.hasTouch ?? false), { option: true, box: true }],
httpCredentials: [({ contextOptions }, use) => use(contextOptions.httpCredentials), { option: true, box: true }],
ignoreHTTPSErrors: [({ contextOptions }, use) => use(contextOptions.ignoreHTTPSErrors ?? false), { option: true, box: true }],
ignoreHTTPSErrors: [({ contextOptions }, use) => use(process.env.PLAYWRIGHT_TEST_CACHE_PROXY ? true : (contextOptions.ignoreHTTPSErrors ?? false)), { option: true, box: true }],

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

There is a way to start Chromium so that it trusts our own root certificate, so that we can sign a certificate for any domain dynamically.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

What about the other browsers?

these; consumers are responsible for slicing and interpreting them with
any argument-parsing library.

## property: FullConfig.httpCache

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Who is reading this one? Let's not add to the FullConfig just yet.

@pavelfeldman pavelfeldman Jul 9, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Overall, fine with not listing. But I have a general distaste towards the almost identical interfaces, so I'd prefer to keep it.

Comment thread docs/src/test-api/class-testconfig.md
Comment thread packages/playwright/src/plugins/cacheProxy/cache.ts Outdated
res.end();
return;
}
if (response.status >= 200 && response.status <= 299)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why only 2xx?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is a subject for discussion, what would you like it to cache?

return;
}
if (response.status >= 200 && response.status <= 299)
await this._cache.set(key, url, response).catch(() => {});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Shouldn't we respect things like Expires, Age, Cache-Control, etc?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I don't this we should respect those - documentes and subresources are delivered as no-cache in the dev / testing environments.

Records browser responses to disk and replays them on later runs. When
`httpCache: { dir, match }` is set, the runner starts a single caching
MITM proxy and routes all browsers through it. GET/2xx responses are
stored verbatim (raw bytes + headers) and matched by an optional URL
glob/regex; https is intercepted with a self-signed cert. One proxy owns
the cache for the whole run, so all workers share it and concurrent
identical misses coalesce into one upstream fetch.
@github-actions

Copy link
Copy Markdown
Contributor

Test results for "MCP"

7735 passed, 1248 skipped


Merge workflow run.

@github-actions

Copy link
Copy Markdown
Contributor

Test results for "tests 1"

3 flaky ⚠️ [chromium-library] › library/video.spec.ts:717 › screencast › should work with video+trace `@chromium-ubuntu-22.04-arm-node20`
⚠️ [chromium-library] › library/inspector/recorder-api.spec.ts:120 › should type `@realtime-time-library-chromium-linux`
⚠️ [firefox-library] › library/heap.spec.ts:223 › should not leak workers `@firefox-ubuntu-22.04-node20`

49549 passed, 1161 skipped


Merge workflow run.

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.

[Feature]is it possible to reuse static resouces cache of previous test run ?

3 participants