Skip to content

Commit ab42a51

Browse files
committed
Avoid sleep in drag'n'drop tests
fix the test page usability: make the elements visible only after they are fully initialized. To force revealing potential flaky tests in the future, I've added a small pause for the initialization code. So the tests should wait until the element appears on the screen - then it's ready for manipulations.
1 parent 5517f44 commit ab42a51

14 files changed

+222
-284
lines changed

common/src/web/dragAndDropTest.html

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<style>
55
<!--
66
.dragme{position:relative;}
7+
.hidden{visibility: hidden;}
78
-->
89
</style>
910
<script language="JavaScript1.2">
@@ -83,20 +84,25 @@
8384
}
8485
}
8586

86-
document.onmousedown=selectmouse;
87-
document.onmouseup=new Function("isdrag=false");
87+
setTimeout(() => {
88+
document.onmousedown = selectmouse;
89+
document.onmouseup = new Function("isdrag=false");
90+
document.querySelectorAll('.hidden').forEach(item => {
91+
item.classList.remove('hidden');
92+
})
93+
}, 30);
8894

8995
//-->
9096
</script>
9197

9298

9399

94-
<img src="icon.gif" class="dragme" id="test1"><br>
95-
<img src="icon.gif" class="dragme" id="test2"><br>
100+
<img src="icon.gif" class="dragme hidden" id="test1"><br>
101+
<img src="icon.gif" class="dragme hidden" id="test2"><br>
96102
<b>"Hi there</b>
97103
<div style="position: absolute; left: 210px; top: 80px; height: 400px; width: 100px; padding: 10em;">
98-
<img src="icon.gif" class="dragme" id="test3"><br>
99-
<img src="icon.gif" class="dragme" id="test4"><br>
104+
<img src="icon.gif" class="dragme hidden" id="test3"><br>
105+
<img src="icon.gif" class="dragme hidden" id="test4"><br>
100106
</div>
101107
</body>
102108
</html>

common/src/web/draggableLists.html

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
</style>
1515
<script type="text/javascript">
1616
$(function() {
17+
setTimeout(function() {
1718
$("#sortable1, #sortable2").sortable({
1819
connectWith: '.connectedSortable'
1920
}).disableSelection();
@@ -34,21 +35,23 @@
3435
drop: function(event, ui) {
3536
report_event("DropIn " + ui.draggable.text());
3637
}
37-
});
3838
});
39+
$("#sortable1, #sortable2").show();
40+
}, 30);
41+
});
3942
</script>
4043
</head>
4144
<body>
4245
<div class="demo">
43-
<ul id="sortable1" class="connectedSortable">
46+
<ul id="sortable1" class="connectedSortable" style="display: none;">
4447
<li id="leftitem-1" class="ui-state-default">LeftItem 1</li>
4548
<li id="leftitem-2" class="ui-state-default">LeftItem 2</li>
4649
<li id="leftitem-3" class="ui-state-default">LeftItem 3</li>
4750
<li id="leftitem-4" class="ui-state-default">LeftItem 4</li>
4851
<li id="leftitem-5" class="ui-state-default">LeftItem 5</li>
4952
</ul>
5053

51-
<ul id="sortable2" class="connectedSortable">
54+
<ul id="sortable2" class="connectedSortable" style="display: none;">
5255
<li id="rightitem-1" class="ui-state-highlight">RightItem 1</li>
5356
<li id="rightitem-2" class="ui-state-highlight">RightItem 2</li>
5457
<li id="rightitem-3" class="ui-state-highlight">RightItem 3</li>

common/src/web/droppableItems.html

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,42 +11,47 @@
1111
#droppable { width: 150px; height: 150px; padding: 0.5em; float: left; margin: 10px; }
1212
</style>
1313
<script type="text/javascript">
14-
$(function() {
15-
$("#draggable").draggable();
16-
$("#droppable").droppable({
17-
drop: function(event, ui) {
18-
$(this).addClass('ui-state-highlight').find('p').html('Dropped!');
19-
}
20-
});
14+
$(function () {
15+
setTimeout(function () {
16+
$("#draggable").draggable();
17+
$("#droppable").droppable({
18+
drop: function () {
19+
$(this).addClass('ui-state-highlight').find('p').html('Dropped!');
20+
}
21+
});
2122

22-
var report_event = function(report_text) {
23-
var reportElement = $("#drop_reports");
24-
var origText = reportElement.text();
23+
const report_event = function (report_text) {
24+
const reportElement = $("#drop_reports");
25+
const origText = reportElement.text();
2526
reportElement.text(origText + " " + report_text);
2627
}
2728

28-
$('body').mousedown(function() {
29-
report_event('down');
29+
$('body').mousedown(function () {
30+
report_event('down');
3031
});
3132

32-
$('body').mousemove(function() {
33-
report_event('move');
33+
$('body').mousemove(function () {
34+
report_event('move');
3435
});
3536

36-
$('body').mouseup(function() {
37-
report_event('up');
37+
$('body').mouseup(function () {
38+
report_event('up');
3839
});
39-
});
40+
41+
$("#droppable").show();
42+
$("#draggable").show();
43+
}, 30);
44+
});
4045
</script>
4146
</head>
4247
<body>
4348
<div class="demo">
4449

45-
<div id="draggable" class="ui-widget-content">
50+
<div id="draggable" class="ui-widget-content" style="display: none;">
4651
<p>Drag me to my target</p>
4752
</div>
4853

49-
<div id="droppable" class="ui-widget-header">
54+
<div id="droppable" class="ui-widget-header" style="display: none;">
5055
<p>Drop here</p>
5156
</div>
5257

common/src/web/macbeth.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
</HEAD>
88
<body bgcolor="#ffffff" text="#000000">
99

10+
<h1>The Tragedy of Macbeth</h1>
11+
1012
<!-- Originally from http://shakespeare.mit.edu/macbeth/full.html -->
1113

1214
<a href="#5.8.86">Quick link to last speech</a>

java/test/org/openqa/selenium/CorrectEventFiringTest.java

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,9 @@
1919

2020
import static org.assertj.core.api.Assertions.*;
2121
import static org.junit.jupiter.api.Assumptions.assumeFalse;
22-
import static org.openqa.selenium.WaitingConditions.elementTextToContain;
23-
import static org.openqa.selenium.WaitingConditions.elementTextToEqual;
24-
import static org.openqa.selenium.WaitingConditions.elementValueToEqual;
22+
import static org.openqa.selenium.WaitingConditions.*;
2523
import static org.openqa.selenium.support.ui.ExpectedConditions.visibilityOfElementLocated;
26-
import static org.openqa.selenium.testing.drivers.Browser.FIREFOX;
27-
import static org.openqa.selenium.testing.drivers.Browser.IE;
28-
import static org.openqa.selenium.testing.drivers.Browser.SAFARI;
24+
import static org.openqa.selenium.testing.drivers.Browser.*;
2925

3026
import java.io.File;
3127
import java.io.IOException;
@@ -392,23 +388,7 @@ public void testSendingKeysToAFocusedElementShouldNotBlurThatElement() {
392388
element.click();
393389

394390
// Wait until focused
395-
boolean focused = false;
396-
WebElement result = driver.findElement(By.id("result"));
397-
for (int i = 0; i < 5; ++i) {
398-
String fired = result.getText();
399-
if (fired.contains("focus")) {
400-
focused = true;
401-
break;
402-
}
403-
try {
404-
Thread.sleep(200);
405-
} catch (InterruptedException e) {
406-
throw new RuntimeException(e);
407-
}
408-
}
409-
assertThat(focused)
410-
.as("If clicking on element didn't focus it in time, we can't proceed with the test")
411-
.isTrue();
391+
wait.until(elementTextToContain(By.id("result"), "focus"));
412392

413393
element.sendKeys("a");
414394
assertEventNotFired("blur", driver);

java/test/org/openqa/selenium/ElementAttributeTest.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import static org.openqa.selenium.testing.drivers.Browser.SAFARI;
2828

2929
import java.util.List;
30-
import java.util.logging.Logger;
3130
import org.junit.jupiter.api.Test;
3231
import org.openqa.selenium.environment.webserver.Page;
3332
import org.openqa.selenium.support.ui.ExpectedConditions;
@@ -36,8 +35,6 @@
3635

3736
class ElementAttributeTest extends JupiterTestBase {
3837

39-
private static final Logger LOG = Logger.getLogger(ElementAttributeTest.class.getName());
40-
4138
@Test
4239
void testShouldReturnNullWhenGettingTheValueOfAnAttributeThatIsNotListed() {
4340
driver.get(pages.simpleTestPage);
@@ -265,12 +262,6 @@ void testCanReturnATextApproximationOfTheStyleAttribute() {
265262
void testShouldCorrectlyReportValueOfColspan() {
266263
driver.get(pages.tables);
267264

268-
try {
269-
Thread.sleep(1000);
270-
} catch (InterruptedException e) {
271-
LOG.severe("Error during execution: " + e.getMessage());
272-
}
273-
274265
WebElement th1 = driver.findElement(By.id("th1"));
275266
WebElement td2 = driver.findElement(By.id("td2"));
276267

java/test/org/openqa/selenium/WaitingConditions.java

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,7 @@ boolean compareText(String expectedValue, String actualValue) {
7777
}
7878

7979
public static ExpectedCondition<String> elementTextToEqual(final By locator, final String value) {
80-
return new ExpectedCondition<String>() {
81-
80+
return new ExpectedCondition<>() {
8281
@Override
8382
public String apply(WebDriver driver) {
8483
String text = driver.findElement(locator).getText();
@@ -96,19 +95,46 @@ public String toString() {
9695
};
9796
}
9897

98+
public static ExpectedCondition<String> elementTextToContain(
99+
final By locator, final String expected) {
100+
return new ExpectedCondition<>() {
101+
@Override
102+
public String apply(WebDriver driver) {
103+
String text = driver.findElement(locator).getText();
104+
return text.contains(expected) ? text : null;
105+
}
106+
107+
@Override
108+
public String toString() {
109+
return String.format("element text did not contain \"%s\"", expected);
110+
}
111+
};
112+
}
113+
114+
public static ExpectedCondition<String> elementTextToMatch(final By locator, final String regex) {
115+
return new ExpectedCondition<>() {
116+
@Override
117+
public String apply(WebDriver driver) {
118+
String text = driver.findElement(locator).getText();
119+
return text.matches(regex) ? text : null;
120+
}
121+
122+
@Override
123+
public String toString() {
124+
return String.format("element text did not match \"%s\"", regex);
125+
}
126+
};
127+
}
128+
99129
public static ExpectedCondition<String> elementValueToEqual(
100130
final WebElement element, final String expectedValue) {
101-
return new ExpectedCondition<String>() {
102-
131+
return new ExpectedCondition<>() {
103132
private String lastValue = "";
104133

105134
@Override
106135
public String apply(WebDriver ignored) {
107136
lastValue = element.getAttribute("value");
108-
if (expectedValue.equals(lastValue)) {
109-
return lastValue;
110-
}
111-
return null;
137+
return expectedValue.equals(lastValue) ? lastValue : null;
112138
}
113139

114140
@Override
@@ -119,15 +145,11 @@ public String toString() {
119145
}
120146

121147
public static ExpectedCondition<String> pageSourceToContain(final String expectedText) {
122-
return new ExpectedCondition<String>() {
148+
return new ExpectedCondition<>() {
123149
@Override
124150
public String apply(WebDriver driver) {
125151
String source = driver.getPageSource();
126-
127-
if (source.contains(expectedText)) {
128-
return source;
129-
}
130-
return null;
152+
return source.contains(expectedText) ? source : null;
131153
}
132154

133155
@Override
@@ -139,17 +161,13 @@ public String toString() {
139161

140162
public static ExpectedCondition<Point> elementLocationToBe(
141163
final WebElement element, final Point expectedLocation) {
142-
return new ExpectedCondition<Point>() {
164+
return new ExpectedCondition<>() {
143165
private Point currentLocation = new Point(0, 0);
144166

145167
@Override
146168
public Point apply(WebDriver ignored) {
147169
currentLocation = element.getLocation();
148-
if (currentLocation.equals(expectedLocation)) {
149-
return expectedLocation;
150-
}
151-
152-
return null;
170+
return currentLocation.equals(expectedLocation) ? expectedLocation : null;
153171
}
154172

155173
@Override
@@ -182,7 +200,7 @@ public static ExpectedCondition<String> newWindowIsOpened(final Set<String> orig
182200
}
183201

184202
public static ExpectedCondition<WebDriver> windowToBeSwitchedToWithName(final String windowName) {
185-
return new ExpectedCondition<WebDriver>() {
203+
return new ExpectedCondition<>() {
186204

187205
@Override
188206
public WebDriver apply(WebDriver driver) {
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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+
package org.openqa.selenium;
19+
20+
import static org.openqa.selenium.WaitingConditions.*;
21+
import static org.openqa.selenium.support.ui.ExpectedConditions.visibilityOfElementLocated;
22+
23+
import java.time.Duration;
24+
import org.junit.jupiter.api.BeforeEach;
25+
import org.junit.jupiter.api.Test;
26+
import org.openqa.selenium.support.ui.WebDriverWait;
27+
import org.openqa.selenium.testing.JupiterTestBase;
28+
29+
class WaitingConditionsTest extends JupiterTestBase {
30+
31+
private final By header = By.tagName("h1");
32+
private WebDriverWait wait;
33+
34+
@BeforeEach
35+
void setUp() {
36+
wait = new WebDriverWait(driver, Duration.ofMillis(1));
37+
driver.get(pages.macbethPage);
38+
shortWait.until(visibilityOfElementLocated(header));
39+
}
40+
41+
@Test
42+
void textEquals() {
43+
wait.until(elementTextToEqual(header, "The Tragedy of Macbeth"));
44+
}
45+
46+
@Test
47+
void textContains() {
48+
wait.until(elementTextToContain(driver.findElement(header), "he Tragedy of"));
49+
wait.until(elementTextToContain(driver.findElement(header), "The Tragedy"));
50+
wait.until(elementTextToContain(driver.findElement(header), "of Macbeth"));
51+
}
52+
53+
@Test
54+
void textMatches() {
55+
wait.until(elementTextToMatch(header, "The Tragedy of Macbeth"));
56+
wait.until(elementTextToMatch(header, ".+ Tragedy of .+"));
57+
}
58+
}

0 commit comments

Comments
 (0)