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