To mock routes in playwright, we can do a page.route, and that page.route will apply for every method of that route. That means that within page.route
, you need to specify
test("Run a test", async ({ page }) => {
page.route('endpoint', route => {
switch (route.request().method()) {
case 'GET':
await route.fullfill(<get_response>)
case 'POST':
await route.fullfill(<post>)
defaut:
await route.continue()
}
})
})
If I need to then use some other response for another case, I can call page.route
again for this route. But let's say I only need to change the POST response. If I were to do this:
test("Run a test", async ({ page }) => {
page.route('endpoint', route => {
switch (route.request().method()) {
case 'GET':
await route.fullfill(<get_response>)
case 'POST':
await route.fullfill(<post_response>)
defaut:
await route.continue()
}
})
// perform some actions
page.route('endpoint', () => {
switch (route.request().method()) {
case 'POST':
await route.fullfill(<different_post_response>)
defaut:
await route.continue()
}
})
})
In this case, all methods of the route
ed endpoint are overwritten, and a GET
call to that endpoint would fall through the route.continue()
.
Is there a more precise way to mock just a single route method in playwright, without overwriting mocks for other methods of the same endpoint?
(An example would be like in cypress, where a user can cy.intercept({ url: 'url', method: METHOD })
, which can be called multiple times with various arguments, but because the method is part of the call option params, there is no interference between methods.)
You can use route.fallback()
to fall back to the previous handler. This lets you set a default handler for all methods, then override it for one method. In your case,
// perform some actions
page.route('endpoint', () => {
switch (route.request().method()) {
case 'POST':
await route.fullfill(<different_post_response>)
defaut:
await route.fallback() // <-- handle any non-POST methods
}
})
You can also use an object with request method handler functions, then set the functions to whatever you want them to be on demand:
const endpointHandlers = {
GET: route => route.fullfill({body: "foo"}),
POST: route => route.fullfill({body: "bar"}),
// ...
};
page.route("endpoint", route => {
const handler = endpointHandlers[route.request.method()];
return handler ? handler(route) : route.continue();
});
// perform some actions
// change one handler on demand:
endpointHandlers.GET = route => route.fullfill({body: "baz"});
For more advanced cases where you need to handle a series of requests, handlers can be arrays of functions acting as queues that are shifted on every request.