diff --git a/docs/src/api/class-apirequestcontext.md b/docs/src/api/class-apirequestcontext.md index 090ea4f52a..35f7c136d7 100644 --- a/docs/src/api/class-apirequestcontext.md +++ b/docs/src/api/class-apirequestcontext.md @@ -16,6 +16,9 @@ context cookies from the response. The method will automatically follow redirect ### param: APIRequestContext.delete.url = %%-fetch-param-url-%% ### option: APIRequestContext.delete.params = %%-fetch-option-params-%% ### option: APIRequestContext.delete.headers = %%-fetch-option-headers-%% +### option: APIRequestContext.delete.data = %%-fetch-option-data-%% +### option: APIRequestContext.delete.form = %%-fetch-option-form-%% +### option: APIRequestContext.delete.multipart = %%-fetch-option-multipart-%% ### option: APIRequestContext.delete.timeout = %%-fetch-option-timeout-%% ### option: APIRequestContext.delete.failOnStatusCode = %%-fetch-option-failonstatuscode-%% ### option: APIRequestContext.delete.ignoreHTTPSErrors = %%-context-option-ignorehttpserrors-%% diff --git a/packages/playwright-core/src/client/fetch.ts b/packages/playwright-core/src/client/fetch.ts index 61494bfb5b..3d29de9fb4 100644 --- a/packages/playwright-core/src/client/fetch.ts +++ b/packages/playwright-core/src/client/fetch.ts @@ -84,7 +84,7 @@ export class FetchRequest extends ChannelOwner { + async delete(url: string, options?: RequestWithBodyOptions): Promise { return this.fetch(url, { ...options, method: 'DELETE', diff --git a/packages/playwright-core/src/server/fetch.ts b/packages/playwright-core/src/server/fetch.ts index d0433f8996..e588b6c1fb 100644 --- a/packages/playwright-core/src/server/fetch.ts +++ b/packages/playwright-core/src/server/fetch.ts @@ -143,7 +143,7 @@ export abstract class FetchRequest extends SdkObject { } let postData; - if (['POST', 'PUT', 'PATCH'].includes(method)) + if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) postData = serializePostData(params, headers); else if (params.postData || params.jsonData || params.formData || params.multipartData) throw new Error(`Method ${method} does not accept post data`); diff --git a/packages/playwright-core/types/types.d.ts b/packages/playwright-core/types/types.d.ts index f8ad28fb91..7a6cf98727 100644 --- a/packages/playwright-core/types/types.d.ts +++ b/packages/playwright-core/types/types.d.ts @@ -11747,11 +11747,25 @@ export interface APIRequestContext { * @param options */ delete(url: string, 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; + /** * Whether to throw on response codes other than 2xx and 3xx. By default response object is returned for all status codes. */ failOnStatusCode?: boolean; + /** + * Provides an object that will be serialized as html form using `application/x-www-form-urlencoded` encoding and sent as + * this request body. If this parameter is specified `content-type` header will be set to + * `application/x-www-form-urlencoded` unless explicitly provided. + */ + form?: { [key: string]: string|number|boolean; }; + /** * Allows to set HTTP headers. */ @@ -11762,6 +11776,29 @@ export interface APIRequestContext { */ ignoreHTTPSErrors?: boolean; + /** + * Provides an object that will be serialized as html form using `multipart/form-data` encoding and sent as this request + * body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless explicitly + * provided. File values can be passed either as [`fs.ReadStream`](https://nodejs.org/api/fs.html#fs_class_fs_readstream) + * or as file-like object containing file name, mime-type and its content. + */ + multipart?: { [key: string]: string|number|boolean|ReadStream|{ + /** + * File name + */ + name: string; + + /** + * File type + */ + mimeType: string; + + /** + * File content + */ + buffer: Buffer; + }; }; + /** * Query parameters to be send with the URL. */ diff --git a/tests/browsercontext-fetch.spec.ts b/tests/browsercontext-fetch.spec.ts index 3f7527d1be..c73204798f 100644 --- a/tests/browsercontext-fetch.spec.ts +++ b/tests/browsercontext-fetch.spec.ts @@ -413,18 +413,20 @@ it('should return error with wrong credentials', async ({ context, server }) => expect(response2.status()).toBe(401); }); -it('should support post data', async ({ context, server }) => { - const [request, response] = await Promise.all([ - server.waitForRequest('/simple.json'), - context.request.post(`${server.PREFIX}/simple.json`, { - data: 'My request' - }) - ]); - expect(request.method).toBe('POST'); - expect((await request.postBody).toString()).toBe('My request'); - expect(response.status()).toBe(200); - expect(request.url).toBe('/simple.json'); -}); +for (const method of ['delete', 'patch', 'post', 'put']) { + it(`${method} should support post data`, async ({ context, server }) => { + const [request, response] = await Promise.all([ + server.waitForRequest('/simple.json'), + context.request[method](`${server.PREFIX}/simple.json`, { + data: 'My request' + }) + ]); + expect(request.method).toBe(method.toUpperCase()); + expect((await request.postBody).toString()).toBe('My request'); + expect(response.status()).toBe(200); + expect(request.url).toBe('/simple.json'); + }); +} it('should add default headers', async ({ context, server, page }) => { const [request] = await Promise.all([