Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/rb/spec/integration/selenium/webdriver/driver_spec.rb
4041 views
1
# frozen_string_literal: true
2
3
# Licensed to the Software Freedom Conservancy (SFC) under one
4
# or more contributor license agreements. See the NOTICE file
5
# distributed with this work for additional information
6
# regarding copyright ownership. The SFC licenses this file
7
# to you under the Apache License, Version 2.0 (the
8
# "License"); you may not use this file except in compliance
9
# with the License. You may obtain a copy of the License at
10
#
11
# http://www.apache.org/licenses/LICENSE-2.0
12
#
13
# Unless required by applicable law or agreed to in writing,
14
# software distributed under the License is distributed on an
15
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
# KIND, either express or implied. See the License for the
17
# specific language governing permissions and limitations
18
# under the License.
19
20
require_relative 'spec_helper'
21
22
module Selenium
23
module WebDriver
24
describe Driver, exclusive: {bidi: false, reason: 'Not yet implemented with BiDi'} do
25
after { reset_driver! if GlobalTestEnv.rbe? && GlobalTestEnv.browser == :chrome }
26
27
it_behaves_like 'driver that can be started concurrently', exclude: [
28
{browser: %i[safari safari_preview]},
29
{browser: :firefox, reason: 'https://github.com/SeleniumHQ/selenium/issues/15451'},
30
{driver: :remote, rbe: true, reason: 'Cannot start 2+ drivers at once.'}
31
]
32
33
it 'creates default capabilities', exclude: {browser: %i[safari safari_preview]} do
34
reset_driver! do |driver|
35
caps = driver.capabilities
36
expect(caps.proxy).to be_nil
37
expect(caps.browser_version).to match(/^\d\d\d?\./)
38
expect(caps.platform_name).not_to be_nil
39
40
expect(caps.accept_insecure_certs).to eq(caps.browser_name == 'firefox')
41
expect(caps.page_load_strategy).to eq 'normal'
42
expect(caps.implicit_timeout).to be_zero
43
expect(caps.page_load_timeout).to eq 300000
44
expect(caps.script_timeout).to eq 30000
45
end
46
end
47
48
it 'gets driver status' do
49
status = driver.status
50
expect(status).to include('ready', 'message')
51
end
52
53
it 'gets the page title' do
54
driver.navigate.to url_for('xhtmlTest.html')
55
expect(driver.title).to eq('XHTML Test Page')
56
end
57
58
it 'gets the page source' do
59
driver.navigate.to url_for('xhtmlTest.html')
60
expect(driver.page_source).to match(%r{<title>XHTML Test Page</title>}i)
61
end
62
63
it 'refreshes the page' do
64
driver.navigate.to url_for('javascriptPage.html')
65
short_wait { driver.find_element(id: 'updatediv') }.click
66
expect(driver.find_element(id: 'dynamo').text).to eq('Fish and chips!')
67
driver.navigate.refresh
68
wait_for_element(id: 'dynamo')
69
expect(driver.find_element(id: 'dynamo').text).to eq("What's for dinner?")
70
end
71
72
describe 'one element' do
73
it 'finds by id' do
74
driver.navigate.to url_for('xhtmlTest.html')
75
element = driver.find_element(id: 'id1')
76
expect(element).to be_a(WebDriver::Element)
77
expect(element.text).to eq('Foo')
78
end
79
80
it 'finds by field name' do
81
driver.navigate.to url_for('formPage.html')
82
expect(driver.find_element(name: 'x').attribute('value')).to eq('name')
83
end
84
85
it 'finds by class name' do
86
driver.navigate.to url_for('xhtmlTest.html')
87
expect(driver.find_element(class: 'header').text).to eq('XHTML Might Be The Future')
88
end
89
90
it 'finds by link text' do
91
driver.navigate.to url_for('xhtmlTest.html')
92
expect(driver.find_element(link: 'Foo').text).to eq('Foo')
93
end
94
95
it 'finds by xpath' do
96
driver.navigate.to url_for('xhtmlTest.html')
97
expect(driver.find_element(xpath: '//h1').text).to eq('XHTML Might Be The Future')
98
end
99
100
it 'finds by css selector' do
101
driver.navigate.to url_for('xhtmlTest.html')
102
expect(driver.find_element(css: 'div.content').attribute('class')).to eq('content')
103
end
104
105
it 'finds by tag name' do
106
driver.navigate.to url_for('xhtmlTest.html')
107
expect(driver.find_element(tag_name: 'div').attribute('class')).to eq('navigation')
108
end
109
110
it 'finds above another' do
111
driver.navigate.to url_for('relative_locators.html')
112
113
above = driver.find_element(relative: {tag_name: 'td', above: {id: 'center'}})
114
expect(above.attribute('id')).to eq('top')
115
end
116
117
it 'finds child element' do
118
driver.navigate.to url_for('nestedElements.html')
119
120
element = driver.find_element(name: 'form2')
121
child = element.find_element(name: 'selectomatic')
122
123
expect(child.attribute('id')).to eq('2')
124
end
125
126
it 'finds child element by tag name' do
127
driver.navigate.to url_for('nestedElements.html')
128
129
element = driver.find_element(name: 'form2')
130
child = element.find_element(tag_name: 'select')
131
132
expect(child.attribute('id')).to eq('2')
133
end
134
135
it 'finds elements with the shortcut syntax' do
136
driver.navigate.to url_for('xhtmlTest.html')
137
138
expect(driver[:id1]).to be_a(WebDriver::Element)
139
expect(driver[xpath: '//h1']).to be_a(WebDriver::Element)
140
end
141
142
it 'raises if element not found' do
143
driver.navigate.to url_for('xhtmlTest.html')
144
expect {
145
driver.find_element(id: 'not-there')
146
}.to raise_error(Error::NoSuchElementError, /errors#nosuchelementexception/)
147
end
148
149
it 'raises if invalid locator',
150
exclude: {browser: %i[safari safari_preview], reason: 'Safari TimeoutError'} do
151
driver.navigate.to url_for('xhtmlTest.html')
152
expect {
153
driver.find_element(xpath: '*?//-')
154
}.to raise_error(Error::InvalidSelectorError, /errors#invalidselectorexception/)
155
end
156
end
157
158
describe 'many elements' do
159
it 'finds by class name' do
160
driver.navigate.to url_for('xhtmlTest.html')
161
expect(driver.find_elements(class: 'nameC').size).to eq(2)
162
end
163
164
it 'finds by css selector' do
165
driver.navigate.to url_for('xhtmlTest.html')
166
expect(driver.find_elements(css: 'p').size).to be_positive
167
end
168
169
it 'finds above element' do
170
driver.navigate.to url_for('relative_locators.html')
171
172
lowest = driver.find_element(id: 'below')
173
above = driver.find_elements(relative: {tag_name: 'p', above: lowest})
174
expect(above.map { |e| e.attribute('id') }).to eq(%w[mid above])
175
end
176
177
it 'finds above another' do
178
driver.navigate.to url_for('relative_locators.html')
179
180
above = driver.find_elements(relative: {css: 'td', above: {id: 'center'}})
181
expect(above.map { |e| e.attribute('id') }).to eq(%w[top topLeft topRight])
182
end
183
184
it 'finds below element' do
185
driver.navigate.to url_for('relative_locators.html')
186
187
midpoint = driver.find_element(id: 'mid')
188
above = driver.find_elements(relative: {id: 'below', below: midpoint})
189
expect(above.map { |e| e.attribute('id') }).to eq(['below'])
190
end
191
192
it 'finds near another within default distance' do
193
driver.navigate.to url_for('relative_locators.html')
194
195
near = driver.find_elements(relative: {tag_name: 'td', near: {id: 'right'}})
196
expect(near.map { |e| e.attribute('id') }).to eq(%w[topRight bottomRight center top bottom])
197
end
198
199
it 'finds near another within custom distance', except: {browser: %i[safari safari_preview]} do
200
driver.navigate.to url_for('relative_locators.html')
201
202
near = driver.find_elements(relative: {tag_name: 'td', near: {id: 'right', distance: 100}})
203
expect(near.map { |e| e.attribute('id') }).to eq(%w[topRight bottomRight center top bottom])
204
end
205
206
it 'finds to the left of another' do
207
driver.navigate.to url_for('relative_locators.html')
208
209
left = driver.find_elements(relative: {tag_name: 'td', left: {id: 'center'}})
210
expect(left.map { |e| e.attribute('id') }).to eq(%w[left topLeft bottomLeft])
211
end
212
213
it 'finds to the right of another' do
214
driver.navigate.to url_for('relative_locators.html')
215
216
right = driver.find_elements(relative: {tag_name: 'td', right: {id: 'center'}})
217
expect(right.map { |e| e.attribute('id') }).to eq(%w[right topRight bottomRight])
218
end
219
220
it 'finds by combined relative locators' do
221
driver.navigate.to url_for('relative_locators.html')
222
223
found = driver.find_elements(relative: {tag_name: 'td', right: {id: 'top'}, above: {id: 'center'}})
224
expect(found.map { |e| e.attribute('id') }).to eq(['topRight'])
225
end
226
227
it 'finds all by empty relative locator' do
228
driver.navigate.to url_for('relative_locators.html')
229
230
expected = driver.find_elements(tag_name: 'p')
231
actual = driver.find_elements(relative: {tag_name: 'p'})
232
expect(actual).to eq(expected)
233
end
234
235
it 'finds children by field name' do
236
driver.navigate.to url_for('nestedElements.html')
237
element = driver.find_element(name: 'form2')
238
children = element.find_elements(name: 'selectomatic')
239
expect(children.size).to eq(2)
240
end
241
end
242
243
describe '#execute_script' do
244
it 'returns strings' do
245
driver.navigate.to url_for('xhtmlTest.html')
246
expect(driver.execute_script('return document.title;')).to eq('XHTML Test Page')
247
end
248
249
it 'returns numbers' do
250
driver.navigate.to url_for('xhtmlTest.html')
251
expect(driver.execute_script('return document.title.length;')).to eq(15)
252
end
253
254
it 'returns elements' do
255
driver.navigate.to url_for('xhtmlTest.html')
256
element = driver.execute_script("return document.getElementById('id1');")
257
expect(element).to be_a(WebDriver::Element)
258
expect(element.text).to eq('Foo')
259
end
260
261
it 'unwraps elements in deep objects' do
262
driver.navigate.to url_for('xhtmlTest.html')
263
result = driver.execute_script(<<~SCRIPT)
264
var e1 = document.getElementById('id1');
265
var body = document.body;
266
267
return {
268
elements: {'body' : body, other: [e1] }
269
};
270
SCRIPT
271
272
expect(result).to be_a(Hash)
273
expect(result['elements']['body']).to be_a(WebDriver::Element)
274
expect(result['elements']['other'].first).to be_a(WebDriver::Element)
275
end
276
277
it 'returns booleans' do
278
driver.navigate.to url_for('xhtmlTest.html')
279
expect(driver.execute_script('return true;')).to be(true)
280
end
281
282
it 'raises if the script is bad' do
283
driver.navigate.to url_for('xhtmlTest.html')
284
expect {
285
driver.execute_script('return squiggle();')
286
}.to raise_error(Selenium::WebDriver::Error::JavascriptError)
287
end
288
289
it 'returns arrays' do
290
driver.navigate.to url_for('xhtmlTest.html')
291
expect(driver.execute_script('return ["zero", "one", "two"];')).to eq(%w[zero one two])
292
end
293
294
it 'is able to call functions on the page' do
295
driver.navigate.to url_for('javascriptPage.html')
296
driver.execute_script("displayMessage('I like cheese');")
297
expect(driver.find_element(id: 'result').text.strip).to eq('I like cheese')
298
end
299
300
it 'is able to pass string arguments' do
301
driver.navigate.to url_for('javascriptPage.html')
302
expect(driver.execute_script("return arguments[0] == 'fish' ? 'fish' : 'not fish';", 'fish')).to eq('fish')
303
end
304
305
it 'is able to pass boolean arguments' do
306
driver.navigate.to url_for('javascriptPage.html')
307
expect(driver.execute_script('return arguments[0] == true;', true)).to be(true)
308
end
309
310
it 'is able to pass numeric arguments' do
311
driver.navigate.to url_for('javascriptPage.html')
312
expect(driver.execute_script('return arguments[0] == 1 ? 1 : 0;', 1)).to eq(1)
313
end
314
315
it 'is able to pass null arguments' do
316
driver.navigate.to url_for('javascriptPage.html')
317
expect(driver.execute_script('return arguments[0];', nil)).to be_nil
318
end
319
320
it 'is able to pass array arguments' do
321
driver.navigate.to url_for('javascriptPage.html')
322
expect(driver.execute_script('return arguments[0];', [1, '2', 3])).to eq([1, '2', 3])
323
end
324
325
it 'is able to pass element arguments' do
326
driver.navigate.to url_for('javascriptPage.html')
327
button = driver.find_element(id: 'plainButton')
328
js = "arguments[0]['flibble'] = arguments[0].getAttribute('id'); return arguments[0]['flibble'];"
329
expect(driver.execute_script(js, button))
330
.to eq('plainButton')
331
end
332
333
it 'is able to pass in multiple arguments' do
334
driver.navigate.to url_for('javascriptPage.html')
335
expect(driver.execute_script('return arguments[0] + arguments[1];', 'one', 'two')).to eq('onetwo')
336
end
337
end
338
339
describe 'execute async script' do
340
before do
341
driver.manage.timeouts.script = 1
342
driver.navigate.to url_for('ajaxy_page.html')
343
end
344
345
it 'is able to return arrays of primitives from async scripts' do
346
result = driver.execute_async_script "arguments[arguments.length - 1]([null, 123, 'abc', true, false]);"
347
expect(result).to eq([nil, 123, 'abc', true, false])
348
end
349
350
it 'is able to pass multiple arguments to async scripts' do
351
result = driver.execute_async_script 'arguments[arguments.length - 1](arguments[0] + arguments[1]);', 1, 2
352
expect(result).to eq(3)
353
end
354
355
# Safari raises TimeoutError instead
356
it 'times out if the callback is not invoked', except: {browser: %i[safari safari_preview]} do
357
expect {
358
# Script is expected to be async and explicitly callback, so this should timeout.
359
driver.execute_async_script 'return 1 + 2;'
360
}.to raise_error(Selenium::WebDriver::Error::ScriptTimeoutError)
361
end
362
end
363
end
364
end # WebDriver
365
end # Selenium
366
367