1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | 'use strict';
|
19 |
|
20 | var fail = require('assert').fail;
|
21 |
|
22 | var webdriver = require('..'),
|
23 | Browser = webdriver.Browser,
|
24 | By = webdriver.By,
|
25 | assert = require('../testing/assert'),
|
26 | test = require('../lib/test');
|
27 |
|
28 |
|
29 | test.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 |
|
52 |
|
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 |
|
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 | });
|