Path: blob/trunk/javascript/selenium-webdriver/test/bidi/generated/script_test.js
11822 views
// Licensed to the Software Freedom Conservancy (SFC) under one1// or more contributor license agreements. See the NOTICE file2// distributed with this work for additional information3// regarding copyright ownership. The SFC licenses this file4// to you under the Apache License, Version 2.0 (the5// "License"); you may not use this file except in compliance6// with the License. You may obtain a copy of the License at7//8// http://www.apache.org/licenses/LICENSE-2.09//10// Unless required by applicable law or agreed to in writing,11// software distributed under the License is distributed on an12// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY13// KIND, either express or implied. See the License for the14// specific language governing permissions and limitations15// under the License.1617'use strict'1819const assert = require('node:assert')20const { suite, Pages } = require('../../../lib/test')21const { Browser } = require('selenium-webdriver')2223const { Script } = require('selenium-webdriver/bidi/generated/script')2425suite(26function (env) {27let driver28let script2930beforeEach(async function () {31driver = await env.builder().build()32script = await Script.create(driver)33})3435afterEach(function () {36return driver.quit()37})3839describe('evaluate', function () {40it('can evaluate a simple expression', async function () {41const contextId = await driver.getWindowHandle()42const result = await script.evaluate({43expression: '1 + 2',44target: { context: contextId },45awaitPromise: false,46})4748assert.strictEqual(result.type, 'success')49assert.strictEqual(result.result.type, 'number')50assert.strictEqual(result.result.value, 3)51})5253it('can evaluate a string expression', async function () {54const contextId = await driver.getWindowHandle()55const result = await script.evaluate({56expression: '"hello" + " " + "world"',57target: { context: contextId },58awaitPromise: false,59})6061assert.strictEqual(result.type, 'success')62assert.strictEqual(result.result.type, 'string')63assert.strictEqual(result.result.value, 'hello world')64})6566it('can evaluate a boolean expression', async function () {67const contextId = await driver.getWindowHandle()68const result = await script.evaluate({69expression: '1 === 1',70target: { context: contextId },71awaitPromise: false,72})7374assert.strictEqual(result.type, 'success')75assert.strictEqual(result.result.type, 'boolean')76assert.strictEqual(result.result.value, true)77})7879it('captures exception details on error', async function () {80const contextId = await driver.getWindowHandle()81const result = await script.evaluate({82expression: 'throw new Error("test error")',83target: { context: contextId },84awaitPromise: false,85})8687assert.strictEqual(result.type, 'exception')88assert.ok(result.exceptionDetails)89assert.ok(result.exceptionDetails.text.includes('test error'))90})9192it('can await a promise', async function () {93const contextId = await driver.getWindowHandle()94const result = await script.evaluate({95expression: 'Promise.resolve(42)',96target: { context: contextId },97awaitPromise: true,98})99100assert.strictEqual(result.type, 'success')101assert.strictEqual(result.result.value, 42)102})103})104105describe('callFunction', function () {106it('can call a function with no arguments', async function () {107const contextId = await driver.getWindowHandle()108const result = await script.callFunction({109functionDeclaration: '() => 1 + 2',110awaitPromise: false,111target: { context: contextId },112})113114assert.strictEqual(result.type, 'success')115assert.strictEqual(result.result.value, 3)116})117118it('can call a function with arguments', async function () {119const contextId = await driver.getWindowHandle()120const result = await script.callFunction({121functionDeclaration: '(a, b) => a + b',122awaitPromise: false,123target: { context: contextId },124arguments: [125{ type: 'number', value: 10 },126{ type: 'number', value: 5 },127],128})129130assert.strictEqual(result.type, 'success')131assert.strictEqual(result.result.value, 15)132})133134it('can call a function that returns a string', async function () {135const contextId = await driver.getWindowHandle()136const result = await script.callFunction({137functionDeclaration: '() => document.title',138awaitPromise: false,139target: { context: contextId },140})141142assert.strictEqual(result.type, 'success')143assert.strictEqual(result.result.type, 'string')144})145146it('can call a function that returns an array', async function () {147const contextId = await driver.getWindowHandle()148const result = await script.callFunction({149functionDeclaration: '() => [1, 2, 3]',150awaitPromise: false,151target: { context: contextId },152})153154assert.strictEqual(result.type, 'success')155assert.strictEqual(result.result.type, 'array')156assert.ok(result.result.value)157})158159it('can call a function in a sandbox', async function () {160const contextId = await driver.getWindowHandle()161const result = await script.callFunction({162functionDeclaration: '() => 42',163awaitPromise: false,164target: { context: contextId, sandbox: 'testSandbox' },165})166167assert.strictEqual(result.type, 'success')168assert.strictEqual(result.result.value, 42)169})170171it('captures exception in callFunction', async function () {172const contextId = await driver.getWindowHandle()173const result = await script.callFunction({174functionDeclaration: '() => { throw new TypeError("bad input") }',175awaitPromise: false,176target: { context: contextId },177})178179assert.strictEqual(result.type, 'exception')180assert.ok(result.exceptionDetails)181})182})183184describe('getRealms', function () {185it('can get all realms', async function () {186const contextId = await driver.getWindowHandle()187await driver.get(Pages.emptyPage)188189const result = await script.getRealms({ context: contextId })190191assert.ok(Array.isArray(result.realms))192assert.ok(result.realms.length > 0)193194const windowRealm = result.realms.find((r) => r.type === 'window')195assert.ok(windowRealm, 'should have a window realm')196assert.ok(windowRealm.realm, 'realm id should be present')197assert.strictEqual(windowRealm.context, contextId)198})199200it('can get realms filtered by type', async function () {201const contextId = await driver.getWindowHandle()202const result = await script.getRealms({ context: contextId, type: 'window' })203204assert.ok(Array.isArray(result.realms))205assert.ok(result.realms.every((r) => r.type === 'window'))206})207208it('can use a realm target for evaluate', async function () {209const contextId = await driver.getWindowHandle()210const realmsResult = await script.getRealms({ context: contextId })211const realmId = realmsResult.realms[0].realm212213const evalResult = await script.evaluate({214expression: '2 * 21',215target: { realm: realmId },216awaitPromise: false,217})218219assert.strictEqual(evalResult.type, 'success')220assert.strictEqual(evalResult.result.value, 42)221})222})223224describe('preload scripts', function () {225it('can add and remove a preload script', async function () {226const result = await script.addPreloadScript({227functionDeclaration: '() => { window._testPreloaded = true; }',228})229230assert.ok(result.script, 'script id should be returned')231assert.strictEqual(typeof result.script, 'string')232233await script.removePreloadScript({ script: result.script })234})235236it('preload script runs on new page navigation', async function () {237const preload = await script.addPreloadScript({238functionDeclaration: '() => { window._preloadedValue = 99; }',239})240241await driver.get(Pages.emptyPage)242243const contextId = await driver.getWindowHandle()244const result = await script.evaluate({245expression: 'window._preloadedValue',246target: { context: contextId },247awaitPromise: false,248})249250assert.strictEqual(result.type, 'success')251assert.strictEqual(result.result.value, 99)252253await script.removePreloadScript({ script: preload.script })254})255256it('preload script scoped to a specific context', async function () {257const contextId = await driver.getWindowHandle()258259const preload = await script.addPreloadScript({260functionDeclaration: '() => { window._scopedPreload = "scoped"; }',261contexts: [contextId],262})263264assert.ok(preload.script)265266await script.removePreloadScript({ script: preload.script })267})268})269270describe('realm events', function () {271it('fires realmCreated when a new context is opened', async function () {272let realmCreated = null273274await script.onRealmCreated((params) => {275if (params.type === 'window') {276realmCreated = params277}278})279280// Opening a new window creates a new realm281await driver.switchTo().newWindow('tab')282await driver.wait(() => realmCreated !== null, 5000)283284assert.ok(realmCreated, 'realmCreated event should have fired')285assert.strictEqual(realmCreated.type, 'window')286assert.ok(realmCreated.realm)287})288289it('fires realmDestroyed when a context is closed', async function () {290const newHandle = await driver291.switchTo()292.newWindow('tab')293.then(() => driver.getWindowHandle())294295let realmDestroyed = null296await script.onRealmDestroyed((params) => {297realmDestroyed = params298})299300await driver.close()301await driver.wait(() => realmDestroyed !== null, 5000)302303// Switch back to original window304const handles = await driver.getAllWindowHandles()305await driver.switchTo().window(handles[0])306307assert.ok(realmDestroyed, 'realmDestroyed event should have fired')308assert.ok(realmDestroyed.realm)309})310})311},312{ browsers: [Browser.CHROME, Browser.FIREFOX] },313)314315316