123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- // 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';
- var fail = require('assert').fail;
- var webdriver = require('..'),
- Browser = webdriver.Browser,
- By = webdriver.By,
- assert = require('../testing/assert'),
- test = require('../lib/test');
- test.suite(function(env) {
- var driver;
- test.before(function*() {
- driver = yield env.builder().build();
- });
- test.after(function() {
- return driver.quit();
- });
- test.beforeEach(function() {
- return driver.get(test.Pages.echoPage);
- });
- describe('executeScript;', function() {
- var shouldHaveFailed = new Error('Should have failed');
- test.it('fails if script throws', function() {
- return execute('throw new Error("boom")')
- .then(function() { throw shouldHaveFailed; })
- .catch(function(e) {
- // The java WebDriver server adds a bunch of crap to error messages.
- // Error message will just be "JavaScript error" for IE.
- assert(e.message).matches(/.*(JavaScript error|boom).*/);
- });
- });
- test.it('fails if script does not parse', function() {
- return execute('throw function\\*')
- .then(function() { throw shouldHaveFailed; })
- .catch(function(e) {
- assert(e).notEqualTo(shouldHaveFailed);
- });
- });
- describe('scripts;', function() {
- test.it('do not pollute the global scope', function*() {
- yield execute('var x = 1;');
- yield assert(execute('return typeof x;')).equalTo('undefined');
- });
- test.it('can set global variables', function*() {
- yield execute('window.x = 1234;');
- yield assert(execute('return x;')).equalTo(1234);
- });
- test.it('may be defined as a function expression', function*() {
- let result = yield execute(function() {
- return 1234 + 'abc';
- });
- assert(result).equalTo('1234abc');
- });
- });
- describe('return values;', function() {
- test.it('returns undefined as null', function() {
- return assert(execute('var x; return x;')).isNull();
- });
- test.it('can return null', function() {
- return assert(execute('return null;')).isNull();
- });
- test.it('can return numbers', function*() {
- yield assert(execute('return 1234')).equalTo(1234);
- yield assert(execute('return 3.1456')).equalTo(3.1456);
- });
- test.it('can return strings', function() {
- return assert(execute('return "hello"')).equalTo('hello');
- });
- test.it('can return booleans', function*() {
- yield assert(execute('return true')).equalTo(true);
- yield assert(execute('return false')).equalTo(false);
- });
- test.it('can return an array of primitives', function() {
- return execute('var x; return [1, false, null, 3.14, x]')
- .then(verifyJson([1, false, null, 3.14, null]));
- });
- test.it('can return nested arrays', function() {
- return execute('return [[1, 2, [3]]]').then(verifyJson([[1, 2, [3]]]));
- });
- test.ignore(env.browsers(Browser.IE)).
- it('can return empty object literal', function() {
- return execute('return {}').then(verifyJson({}));
- });
- test.it('can return object literals', function() {
- return execute('return {a: 1, b: false, c: null}').then(result => {
- verifyJson(['a', 'b', 'c'])(Object.keys(result).sort());
- assert(result.a).equalTo(1);
- assert(result.b).equalTo(false);
- assert(result.c).isNull();
- });
- });
- test.it('can return complex object literals', function() {
- return execute('return {a:{b: "hello"}}')
- .then(verifyJson({a:{b: 'hello'}}));
- });
- test.it('can return dom elements as web elements', function*() {
- let result =
- yield execute('return document.querySelector(".header.host")');
- assert(result).instanceOf(webdriver.WebElement);
- return assert(result.getText()).startsWith('host: ');
- });
- test.it('can return array of dom elements', function*() {
- let result = yield execute(
- 'var nodes = document.querySelectorAll(".request,.host");' +
- 'return [nodes[0], nodes[1]];');
- assert(result.length).equalTo(2);
- assert(result[0]).instanceOf(webdriver.WebElement);
- yield assert(result[0].getText()).startsWith('GET ');
- assert(result[1]).instanceOf(webdriver.WebElement);
- yield assert(result[1].getText()).startsWith('host: ');
- });
- test.it('can return a NodeList as an array of web elements', function*() {
- let result =
- yield execute('return document.querySelectorAll(".request,.host");')
- assert(result.length).equalTo(2);
- assert(result[0]).instanceOf(webdriver.WebElement);
- yield assert(result[0].getText()).startsWith('GET ');
- assert(result[1]).instanceOf(webdriver.WebElement);
- yield assert(result[1].getText()).startsWith('host: ');
- });
- test.it('can return object literal with element property', function*() {
- let result = yield execute('return {a: document.body}');
- assert(result.a).instanceOf(webdriver.WebElement);
- yield assert(result.a.getTagName()).equalTo('body');
- });
- });
- describe('parameters;', function() {
- test.it('can pass numeric arguments', function*() {
- yield assert(execute('return arguments[0]', 12)).equalTo(12);
- yield assert(execute('return arguments[0]', 3.14)).equalTo(3.14);
- });
- test.it('can pass boolean arguments', function*() {
- yield assert(execute('return arguments[0]', true)).equalTo(true);
- yield assert(execute('return arguments[0]', false)).equalTo(false);
- });
- test.it('can pass string arguments', function*() {
- yield assert(execute('return arguments[0]', 'hi')).equalTo('hi');
- });
- test.it('can pass null arguments', function*() {
- yield assert(execute('return arguments[0] === null', null)).equalTo(true);
- yield assert(execute('return arguments[0]', null)).equalTo(null);
- });
- test.it('passes undefined as a null argument', function*() {
- var x;
- yield assert(execute('return arguments[0] === null', x)).equalTo(true);
- yield assert(execute('return arguments[0]', x)).equalTo(null);
- });
- test.it('can pass multiple arguments', function*() {
- yield assert(execute('return arguments.length')).equalTo(0);
- yield assert(execute('return arguments.length', 1, 'a', false)).equalTo(3);
- });
- test.ignore(env.browsers(Browser.FIREFOX, Browser.SAFARI)).
- it('can return arguments object as array', function*() {
- let val = yield execute('return arguments', 1, 'a', false);
- assert(val.length).equalTo(3);
- assert(val[0]).equalTo(1);
- assert(val[1]).equalTo('a');
- assert(val[2]).equalTo(false);
- });
- test.it('can pass object literal', function*() {
- let result = yield execute(
- 'return [typeof arguments[0], arguments[0].a]', {a: 'hello'})
- assert(result[0]).equalTo('object');
- assert(result[1]).equalTo('hello');
- });
- test.it('WebElement arguments are passed as DOM elements', function*() {
- let el = yield driver.findElement(By.tagName('div'));
- let result =
- yield execute('return arguments[0].tagName.toLowerCase();', el);
- assert(result).equalTo('div');
- });
- test.it('can pass array containing object literals', function*() {
- let result = yield execute('return arguments[0]', [{color: "red"}]);
- assert(result.length).equalTo(1);
- assert(result[0].color).equalTo('red');
- });
- test.it('does not modify object literal parameters', function() {
- var input = {color: 'red'};
- return execute('return arguments[0];', input).then(verifyJson(input));
- });
- });
- // See https://code.google.com/p/selenium/issues/detail?id=8223.
- describe('issue 8223;', function() {
- describe('using for..in loops;', function() {
- test.it('can return array built from for-loop index', function() {
- return execute(function() {
- var ret = [];
- for (var i = 0; i < 3; i++) {
- ret.push(i);
- }
- return ret;
- }).then(verifyJson[0, 1, 2]);
- });
- test.it('can copy input array contents', function() {
- return execute(function(input) {
- var ret = [];
- for (var i in input) {
- ret.push(input[i]);
- }
- return ret;
- }, ['fa', 'fe', 'fi']).then(verifyJson(['fa', 'fe', 'fi']));
- });
- test.it('can iterate over input object keys', function() {
- return execute(function(thing) {
- var ret = [];
- for (var w in thing.words) {
- ret.push(thing.words[w].word);
- }
- return ret;
- }, {words: [{word: 'fa'}, {word: 'fe'}, {word: 'fi'}]})
- .then(verifyJson(['fa', 'fe', 'fi']));
- });
- describe('recursive functions;', function() {
- test.it('can build array from input', function() {
- var input = ['fa', 'fe', 'fi'];
- return execute(function(thearray) {
- var ret = [];
- function build_response(thearray, ret) {
- ret.push(thearray.shift());
- return (!thearray.length && ret
- || build_response(thearray, ret));
- }
- return build_response(thearray, ret);
- }, input).then(verifyJson(input));
- });
- test.it('can build array from elements in object', function() {
- var input = {words: [{word: 'fa'}, {word: 'fe'}, {word: 'fi'}]};
- return execute(function(thing) {
- var ret = [];
- function build_response(thing, ret) {
- var item = thing.words.shift();
- ret.push(item.word);
- return (!thing.words.length && ret
- || build_response(thing, ret));
- }
- return build_response(thing, ret);
- }, input).then(verifyJson(['fa', 'fe', 'fi']));
- });
- });
- });
- });
- describe('async timeouts', function() {
- var TIMEOUT_IN_MS = 200;
- var ACCEPTABLE_WAIT = TIMEOUT_IN_MS / 10;
- var TOO_LONG_WAIT = TIMEOUT_IN_MS * 10;
- before(function() {
- return driver.manage().timeouts().setScriptTimeout(TIMEOUT_IN_MS)
- });
- test.it('does not fail if script execute in time', function() {
- return executeTimeOutScript(ACCEPTABLE_WAIT);
- });
- test.it('fails if script took too long', function() {
- return executeTimeOutScript(TOO_LONG_WAIT)
- .then(function() {
- fail('it should have timed out');
- }).catch(function(e) {
- assert(e.name).equalTo('ScriptTimeoutError');
- });
- });
- function executeTimeOutScript(sleepTime) {
- return driver.executeAsyncScript(function(sleepTime) {
- var callback = arguments[arguments.length - 1];
- setTimeout(callback, sleepTime)
- }, sleepTime);
- }
- })
- });
- function verifyJson(expected) {
- return function(actual) {
- return assert(JSON.stringify(actual)).equalTo(JSON.stringify(expected));
- };
- }
- function execute() {
- return driver.executeScript.apply(driver, arguments);
- }
- });
|