mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
feat(webdriver): support Page.deleteCookie()
for WebDriver BiDi (#12031)
This commit is contained in:
parent
7284576690
commit
7fe22b533d
@ -12,9 +12,9 @@ export interface DeleteCookiesRequest
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Modifiers | Type | Description | Default |
|
||||
| -------- | --------------------- | ------ | --------------------------------------------------------------------------------------------------- | ------- |
|
||||
| domain | <code>optional</code> | string | If specified, deletes only cookies with the exact domain. | |
|
||||
| name | | string | Name of the cookies to remove. | |
|
||||
| path | <code>optional</code> | string | If specified, deletes only cookies with the exact path. | |
|
||||
| url | <code>optional</code> | string | If specified, deletes all the cookies with the given name where domain and path match provided URL. | |
|
||||
| Property | Modifiers | Type | Description | Default |
|
||||
| -------- | --------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||
| domain | <code>optional</code> | string | If specified, deletes only cookies with the exact domain. | |
|
||||
| name | | string | Name of the cookies to remove. | |
|
||||
| path | <code>optional</code> | string | If specified, deletes only cookies with the exact path. | |
|
||||
| url | <code>optional</code> | string | If specified, deletes all the cookies with the given name where domain and path match provided URL. Otherwise, deletes only cookies related to the current page's domain. | |
|
||||
|
@ -28,6 +28,7 @@ import {Coverage} from '../cdp/Coverage.js';
|
||||
import {EmulationManager} from '../cdp/EmulationManager.js';
|
||||
import {Tracing} from '../cdp/Tracing.js';
|
||||
import type {Cookie, CookieParam, CookieSameSite} from '../common/Cookie.js';
|
||||
import type {DeleteCookiesRequest} from '../common/Cookie.js';
|
||||
import {UnsupportedOperation} from '../common/Errors.js';
|
||||
import {EventEmitter} from '../common/EventEmitter.js';
|
||||
import type {PDFOptions} from '../common/PDFOptions.js';
|
||||
@ -559,9 +560,6 @@ export class BidiPage extends Page {
|
||||
),
|
||||
};
|
||||
|
||||
// TODO: delete cookie before setting them.
|
||||
// await this.deleteCookie(bidiCookie);
|
||||
|
||||
if (cookie.partitionKey !== undefined) {
|
||||
await this.browserContext().userContext.setCookie(
|
||||
bidiCookie,
|
||||
@ -573,8 +571,32 @@ export class BidiPage extends Page {
|
||||
}
|
||||
}
|
||||
|
||||
override deleteCookie(): never {
|
||||
throw new UnsupportedOperation();
|
||||
override async deleteCookie(
|
||||
...cookies: DeleteCookiesRequest[]
|
||||
): Promise<void> {
|
||||
await Promise.all(
|
||||
cookies.map(async deleteCookieRequest => {
|
||||
const cookieUrl = deleteCookieRequest.url ?? this.url();
|
||||
const normalizedUrl = URL.canParse(cookieUrl)
|
||||
? new URL(cookieUrl)
|
||||
: undefined;
|
||||
|
||||
const domain = deleteCookieRequest.domain ?? normalizedUrl?.hostname;
|
||||
assert(
|
||||
domain !== undefined,
|
||||
`At least one of the url and domain needs to be specified`
|
||||
);
|
||||
|
||||
const filter = {
|
||||
domain: domain,
|
||||
name: deleteCookieRequest.name,
|
||||
...(deleteCookieRequest.path !== undefined
|
||||
? {path: deleteCookieRequest.path}
|
||||
: {}),
|
||||
};
|
||||
await this.#frame.browsingContext.deleteCookie(filter);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
override async removeExposedFunction(name: string): Promise<void> {
|
||||
|
@ -547,4 +547,24 @@ export class BrowsingContext extends EventEmitter<{
|
||||
this.#disposables.dispose();
|
||||
super[disposeSymbol]();
|
||||
}
|
||||
|
||||
@throwIfDisposed<BrowsingContext>(context => {
|
||||
// SAFETY: Disposal implies this exists.
|
||||
return context.#reason!;
|
||||
})
|
||||
async deleteCookie(
|
||||
...cookieFilters: Bidi.Storage.CookieFilter[]
|
||||
): Promise<void> {
|
||||
await Promise.all(
|
||||
cookieFilters.map(async filter => {
|
||||
await this.#session.send('storage.deleteCookies', {
|
||||
filter: filter,
|
||||
partition: {
|
||||
type: 'context',
|
||||
context: this.id,
|
||||
},
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -137,6 +137,10 @@ export interface Commands {
|
||||
returnType: Bidi.EmptyResult;
|
||||
};
|
||||
|
||||
'storage.deleteCookies': {
|
||||
params: Bidi.Storage.DeleteCookiesParameters;
|
||||
returnType: Bidi.Storage.DeleteCookiesResult;
|
||||
};
|
||||
'storage.getCookies': {
|
||||
params: Bidi.Storage.GetCookiesParameters;
|
||||
returnType: Bidi.Storage.GetCookiesResult;
|
||||
|
@ -172,7 +172,7 @@ export interface DeleteCookiesRequest {
|
||||
name: string;
|
||||
/**
|
||||
* If specified, deletes all the cookies with the given name where domain and path match
|
||||
* provided URL.
|
||||
* provided URL. Otherwise, deletes only cookies related to the current page's domain.
|
||||
*/
|
||||
url?: string;
|
||||
/**
|
||||
|
@ -276,6 +276,13 @@
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[cookies.spec] Cookie specs Page.deleteCookie should delete cookie for specified URL regardless of the current page",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["firefox"],
|
||||
"expectations": ["SKIP"],
|
||||
"comment": "The test relies on the default page partition key do not contain the source origin. This is not the case for Firefox."
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[coverage.spec] *",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -1081,22 +1088,46 @@
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[cookies.spec] Cookie specs Page.deleteCookie should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[cookies.spec] Cookie specs Page.deleteCookie should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[cookies.spec] Cookie specs Page.deleteCookie should work",
|
||||
"testIdPattern": "[cookies.spec] Cookie specs Page.deleteCookie should delete cookie",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
"expectations": ["FAIL"],
|
||||
"comment": "Firefox default partition key is inconsistent: #12004"
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[cookies.spec] Cookie specs Page.deleteCookie should delete cookie",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["FAIL"],
|
||||
"comment": "Not supported with cdp"
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[cookies.spec] Cookie specs Page.deleteCookie should delete cookie for specified URL",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"],
|
||||
"comment": "Firefox default partition key is inconsistent: #12004"
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[cookies.spec] Cookie specs Page.deleteCookie should delete cookie for specified URL",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["FAIL"],
|
||||
"comment": "Not supported with cdp"
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[cookies.spec] Cookie specs Page.deleteCookie should not delete cookie for different domain",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"],
|
||||
"comment": "Firefox default partition key is inconsistent: #12004"
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[cookies.spec] Cookie specs Page.deleteCookie should not delete cookie for different domain",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["FAIL"],
|
||||
"comment": "Not supported with cdp"
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[cookies.spec] Cookie specs Page.setCookie should be able to set insecure cookie for HTTP website",
|
||||
@ -1194,12 +1225,6 @@
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["FAIL", "PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[defaultbrowsercontext.spec] DefaultBrowserContext page.deleteCookie() should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[defaultbrowsercontext.spec] DefaultBrowserContext page.deleteCookie() should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
|
@ -558,7 +558,7 @@ describe('Cookie specs', () => {
|
||||
});
|
||||
|
||||
describe('Page.deleteCookie', function () {
|
||||
it('should work', async () => {
|
||||
it('should delete cookie', async () => {
|
||||
const {page, server} = await getTestState();
|
||||
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
@ -584,5 +584,139 @@ describe('Cookie specs', () => {
|
||||
'cookie1=1; cookie3=3'
|
||||
);
|
||||
});
|
||||
it('should not delete cookie for different domain', async () => {
|
||||
const {page, server} = await getTestState();
|
||||
const COOKIE_DESTINATION_URL = 'https://example.com';
|
||||
const COOKIE_NAME = 'some_cookie_name';
|
||||
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
// Set a cookie for the current page.
|
||||
await page.setCookie({
|
||||
name: COOKIE_NAME,
|
||||
value: 'local page cookie value',
|
||||
});
|
||||
expect(await page.cookies()).toHaveLength(1);
|
||||
|
||||
// Set a cookie for different domain.
|
||||
await page.setCookie({
|
||||
url: COOKIE_DESTINATION_URL,
|
||||
name: COOKIE_NAME,
|
||||
value: 'COOKIE_DESTINATION_URL cookie value',
|
||||
});
|
||||
expect(await page.cookies(COOKIE_DESTINATION_URL)).toHaveLength(1);
|
||||
|
||||
await page.deleteCookie({name: COOKIE_NAME});
|
||||
|
||||
// Verify the cookie is deleted for the current page.
|
||||
expect(await page.cookies()).toHaveLength(0);
|
||||
|
||||
// Verify the cookie is not deleted for different domain.
|
||||
await expectCookieEquals(await page.cookies(COOKIE_DESTINATION_URL), [
|
||||
{
|
||||
name: COOKIE_NAME,
|
||||
value: 'COOKIE_DESTINATION_URL cookie value',
|
||||
domain: 'example.com',
|
||||
path: '/',
|
||||
sameParty: false,
|
||||
expires: -1,
|
||||
size: 51,
|
||||
httpOnly: false,
|
||||
secure: true,
|
||||
session: true,
|
||||
sourceScheme: 'Secure',
|
||||
},
|
||||
]);
|
||||
});
|
||||
it('should delete cookie for specified URL', async () => {
|
||||
const {page, server} = await getTestState();
|
||||
const COOKIE_DESTINATION_URL = 'https://example.com';
|
||||
const COOKIE_NAME = 'some_cookie_name';
|
||||
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
// Set a cookie for the current page.
|
||||
await page.setCookie({
|
||||
name: COOKIE_NAME,
|
||||
value: 'some_cookie_value',
|
||||
});
|
||||
expect(await page.cookies()).toHaveLength(1);
|
||||
|
||||
// Set a cookie for specified URL.
|
||||
await page.setCookie({
|
||||
url: COOKIE_DESTINATION_URL,
|
||||
name: COOKIE_NAME,
|
||||
value: 'another_cookie_value',
|
||||
});
|
||||
expect(await page.cookies(COOKIE_DESTINATION_URL)).toHaveLength(1);
|
||||
|
||||
// Delete the cookie for specified URL.
|
||||
await page.deleteCookie({
|
||||
url: COOKIE_DESTINATION_URL,
|
||||
name: COOKIE_NAME,
|
||||
});
|
||||
|
||||
// Verify the cookie is deleted for specified URL.
|
||||
expect(await page.cookies(COOKIE_DESTINATION_URL)).toHaveLength(0);
|
||||
|
||||
// Verify the cookie is not deleted for the current page.
|
||||
await expectCookieEquals(await page.cookies(), [
|
||||
{
|
||||
name: COOKIE_NAME,
|
||||
value: 'some_cookie_value',
|
||||
domain: 'localhost',
|
||||
path: '/',
|
||||
sameParty: false,
|
||||
expires: -1,
|
||||
size: 33,
|
||||
httpOnly: false,
|
||||
secure: false,
|
||||
session: true,
|
||||
sourceScheme: 'NonSecure',
|
||||
},
|
||||
]);
|
||||
});
|
||||
it('should delete cookie for specified URL regardless of the current page', async () => {
|
||||
// This test verifies the page.deleteCookie method deletes cookies for the custom
|
||||
// destination URL, even if it was set from another page. Depending on the cookie
|
||||
// partitioning implementation, this test case does not pass, if source origin is in
|
||||
// the default cookie partition.
|
||||
|
||||
const {page, server} = await getTestState();
|
||||
const COOKIE_DESTINATION_URL = 'https://example.com';
|
||||
const COOKIE_NAME = 'some_cookie_name';
|
||||
const URL_1 = server.EMPTY_PAGE;
|
||||
const URL_2 = server.CROSS_PROCESS_PREFIX + '/empty.html';
|
||||
|
||||
await page.goto(URL_1);
|
||||
// Set a cookie for the COOKIE_DESTINATION from URL_1.
|
||||
await page.setCookie({
|
||||
url: COOKIE_DESTINATION_URL,
|
||||
name: COOKIE_NAME,
|
||||
value: 'Cookie from URL_1',
|
||||
});
|
||||
expect(await page.cookies(COOKIE_DESTINATION_URL)).toHaveLength(1);
|
||||
|
||||
await page.goto(URL_2);
|
||||
// Set a cookie for the COOKIE_DESTINATION from URL_2.
|
||||
await page.setCookie({
|
||||
url: COOKIE_DESTINATION_URL,
|
||||
name: COOKIE_NAME,
|
||||
value: 'Cookie from URL_2',
|
||||
});
|
||||
expect(await page.cookies(COOKIE_DESTINATION_URL)).toHaveLength(1);
|
||||
|
||||
// Delete the cookie for the COOKIE_DESTINATION from URL_2.
|
||||
await page.deleteCookie({
|
||||
name: COOKIE_NAME,
|
||||
url: COOKIE_DESTINATION_URL,
|
||||
});
|
||||
|
||||
// Expect the cookie for the COOKIE_DESTINATION from URL_2 is deleted.
|
||||
expect(await page.cookies(COOKIE_DESTINATION_URL)).toHaveLength(0);
|
||||
|
||||
// Navigate back to the URL_1.
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
// Expect the cookie for the COOKIE_DESTINATION from URL_1 is deleted.
|
||||
expect(await page.cookies(COOKIE_DESTINATION_URL)).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user