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