Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/rb/spec/integration/selenium/webdriver/element_spec.rb
1864 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 Element, exclusive: {bidi: false, reason: 'Not yet implemented with BiDi'} do
25
it 'clicks' do
26
driver.navigate.to url_for('formPage.html')
27
expect { driver.find_element(id: 'imageButton').click }.not_to raise_error
28
reset_driver!(time: 1) if %i[safari safari_preview].include? GlobalTestEnv.browser
29
end
30
31
# Safari returns "click intercepted" error instead of "element click intercepted"
32
it 'raises if different element receives click', except: {browser: %i[safari safari_preview]} do
33
driver.navigate.to url_for('click_tests/overlapping_elements.html')
34
expect { driver.find_element(id: 'contents').click }.to raise_error(Error::ElementClickInterceptedError)
35
end
36
37
# Safari returns "click intercepted" error instead of "element click intercepted"
38
it 'raises if element is partially covered', except: {browser: %i[safari safari_preview]} do
39
driver.navigate.to url_for('click_tests/overlapping_elements.html')
40
expect { driver.find_element(id: 'other_contents').click }.to raise_error(Error::ElementClickInterceptedError)
41
end
42
43
it 'raises if element stale' do
44
driver.navigate.to url_for('formPage.html')
45
button = driver.find_element(id: 'imageButton')
46
driver.navigate.refresh
47
48
expect { button.click }.to raise_exception(Error::StaleElementReferenceError,
49
/errors#stale-element-reference-exception/)
50
51
reset_driver!(time: 1) if %i[safari safari_preview].include? GlobalTestEnv.browser
52
end
53
54
describe '#submit' do
55
it 'valid submit button' do
56
driver.navigate.to url_for('formPage.html')
57
driver.find_element(id: 'submitButton').submit
58
59
sleep 0.5
60
expect(driver.title).to eq('We Arrive Here')
61
end
62
63
it 'any input element in form' do
64
driver.navigate.to url_for('formPage.html')
65
driver.find_element(id: 'checky').submit
66
67
sleep 0.5
68
expect(driver.title).to eq('We Arrive Here')
69
end
70
71
it 'any element in form' do
72
driver.navigate.to url_for('formPage.html')
73
driver.find_element(css: 'form > p').submit
74
75
sleep 0.5
76
expect(driver.title).to eq('We Arrive Here')
77
end
78
79
it 'button with id submit' do
80
driver.navigate.to url_for('formPage.html')
81
driver.find_element(id: 'submit').submit
82
83
sleep 0.5
84
expect(driver.title).to eq('We Arrive Here')
85
end
86
87
it 'button with name submit' do
88
driver.navigate.to url_for('formPage.html')
89
driver.find_element(name: 'submit').submit
90
91
sleep 0.5
92
expect(driver.title).to eq('We Arrive Here')
93
end
94
95
it 'errors with button outside form' do
96
driver.navigate.to url_for('formPage.html')
97
expect { driver.find_element(name: 'SearchableText').submit }.to raise_error(Error::UnsupportedOperationError)
98
end
99
end
100
101
it 'sends empty keys' do
102
driver.navigate.to url_for('formPage.html')
103
element = wait_for_element(id: 'working')
104
element.send_keys
105
expect(element.text).to be_empty
106
end
107
108
it 'sends string keys' do
109
driver.navigate.to url_for('formPage.html')
110
wait_for_element(id: 'working')
111
expect { driver.find_element(id: 'working').send_keys('foo', 'bar') }.not_to raise_error
112
end
113
114
it 'sends key presses' do
115
driver.navigate.to url_for('javascriptPage.html')
116
key_reporter = driver.find_element(id: 'keyReporter')
117
118
key_reporter.send_keys('Tet', :arrow_left, 's')
119
expect(key_reporter.attribute('value')).to eq('Test')
120
end
121
122
# https://github.com/mozilla/geckodriver/issues/245
123
it 'sends key presses chords', except: {browser: %i[firefox safari safari_preview]} do
124
driver.navigate.to url_for('javascriptPage.html')
125
key_reporter = driver.find_element(id: 'keyReporter')
126
127
key_reporter.send_keys([:shift, 'h'], 'ello')
128
expect(key_reporter.attribute('value')).to eq('Hello')
129
end
130
131
it 'handles file uploads' do
132
driver.navigate.to url_for('formPage.html')
133
134
element = driver.find_element(id: 'upload')
135
expect(element.attribute('value')).to be_empty
136
137
path = WebDriver::Platform.windows? ? WebDriver::Platform.windows_path(__FILE__) : __FILE__
138
139
element.send_keys path
140
141
expect(element.attribute('value')).to include(File.basename(path))
142
end
143
144
describe 'properties and attributes' do
145
before { driver.navigate.to url_for('formPage.html') }
146
147
context 'when string type' do
148
let(:element) { driver.find_element(id: 'checky') }
149
let(:prop_or_attr) { 'type' }
150
151
it '#dom_attribute returns attribute value' do
152
expect(element.dom_attribute(prop_or_attr)).to eq 'checkbox'
153
end
154
155
it '#property returns property value' do
156
expect(element.property(prop_or_attr)).to eq 'checkbox'
157
end
158
159
it '#attribute returns value' do
160
expect(element.attribute(prop_or_attr)).to eq 'checkbox'
161
end
162
end
163
164
context 'when numeric type' do
165
let(:element) { driver.find_element(id: 'withText') }
166
let(:prop_or_attr) { 'rows' }
167
168
it '#dom_attribute String' do
169
expect(element.dom_attribute(prop_or_attr)).to eq '5'
170
end
171
172
it '#property returns Number' do
173
expect(element.property(prop_or_attr)).to eq 5
174
end
175
176
it '#attribute returns String' do
177
expect(element.attribute(prop_or_attr)).to eq '5'
178
end
179
end
180
181
context 'with boolean type of true' do
182
let(:element) { driver.find_element(id: 'checkedchecky') }
183
let(:prop_or_attr) { 'checked' }
184
185
it '#dom_attribute returns String', except: {browser: :safari} do
186
expect(element.dom_attribute(prop_or_attr)).to eq 'true'
187
end
188
189
it '#property returns true' do
190
expect(element.property(prop_or_attr)).to be true
191
end
192
193
it '#attribute returns String' do
194
expect(element.attribute(prop_or_attr)).to eq 'true'
195
end
196
197
it '#dom_attribute does not update after click', except: {browser: :safari} do
198
element.click
199
expect(element.dom_attribute(prop_or_attr)).to eq 'true'
200
end
201
202
it '#property updates to false after click' do
203
element.click
204
expect(element.property(prop_or_attr)).to be false
205
end
206
207
it '#attribute updates to nil after click' do
208
element.click
209
expect(element.attribute(prop_or_attr)).to be_nil
210
end
211
end
212
213
context 'with boolean type of false' do
214
let(:element) { driver.find_element(id: 'checky') }
215
let(:prop_or_attr) { 'checked' }
216
217
it '#dom_attribute returns nil' do
218
expect(element.dom_attribute(prop_or_attr)).to be_nil
219
end
220
221
it '#property returns false' do
222
expect(element.property(prop_or_attr)).to be false
223
end
224
225
it '#attribute returns nil' do
226
expect(element.attribute(prop_or_attr)).to be_nil
227
end
228
229
it '#dom_attribute does not update after click' do
230
element.click
231
expect(element.dom_attribute(prop_or_attr)).to be_nil
232
end
233
234
it '#property updates to true after click' do
235
element.click
236
expect(element.property(prop_or_attr)).to be true
237
end
238
239
it '#attribute updates to String after click' do
240
element.click
241
expect(element.attribute(prop_or_attr)).to eq 'true'
242
end
243
end
244
245
context 'when property exists but attribute does not' do
246
let(:element) { driver.find_element(id: 'withText') }
247
let(:prop_or_attr) { 'value' }
248
249
it '#dom_attribute returns nil' do
250
expect(element.dom_attribute(prop_or_attr)).to be_nil
251
end
252
253
it '#property returns default property' do
254
expect(element.property(prop_or_attr)).to eq 'Example text'
255
end
256
257
it '#attribute returns default property' do
258
expect(element.attribute(prop_or_attr)).to eq 'Example text'
259
end
260
261
it '#property returns updated property' do
262
element.clear
263
expect(element.property(prop_or_attr)).to be_empty
264
end
265
266
it '#attribute returns updated property' do
267
element.clear
268
expect(element.attribute(prop_or_attr)).to be_empty
269
end
270
end
271
272
context 'when attribute exists but property does not' do
273
let(:element) { driver.find_element(id: 'vsearchGadget') }
274
let(:prop_or_attr) { 'accesskey' }
275
276
it '#dom_attribute returns attribute' do
277
expect(element.dom_attribute(prop_or_attr)).to eq '4'
278
end
279
280
it '#property returns nil' do
281
expect(element.property(prop_or_attr)).to be_nil
282
end
283
284
it '#attribute returns attribute' do
285
expect(element.attribute(prop_or_attr)).to eq '4'
286
end
287
end
288
289
context 'when neither attribute nor property exists' do
290
let(:element) { driver.find_element(id: 'checky') }
291
let(:prop_or_attr) { 'nonexistent' }
292
293
it '#dom_attribute returns nil' do
294
expect(element.dom_attribute(prop_or_attr)).to be_nil
295
end
296
297
it '#property returns nil' do
298
expect(element.property(prop_or_attr)).to be_nil
299
end
300
301
it '#attribute returns nil' do
302
expect(element.attribute(prop_or_attr)).to be_nil
303
end
304
end
305
306
describe 'style' do
307
before { driver.navigate.to url_for('clickEventPage.html') }
308
309
let(:element) { driver.find_element(id: 'result') }
310
let(:prop_or_attr) { 'style' }
311
312
it '#dom_attribute attribute with no formatting' do
313
expect(element.dom_attribute(prop_or_attr)).to eq 'width:300;height:60'
314
end
315
316
# TODO: This might not be correct behavior
317
it '#property returns object',
318
except: [{browser: :firefox,
319
reason: 'https://github.com/mozilla/geckodriver/issues/1846'},
320
{browser: :safari}] do
321
expect(element.property(prop_or_attr)).to eq %w[width height]
322
end
323
324
it '#attribute returns attribute with formatting' do
325
expect(element.attribute(prop_or_attr)).to eq 'width: 300px; height: 60px;'
326
end
327
end
328
329
describe 'incorrect casing' do
330
let(:element) { driver.find_element(id: 'checky') }
331
let(:prop_or_attr) { 'nAme' }
332
333
it '#dom_attribute returns correctly cased attribute' do
334
expect(element.dom_attribute(prop_or_attr)).to eq 'checky'
335
end
336
337
it '#property returns nil' do
338
expect(element.property(prop_or_attr)).to be_nil
339
end
340
341
it '#attribute returns correctly cased attribute' do
342
expect(element.attribute(prop_or_attr)).to eq 'checky'
343
end
344
end
345
346
describe 'property attribute case difference with attribute casing' do
347
let(:element) { driver.find_element(name: 'readonly') }
348
let(:prop_or_attr) { 'readonly' }
349
350
it '#dom_attribute returns a String', except: {browser: :safari} do
351
expect(element.dom_attribute(prop_or_attr)).to eq 'true'
352
end
353
354
it '#property returns nil' do
355
expect(element.property(prop_or_attr)).to be_nil
356
end
357
358
it '#attribute returns a String' do
359
expect(element.attribute(prop_or_attr)).to eq 'true'
360
end
361
end
362
363
describe 'property attribute case difference with property casing' do
364
let(:element) { driver.find_element(name: 'readonly') }
365
let(:prop_or_attr) { 'readOnly' }
366
367
it '#dom_attribute returns a String',
368
except: [{browser: :firefox,
369
reason: 'https://github.com/mozilla/geckodriver/issues/1850'},
370
{browser: :safari}] do
371
expect(element.dom_attribute(prop_or_attr)).to eq 'true'
372
end
373
374
it '#property returns property as true' do
375
expect(element.property(prop_or_attr)).to be true
376
end
377
378
it '#attribute returns property as String' do
379
expect(element.attribute(prop_or_attr)).to eq 'true'
380
end
381
end
382
383
describe 'property attribute name difference with attribute naming' do
384
let(:element) { driver.find_element(id: 'wallace') }
385
let(:prop_or_attr) { 'class' }
386
387
it '#dom_attribute returns attribute value' do
388
expect(element.dom_attribute(prop_or_attr)).to eq 'gromit'
389
end
390
391
it '#property returns nil' do
392
expect(element.property(prop_or_attr)).to be_nil
393
end
394
395
it '#attribute returns attribute value' do
396
expect(element.attribute(prop_or_attr)).to eq 'gromit'
397
end
398
end
399
400
describe 'property attribute name difference with property naming' do
401
let(:element) { driver.find_element(id: 'wallace') }
402
let(:prop_or_attr) { 'className' }
403
404
it '#dom_attribute returns nil' do
405
expect(element.dom_attribute(prop_or_attr)).to be_nil
406
end
407
408
it '#property returns property value' do
409
expect(element.property(prop_or_attr)).to eq 'gromit'
410
end
411
412
it '#attribute returns property value' do
413
expect(element.attribute(prop_or_attr)).to eq 'gromit'
414
end
415
end
416
417
describe 'property attribute value difference' do
418
let(:element) { driver.find_element(tag_name: 'form') }
419
let(:prop_or_attr) { 'action' }
420
421
it '#dom_attribute returns attribute value' do
422
expect(element.dom_attribute(prop_or_attr)).to eq 'resultPage.html'
423
end
424
425
it '#property returns property value' do
426
expect(element.property(prop_or_attr)).to match(%r{http://(.+)/resultPage\.html})
427
end
428
429
it '#attribute returns property value' do
430
expect(element.attribute(prop_or_attr)).to match(%r{http://(.+)/resultPage\.html})
431
end
432
end
433
end
434
435
it 'returns ARIA role' do
436
driver.navigate.to 'data:text/html,' \
437
"<div role='heading' aria-level='1'>Level 1 Header</div>" \
438
'<h1>Level 1 Header</h1>' \
439
"<h2 role='alert'>Level 2 Header</h2>"
440
expect(driver.find_element(tag_name: 'div').aria_role).to eq('heading')
441
expect(driver.find_element(tag_name: 'h1').aria_role).to eq('heading')
442
expect(driver.find_element(tag_name: 'h2').aria_role).to eq('alert')
443
end
444
445
it 'returns accessible name' do
446
driver.navigate.to 'data:text/html,<h1>Level 1 Header</h1>'
447
expect(driver.find_element(tag_name: 'h1').accessible_name).to eq('Level 1 Header')
448
end
449
450
it 'clears' do
451
driver.navigate.to url_for('formPage.html')
452
expect { driver.find_element(id: 'withText').clear }.not_to raise_error
453
end
454
455
it 'gets and set selected' do
456
driver.navigate.to url_for('formPage.html')
457
458
cheese = driver.find_element(id: 'cheese')
459
peas = driver.find_element(id: 'peas')
460
461
cheese.click
462
463
expect(cheese).to be_selected
464
expect(peas).not_to be_selected
465
466
peas.click
467
468
expect(peas).to be_selected
469
expect(cheese).not_to be_selected
470
end
471
472
it 'gets enabled' do
473
driver.navigate.to url_for('formPage.html')
474
expect(driver.find_element(id: 'notWorking')).not_to be_enabled
475
end
476
477
it 'gets text' do
478
driver.navigate.to url_for('xhtmlTest.html')
479
expect(driver.find_element(class: 'header').text).to eq('XHTML Might Be The Future')
480
end
481
482
it 'gets displayed' do
483
driver.navigate.to url_for('xhtmlTest.html')
484
expect(driver.find_element(class: 'header')).to be_displayed
485
end
486
487
describe 'size and location' do
488
it 'gets current location' do
489
driver.navigate.to url_for('xhtmlTest.html')
490
loc = driver.find_element(class: 'header').location
491
492
expect(loc.x).to be >= 1
493
expect(loc.y).to be >= 1
494
end
495
496
it 'gets location once scrolled into view' do
497
driver.navigate.to url_for('javascriptPage.html')
498
loc = driver.find_element(id: 'keyUp').location_once_scrolled_into_view
499
500
expect(loc.x).to be >= 1
501
expect(loc.y).to be >= 0 # can be 0 if scrolled to the top
502
end
503
504
it 'gets size' do
505
driver.navigate.to url_for('xhtmlTest.html')
506
size = driver.find_element(class: 'header').size
507
508
expect(size.width).to be_positive
509
expect(size.height).to be_positive
510
end
511
512
it 'gets rect' do
513
driver.navigate.to url_for('xhtmlTest.html')
514
rect = driver.find_element(class: 'header').rect
515
516
expect(rect.x).to be_positive
517
expect(rect.y).to be_positive
518
expect(rect.width).to be_positive
519
expect(rect.height).to be_positive
520
end
521
end
522
523
# IE - https://github.com/SeleniumHQ/selenium/pull/4043
524
it 'drags and drop', except: {browser: :ie} do
525
driver.navigate.to url_for('dragAndDropTest.html')
526
527
img1 = driver.find_element(id: 'test1')
528
img2 = driver.find_element(id: 'test2')
529
530
driver.action.drag_and_drop_by(img1, 100, 100)
531
.drag_and_drop(img2, img1)
532
.perform
533
534
expect(img1.location).to eq(img2.location)
535
end
536
537
it 'gets css property' do
538
driver.navigate.to url_for('javascriptPage.html')
539
element = driver.find_element(id: 'green-parent')
540
541
style1 = element.css_value('background-color')
542
style2 = element.style('background-color') # backwards compatibility
543
544
acceptable = ['rgb(0, 128, 0)', '#008000', 'rgba(0,128,0,1)', 'rgba(0, 128, 0, 1)']
545
expect(acceptable).to include(style1, style2)
546
end
547
548
it 'knows when two elements are equal' do
549
driver.navigate.to url_for('simpleTest.html')
550
551
body = driver.find_element(tag_name: 'body')
552
xbody = driver.find_element(xpath: '//body')
553
jsbody = driver.execute_script('return document.getElementsByTagName("body")[0]')
554
555
expect(body).to eq(xbody)
556
expect(body).to eq(jsbody)
557
expect(body).to eql(xbody)
558
expect(body).to eql(jsbody)
559
end
560
561
it 'knows when element arrays are equal' do
562
driver.navigate.to url_for('simpleTest.html')
563
564
tags = driver.find_elements(tag_name: 'div')
565
jstags = driver.execute_script('return document.getElementsByTagName("div")')
566
567
expect(tags).to eq(jstags)
568
end
569
570
it 'knows when two elements are not equal' do
571
driver.navigate.to url_for('simpleTest.html')
572
573
elements = driver.find_elements(tag_name: 'p')
574
p1 = elements.fetch(0)
575
p2 = elements.fetch(1)
576
577
expect(p1).not_to eq(p2)
578
expect(p1).not_to eql(p2)
579
end
580
581
it 'returns the same #hash for equal elements when found by Driver#find_element' do
582
driver.navigate.to url_for('simpleTest.html')
583
584
body = driver.find_element(tag_name: 'body')
585
xbody = driver.find_element(xpath: '//body')
586
587
expect(body.hash).to eq(xbody.hash)
588
end
589
590
it 'returns the same #hash for equal elements when found by Driver#find_elements' do
591
driver.navigate.to url_for('simpleTest.html')
592
593
body = driver.find_elements(tag_name: 'body').fetch(0)
594
xbody = driver.find_elements(xpath: '//body').fetch(0)
595
596
expect(body.hash).to eq(xbody.hash)
597
end
598
end
599
end # WebDriver
600
end # Selenium
601
602