// 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') require('../../lib/test/fileserver') const { suite, ignore } = require('../../lib/test') const { Browser } = require('selenium-webdriver') const Storage = require('selenium-webdriver/bidi/storage') const fileserver = require('../../lib/test/fileserver') const { CookieFilter } = require('selenium-webdriver/bidi/cookieFilter') const { BytesValue, SameSite } = require('selenium-webdriver/bidi/networkTypes') const { BrowsingContextPartitionDescriptor, StorageKeyPartitionDescriptor, } = require('selenium-webdriver/bidi/partitionDescriptor') const BrowserBiDi = require('selenium-webdriver/bidi/browser') const BrowsingContext = require('selenium-webdriver/bidi/browsingContext') const { CreateContextParameters } = require('selenium-webdriver/bidi/createContextParameters') const { PartialCookie } = require('selenium-webdriver/bidi/partialCookie') suite( function (env) { describe('BiDi Storage', function () { let driver beforeEach(async function () { driver = await env.builder().build() await driver.get(fileserver.Pages.ajaxyPage) await driver.manage().deleteAllCookies() return assertHasCookies() }) afterEach(function () { return driver.quit() }) it('can get cookie by name', async function () { const cookie = createCookieSpec() await driver.manage().addCookie(cookie) const cookieFilter = new CookieFilter() .name(cookie.name) .value(new BytesValue(BytesValue.Type.STRING, cookie.value)) const storage = await Storage(driver) const result = await storage.getCookies(cookieFilter) assert.strictEqual(result.cookies[0].value.value, cookie.value) }) ignore(env.browsers(Browser.CHROME, Browser.EDGE)).it( 'can get cookie in default user context', async function () { const windowHandle = await driver.getWindowHandle() const cookie = createCookieSpec() await driver.manage().addCookie(cookie) const cookieFilter = new CookieFilter() .name(cookie.name) .value(new BytesValue(BytesValue.Type.STRING, cookie.value)) await driver.switchTo().newWindow('window') const descriptor = new BrowsingContextPartitionDescriptor(await driver.getWindowHandle()) const storage = await Storage(driver) const resultAfterSwitchingContext = await storage.getCookies(cookieFilter, descriptor) assert.strictEqual(resultAfterSwitchingContext.cookies[0].value.value, cookie.value) await driver.switchTo().window(windowHandle) const descriptorAfterSwitchingBack = new BrowsingContextPartitionDescriptor(await driver.getWindowHandle()) const result = await storage.getCookies(cookieFilter, descriptorAfterSwitchingBack) assert.strictEqual(result.cookies[0].value.value, cookie.value) const partitionKey = result.partitionKey assert.notEqual(partitionKey.userContext, null) assert.notEqual(partitionKey.sourceOrigin, null) assert.strictEqual(partitionKey.userContext, 'default') }, ) it('can get cookie in a user context', async function () { const browser = await BrowserBiDi(driver) const userContext = await browser.createUserContext() const windowHandle = await driver.getWindowHandle() const cookie = { name: getRandomString(), value: 'set', } const partitionDescriptor = new StorageKeyPartitionDescriptor().userContext(userContext) const storage = await Storage(driver) const cookieDomain = fileserver.getHostName() const partialCookie = new PartialCookie( cookie.name, new BytesValue(BytesValue.Type.STRING, cookie.value), cookieDomain, ) await storage.setCookie(partialCookie, partitionDescriptor) const cookieFilter = new CookieFilter().name(cookie.name).value(new BytesValue(BytesValue.Type.STRING, 'set')) // Create a new browsing context with the user context const createParams = new CreateContextParameters().userContext(userContext) const browsingContext = await BrowsingContext(driver, { type: 'tab', createParameters: createParams, }) await driver.switchTo().window(browsingContext.id) const result = await storage.getCookies(cookieFilter, partitionDescriptor) assert.strictEqual(result.cookies.length > 0, true, 'Expected at least one cookie') assert.strictEqual(result.cookies[0].value.value, cookie.value) // Check if cookies were found assert.strictEqual(result.cookies.length > 0, true, 'Expected at least one cookie') assert.strictEqual(result.cookies[0].value.value, cookie.value) // Check partitionKey if it exists if (result.partitionKey) { const partitionKey = result.partitionKey assert.notEqual(partitionKey.userContext, null, 'Expected userContext to be non-null') assert.strictEqual(partitionKey.userContext, userContext, 'Expected userContext to match') } await driver.switchTo().window(windowHandle) const browsingContextPartitionDescriptor = new BrowsingContextPartitionDescriptor(windowHandle) const resultAfterSwitchingBack = await storage.getCookies(cookieFilter, browsingContextPartitionDescriptor) assert.strictEqual(resultAfterSwitchingBack.cookies.length, 0) }) it('can add cookie', async function () { const cookie = createCookieSpec() const storage = await Storage(driver) await storage.setCookie( new PartialCookie(cookie.name, new BytesValue(BytesValue.Type.STRING, cookie.value), fileserver.whereIs('/')), ) const cookieFilter = new CookieFilter() .name(cookie.name) .value(new BytesValue(BytesValue.Type.STRING, cookie.value)) const result = await storage.getCookies(cookieFilter) assert.strictEqual(result.cookies[0].value.value, cookie.value) }) it('can add and get cookie with all parameters', async function () { const cookie = createCookieSpec() const storage = await Storage(driver) const now = Date.now() const oneHourInMillis = 3600 * 1000 const expiry = now + oneHourInMillis const partitionDescriptor = new BrowsingContextPartitionDescriptor(await driver.getWindowHandle()) await storage.setCookie( new PartialCookie(cookie.name, new BytesValue(BytesValue.Type.STRING, cookie.value), fileserver.whereIs('/')) .path('/ajaxy_page.html') .size(100) .httpOnly(true) .secure(false) .sameSite(SameSite.LAX) .expiry(expiry), partitionDescriptor, ) const cookieFilter = new CookieFilter() .name(cookie.name) .value(new BytesValue(BytesValue.Type.STRING, cookie.value)) const result = await storage.getCookies(cookieFilter) const resultCookie = result.cookies[0] assert.strictEqual(resultCookie.name, cookie.name) assert.strictEqual(resultCookie.value.value, cookie.value) assert.strictEqual(resultCookie.domain.includes('http'), true) assert.strictEqual(resultCookie.path, '/ajaxy_page.html') assert.strictEqual(resultCookie.size > 0, true) assert.strictEqual(resultCookie.httpOnly, true) assert.strictEqual(resultCookie.secure, false) assert.strictEqual(resultCookie.sameSite, SameSite.LAX) assert.notEqual(resultCookie.expires, null) }) it('can get all cookies', async function () { const cookie1 = createCookieSpec() const cookie2 = createCookieSpec() await driver.manage().addCookie(cookie1) await driver.manage().addCookie(cookie2) const storage = await Storage(driver) const result = await storage.getCookies() assert.strictEqual(result.cookies[0].value.value, cookie1.value) assert.strictEqual(result.cookies[1].value.value, cookie2.value) }) it('can delete all cookies', async function () { const cookie1 = createCookieSpec() const cookie2 = createCookieSpec() await driver.manage().addCookie(cookie1) await driver.manage().addCookie(cookie2) const storage = await Storage(driver) await storage.deleteCookies(new CookieFilter()) const result = await storage.getCookies() assert.strictEqual(result.cookies.length, 0) }) it('can delete cookie by name', async function () { const cookie1 = createCookieSpec() const cookie2 = createCookieSpec() const storage = await Storage(driver) await driver.manage().addCookie(cookie1) await driver.manage().addCookie(cookie2) const result1 = await storage.getCookies(new CookieFilter()) assert.strictEqual(result1.cookies.length, 2) await storage.deleteCookies(new CookieFilter().name(cookie1.name)) const result = await storage.getCookies(new CookieFilter()) assert.strictEqual(result.cookies.length, 1) }) function createCookieSpec(opt_options) { let spec = { name: getRandomString(), value: getRandomString(), } if (opt_options) { spec = Object.assign(spec, opt_options) } return spec } 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 buildCookieMap(cookies) { const map = {} cookies.forEach(function (cookie) { map[cookie.name] = cookie }) return map } function getRandomString() { const x = 1234567890 return Math.floor(Math.random() * x).toString(36) } }) }, { browsers: [Browser.FIREFOX, Browser.CHROME, Browser.EDGE] }, )