UNPKG

12.4 kBJavaScriptView Raw
1// Licensed to the Software Freedom Conservancy (SFC) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The SFC licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18'use strict';
19
20var fail = require('assert').fail;
21
22var webdriver = require('..'),
23 Browser = webdriver.Browser,
24 By = webdriver.By,
25 assert = require('../testing/assert'),
26 test = require('../lib/test');
27
28
29test.suite(function(env) {
30 var driver;
31
32 test.before(function*() {
33 driver = yield env.builder().build();
34 });
35
36 test.after(function() {
37 return driver.quit();
38 });
39
40 test.beforeEach(function() {
41 return driver.get(test.Pages.echoPage);
42 });
43
44 describe('executeScript;', function() {
45 var shouldHaveFailed = new Error('Should have failed');
46
47 test.it('fails if script throws', function() {
48 return execute('throw new Error("boom")')
49 .then(function() { throw shouldHaveFailed; })
50 .catch(function(e) {
51 // The java WebDriver server adds a bunch of crap to error messages.
52 // Error message will just be "JavaScript error" for IE.
53 assert(e.message).matches(/.*(JavaScript error|boom).*/);
54 });
55 });
56
57 test.it('fails if script does not parse', function() {
58 return execute('throw function\\*')
59 .then(function() { throw shouldHaveFailed; })
60 .catch(function(e) {
61 assert(e).notEqualTo(shouldHaveFailed);
62 });
63 });
64
65 describe('scripts;', function() {
66 test.it('do not pollute the global scope', function*() {
67 yield execute('var x = 1;');
68 yield assert(execute('return typeof x;')).equalTo('undefined');
69 });
70
71 test.it('can set global variables', function*() {
72 yield execute('window.x = 1234;');
73 yield assert(execute('return x;')).equalTo(1234);
74 });
75
76 test.it('may be defined as a function expression', function*() {
77 let result = yield execute(function() {
78 return 1234 + 'abc';
79 });
80 assert(result).equalTo('1234abc');
81 });
82 });
83
84 describe('return values;', function() {
85
86 test.it('returns undefined as null', function() {
87 return assert(execute('var x; return x;')).isNull();
88 });
89
90 test.it('can return null', function() {
91 return assert(execute('return null;')).isNull();
92 });
93
94 test.it('can return numbers', function*() {
95 yield assert(execute('return 1234')).equalTo(1234);
96 yield assert(execute('return 3.1456')).equalTo(3.1456);
97 });
98
99 test.it('can return strings', function() {
100 return assert(execute('return "hello"')).equalTo('hello');
101 });
102
103 test.it('can return booleans', function*() {
104 yield assert(execute('return true')).equalTo(true);
105 yield assert(execute('return false')).equalTo(false);
106 });
107
108 test.it('can return an array of primitives', function() {
109 return execute('var x; return [1, false, null, 3.14, x]')
110 .then(verifyJson([1, false, null, 3.14, null]));
111 });
112
113 test.it('can return nested arrays', function() {
114 return execute('return [[1, 2, [3]]]').then(verifyJson([[1, 2, [3]]]));
115 });
116
117 test.ignore(env.browsers(Browser.IE)).
118 it('can return empty object literal', function() {
119 return execute('return {}').then(verifyJson({}));
120 });
121
122 test.it('can return object literals', function() {
123 return execute('return {a: 1, b: false, c: null}').then(result => {
124 verifyJson(['a', 'b', 'c'])(Object.keys(result).sort());
125 assert(result.a).equalTo(1);
126 assert(result.b).equalTo(false);
127 assert(result.c).isNull();
128 });
129 });
130
131 test.it('can return complex object literals', function() {
132 return execute('return {a:{b: "hello"}}')
133 .then(verifyJson({a:{b: 'hello'}}));
134 });
135
136 test.it('can return dom elements as web elements', function*() {
137 let result =
138 yield execute('return document.querySelector(".header.host")');
139 assert(result).instanceOf(webdriver.WebElement);
140
141 return assert(result.getText()).startsWith('host: ');
142 });
143
144 test.it('can return array of dom elements', function*() {
145 let result = yield execute(
146 'var nodes = document.querySelectorAll(".request,.host");' +
147 'return [nodes[0], nodes[1]];');
148 assert(result.length).equalTo(2);
149
150 assert(result[0]).instanceOf(webdriver.WebElement);
151 yield assert(result[0].getText()).startsWith('GET ');
152
153 assert(result[1]).instanceOf(webdriver.WebElement);
154 yield assert(result[1].getText()).startsWith('host: ');
155 });
156
157 test.it('can return a NodeList as an array of web elements', function*() {
158 let result =
159 yield execute('return document.querySelectorAll(".request,.host");')
160
161 assert(result.length).equalTo(2);
162
163 assert(result[0]).instanceOf(webdriver.WebElement);
164 yield assert(result[0].getText()).startsWith('GET ');
165
166 assert(result[1]).instanceOf(webdriver.WebElement);
167 yield assert(result[1].getText()).startsWith('host: ');
168 });
169
170 test.it('can return object literal with element property', function*() {
171 let result = yield execute('return {a: document.body}');
172
173 assert(result.a).instanceOf(webdriver.WebElement);
174 yield assert(result.a.getTagName()).equalTo('body');
175 });
176 });
177
178 describe('parameters;', function() {
179 test.it('can pass numeric arguments', function*() {
180 yield assert(execute('return arguments[0]', 12)).equalTo(12);
181 yield assert(execute('return arguments[0]', 3.14)).equalTo(3.14);
182 });
183
184 test.it('can pass boolean arguments', function*() {
185 yield assert(execute('return arguments[0]', true)).equalTo(true);
186 yield assert(execute('return arguments[0]', false)).equalTo(false);
187 });
188
189 test.it('can pass string arguments', function*() {
190 yield assert(execute('return arguments[0]', 'hi')).equalTo('hi');
191 });
192
193 test.it('can pass null arguments', function*() {
194 yield assert(execute('return arguments[0] === null', null)).equalTo(true);
195 yield assert(execute('return arguments[0]', null)).equalTo(null);
196 });
197
198 test.it('passes undefined as a null argument', function*() {
199 var x;
200 yield assert(execute('return arguments[0] === null', x)).equalTo(true);
201 yield assert(execute('return arguments[0]', x)).equalTo(null);
202 });
203
204 test.it('can pass multiple arguments', function*() {
205 yield assert(execute('return arguments.length')).equalTo(0);
206 yield assert(execute('return arguments.length', 1, 'a', false)).equalTo(3);
207 });
208
209 test.ignore(env.browsers(Browser.FIREFOX, Browser.SAFARI)).
210 it('can return arguments object as array', function*() {
211 let val = yield execute('return arguments', 1, 'a', false);
212
213 assert(val.length).equalTo(3);
214 assert(val[0]).equalTo(1);
215 assert(val[1]).equalTo('a');
216 assert(val[2]).equalTo(false);
217 });
218
219 test.it('can pass object literal', function*() {
220 let result = yield execute(
221 'return [typeof arguments[0], arguments[0].a]', {a: 'hello'})
222 assert(result[0]).equalTo('object');
223 assert(result[1]).equalTo('hello');
224 });
225
226 test.it('WebElement arguments are passed as DOM elements', function*() {
227 let el = yield driver.findElement(By.tagName('div'));
228 let result =
229 yield execute('return arguments[0].tagName.toLowerCase();', el);
230 assert(result).equalTo('div');
231 });
232
233 test.it('can pass array containing object literals', function*() {
234 let result = yield execute('return arguments[0]', [{color: "red"}]);
235 assert(result.length).equalTo(1);
236 assert(result[0].color).equalTo('red');
237 });
238
239 test.it('does not modify object literal parameters', function() {
240 var input = {color: 'red'};
241 return execute('return arguments[0];', input).then(verifyJson(input));
242 });
243 });
244
245 // See https://code.google.com/p/selenium/issues/detail?id=8223.
246 describe('issue 8223;', function() {
247 describe('using for..in loops;', function() {
248 test.it('can return array built from for-loop index', function() {
249 return execute(function() {
250 var ret = [];
251 for (var i = 0; i < 3; i++) {
252 ret.push(i);
253 }
254 return ret;
255 }).then(verifyJson[0, 1, 2]);
256 });
257
258 test.it('can copy input array contents', function() {
259 return execute(function(input) {
260 var ret = [];
261 for (var i in input) {
262 ret.push(input[i]);
263 }
264 return ret;
265 }, ['fa', 'fe', 'fi']).then(verifyJson(['fa', 'fe', 'fi']));
266 });
267
268 test.it('can iterate over input object keys', function() {
269 return execute(function(thing) {
270 var ret = [];
271 for (var w in thing.words) {
272 ret.push(thing.words[w].word);
273 }
274 return ret;
275 }, {words: [{word: 'fa'}, {word: 'fe'}, {word: 'fi'}]})
276 .then(verifyJson(['fa', 'fe', 'fi']));
277 });
278
279 describe('recursive functions;', function() {
280 test.it('can build array from input', function() {
281 var input = ['fa', 'fe', 'fi'];
282 return execute(function(thearray) {
283 var ret = [];
284 function build_response(thearray, ret) {
285 ret.push(thearray.shift());
286 return (!thearray.length && ret
287 || build_response(thearray, ret));
288 }
289 return build_response(thearray, ret);
290 }, input).then(verifyJson(input));
291 });
292
293 test.it('can build array from elements in object', function() {
294 var input = {words: [{word: 'fa'}, {word: 'fe'}, {word: 'fi'}]};
295 return execute(function(thing) {
296 var ret = [];
297 function build_response(thing, ret) {
298 var item = thing.words.shift();
299 ret.push(item.word);
300 return (!thing.words.length && ret
301 || build_response(thing, ret));
302 }
303 return build_response(thing, ret);
304 }, input).then(verifyJson(['fa', 'fe', 'fi']));
305 });
306 });
307 });
308 });
309
310 describe('async timeouts', function() {
311 var TIMEOUT_IN_MS = 200;
312 var ACCEPTABLE_WAIT = TIMEOUT_IN_MS / 10;
313 var TOO_LONG_WAIT = TIMEOUT_IN_MS * 10;
314
315 before(function() {
316 return driver.manage().timeouts().setScriptTimeout(TIMEOUT_IN_MS)
317 });
318
319 test.it('does not fail if script execute in time', function() {
320 return executeTimeOutScript(ACCEPTABLE_WAIT);
321 });
322
323 test.it('fails if script took too long', function() {
324 return executeTimeOutScript(TOO_LONG_WAIT)
325 .then(function() {
326 fail('it should have timed out');
327 }).catch(function(e) {
328 assert(e.name).equalTo('ScriptTimeoutError');
329 });
330 });
331
332 function executeTimeOutScript(sleepTime) {
333 return driver.executeAsyncScript(function(sleepTime) {
334 var callback = arguments[arguments.length - 1];
335 setTimeout(callback, sleepTime)
336 }, sleepTime);
337 }
338 })
339 });
340
341 function verifyJson(expected) {
342 return function(actual) {
343 return assert(JSON.stringify(actual)).equalTo(JSON.stringify(expected));
344 };
345 }
346
347 function execute() {
348 return driver.executeScript.apply(driver, arguments);
349 }
350});