feat(playwright-core): add remove cookies api (#29698)

This commit is contained in:
PaulTriandafilov 2024-03-02 17:27:01 +02:00 committed by GitHub
parent ef924c14e7
commit 8e48ee714d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 334 additions and 1 deletions

View File

@ -1010,6 +1010,27 @@ Creates a new page in the browser context.
Returns all open pages in the context.
## async method: BrowserContext.removeCookies
* since: v1.43
Removes cookies from context. At least one of the removal criteria should be provided.
**Usage**
```js
await browserContext.removeCookies({ name: 'session-id' });
await browserContext.removeCookies({ domain: 'my-origin.com' });
await browserContext.removeCookies({ path: '/api/v1' });
await browserContext.removeCookies({ name: 'session-id', domain: 'my-origin.com' });
```
### param: BrowserContext.removeCookies.filter
* since: v1.43
- `filter` <[Object]>
- `name` ?<[string]>
- `domain` ?<[string]>
- `path` ?<[string]>
## property: BrowserContext.request
* since: v1.16
* langs:

View File

@ -269,6 +269,10 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
await this._channel.clearCookies();
}
async removeCookies(filter: network.RemoveNetworkCookieParam): Promise<void> {
await this._channel.removeCookies({ filter });
}
async grantPermissions(permissions: string[], options?: { origin?: string }): Promise<void> {
await this._channel.grantPermissions({ permissions, ...options });
}

View File

@ -58,6 +58,12 @@ export type SetNetworkCookieParam = {
sameSite?: 'Strict' | 'Lax' | 'None'
};
export type RemoveNetworkCookieParam = {
name?: string,
domain?: string,
path?: string,
};
type SerializedFallbackOverrides = {
url?: string;
method?: string;

View File

@ -828,6 +828,14 @@ scheme.BrowserContextAddInitScriptParams = tObject({
scheme.BrowserContextAddInitScriptResult = tOptional(tObject({}));
scheme.BrowserContextClearCookiesParams = tOptional(tObject({}));
scheme.BrowserContextClearCookiesResult = tOptional(tObject({}));
scheme.BrowserContextRemoveCookiesParams = tObject({
filter: tObject({
name: tOptional(tString),
domain: tOptional(tString),
path: tOptional(tString),
}),
});
scheme.BrowserContextRemoveCookiesResult = tOptional(tObject({}));
scheme.BrowserContextClearPermissionsParams = tOptional(tObject({}));
scheme.BrowserContextClearPermissionsResult = tOptional(tObject({}));
scheme.BrowserContextCloseParams = tObject({

View File

@ -276,6 +276,22 @@ export abstract class BrowserContext extends SdkObject {
return await this.doGetCookies(urls as string[]);
}
async removeCookies(filter: {name?: string, domain?: string, path?: string}): Promise<void> {
if (!filter.name && !filter.domain && !filter.path)
throw new Error(`Either name, domain or path are required`);
const currentCookies = await this.cookies();
const cookiesToKeep = currentCookies.filter(cookie => {
return !((!filter.name || filter.name === cookie.name) &&
(!filter.domain || filter.domain === cookie.domain) &&
(!filter.path || filter.path === cookie.path));
});
await this.clearCookies();
await this.addCookies(cookiesToKeep);
}
setHTTPCredentials(httpCredentials?: types.Credentials): Promise<void> {
return this.doSetHTTPCredentials(httpCredentials);
}

View File

@ -224,6 +224,10 @@ export class BrowserContextDispatcher extends Dispatcher<BrowserContext, channel
await this._context.clearCookies();
}
async removeCookies(params: channels.BrowserContextRemoveCookiesParams): Promise<void> {
await this._context.removeCookies(params.filter);
}
async grantPermissions(params: channels.BrowserContextGrantPermissionsParams): Promise<void> {
await this._context.grantPermissions(params.permissions, params.origin);
}

View File

@ -8441,6 +8441,28 @@ export interface BrowserContext {
*/
pages(): Array<Page>;
/**
* Removes cookies from context. The method will throw an error if either name, domain or path has not been passed.
*
* **Usage**
*
* ```js
* await browserContext.removeCookies({ name: 'session-id' });
* await browserContext.removeCookies({ domain: 'my-origin.com' });
* await browserContext.removeCookies({ path: '/api/v1' });
* await browserContext.removeCookies({ name: 'session-id', domain: 'my-origin.com' });
* ```
*
* @param filter
*/
removeCookies(filter: {
name?: string;
domain?: string;
path?: string;
}): Promise<void>;
/**
* Routing provides the capability to modify network requests that are made by any page in the browser context. Once
* route is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or aborted.

View File

@ -1427,6 +1427,7 @@ export interface BrowserContextChannel extends BrowserContextEventTarget, EventT
addCookies(params: BrowserContextAddCookiesParams, metadata?: CallMetadata): Promise<BrowserContextAddCookiesResult>;
addInitScript(params: BrowserContextAddInitScriptParams, metadata?: CallMetadata): Promise<BrowserContextAddInitScriptResult>;
clearCookies(params?: BrowserContextClearCookiesParams, metadata?: CallMetadata): Promise<BrowserContextClearCookiesResult>;
removeCookies(params: BrowserContextRemoveCookiesParams, metadata?: CallMetadata): Promise<BrowserContextRemoveCookiesResult>;
clearPermissions(params?: BrowserContextClearPermissionsParams, metadata?: CallMetadata): Promise<BrowserContextClearPermissionsResult>;
close(params: BrowserContextCloseParams, metadata?: CallMetadata): Promise<BrowserContextCloseResult>;
cookies(params: BrowserContextCookiesParams, metadata?: CallMetadata): Promise<BrowserContextCookiesResult>;
@ -1523,6 +1524,17 @@ export type BrowserContextAddInitScriptResult = void;
export type BrowserContextClearCookiesParams = {};
export type BrowserContextClearCookiesOptions = {};
export type BrowserContextClearCookiesResult = void;
export type BrowserContextRemoveCookiesParams = {
filter: {
name?: string,
domain?: string,
path?: string,
},
};
export type BrowserContextRemoveCookiesOptions = {
};
export type BrowserContextRemoveCookiesResult = void;
export type BrowserContextClearPermissionsParams = {};
export type BrowserContextClearPermissionsOptions = {};
export type BrowserContextClearPermissionsResult = void;

View File

@ -1032,6 +1032,15 @@ BrowserContext:
clearCookies:
removeCookies:
parameters:
filter:
type: object
properties:
name: string?
domain: string?
path: string?
clearPermissions:
close:
@ -3222,7 +3231,7 @@ ElectronApplication:
events:
close:
console:
parameters:
parameters:
$mixin: ConsoleMessage
Android:

View File

@ -0,0 +1,231 @@
/**
* Copyright 2018 Google Inc. All rights reserved.
* Modifications copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { contextTest as it, expect } from '../config/browserTest';
it('should remove cookies by name', async ({ context, page, server }) => {
await context.addCookies([{
name: 'cookie1',
value: '1',
domain: 'www.example.com',
path: '/',
},
{
name: 'cookie2',
value: '2',
domain: 'www.example.com',
path: '/',
}
]);
await page.goto('https://www.example.com');
expect(await page.evaluate('document.cookie')).toBe('cookie1=1; cookie2=2');
await context.removeCookies({ name: 'cookie1' });
expect(await page.evaluate('document.cookie')).toBe('cookie2=2');
});
it('should remove cookies by domain', async ({ context, page, server }) => {
await context.addCookies([{
name: 'cookie1',
value: '1',
domain: 'www.example.com',
path: '/',
},
{
name: 'cookie2',
value: '2',
domain: 'www.example.org',
path: '/',
}
]);
await page.goto('https://www.example.com');
expect(await page.evaluate('document.cookie')).toBe('cookie1=1');
await page.goto('https://www.example.org');
expect(await page.evaluate('document.cookie')).toBe('cookie2=2');
await context.removeCookies({ domain: 'www.example.org' });
expect(await page.evaluate('document.cookie')).toBe('');
await page.goto('https://www.example.com');
expect(await page.evaluate('document.cookie')).toBe('cookie1=1');
});
it('should remove cookies by path', async ({ context, page, server }) => {
await context.addCookies([{
name: 'cookie1',
value: '1',
domain: 'www.example.com',
path: '/api/v1',
},
{
name: 'cookie2',
value: '2',
domain: 'www.example.com',
path: '/api/v2',
},
{
name: 'cookie3',
value: '3',
domain: 'www.example.com',
path: '/',
}
]);
await page.goto('https://www.example.com/api/v1');
expect(await page.evaluate('document.cookie')).toBe('cookie1=1; cookie3=3');
await context.removeCookies({ path: '/api/v1' });
expect(await page.evaluate('document.cookie')).toBe('cookie3=3');
await page.goto('https://www.example.com/api/v2');
expect(await page.evaluate('document.cookie')).toBe('cookie2=2; cookie3=3');
await page.goto('https://www.example.com/');
expect(await page.evaluate('document.cookie')).toBe('cookie3=3');
});
it('should remove cookies by name and domain', async ({ context, page, server }) => {
await context.addCookies([{
name: 'cookie1',
value: '1',
domain: 'www.example.com',
path: '/',
},
{
name: 'cookie1',
value: '1',
domain: 'www.example.org',
path: '/',
}
]);
await page.goto('https://www.example.com');
expect(await page.evaluate('document.cookie')).toBe('cookie1=1');
await context.removeCookies({ name: 'cookie1', domain: 'www.example.com' });
expect(await page.evaluate('document.cookie')).toBe('');
await page.goto('https://www.example.org');
expect(await page.evaluate('document.cookie')).toBe('cookie1=1');
});
it('should remove cookies by name and path', async ({ context, page, server }) => {
await context.addCookies([{
name: 'cookie1',
value: '1',
domain: 'www.example.com',
path: '/api/v1',
},
{
name: 'cookie1',
value: '1',
domain: 'www.example.com',
path: '/api/v2',
},
{
name: 'cookie3',
value: '3',
domain: 'www.example.com',
path: '/',
}
]);
await page.goto('https://www.example.com/api/v1');
expect(await page.evaluate('document.cookie')).toBe('cookie1=1; cookie3=3');
await context.removeCookies({ name: 'cookie1', path: '/api/v1' });
expect(await page.evaluate('document.cookie')).toBe('cookie3=3');
await page.goto('https://www.example.com/api/v2');
expect(await page.evaluate('document.cookie')).toBe('cookie1=1; cookie3=3');
await page.goto('https://www.example.com/');
expect(await page.evaluate('document.cookie')).toBe('cookie3=3');
});
it('should remove cookies by domain and path', async ({ context, page, server }) => {
await context.addCookies([{
name: 'cookie1',
value: '1',
domain: 'www.example.com',
path: '/api/v1',
},
{
name: 'cookie2',
value: '2',
domain: 'www.example.com',
path: '/api/v2',
},
{
name: 'cookie3',
value: '3',
domain: 'www.example.org',
path: '/api/v1',
},
{
name: 'cookie4',
value: '4',
domain: 'www.example.org',
path: '/api/v2',
}
]);
await page.goto('https://www.example.com/api/v1');
expect(await page.evaluate('document.cookie')).toBe('cookie1=1');
await context.removeCookies({ domain: 'www.example.com', path: '/api/v1' });
expect(await page.evaluate('document.cookie')).toBe('');
await page.goto('https://www.example.com/api/v2');
expect(await page.evaluate('document.cookie')).toBe('cookie2=2');
await page.goto('https://www.example.org/api/v2');
expect(await page.evaluate('document.cookie')).toBe('cookie4=4');
});
it('should remove cookies by name, domain and path', async ({ context, page, server }) => {
await context.addCookies([{
name: 'cookie1',
value: '1',
domain: 'www.example.com',
path: '/api/v1',
},
{
name: 'cookie2',
value: '2',
domain: 'www.example.com',
path: '/api/v2',
},
{
name: 'cookie1',
value: '1',
domain: 'www.example.org',
path: '/api/v1',
},
]);
await page.goto('https://www.example.com/api/v1');
expect(await page.evaluate('document.cookie')).toBe('cookie1=1');
await context.removeCookies({ name: 'cookie1', domain: 'www.example.com', path: '/api/v1' });
expect(await page.evaluate('document.cookie')).toBe('');
await page.goto('https://www.example.com/api/v2');
expect(await page.evaluate('document.cookie')).toBe('cookie2=2');
await page.goto('https://www.example.org/api/v1');
expect(await page.evaluate('document.cookie')).toBe('cookie1=1');
});
it('should throw if empty object is passed', async ({ context, page, server }) => {
await context.addCookies([{
name: 'cookie1',
value: '1',
domain: 'www.example.com',
path: '/',
},
{
name: 'cookie2',
value: '2',
domain: 'www.example.com',
path: '/',
},
]);
await page.goto('https://www.example.com/');
expect(await page.evaluate('document.cookie')).toBe('cookie1=1; cookie2=2');
const error = await context.removeCookies({ }).catch(e => e);
expect(error.message).toContain(`Either name, domain or path are required`);
expect(await page.evaluate('document.cookie')).toBe('cookie1=1; cookie2=2');
});