MarketSquare / MarketSquare/robotframework-browser
Add network request mocking keyword family: `Mock Response`, `Abort Requests`, `Modify Requests`, `Remove Route`, `Remove All Routes`
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 655
- Forks
- 147
- Avg merge
- 5h 27m
- Merged PRs (30d)
- 59
Description
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/ordersreturn 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 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).- Optional stretch goal: named-only
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).
*** 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
- browserContext.route / page.route (incl. the
timesoption) - route.fulfill —
Mock Response - route.abort —
Abort Requests - route.continue —
Modify Requests - route.fetch — optional
base_on_server_responsestretch - browserContext.unroute / browserContext.unrouteAll —
Remove Route/Remove All Routes
Implementation notes
- New RPCs in
protobuf/playwright.protofor registering/removing route rules (rule spec message: matcher, action, action payload, times, scope). - Node-side rule store in
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. - New Python keywords in
Browser/keywords/network.py, docs,inv buildstub regen. - New atest suite against the dynamic test app (fixture endpoints for fulfill/abort/continue,
times=, scope behavior acrossNew 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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with docs/plan/playwright-feature-gap-plan.md and the existing Add Locator Handler Custom implementation to understand the declarative keyword pattern. Then inspect protobuf/playwright.proto, node/playwright-wrapper, and Browser/keywords/network.py, followed by the dynamic test app and atest suite. Done means the five route keywords, RPCs, scope and times behavior, documentation, regenerated stubs, and end-to-end tests are implemented.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- playwright, python
- Domain
- testing-qa
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100