| // Licensed to the Software Freedom Conservancy (SFC) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The SFC licenses this file |
| // to you 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. |
| |
| 'use strict' |
| |
| const assert = require('node:assert') |
| const { URL } = require('node:url') |
| |
| const { ignore, suite } = require('../lib/test') |
| const fileserver = require('../lib/test/fileserver') |
| const { Browser } = require('selenium-webdriver') |
| |
| suite(function (env) { |
| let driver |
| |
| before(async function () { |
| driver = await env.builder().build() |
| }) |
| |
| after(function () { |
| return driver.quit() |
| }) |
| |
| describe('Cookie Management;', function () { |
| beforeEach(async function () { |
| await driver.get(fileserver.Pages.ajaxyPage) |
| await driver.manage().deleteAllCookies() |
| return assertHasCookies() |
| }) |
| |
| it('can add new cookies', async function () { |
| const cookie = createCookieSpec() |
| |
| await driver.manage().addCookie(cookie) |
| await driver |
| .manage() |
| .getCookie(cookie.name) |
| .then(function (actual) { |
| assert.strictEqual(actual.value, cookie.value) |
| }) |
| }) |
| |
| it('Get Cookie: throw error if name is null', async function () { |
| const cookie = createCookieSpec() |
| await driver.manage().addCookie(cookie) |
| await assert.rejects(async () => await driver.manage().getCookie(null), { |
| name: 'InvalidArgumentError', |
| message: `Cookie name cannot be empty`, |
| }) |
| }) |
| |
| it('Delete cookie: throw error if name is null', async function () { |
| const cookie = createCookieSpec() |
| await driver.manage().addCookie(cookie) |
| await assert.rejects(async () => await driver.manage().deleteCookie(null), { |
| name: 'InvalidArgumentError', |
| message: `Cookie name cannot be empty`, |
| }) |
| }) |
| |
| it('can get all cookies', async function () { |
| const cookie1 = createCookieSpec() |
| const cookie2 = createCookieSpec() |
| |
| await driver.manage().addCookie(cookie1) |
| await driver.manage().addCookie(cookie2) |
| |
| return assertHasCookies(cookie1, cookie2) |
| }) |
| |
| ignore(env.browsers(Browser.INTERNET_EXPLORER)).it( |
| 'only returns cookies visible to the current page', |
| async function () { |
| const cookie1 = createCookieSpec() |
| |
| await driver.manage().addCookie(cookie1) |
| |
| const pageUrl = fileserver.whereIs('page/1') |
| const cookie2 = createCookieSpec({ |
| path: new URL(pageUrl).pathname, |
| }) |
| await driver.get(pageUrl) |
| await driver.manage().addCookie(cookie2) |
| await assertHasCookies(cookie1, cookie2) |
| |
| await driver.get(fileserver.Pages.ajaxyPage) |
| await assertHasCookies(cookie1) |
| |
| await driver.get(pageUrl) |
| await assertHasCookies(cookie1, cookie2) |
| }, |
| ) |
| |
| it('can delete all cookies', async function () { |
| const cookie1 = createCookieSpec() |
| const cookie2 = createCookieSpec() |
| |
| await driver.executeScript( |
| 'document.cookie = arguments[0] + "=" + arguments[1];' + 'document.cookie = arguments[2] + "=" + arguments[3];', |
| cookie1.name, |
| cookie1.value, |
| cookie2.name, |
| cookie2.value, |
| ) |
| await assertHasCookies(cookie1, cookie2) |
| |
| await driver.manage().deleteAllCookies() |
| await assertHasCookies() |
| }) |
| |
| it('can delete cookies by name', async function () { |
| const cookie1 = createCookieSpec() |
| const cookie2 = createCookieSpec() |
| |
| await driver.executeScript( |
| 'document.cookie = arguments[0] + "=" + arguments[1];' + 'document.cookie = arguments[2] + "=" + arguments[3];', |
| cookie1.name, |
| cookie1.value, |
| cookie2.name, |
| cookie2.value, |
| ) |
| await assertHasCookies(cookie1, cookie2) |
| |
| await driver.manage().deleteCookie(cookie1.name) |
| await assertHasCookies(cookie2) |
| }) |
| |
| it('should only delete cookie with exact name', async function () { |
| const cookie1 = createCookieSpec() |
| const cookie2 = createCookieSpec() |
| const cookie3 = { name: cookie1.name + 'xx', value: cookie1.value } |
| |
| await driver.executeScript( |
| 'document.cookie = arguments[0] + "=" + arguments[1];' + |
| 'document.cookie = arguments[2] + "=" + arguments[3];' + |
| 'document.cookie = arguments[4] + "=" + arguments[5];', |
| cookie1.name, |
| cookie1.value, |
| cookie2.name, |
| cookie2.value, |
| cookie3.name, |
| cookie3.value, |
| ) |
| await assertHasCookies(cookie1, cookie2, cookie3) |
| |
| await driver.manage().deleteCookie(cookie1.name) |
| await assertHasCookies(cookie2, cookie3) |
| }) |
| |
| it('can delete cookies set higher in the path', async function () { |
| const cookie = createCookieSpec() |
| const childUrl = fileserver.whereIs('child/childPage.html') |
| const grandchildUrl = fileserver.whereIs('child/grandchild/grandchildPage.html') |
| |
| await driver.get(childUrl) |
| await driver.manage().addCookie(cookie) |
| await assertHasCookies(cookie) |
| |
| await driver.get(grandchildUrl) |
| await assertHasCookies(cookie) |
| |
| await driver.manage().deleteCookie(cookie.name) |
| await assertHasCookies() |
| |
| await driver.get(childUrl) |
| await assertHasCookies() |
| }) |
| |
| ignore(env.browsers(Browser.FIREFOX, Browser.INTERNET_EXPLORER)).it( |
| 'should retain cookie expiry', |
| async function () { |
| let expirationDelay = 5 * 1000 |
| let expiry = new Date(Date.now() + expirationDelay) |
| let cookie = createCookieSpec({ expiry }) |
| |
| await driver.manage().addCookie(cookie) |
| await driver |
| .manage() |
| .getCookie(cookie.name) |
| .then(function (actual) { |
| assert.strictEqual(actual.value, cookie.value) |
| |
| // expiry times should be in seconds since January 1, 1970 UTC |
| assert.strictEqual(actual.expiry, Math.floor(expiry.getTime() / 1000)) |
| }) |
| |
| await driver.sleep(expirationDelay) |
| await assertHasCookies() |
| }, |
| ) |
| |
| ignore(env.browsers(Browser.FIREFOX, Browser.INTERNET_EXPLORER, Browser.SAFARI)).it( |
| 'can add same site cookie property to `Strict`', |
| async function () { |
| let cookie = createSameSiteCookieSpec('Strict') |
| let childUrl = fileserver.whereIs('child/childPage.html') |
| await driver.get(childUrl) |
| await driver.manage().addCookie(cookie) |
| const actual = await driver.manage().getCookie(cookie.name) |
| assert.strictEqual(actual.sameSite, 'Strict') |
| }, |
| ) |
| |
| ignore(env.browsers(Browser.FIREFOX, Browser.INTERNET_EXPLORER, Browser.SAFARI)).it( |
| 'can add same site cookie property to `Lax`', |
| async function () { |
| let cookie = createSameSiteCookieSpec('Lax') |
| let childUrl = fileserver.whereIs('child/childPage.html') |
| await driver.get(childUrl) |
| await driver.manage().addCookie(cookie) |
| const actualCookie = await driver.manage().getCookie(cookie.name) |
| assert.strictEqual(actualCookie.sameSite, 'Lax') |
| }, |
| ) |
| |
| ignore(env.browsers(Browser.INTERNET_EXPLORER, Browser.SAFARI)).it( |
| 'can add same site cookie property to `None` when cookie is Secure', |
| async function () { |
| let cookie = createSameSiteCookieSpec('None', { |
| secure: true, |
| }) |
| let childUrl = fileserver.whereIs('child/childPage.html') |
| await driver.get(childUrl) |
| await driver.manage().addCookie(cookie) |
| await assert.doesNotReject(async () => await driver.manage().addCookie(cookie)) |
| }, |
| ) |
| |
| ignore(env.browsers(Browser.INTERNET_EXPLORER, Browser.SAFARI)).it( |
| 'throws an error if same site is set to `None` and the cookie is not Secure', |
| async function () { |
| let cookie = createSameSiteCookieSpec('None') |
| let childUrl = fileserver.whereIs('child/childPage.html') |
| await driver.get(childUrl) |
| await assert.rejects(async () => await driver.manage().addCookie(cookie), { |
| name: 'InvalidArgumentError', |
| message: `Invalid cookie configuration: SameSite=None must be Secure`, |
| }) |
| }, |
| ) |
| |
| ignore(env.browsers(Browser.INTERNET_EXPLORER, Browser.SAFARI)).it( |
| 'throws an error if same site cookie property is invalid', |
| async function () { |
| let cookie = createSameSiteCookieSpec('Foo') |
| let childUrl = fileserver.whereIs('child/childPage.html') |
| await driver.get(childUrl) |
| await assert.rejects(async () => await driver.manage().addCookie(cookie), { |
| name: 'InvalidArgumentError', |
| message: `Invalid sameSite cookie value 'Foo'. It should be one of "Lax", "Strict" or "None"`, |
| }) |
| }, |
| ) |
| }) |
| |
| function createCookieSpec(opt_options) { |
| let spec = { |
| name: getRandomString(), |
| value: getRandomString(), |
| } |
| if (opt_options) { |
| spec = Object.assign(spec, opt_options) |
| } |
| return spec |
| } |
| |
| function createSameSiteCookieSpec(sameSiteVal, extraProps) { |
| return { |
| name: getRandomString(), |
| value: getRandomString(), |
| sameSite: sameSiteVal, |
| ...extraProps, |
| } |
| } |
| |
| function buildCookieMap(cookies) { |
| const map = {} |
| cookies.forEach(function (cookie) { |
| map[cookie.name] = cookie |
| }) |
| return map |
| } |
| |
| function assertHasCookies(...expected) { |
| return driver |
| .manage() |
| .getCookies() |
| .then(function (cookies) { |
| assert.strictEqual( |
| cookies.length, |
| expected.length, |
| 'Wrong # of cookies.' + |
| '\n Expected: ' + |
| JSON.stringify(expected) + |
| '\n Was : ' + |
| JSON.stringify(cookies), |
| ) |
| |
| const map = buildCookieMap(cookies) |
| for (let i = 0; i < expected.length; ++i) { |
| assert.strictEqual(expected[i].value, map[expected[i].name].value) |
| } |
| }) |
| } |
| |
| function getRandomString() { |
| const x = 1234567890 |
| return Math.floor(Math.random() * x).toString(36) |
| } |
| }) |