Use case
Network mocking is the single biggest Playwright capability that Browser library does not expose at all today: there is no keyword, no wrapper code, and no proto RPC for page.route/context.route. Users cannot:
- Stub an API endpoint to test the frontend in isolation from the backend (return fixture JSON for
/api/**).
- Test error paths deterministically (make
/api/orders return a 500 without breaking the real backend).
- Block unwanted requests (abort analytics beacons, ads, or all images to speed up suites).
- Modify outgoing requests (inject/override headers, redirect a request to a different URL, change method or post data).
There is currently no workaround inside the library — users who need mocking must run an external proxy or a separate mock server, which defeats the point of an integrated browser automation library. Nearly every real-world suite eventually needs at least one of these capabilities, which makes this the flagship feature of the network milestone.
Playwright's route API is callback-based, which does not fit the keyword model. The design decision (see docs/plan/playwright-feature-gap-plan.md) is to reshape it into declarative rules stored node-side, exposed as separate verb keywords (not a single Route keyword with an action enum). The library already uses this reshaping pattern in Add Locator Handler Custom.
Proposed keyword / arguments
All keywords take a matcher (URL glob pattern or regex) with the same semantics as Wait For Request / Wait For Response (reusing deserializeUrlOrPredicate). All rule-creating keywords default to scope=Context so mocks survive navigations and apply to popups/new pages; pass named-only scope=Page to narrow to the current page.
Mock Response matcher *, status=200 body=None json=None path=None content_type=None headers=None times=None scope=Context
Abort Requests matcher *, error_code=failed times=None scope=Context
Modify Requests matcher *, headers=None url=None method=None post_data=None scope=Context
Remove Route matcher
Remove All Routes
Mock Response fulfills matching requests. Exactly one of body, json, path (file with response body) provides the payload; json sets content-type: application/json automatically.
Abort Requests aborts matching requests with the given Playwright error code (failed, aborted, accessdenied, connectionrefused, internetdisconnected, ...).
Modify Requests continues matching requests with overrides (extra/overridden headers, rewritten URL, method, or post data).
times= limits how many times a rule fires before it is removed automatically (maps to the route option times).
- Optional stretch goal: named-only
base_on_server_response=True on Mock Response — fetch the real response first (route.fetch) and fulfill with the given fields merged on top, so users can mutate real responses (e.g. patch one JSON field).
*** Test Cases ***
Frontend Renders Empty User List
Mock Response **/api/users json={"users": []}
Go To ${APP_URL}
Get Text id=user-list-empty == No users found
Error Banner On Server Failure
Mock Response **/api/orders status=500 json={"error": "boom"} times=1
Click id=load-orders
Get Text css=.error-banner contains Something went wrong
Block Analytics For Whole Suite
Abort Requests /.*google-analytics.*/
Inject Auth Header Only On Current Page
Modify Requests **/api/** headers={"Authorization": "Bearer ${token}"} scope=Page
Cleanup
Remove Route **/api/users
Remove All Routes
Playwright API
Implementation notes
- New RPCs in
protobuf/playwright.proto for registering/removing route rules (rule spec message: matcher, action, action payload, times, scope).
- Node-side rule store in
node/playwright-wrapper: one real route() handler per registered matcher that executes the stored declarative action; matcher parsing reuses the existing deserializeUrlOrPredicate from the Wait For Request/Response path. Rule ordering semantics (last registered wins, Playwright-style) must be defined and documented.
- New Python keywords in
Browser/keywords/network.py, docs, inv build stub regen.
- New atest suite against the dynamic test app (fixture endpoints for fulfill/abort/continue,
times=, scope behavior across New Page/navigation).
- This is a full milestone on its own (see plan: Wave 2, "Network mocking").
Backwards compatibility
Purely additive: five new keywords, no changes to any existing keyword or return value. Existing suites are unaffected unless they call the new keywords.
Use case
Network mocking is the single biggest Playwright capability that Browser library does not expose at all today: there is no keyword, no wrapper code, and no proto RPC for
page.route/context.route. Users cannot:/api/**)./api/ordersreturn a 500 without breaking the real backend).There is currently no workaround inside the library — users who need mocking must run an external proxy or a separate mock server, which defeats the point of an integrated browser automation library. Nearly every real-world suite eventually needs at least one of these capabilities, which makes this the flagship feature of the network milestone.
Playwright's route API is callback-based, which does not fit the keyword model. The design decision (see
docs/plan/playwright-feature-gap-plan.md) is to reshape it into declarative rules stored node-side, exposed as separate verb keywords (not a singleRoutekeyword with an action enum). The library already uses this reshaping pattern inAdd Locator Handler Custom.Proposed keyword / arguments
All keywords take a
matcher(URL glob pattern or regex) with the same semantics asWait For Request/Wait For Response(reusingdeserializeUrlOrPredicate). All rule-creating keywords default toscope=Contextso mocks survive navigations and apply to popups/new pages; pass named-onlyscope=Pageto narrow to the current page.Mock Responsefulfills matching requests. Exactly one ofbody,json,path(file with response body) provides the payload;jsonsetscontent-type: application/jsonautomatically.Abort Requestsaborts matching requests with the given Playwright error code (failed,aborted,accessdenied,connectionrefused,internetdisconnected, ...).Modify Requestscontinues matching requests with overrides (extra/overridden headers, rewritten URL, method, or post data).times=limits how many times a rule fires before it is removed automatically (maps to therouteoptiontimes).base_on_server_response=TrueonMock Response— fetch the real response first (route.fetch) and fulfill with the given fields merged on top, so users can mutate real responses (e.g. patch one JSON field).Playwright API
timesoption)Mock ResponseAbort RequestsModify Requestsbase_on_server_responsestretchRemove Route/Remove All RoutesImplementation notes
protobuf/playwright.protofor registering/removing route rules (rule spec message: matcher, action, action payload, times, scope).node/playwright-wrapper: one realroute()handler per registered matcher that executes the stored declarative action; matcher parsing reuses the existingdeserializeUrlOrPredicatefrom the Wait For Request/Response path. Rule ordering semantics (last registered wins, Playwright-style) must be defined and documented.Browser/keywords/network.py, docs,inv buildstub regen.times=, scope behavior acrossNew Page/navigation).Backwards compatibility
Purely additive: five new keywords, no changes to any existing keyword or return value. Existing suites are unaffected unless they call the new keywords.