diff --git a/packages/playwright-core/src/server/cookieStore.ts b/packages/playwright-core/src/server/cookieStore.ts index 332a212cd2..fbf3f718f0 100644 --- a/packages/playwright-core/src/server/cookieStore.ts +++ b/packages/playwright-core/src/server/cookieStore.ts @@ -83,22 +83,18 @@ export class CookieStore { } private _addCookie(cookie: Cookie) { - if (cookie.expired()) - return; let set = this._nameToCookies.get(cookie.name()); if (!set) { set = new Set(); this._nameToCookies.set(cookie.name(), set); } - CookieStore.pruneExpired(set); // https://datatracker.ietf.org/doc/html/rfc6265#section-5.3 for (const other of set) { - if (other.equals(cookie)) { - cookie.updateExpiresFrom(other); + if (other.equals(cookie)) set.delete(other); - } } set.add(cookie); + CookieStore.pruneExpired(set); } private *_cookiesIterator(): IterableIterator { diff --git a/tests/library/global-fetch-cookie.spec.ts b/tests/library/global-fetch-cookie.spec.ts index e0b91d2208..d089db18a7 100644 --- a/tests/library/global-fetch-cookie.spec.ts +++ b/tests/library/global-fetch-cookie.spec.ts @@ -20,8 +20,8 @@ import type { APIRequestContext } from 'playwright-core'; import { expect, playwrightTest } from '../config/browserTest'; export type GlobalFetchFixtures = { - request: APIRequestContext; - }; + request: APIRequestContext; +}; const it = playwrightTest.extend({ request: async ({ playwright }, use) => { @@ -206,6 +206,60 @@ it('should store cookie from Set-Cookie header even if it contains equal signs', }); }); +it('should override cookie from Set-Cookie header', async ({ request, server }) => { + const tomorrow = new Date(); + tomorrow.setDate(tomorrow.getDate() + 1); + + server.setRoute('/setcookie.html', (req, res) => { + res.setHeader('Set-Cookie', [`a=old; expires=${tomorrow.toUTCString()}`]); + res.end(); + }); + + const dayAfterTomorrow = new Date(tomorrow); + dayAfterTomorrow.setDate(tomorrow.getDate() + 1); + const dayAfterTomorrowInSeconds = Math.floor(dayAfterTomorrow.valueOf() / 1000); + server.setRoute('/updatecookie.html', (req, res) => { + res.setHeader('Set-Cookie', [`a=new; expires=${dayAfterTomorrow.toUTCString()}`]); + res.end(); + }); + + await request.get(`${server.PREFIX}/setcookie.html`); + await request.get(`${server.PREFIX}/updatecookie.html`); + + const state = await request.storageState(); + + expect(state.cookies).toHaveLength(1); + expect(state.cookies[0].name).toBe(`a`); + expect(state.cookies[0].value).toBe(`new`); + expect(state.cookies[0].expires).toBe(dayAfterTomorrowInSeconds); +}); + +it('should override cookie from Set-Cookie header even if it expired', async ({ request, server }) => { + const tomorrow = new Date(); + tomorrow.setDate(tomorrow.getDate() + 1); + + server.setRoute('/setcookie.html', (req, res) => { + res.setHeader('Set-Cookie', [`a=ok`, `b=ok; expires=${tomorrow.toUTCString()}`]); + res.end(); + }); + + server.setRoute('/unsetsetcookie.html', (req, res) => { + const pastDateString = new Date(1970, 0, 1, 0, 0, 0, 0).toUTCString(); + res.setHeader('Set-Cookie', [`a=; expires=${pastDateString}`, `b=; expires=${pastDateString}`]); + res.end(); + }); + + await request.get(`${server.PREFIX}/setcookie.html`); + await request.get(`${server.PREFIX}/unsetsetcookie.html`); + + const [serverRequest] = await Promise.all([ + server.waitForRequest('/empty.html'), + request.get(server.EMPTY_PAGE) + ]); + + expect(serverRequest.headers.cookie).toBeFalsy(); +}); + it('should export cookies to storage state', async ({ request, server }) => { const expires = new Date('12/31/2100 PST'); server.setRoute('/setcookie.html', (req, res) => {