Path: blob/trunk/javascript/selenium-webdriver/test/execute_script_test.js
2884 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 { Browser, By, WebElement, error } = require('selenium-webdriver')21const { Pages, ignore, suite } = require('../lib/test')2223suite(function (env) {24var driver2526before(async function () {27driver = await env.builder().build()28})2930after(function () {31return driver.quit()32})3334beforeEach(function () {35return driver.get(Pages.echoPage)36})3738describe('executeScript;', function () {39var shouldHaveFailed = new Error('Should have failed')4041it('fails if script throws', function () {42return execute('throw new Error("boom")')43.then(function () {44throw shouldHaveFailed45})46.catch(function (e) {47// The java WebDriver server adds a bunch of crap to error messages.48// Error message will just be "JavaScript error" for IE.49assert.ok(/.*(JavaScript error|boom).*/.test(e.message), `Unexpected error: ${e.message}`)50})51})5253it('fails if script does not parse', function () {54return execute('throw function\\*')55.then(function () {56throw shouldHaveFailed57})58.catch(function (e) {59assert.notEqual(e, shouldHaveFailed)60})61})6263describe('scripts;', function () {64it('do not pollute the global scope', async function () {65await execute('var x = 1;')66assert.strictEqual(await execute('return typeof x;'), 'undefined')67})6869it('can set global variables', async function () {70await execute('window.x = 1234;')71assert.strictEqual(await execute('return x;'), 1234)72})7374it('may be defined as a function expression', async function () {75let result = await execute(function () {76return 1234 + 'abc'77})78assert.strictEqual(result, '1234abc')79})80})8182describe('return values;', function () {83it('returns undefined as null', async function () {84assert.strictEqual(await execute('var x; return x;'), null)85})8687it('can return null', async function () {88assert.strictEqual(await execute('return null;'), null)89})9091it('can return numbers', async function () {92assert.strictEqual(await execute('return 1234'), 1234)93assert.strictEqual(await execute('return 3.1456'), 3.1456)94})9596it('can return strings', async function () {97assert.strictEqual(await execute('return "hello"'), 'hello')98})99100it('can return booleans', async function () {101assert.strictEqual(await execute('return true'), true)102assert.strictEqual(await execute('return false'), false)103})104105it('can return an array of primitives', function () {106return execute('var x; return [1, false, null, 3.14, x]').then(verifyJson([1, false, null, 3.14, null]))107})108109it('can return nested arrays', function () {110return execute('return [[1, 2, [3]]]').then(verifyJson([[1, 2, [3]]]))111})112113ignore(env.browsers(Browser.INTERNET_EXPLORER)).it('can return empty object literal', function () {114return execute('return {}').then(verifyJson({}))115})116117it('can return object literals', function () {118return execute('return {a: 1, b: false, c: null}').then((result) => {119verifyJson(['a', 'b', 'c'])(Object.keys(result).sort())120assert.strictEqual(result.a, 1)121assert.strictEqual(result.b, false)122assert.strictEqual(result.c, null)123})124})125126it('can return complex object literals', function () {127return execute('return {a:{b: "hello"}}').then(verifyJson({ a: { b: 'hello' } }))128})129130it('can return dom elements as web elements', async function () {131let result = await execute('return document.querySelector(".header.host")')132assert.ok(result instanceof WebElement)133134let text = await result.getText()135assert.ok(text.startsWith('host: '), `got: ${text}`)136})137138it('can return array of dom elements', async function () {139let result = await execute(140'var nodes = document.querySelectorAll(".request,.host");' + 'return [nodes[0], nodes[1]];',141)142assert.strictEqual(result.length, 2)143144assert.ok(result[0] instanceof WebElement)145assert.ok((await result[0].getText()).startsWith('GET '))146147assert.ok(result[1] instanceof WebElement)148assert.ok((await result[1].getText()).startsWith('host: '))149})150151it('can return a NodeList as an array of web elements', async function () {152let result = await execute('return document.querySelectorAll(".request,.host");')153154assert.strictEqual(result.length, 2)155156assert.ok(result[0] instanceof WebElement)157assert.ok((await result[0].getText()).startsWith('GET '))158159assert.ok(result[1] instanceof WebElement)160assert.ok((await result[1].getText()).startsWith('host: '))161})162163it('can return object literal with element property', async function () {164let result = await execute('return {a: document.body}')165166assert.ok(result.a instanceof WebElement)167assert.strictEqual((await result.a.getTagName()).toLowerCase(), 'body')168})169})170171describe('parameters;', function () {172it('can pass numeric arguments', async function () {173assert.strictEqual(await execute('return arguments[0]', 12), 12)174assert.strictEqual(await execute('return arguments[0]', 3.14), 3.14)175})176177it('can pass boolean arguments', async function () {178assert.strictEqual(await execute('return arguments[0]', true), true)179assert.strictEqual(await execute('return arguments[0]', false), false)180})181182it('can pass string arguments', async function () {183assert.strictEqual(await execute('return arguments[0]', 'hi'), 'hi')184})185186it('can pass null arguments', async function () {187assert.strictEqual(await execute('return arguments[0] === null', null), true)188assert.strictEqual(await execute('return arguments[0]', null), null)189})190191it('passes undefined as a null argument', async function () {192var x193assert.strictEqual(await execute('return arguments[0] === null', x), true)194assert.strictEqual(await execute('return arguments[0]', x), null)195})196197it('can pass multiple arguments', async function () {198assert.strictEqual(await execute('return arguments.length'), 0)199assert.strictEqual(await execute('return arguments.length', 1, 'a', false), 3)200})201202ignore(env.browsers(Browser.FIREFOX, Browser.SAFARI)).it(203'can return arguments object as array',204async function () {205let val = await execute('return arguments', 1, 'a', false)206207assert.strictEqual(val.length, 3)208assert.strictEqual(val[0], 1)209assert.strictEqual(val[1], 'a')210assert.strictEqual(val[2], false)211},212)213214it('can pass object literal', async function () {215let result = await execute('return [typeof arguments[0], arguments[0].a]', { a: 'hello' })216assert.strictEqual(result[0], 'object')217assert.strictEqual(result[1], 'hello')218})219220it('WebElement arguments are passed as DOM elements', async function () {221let el = await driver.findElement(By.tagName('div'))222let result = await execute('return arguments[0].tagName.toLowerCase();', el)223assert.strictEqual(result, 'div')224})225226it('can pass array containing object literals', async function () {227let result = await execute('return arguments[0]', [{ color: 'red' }])228assert.strictEqual(result.length, 1)229assert.strictEqual(result[0].color, 'red')230})231232it('does not modify object literal parameters', function () {233var input = { color: 'red' }234return execute('return arguments[0];', input).then(verifyJson(input))235})236})237238// See https://code.google.com/p/selenium/issues/detail?id=8223.239describe('issue 8223;', function () {240describe('using for..in loops;', function () {241it('can return array built from for-loop index', function () {242return execute(function () {243var ret = []244for (var i = 0; i < 3; i++) {245ret.push(i)246}247return ret248}).then(verifyJson[(0, 1, 2)])249})250251it('can copy input array contents', function () {252return execute(253function (input) {254var ret = []255for (var i in input) {256ret.push(input[i])257}258return ret259},260['fa', 'fe', 'fi'],261).then(verifyJson(['fa', 'fe', 'fi']))262})263264it('can iterate over input object keys', function () {265return execute(266function (thing) {267var ret = []268for (var w in thing.words) {269ret.push(thing.words[w].word)270}271return ret272},273{ words: [{ word: 'fa' }, { word: 'fe' }, { word: 'fi' }] },274).then(verifyJson(['fa', 'fe', 'fi']))275})276277describe('recursive functions;', function () {278it('can build array from input', function () {279var input = ['fa', 'fe', 'fi']280return execute(function (thearray) {281var ret = []282283function build_response(thearray, ret) {284ret.push(thearray.shift())285return (!thearray.length && ret) || build_response(thearray, ret)286}287288return build_response(thearray, ret)289}, input).then(verifyJson(input))290})291292it('can build array from elements in object', function () {293var input = {294words: [{ word: 'fa' }, { word: 'fe' }, { word: 'fi' }],295}296return execute(function (thing) {297var ret = []298299function build_response(thing, ret) {300var item = thing.words.shift()301ret.push(item.word)302return (!thing.words.length && ret) || build_response(thing, ret)303}304305return build_response(thing, ret)306}, input).then(verifyJson(['fa', 'fe', 'fi']))307})308})309})310})311312describe('async timeouts', function () {313var TIMEOUT_IN_MS = 200314var ACCEPTABLE_WAIT = TIMEOUT_IN_MS / 10315var TOO_LONG_WAIT = TIMEOUT_IN_MS * 10316317before(function () {318return driver.manage().setTimeouts({ script: TIMEOUT_IN_MS })319})320321it('does not fail if script execute in time', function () {322return executeTimeOutScript(ACCEPTABLE_WAIT)323})324325it('fails if script took too long', function () {326return executeTimeOutScript(TOO_LONG_WAIT)327.then(function () {328assert.fail('it should have timed out')329})330.catch(function (e) {331if (env.browser.name === Browser.SAFARI) {332assert.strictEqual(e.name, error.TimeoutError.name)333} else {334assert.strictEqual(e.name, error.ScriptTimeoutError.name)335}336})337})338339function executeTimeOutScript(sleepTime) {340return driver.executeAsyncScript(function (sleepTime) {341var callback = arguments[arguments.length - 1]342setTimeout(callback, sleepTime)343}, sleepTime)344}345})346})347348function verifyJson(expected) {349return function (actual) {350assert.strictEqual(JSON.stringify(actual), JSON.stringify(expected))351}352}353354function execute() {355return driver.executeScript.apply(driver, arguments)356}357})358359360