Skip to content

Commit 88a8296

Browse files
authored
fix flaky Ruby test element_spec.rb (#16709)
* fix flaky Ruby test `element_spec.rb` Wait until the new URL gets loaded. Sometimes after executing `driver.navigate.to url_for('new_page.html')` the browser is still showing the previous page. Example of failure: ```ruby Selenium::WebDriver::Element raises if different element receives click Failure/Error: element = wait_for_element(id: 'contents', timeout: 10) Selenium::WebDriver::Error::TimeoutError: could not find element {:id=>"contents", :timeout=>10} in 25 seconds; page url: http://localhost:49887/resultPage.html?x=25&y=25; page source: <p id="greeting">Success!</p> ... # ./rb/lib/selenium/webdriver/common/wait.rb:76:in `until' # /Users/runner/work/selenium/selenium/rb/spec/integration/selenium/webdriver/spec_support/helpers.rb:93:in `wait_for_element' # ./rb/spec/integration/selenium/webdriver/element_spec.rb:35:in `block (2 levels) in <module:WebDriver>' ``` See https://github.com/SeleniumHQ/selenium/actions/runs/20055175531/job/57520193372#step:19:920 for example. * Open a blank page before every test It's a good practice to avoid tests affecting each other: 1. Open "about:blank" page - this stops any current activity / background requests / animations on the previous page 2. Open an empty page which clears sessionStorage, localStorage and cookies. This technique allows reusing the browser between tests, while keeping the tests independent.
1 parent 7284ec4 commit 88a8296

File tree

3 files changed

+51
-37
lines changed

3 files changed

+51
-37
lines changed

common/src/web/blank.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,6 @@
1-
<html><head><title>blank</title></head><body></body></html>
1+
<html><head><title>blank</title></head><body>
2+
<script>
3+
localStorage.clear();
4+
sessionStorage.clear();
5+
</script>
6+
</body></html>

rb/spec/integration/selenium/webdriver/element_spec.rb

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -23,28 +23,28 @@ module Selenium
2323
module WebDriver
2424
describe Element, exclusive: {bidi: false, reason: 'Not yet implemented with BiDi'} do
2525
it 'clicks' do
26-
driver.navigate.to url_for('formPage.html')
26+
open_file 'formPage.html'
2727
element = wait_for_element(id: 'imageButton')
2828
expect { element.click }.not_to raise_error
2929
reset_driver!(time: 1) if %i[safari safari_preview].include? GlobalTestEnv.browser
3030
end
3131

3232
# Safari returns "click intercepted" error instead of "element click intercepted"
3333
it 'raises if different element receives click', except: {browser: %i[safari safari_preview]} do
34-
driver.navigate.to url_for('click_tests/overlapping_elements.html')
34+
open_file 'click_tests/overlapping_elements.html'
3535
element = wait_for_element(id: 'contents', timeout: 10)
3636
expect { element.click }.to raise_error(Error::ElementClickInterceptedError)
3737
end
3838

3939
# Safari returns "click intercepted" error instead of "element click intercepted"
4040
it 'raises if element is partially covered', except: {browser: %i[safari safari_preview]} do
41-
driver.navigate.to url_for('click_tests/overlapping_elements.html')
41+
open_file 'click_tests/overlapping_elements.html'
4242
element = wait_for_element(id: 'other_contents')
4343
expect { element.click }.to raise_error(Error::ElementClickInterceptedError)
4444
end
4545

4646
it 'raises if element stale' do
47-
driver.navigate.to url_for('formPage.html')
47+
open_file 'formPage.html'
4848
button = wait_for_element(id: 'imageButton')
4949
driver.navigate.refresh
5050

@@ -56,67 +56,67 @@ module WebDriver
5656

5757
describe '#submit' do
5858
it 'valid submit button' do
59-
driver.navigate.to url_for('formPage.html')
59+
open_file 'formPage.html'
6060
wait_for_element(id: 'submitButton').submit
6161

6262
wait_for_url('resultPage.html')
6363
expect(driver.title).to eq('We Arrive Here')
6464
end
6565

6666
it 'any input element in form' do
67-
driver.navigate.to url_for('formPage.html')
67+
open_file 'formPage.html'
6868
wait_for_element(id: 'checky').submit
6969

7070
wait_for_url('resultPage.html')
7171
expect(driver.title).to eq('We Arrive Here')
7272
end
7373

7474
it 'any element in form' do
75-
driver.navigate.to url_for('formPage.html')
75+
open_file 'formPage.html'
7676
wait_for_element(css: 'form > p').submit
7777

7878
wait_for_url('resultPage.html')
7979
expect(driver.title).to eq('We Arrive Here')
8080
end
8181

8282
it 'button with id submit' do
83-
driver.navigate.to url_for('formPage.html')
83+
open_file 'formPage.html'
8484
wait_for_element(id: 'submit').submit
8585

8686
wait_for_url('resultPage.html')
8787
expect(driver.title).to eq('We Arrive Here')
8888
end
8989

9090
it 'button with name submit' do
91-
driver.navigate.to url_for('formPage.html')
91+
open_file 'formPage.html'
9292
wait_for_element(name: 'submit').submit
9393

9494
wait_for_url('resultPage.html')
9595
expect(driver.title).to eq('We Arrive Here')
9696
end
9797

9898
it 'errors with button outside form' do
99-
driver.navigate.to url_for('formPage.html')
99+
open_file 'formPage.html'
100100
element = wait_for_element(name: 'SearchableText')
101101
expect { element.submit }.to raise_error(Error::UnsupportedOperationError)
102102
end
103103
end
104104

105105
it 'sends empty keys' do
106-
driver.navigate.to url_for('formPage.html')
106+
open_file 'formPage.html'
107107
element = wait_for_element(id: 'working')
108108
element.send_keys
109109
expect(element.text).to be_empty
110110
end
111111

112112
it 'sends string keys' do
113-
driver.navigate.to url_for('formPage.html')
113+
open_file 'formPage.html'
114114
wait_for_element(id: 'working')
115115
expect { driver.find_element(id: 'working').send_keys('foo', 'bar') }.not_to raise_error
116116
end
117117

118118
it 'sends key presses' do
119-
driver.navigate.to url_for('javascriptPage.html')
119+
open_file 'javascriptPage.html'
120120
key_reporter = wait_for_element(id: 'keyReporter')
121121

122122
key_reporter.send_keys('Tet', :arrow_left, 's')
@@ -125,15 +125,15 @@ module WebDriver
125125

126126
# https://github.com/mozilla/geckodriver/issues/245
127127
it 'sends key presses chords', except: {browser: %i[firefox safari safari_preview]} do
128-
driver.navigate.to url_for('javascriptPage.html')
128+
open_file 'javascriptPage.html'
129129
key_reporter = wait_for_element(id: 'keyReporter')
130130

131131
key_reporter.send_keys([:shift, 'h'], 'ello')
132132
expect(key_reporter.attribute('value')).to eq('Hello')
133133
end
134134

135135
it 'handles file uploads' do
136-
driver.navigate.to url_for('formPage.html')
136+
open_file 'formPage.html'
137137

138138
element = wait_for_element(id: 'upload')
139139
expect(element.attribute('value')).to be_empty
@@ -146,7 +146,7 @@ module WebDriver
146146
end
147147

148148
describe 'properties and attributes' do
149-
before { driver.navigate.to url_for('formPage.html') }
149+
before { open_file 'formPage.html' }
150150

151151
context 'when string type' do
152152
let(:element) { wait_for_element(id: 'checky') }
@@ -308,7 +308,7 @@ module WebDriver
308308
end
309309

310310
describe 'style' do
311-
before { driver.navigate.to url_for('clickEventPage.html') }
311+
before { open_file 'clickEventPage.html' }
312312

313313
let(:element) { wait_for_element(id: 'result') }
314314
let(:prop_or_attr) { 'style' }
@@ -452,13 +452,13 @@ module WebDriver
452452
end
453453

454454
it 'clears' do
455-
driver.navigate.to url_for('formPage.html')
455+
open_file 'formPage.html'
456456
element = wait_for_element(id: 'withText')
457457
expect { element.clear }.not_to raise_error
458458
end
459459

460460
it 'gets and set selected' do
461-
driver.navigate.to url_for('formPage.html')
461+
open_file 'formPage.html'
462462

463463
cheese = wait_for_element(id: 'cheese')
464464
peas = wait_for_element(id: 'peas')
@@ -475,50 +475,50 @@ module WebDriver
475475
end
476476

477477
it 'gets enabled' do
478-
driver.navigate.to url_for('formPage.html')
478+
open_file 'formPage.html'
479479
element = wait_for_element(id: 'notWorking')
480480
expect(element).not_to be_enabled
481481
end
482482

483483
it 'gets text' do
484-
driver.navigate.to url_for('xhtmlTest.html')
484+
open_file 'xhtmlTest.html'
485485
element = wait_for_element(class: 'header')
486486
expect(element.text).to eq('XHTML Might Be The Future')
487487
end
488488

489489
it 'gets displayed' do
490-
driver.navigate.to url_for('xhtmlTest.html')
490+
open_file 'xhtmlTest.html'
491491
element = wait_for_element(class: 'header')
492492
expect(element).to be_displayed
493493
end
494494

495495
describe 'size and location' do
496496
it 'gets current location' do
497-
driver.navigate.to url_for('xhtmlTest.html')
497+
open_file 'xhtmlTest.html'
498498
loc = wait_for_element(class: 'header').location
499499

500500
expect(loc.x).to be >= 1
501501
expect(loc.y).to be >= 1
502502
end
503503

504504
it 'gets location once scrolled into view' do
505-
driver.navigate.to url_for('javascriptPage.html')
505+
open_file 'javascriptPage.html'
506506
loc = wait_for_element(id: 'keyUp').location_once_scrolled_into_view
507507

508508
expect(loc.x).to be >= 1
509509
expect(loc.y).to be >= 0 # can be 0 if scrolled to the top
510510
end
511511

512512
it 'gets size' do
513-
driver.navigate.to url_for('xhtmlTest.html')
513+
open_file 'xhtmlTest.html'
514514
size = wait_for_element(class: 'header').size
515515

516516
expect(size.width).to be_positive
517517
expect(size.height).to be_positive
518518
end
519519

520520
it 'gets rect' do
521-
driver.navigate.to url_for('xhtmlTest.html')
521+
open_file 'xhtmlTest.html'
522522
rect = wait_for_element(class: 'header').rect
523523

524524
expect(rect.x).to be_positive
@@ -530,7 +530,7 @@ module WebDriver
530530

531531
# IE - https://github.com/SeleniumHQ/selenium/pull/4043
532532
it 'drags and drop', except: {browser: :ie} do
533-
driver.navigate.to url_for('dragAndDropTest.html')
533+
open_file 'dragAndDropTest.html'
534534

535535
img1 = wait_for_element(id: 'test1')
536536
img2 = wait_for_element(id: 'test2')
@@ -543,7 +543,7 @@ module WebDriver
543543
end
544544

545545
it 'gets css property' do
546-
driver.navigate.to url_for('javascriptPage.html')
546+
open_file 'javascriptPage.html'
547547
element = wait_for_element(id: 'green-parent')
548548

549549
style1 = element.css_value('background-color')
@@ -554,7 +554,7 @@ module WebDriver
554554
end
555555

556556
it 'knows when two elements are equal' do
557-
driver.navigate.to url_for('simpleTest.html')
557+
open_file 'simpleTest.html'
558558

559559
body = wait_for_element(tag_name: 'body')
560560
xbody = wait_for_element(xpath: '//body')
@@ -567,7 +567,7 @@ module WebDriver
567567
end
568568

569569
it 'knows when element arrays are equal' do
570-
driver.navigate.to url_for('simpleTest.html')
570+
open_file 'simpleTest.html'
571571

572572
tags = driver.find_elements(tag_name: 'div')
573573
jstags = driver.execute_script('return document.getElementsByTagName("div")')
@@ -576,7 +576,7 @@ module WebDriver
576576
end
577577

578578
it 'knows when two elements are not equal' do
579-
driver.navigate.to url_for('simpleTest.html')
579+
open_file 'simpleTest.html'
580580

581581
elements = driver.find_elements(tag_name: 'p')
582582
p1 = elements.fetch(0)
@@ -587,7 +587,7 @@ module WebDriver
587587
end
588588

589589
it 'returns the same #hash for equal elements when found by Driver#find_element' do
590-
driver.navigate.to url_for('simpleTest.html')
590+
open_file 'simpleTest.html'
591591

592592
body = driver.find_element(tag_name: 'body')
593593
xbody = driver.find_element(xpath: '//body')
@@ -596,7 +596,7 @@ module WebDriver
596596
end
597597

598598
it 'returns the same #hash for equal elements when found by Driver#find_elements' do
599-
driver.navigate.to url_for('simpleTest.html')
599+
open_file 'simpleTest.html'
600600

601601
body = driver.find_elements(tag_name: 'body').fetch(0)
602602
xbody = driver.find_elements(xpath: '//body').fetch(0)

rb/spec/integration/selenium/webdriver/spec_support/helpers.rb

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,10 @@ def wait_for_element(locator, timeout = 25)
9393
wait.until { driver.find_element(locator) }
9494
end
9595

96-
def wait_for_url(new_url)
97-
wait = Wait.new(timeout: 5)
96+
def wait_for_url(new_url, timeout = 15)
97+
wait = Wait.new(timeout: timeout, message_provider: lambda {
98+
"could not wait for URL #{new_url} in #{timeout} seconds;\nactual page url: #{driver.current_url};\n"
99+
})
98100
wait.until do
99101
driver.current_url.include?(new_url)
100102
end
@@ -106,10 +108,17 @@ def wait_for_devtools_target(target_type:)
106108
end
107109

108110
def wait_for_title(title:)
109-
wait = Wait.new(timeout: 5)
111+
wait = Wait.new(timeout: 15)
110112
wait.until { driver.title == title }
111113
end
112114

115+
def open_file(file_name)
116+
driver.navigate.to 'about:blank'
117+
driver.navigate.to url_for('blank.html')
118+
driver.navigate.to url_for(file_name)
119+
wait_for_url(file_name)
120+
end
121+
113122
def wait(timeout = 10)
114123
Wait.new(timeout: timeout)
115124
end

0 commit comments

Comments
 (0)