feat(api): introduce route.fetch and route.fulfill(json) (#19184)
This commit is contained in:
parent
878401ff2b
commit
f0e8d8f074
|
|
@ -74,7 +74,7 @@ async def handle(route, request):
|
|||
"bar": None # remove "bar" header
|
||||
}
|
||||
await route.continue_(headers=headers)
|
||||
}
|
||||
|
||||
await page.route("**/*", handle)
|
||||
```
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ def handle(route, request):
|
|||
"bar": None # remove "bar" header
|
||||
}
|
||||
route.continue_(headers=headers)
|
||||
}
|
||||
|
||||
page.route("**/*", handle)
|
||||
```
|
||||
|
||||
|
|
@ -110,21 +110,21 @@ If set changes the request URL. New URL must have same protocol as original one.
|
|||
* since: v1.8
|
||||
- `method` <[string]>
|
||||
|
||||
If set changes the request method (e.g. GET or POST)
|
||||
If set changes the request method (e.g. GET or POST).
|
||||
|
||||
### option: Route.continue.postData
|
||||
* since: v1.8
|
||||
* langs: js, python, java
|
||||
- `postData` <[string]|[Buffer]>
|
||||
|
||||
If set changes the post data of request
|
||||
If set changes the post data of request.
|
||||
|
||||
### option: Route.continue.postData
|
||||
* since: v1.8
|
||||
* langs: csharp
|
||||
- `postData` <[Buffer]>
|
||||
|
||||
If set changes the post data of request
|
||||
If set changes the post data of request.
|
||||
|
||||
### option: Route.continue.headers
|
||||
* since: v1.8
|
||||
|
|
@ -349,7 +349,7 @@ async def handle(route, request):
|
|||
"bar": None # remove "bar" header
|
||||
}
|
||||
await route.fallback(headers=headers)
|
||||
}
|
||||
|
||||
await page.route("**/*", handle)
|
||||
```
|
||||
|
||||
|
|
@ -362,7 +362,7 @@ def handle(route, request):
|
|||
"bar": None # remove "bar" header
|
||||
}
|
||||
route.fallback(headers=headers)
|
||||
}
|
||||
|
||||
page.route("**/*", handle)
|
||||
```
|
||||
|
||||
|
|
@ -386,21 +386,21 @@ affect the route matching, all the routes are matched using the original request
|
|||
* since: v1.23
|
||||
- `method` <[string]>
|
||||
|
||||
If set changes the request method (e.g. GET or POST)
|
||||
If set changes the request method (e.g. GET or POST).
|
||||
|
||||
### option: Route.fallback.postData
|
||||
* since: v1.23
|
||||
* langs: js, python, java
|
||||
- `postData` <[string]|[Buffer]>
|
||||
|
||||
If set changes the post data of request
|
||||
If set changes the post data of request.
|
||||
|
||||
### option: Route.fallback.postData
|
||||
* since: v1.23
|
||||
* langs: csharp
|
||||
- `postData` <[Buffer]>
|
||||
|
||||
If set changes the post data of request
|
||||
If set changes the post data of request.
|
||||
|
||||
### option: Route.fallback.headers
|
||||
* since: v1.23
|
||||
|
|
@ -408,6 +408,93 @@ If set changes the post data of request
|
|||
|
||||
If set changes the request HTTP headers. Header values will be converted to a string.
|
||||
|
||||
## async method: Route.fetch
|
||||
* since: v1.29
|
||||
- returns: <[APIResponse]>
|
||||
|
||||
Performs the request and fetches result without fulfilling it, so that the response
|
||||
could be modified and then fulfilled.
|
||||
|
||||
**Usage**
|
||||
|
||||
```js
|
||||
await page.route('https://dog.ceo/api/breeds/list/all', async route => {
|
||||
const response = await route.fetch();
|
||||
const json = await response.json();
|
||||
json.message['big_red_dog'] = [];
|
||||
await route.fulfill({ response, json });
|
||||
});
|
||||
```
|
||||
|
||||
```java
|
||||
page.route("https://dog.ceo/api/breeds/list/all", route -> {
|
||||
APIResponse response = route.fetch();
|
||||
JsonObject json = new Gson().fromJson(response.text(), JsonObject.class);
|
||||
json.set("big_red_dog", new JsonArray());
|
||||
route.fulfill(new Route.FulfillOptions()
|
||||
.setResponse(response)
|
||||
.setBody(json.toString()));
|
||||
});
|
||||
```
|
||||
|
||||
```python async
|
||||
async def handle(route):
|
||||
response = await route.fulfill()
|
||||
json = await response.json()
|
||||
json["big_red_dog"] = []
|
||||
await route.fulfill(response=response, json=json)
|
||||
|
||||
await page.route("https://dog.ceo/api/breeds/list/all", handle)
|
||||
```
|
||||
|
||||
```python sync
|
||||
def handle(route):
|
||||
response = route.fulfill()
|
||||
json = response.json()
|
||||
json["big_red_dog"] = []
|
||||
route.fulfill(response=response, json=json)
|
||||
|
||||
page.route("https://dog.ceo/api/breeds/list/all", handle)
|
||||
```
|
||||
|
||||
```csharp
|
||||
await page.RouteAsync("https://dog.ceo/api/breeds/list/all", async route =>
|
||||
{
|
||||
var response = await route.FetchAsync();
|
||||
dynamic json = await response.JsonAsync();
|
||||
json.big_red_dog = new string[] {};
|
||||
await route.FulfillAsync(new() { Response = response, Json = json });
|
||||
});
|
||||
```
|
||||
|
||||
### option: Route.fetch.url
|
||||
* since: v1.29
|
||||
- `url` <[string]>
|
||||
|
||||
If set changes the request URL. New URL must have same protocol as original one.
|
||||
|
||||
### option: Route.fetch.method
|
||||
* since: v1.29
|
||||
- `method` <[string]>
|
||||
|
||||
If set changes the request method (e.g. GET or POST).
|
||||
|
||||
### option: Route.fetch.postData = %%-js-python-csharp-fetch-option-data-%%
|
||||
* since: v1.29
|
||||
|
||||
### option: Route.fetch.data
|
||||
* since: v1.29
|
||||
* langs: csharp
|
||||
- `postData` <[Buffer]>
|
||||
|
||||
If set changes the post data of request.
|
||||
|
||||
### option: Route.fetch.headers
|
||||
* since: v1.29
|
||||
- `headers` <[Object]<[string], [string]>>
|
||||
|
||||
If set changes the request HTTP headers. Header values will be converted to a string.
|
||||
|
||||
## async method: Route.fulfill
|
||||
* since: v1.8
|
||||
|
||||
|
|
@ -451,10 +538,12 @@ page.route("**/*", lambda route: route.fulfill(
|
|||
```
|
||||
|
||||
```csharp
|
||||
await page.RouteAsync("**/*", route => route.FulfillAsync(
|
||||
status: 404,
|
||||
contentType: "text/plain",
|
||||
body: "Not Found!"));
|
||||
await page.RouteAsync("**/*", route => route.FulfillAsync(new ()
|
||||
{
|
||||
Status = 404,
|
||||
ContentType = "text/plain",
|
||||
Body = "Not Found!")
|
||||
});
|
||||
```
|
||||
|
||||
An example of serving static file:
|
||||
|
|
@ -477,7 +566,7 @@ page.route("**/xhr_endpoint", lambda route: route.fulfill(path="mock_data.json")
|
|||
```
|
||||
|
||||
```csharp
|
||||
await page.RouteAsync("**/xhr_endpoint", route => route.FulfillAsync(new RouteFulfillOptions { Path = "mock_data.json" }));
|
||||
await page.RouteAsync("**/xhr_endpoint", route => route.FulfillAsync(new() { Path = "mock_data.json" }));
|
||||
```
|
||||
|
||||
### option: Route.fulfill.status
|
||||
|
|
@ -519,6 +608,57 @@ Optional response body as text.
|
|||
|
||||
Optional response body as raw bytes.
|
||||
|
||||
### option: Route.fulfill.json
|
||||
* since: v1.29
|
||||
* langs: js, python
|
||||
- `json` <[Serializable]>
|
||||
|
||||
JSON response. This method will set the content type to `application/json` if not set.
|
||||
|
||||
**Usage**
|
||||
|
||||
```js
|
||||
await page.route('https://dog.ceo/api/breeds/list/all', async route => {
|
||||
const json = {
|
||||
message: { 'test_breed': [] }
|
||||
};
|
||||
await route.fulfill({ json });
|
||||
});
|
||||
```
|
||||
|
||||
```python async
|
||||
async def handle(route):
|
||||
json = { "test_breed": [] }
|
||||
await route.fulfill(json=json)
|
||||
|
||||
await page.route("https://dog.ceo/api/breeds/list/all", handle)
|
||||
```
|
||||
|
||||
```python sync
|
||||
async def handle(route):
|
||||
json = { "test_breed": [] }
|
||||
route.fulfill(json=json)
|
||||
|
||||
page.route("https://dog.ceo/api/breeds/list/all", handle)
|
||||
```
|
||||
|
||||
### option: Route.fulfill.json
|
||||
* since: v1.29
|
||||
* langs: csharp
|
||||
- `json` <[JsonElement]>
|
||||
|
||||
JSON response. This method will set the content type to `application/json` if not set.
|
||||
|
||||
**Usage**
|
||||
|
||||
```csharp
|
||||
await page.RouteAsync("https://dog.ceo/api/breeds/list/all", async route =>
|
||||
{
|
||||
var json = /* JsonElement with test payload */;
|
||||
await route.FulfillAsync(new () { Json: json });
|
||||
});
|
||||
```
|
||||
|
||||
### option: Route.fulfill.path
|
||||
* since: v1.8
|
||||
- `path` <[path]>
|
||||
|
|
|
|||
|
|
@ -345,6 +345,7 @@ var waitForResponseTask = page.WaitForResponseAsync(r => r.Url.Contains(token));
|
|||
await page.GetByText("Update").ClickAsync();
|
||||
var response = await waitForResponseTask;
|
||||
```
|
||||
|
||||
## Handle requests
|
||||
|
||||
```js
|
||||
|
|
@ -413,7 +414,7 @@ page.goto("https://example.com")
|
|||
|
||||
```csharp
|
||||
await page.RouteAsync("**/api/fetch_data", async route => {
|
||||
await route.FulfillAsync(status: 200, body: testData);
|
||||
await route.FulfillAsync(new() { Status = 200, Body = testData });
|
||||
});
|
||||
await page.GotoAsync("https://example.com");
|
||||
```
|
||||
|
|
|
|||
|
|
@ -375,11 +375,12 @@ context.route('**', handle)
|
|||
await context.RouteAsync("**", async route => {
|
||||
if (route.request().serviceWorker() != null) {
|
||||
// NB: calling route.request.frame here would THROW
|
||||
await route.FulfillAsync(
|
||||
contentType: "text/plain",
|
||||
status: 200,
|
||||
body: "from sw"
|
||||
);
|
||||
await route.FulfillAsync(new ()
|
||||
{
|
||||
ContentType = "text/plain",
|
||||
Status = 200,
|
||||
Body = "from sw"
|
||||
});
|
||||
} else {
|
||||
await route.Continue()Async();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import { kBrowserOrContextClosedError } from '../common/errors';
|
|||
import { assert, headersObjectToArray, isFilePayload, isString, objectToArray } from '../utils';
|
||||
import { mkdirIfNeeded } from '../utils/fileUtils';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import * as network from './network';
|
||||
import { RawHeaders } from './network';
|
||||
import type { FilePayload, Headers, StorageState } from './types';
|
||||
import type { Playwright } from './playwright';
|
||||
|
|
@ -142,17 +141,22 @@ export class APIRequestContext extends ChannelOwner<channels.APIRequestContextCh
|
|||
}
|
||||
|
||||
async fetch(urlOrRequest: string | api.Request, options: FetchOptions = {}): Promise<APIResponse> {
|
||||
const url = isString(urlOrRequest) ? urlOrRequest : undefined;
|
||||
const request = isString(urlOrRequest) ? undefined : urlOrRequest;
|
||||
return this._innerFetch({ url, request, ...options });
|
||||
}
|
||||
|
||||
async _innerFetch(options: FetchOptions & { url?: string, request?: api.Request } = {}): Promise<APIResponse> {
|
||||
return this._wrapApiCall(async () => {
|
||||
const request: network.Request | undefined = (urlOrRequest instanceof network.Request) ? urlOrRequest as network.Request : undefined;
|
||||
assert(request || typeof urlOrRequest === 'string', 'First argument must be either URL string or Request');
|
||||
assert(options.request || typeof options.url === 'string', 'First argument must be either URL string or Request');
|
||||
assert((options.data === undefined ? 0 : 1) + (options.form === undefined ? 0 : 1) + (options.multipart === undefined ? 0 : 1) <= 1, `Only one of 'data', 'form' or 'multipart' can be specified`);
|
||||
assert(options.maxRedirects === undefined || options.maxRedirects >= 0, `'maxRedirects' should be greater than or equal to '0'`);
|
||||
const url = request ? request.url() : urlOrRequest as string;
|
||||
const url = options.url !== undefined ? options.url : options.request!.url();
|
||||
const params = objectToArray(options.params);
|
||||
const method = options.method || request?.method();
|
||||
const method = options.method || options.request?.method();
|
||||
const maxRedirects = options.maxRedirects;
|
||||
// Cannot call allHeaders() here as the request may be paused inside route handler.
|
||||
const headersObj = options.headers || request?.headers() ;
|
||||
const headersObj = options.headers || options.request?.headers() ;
|
||||
const headers = headersObj ? headersObjectToArray(headersObj) : undefined;
|
||||
let jsonData: any;
|
||||
let formData: channels.NameValue[] | undefined;
|
||||
|
|
@ -190,7 +194,7 @@ export class APIRequestContext extends ChannelOwner<channels.APIRequestContextCh
|
|||
}
|
||||
}
|
||||
if (postDataBuffer === undefined && jsonData === undefined && formData === undefined && multipartData === undefined)
|
||||
postDataBuffer = request?.postDataBuffer() || undefined;
|
||||
postDataBuffer = options.request?.postDataBuffer() || undefined;
|
||||
const result = await this._channel.fetch({
|
||||
url,
|
||||
params,
|
||||
|
|
|
|||
|
|
@ -307,7 +307,14 @@ export class Route extends ChannelOwner<channels.RouteChannel> implements api.Ro
|
|||
this._reportHandled(true);
|
||||
}
|
||||
|
||||
async fulfill(options: { response?: api.APIResponse, status?: number, headers?: Headers, contentType?: string, body?: string | Buffer, path?: string } = {}) {
|
||||
async fetch(options: FallbackOverrides = {}) {
|
||||
return await this._wrapApiCall(async () => {
|
||||
const context = this.request()._context();
|
||||
return context.request._innerFetch({ request: this.request(), data: options.postData, ...options });
|
||||
});
|
||||
}
|
||||
|
||||
async fulfill(options: { response?: api.APIResponse, status?: number, headers?: Headers, contentType?: string, body?: string | Buffer, json?: any, path?: string } = {}) {
|
||||
this._checkNotHandled();
|
||||
await this._wrapApiCall(async () => {
|
||||
await this._innerFulfill(options);
|
||||
|
|
@ -315,10 +322,15 @@ export class Route extends ChannelOwner<channels.RouteChannel> implements api.Ro
|
|||
});
|
||||
}
|
||||
|
||||
private async _innerFulfill(options: { response?: api.APIResponse, status?: number, headers?: Headers, contentType?: string, body?: string | Buffer, path?: string } = {}): Promise<void> {
|
||||
private async _innerFulfill(options: { response?: api.APIResponse, status?: number, headers?: Headers, contentType?: string, body?: string | Buffer, json?: any, path?: string } = {}): Promise<void> {
|
||||
let fetchResponseUid;
|
||||
let { status: statusOption, headers: headersOption, body } = options;
|
||||
|
||||
if (options.json !== undefined) {
|
||||
assert(options.body === undefined, 'Can specify either body or json parameters');
|
||||
body = JSON.stringify(options.json);
|
||||
}
|
||||
|
||||
if (options.response instanceof APIResponse) {
|
||||
statusOption ??= options.response.status();
|
||||
headersOption ??= options.response.headers();
|
||||
|
|
@ -351,6 +363,8 @@ export class Route extends ChannelOwner<channels.RouteChannel> implements api.Ro
|
|||
headers[header.toLowerCase()] = String(headersOption![header]);
|
||||
if (options.contentType)
|
||||
headers['content-type'] = String(options.contentType);
|
||||
else if (options.json)
|
||||
headers['content-type'] = 'application/json';
|
||||
else if (options.path)
|
||||
headers['content-type'] = mime.getType(options.path) || 'application/octet-stream';
|
||||
if (length && !('content-length' in headers))
|
||||
|
|
|
|||
66
packages/playwright-core/types/types.d.ts
vendored
66
packages/playwright-core/types/types.d.ts
vendored
|
|
@ -17021,12 +17021,12 @@ export interface Route {
|
|||
headers?: { [key: string]: string; };
|
||||
|
||||
/**
|
||||
* If set changes the request method (e.g. GET or POST)
|
||||
* If set changes the request method (e.g. GET or POST).
|
||||
*/
|
||||
method?: string;
|
||||
|
||||
/**
|
||||
* If set changes the post data of request
|
||||
* If set changes the post data of request.
|
||||
*/
|
||||
postData?: string|Buffer;
|
||||
|
||||
|
|
@ -17108,12 +17108,12 @@ export interface Route {
|
|||
headers?: { [key: string]: string; };
|
||||
|
||||
/**
|
||||
* If set changes the request method (e.g. GET or POST)
|
||||
* If set changes the request method (e.g. GET or POST).
|
||||
*/
|
||||
method?: string;
|
||||
|
||||
/**
|
||||
* If set changes the post data of request
|
||||
* If set changes the post data of request.
|
||||
*/
|
||||
postData?: string|Buffer;
|
||||
|
||||
|
|
@ -17124,6 +17124,47 @@ export interface Route {
|
|||
url?: string;
|
||||
}): Promise<void>;
|
||||
|
||||
/**
|
||||
* Performs the request and fetches result without fulfilling it, so that the response could be modified and then
|
||||
* fulfilled.
|
||||
*
|
||||
* **Usage**
|
||||
*
|
||||
* ```js
|
||||
* await page.route('https://dog.ceo/api/breeds/list/all', async route => {
|
||||
* const response = await route.fetch();
|
||||
* const json = await response.json();
|
||||
* json.message['big_red_dog'] = [];
|
||||
* await route.fulfill({ response, json });
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @param options
|
||||
*/
|
||||
fetch(options?: {
|
||||
/**
|
||||
* Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string
|
||||
* and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type`
|
||||
* header will be set to `application/octet-stream` if not explicitly set.
|
||||
*/
|
||||
data?: string|Buffer|Serializable;
|
||||
|
||||
/**
|
||||
* If set changes the request HTTP headers. Header values will be converted to a string.
|
||||
*/
|
||||
headers?: { [key: string]: string; };
|
||||
|
||||
/**
|
||||
* If set changes the request method (e.g. GET or POST).
|
||||
*/
|
||||
method?: string;
|
||||
|
||||
/**
|
||||
* If set changes the request URL. New URL must have same protocol as original one.
|
||||
*/
|
||||
url?: string;
|
||||
}): Promise<APIResponse>;
|
||||
|
||||
/**
|
||||
* Fulfills route's request with given response.
|
||||
*
|
||||
|
|
@ -17165,6 +17206,23 @@ export interface Route {
|
|||
*/
|
||||
headers?: { [key: string]: string; };
|
||||
|
||||
/**
|
||||
* JSON response. This method will set the content type to `application/json` if not set.
|
||||
*
|
||||
* **Usage**
|
||||
*
|
||||
* ```js
|
||||
* await page.route('https://dog.ceo/api/breeds/list/all', async route => {
|
||||
* const json = {
|
||||
* message: { 'test_breed': [] }
|
||||
* };
|
||||
* await route.fulfill({ json });
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
json?: Serializable;
|
||||
|
||||
/**
|
||||
* File path to respond with. The content type will be inferred from file extension. If `path` is a relative path,
|
||||
* then it is resolved relative to the current working directory.
|
||||
|
|
|
|||
|
|
@ -797,11 +797,6 @@ it('should dispose when context closes', async function({ context, server }) {
|
|||
expect(error.message).toContain('Response has been disposed');
|
||||
});
|
||||
|
||||
it('should throw on invalid first argument', async function({ context }) {
|
||||
const error = await context.request.get({} as any).catch(e => e);
|
||||
expect(error.message).toContain('First argument must be either URL string or Request');
|
||||
});
|
||||
|
||||
it('should override request parameters', async function({ context, page, server }) {
|
||||
const [pageReq] = await Promise.all([
|
||||
page.waitForRequest('**/*'),
|
||||
|
|
|
|||
|
|
@ -380,3 +380,18 @@ it('should fulfill preload link requests', async ({ page, server, browserName })
|
|||
expect(color).toBe('rgb(0, 128, 0)');
|
||||
});
|
||||
|
||||
it('should fulfill json', async ({ page, server }) => {
|
||||
await page.route('**/*', route => {
|
||||
route.fulfill({
|
||||
status: 201,
|
||||
headers: {
|
||||
foo: 'bar'
|
||||
},
|
||||
json: { bar: 'baz' },
|
||||
});
|
||||
});
|
||||
const response = await page.goto(server.EMPTY_PAGE);
|
||||
expect(response.status()).toBe(201);
|
||||
expect(response.headers()['content-type']).toBe('application/json');
|
||||
expect(await page.evaluate(() => document.body.textContent)).toBe(JSON.stringify({ bar: 'baz' }));
|
||||
});
|
||||
|
|
|
|||
|
|
@ -20,12 +20,10 @@ import { expect, test as base } from './pageTest';
|
|||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
const it = base.extend<{
|
||||
// We access test servers at 10.0.2.2 from inside the browser on Android,
|
||||
// which is actually forwarded to the desktop localhost.
|
||||
// To use request such an url with apiRequestContext on the desktop, we need to change it back to localhost.
|
||||
rewriteAndroidLoopbackURL(url: string): string
|
||||
}>({
|
||||
const it = base.extend<{ rewriteAndroidLoopbackURL(url: string): string }>({
|
||||
rewriteAndroidLoopbackURL: ({ isAndroid }, use) => use(givenURL => {
|
||||
if (!isAndroid)
|
||||
return givenURL;
|
||||
|
|
@ -195,3 +193,42 @@ it('should intercept multipart/form-data request body', async ({ page, server, a
|
|||
expect(request.method()).toBe('POST');
|
||||
expect(request.postData()).toContain(fs.readFileSync(filePath, 'utf8'));
|
||||
});
|
||||
|
||||
it('should fulfill intercepted response using alias', async ({ page, server, isElectron, isAndroid }) => {
|
||||
it.fixme(isElectron, 'error: Browser context management is not supported.');
|
||||
it.skip(isAndroid, 'The internal Android localhost (10.0.0.2) != the localhost on the host');
|
||||
await page.route('**/*', async route => {
|
||||
const response = await route.fetch();
|
||||
await route.fulfill({ response });
|
||||
});
|
||||
const response = await page.goto(server.PREFIX + '/empty.html');
|
||||
expect(response.status()).toBe(200);
|
||||
expect(response.headers()['content-type']).toContain('text/html');
|
||||
});
|
||||
|
||||
it('should intercept with url override', async ({ page, server, isElectron, isAndroid }) => {
|
||||
it.fixme(isElectron, 'error: Browser context management is not supported.');
|
||||
it.skip(isAndroid, 'The internal Android localhost (10.0.0.2) != the localhost on the host');
|
||||
await page.route('**/*.html', async route => {
|
||||
const response = await route.fetch({ url: server.PREFIX + '/one-style.html' });
|
||||
await route.fulfill({ response });
|
||||
});
|
||||
const response = await page.goto(server.PREFIX + '/empty.html');
|
||||
expect(response.status()).toBe(200);
|
||||
expect((await response.body()).toString()).toContain('one-style.css');
|
||||
});
|
||||
|
||||
it('should intercept with post data override', async ({ page, server, isElectron, isAndroid }) => {
|
||||
it.fixme(isElectron, 'error: Browser context management is not supported.');
|
||||
it.skip(isAndroid, 'The internal Android localhost (10.0.0.2) != the localhost on the host');
|
||||
const requestPromise = server.waitForRequest('/empty.html');
|
||||
await page.route('**/*.html', async route => {
|
||||
const response = await route.fetch({
|
||||
data: { 'foo': 'bar' },
|
||||
});
|
||||
await route.fulfill({ response });
|
||||
});
|
||||
await page.goto(server.PREFIX + '/empty.html');
|
||||
const request = await requestPromise;
|
||||
expect((await request.postBody).toString()).toBe(JSON.stringify({ 'foo': 'bar' }));
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue