You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
351 lines
12 KiB
JavaScript
351 lines
12 KiB
JavaScript
// 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);
|
|
}
|
|
});
|