Skip to content

Commit 6337126

Browse files
committed
Resolve #273 - Improve wait tests
This means that when using a remote web driver, the delays will be longer and there will be a greater difference between the duration waited and the threshold for an error. This will avoid the tests "passing by accident" or "failing by accident" due to latency involved in using a remote web driver.
1 parent 7b64224 commit 6337126

2 files changed

Lines changed: 48 additions & 38 deletions

File tree

Tests/CSF.Screenplay.Selenium.Tests/Actions/WaitTests.cs

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
using System;
33
using CSF.Screenplay.Performables;
44
using CSF.Screenplay.Selenium.Elements;
5+
using OpenQA.Selenium;
6+
using OpenQA.Selenium.Remote;
57
using static CSF.Screenplay.PerformanceStarter;
68
using static CSF.Screenplay.Selenium.PerformableBuilder;
79

@@ -18,21 +20,28 @@ static readonly ITarget
1820

1921
static readonly NamedUri testPage = new NamedUri("WaitTests.html", "the test page");
2022

23+
static int GetDelayMilliseconds(Actor actor)
24+
=> actor.GetAbility<BrowseTheWeb>().WebDriver.Unproxy() is RemoteWebDriver ? 1500 : 250;
25+
26+
static int GetSufficientWaitMilliseconds(Actor actor)
27+
=> actor.GetAbility<BrowseTheWeb>().WebDriver.Unproxy() is RemoteWebDriver ? 2000 : 600;
28+
29+
static int GetInsufficientWaitMilliseconds(Actor actor) => 50;
30+
2131
[Test, Screenplay]
2232
public async Task WaitingForSufficientTimeShouldSucceed(IStage stage)
2333
{
2434
var webster = stage.Spotlight<Webster>();
2535

2636
await Given(webster).WasAbleTo(OpenTheUrl(testPage));
27-
await Given(webster).WasAbleTo(EnterTheText("250").Into(delayTimer));
37+
await Given(webster).WasAbleTo(EnterTheText(GetDelayMilliseconds(webster).ToString()).Into(delayTimer));
2838
await When(webster).AttemptsTo(ClickOn(clickableButton));
2939
await Then(webster).Should(WaitUntil(displayText.Has().Text("Clicked, and 250ms has elapsed"))
30-
.ForAtMost(TimeSpan.FromMilliseconds(500))
31-
.WithPollingInterval(TimeSpan.FromMilliseconds(150))
40+
.ForAtMost(TimeSpan.FromMilliseconds(GetSufficientWaitMilliseconds(webster)))
3241
);
3342
var contents = await Then(webster).Should(ReadFromTheElement(displayText).TheText());
3443

35-
Assert.That(contents, Is.EqualTo("Clicked, and 250ms has elapsed"));
44+
Assert.That(contents, Is.EqualTo($"Clicked, and {GetDelayMilliseconds(webster)}ms has elapsed"));
3645
}
3746

3847
[Test, Screenplay]
@@ -41,16 +50,15 @@ public async Task WaitingForSufficientTimeWithIgnoredExceptionsShouldSucceed(ISt
4150
var webster = stage.Spotlight<Webster>();
4251

4352
await Given(webster).WasAbleTo(OpenTheUrl(testPage));
44-
await Given(webster).WasAbleTo(EnterTheText("250").Into(delayTimer));
53+
await Given(webster).WasAbleTo(EnterTheText(GetDelayMilliseconds(webster).ToString()).Into(delayTimer));
4554
await When(webster).AttemptsTo(ClickOn(clickableButton));
46-
await Then(webster).Should(WaitUntil(displayTextSpan.Has().Text("250"))
47-
.ForAtMost(TimeSpan.FromMilliseconds(500))
48-
.WithPollingInterval(TimeSpan.FromMilliseconds(50))
55+
await Then(webster).Should(WaitUntil(displayTextSpan.Has().Text(GetDelayMilliseconds(webster).ToString()))
56+
.ForAtMost(TimeSpan.FromMilliseconds(GetSufficientWaitMilliseconds(webster)))
4957
.IgnoringTheseExceptionTypes(typeof(TargetNotFoundException))
5058
);
5159
var contents = await Then(webster).Should(ReadFromTheElement(displayText).TheText());
5260

53-
Assert.That(contents, Is.EqualTo("Clicked, and 250ms has elapsed"));
61+
Assert.That(contents, Is.EqualTo($"Clicked, and {GetDelayMilliseconds(webster)}ms has elapsed"));
5462
}
5563

5664
[Test, Screenplay]
@@ -59,16 +67,15 @@ public async Task WaitingForSufficientTimeWithoutIgnoredExceptionsShouldSucceed(
5967
var webster = stage.Spotlight<Webster>();
6068

6169
await Given(webster).WasAbleTo(OpenTheUrl(testPage));
62-
await Given(webster).WasAbleTo(EnterTheText("250").Into(delayTimer));
70+
await Given(webster).WasAbleTo(EnterTheText(GetDelayMilliseconds(webster).ToString()).Into(delayTimer));
6371
await When(webster).AttemptsTo(ClickOn(clickableButton));
64-
await Then(webster).Should(WaitUntil(displayTextSpan.Has().Text("250"))
65-
.ForAtMost(TimeSpan.FromMilliseconds(500))
66-
.WithPollingInterval(TimeSpan.FromMilliseconds(50))
72+
await Then(webster).Should(WaitUntil(displayTextSpan.Has().Text(GetDelayMilliseconds(webster).ToString()))
73+
.ForAtMost(TimeSpan.FromMilliseconds(GetSufficientWaitMilliseconds(webster)))
6774
// No ignored exceptions specified here, but the default behaviour will ignore TargetNotFoundException
6875
);
6976
var contents = await Then(webster).Should(ReadFromTheElement(displayText).TheText());
7077

71-
Assert.That(contents, Is.EqualTo("Clicked, and 250ms has elapsed"));
78+
Assert.That(contents, Is.EqualTo($"Clicked, and {GetDelayMilliseconds(webster)}ms has elapsed"));
7279
}
7380

7481
[Test, Screenplay]
@@ -77,11 +84,10 @@ public async Task WaitingForSufficientTimeWithEmptyIgnoredExceptionsShouldThrow(
7784
var webster = stage.Spotlight<Webster>();
7885

7986
await Given(webster).WasAbleTo(OpenTheUrl(testPage));
80-
await Given(webster).WasAbleTo(EnterTheText("250").Into(delayTimer));
87+
await Given(webster).WasAbleTo(EnterTheText(GetDelayMilliseconds(webster).ToString()).Into(delayTimer));
8188
await When(webster).AttemptsTo(ClickOn(clickableButton));
82-
Assert.That(async () => await Then(webster).Should(WaitUntil(displayTextSpan.Has().Text("250"))
83-
.ForAtMost(TimeSpan.FromMilliseconds(500))
84-
.WithPollingInterval(TimeSpan.FromMilliseconds(50))
89+
Assert.That(async () => await Then(webster).Should(WaitUntil(displayTextSpan.Has().Text(GetDelayMilliseconds(webster).ToString()))
90+
.ForAtMost(TimeSpan.FromMilliseconds(GetSufficientWaitMilliseconds(webster)))
8591
.IgnoringTheseExceptionTypes() // Explicitly empty
8692
), Throws.InstanceOf<PerformableException>());
8793
}
@@ -92,40 +98,41 @@ public async Task WaitingForInsufficientTimeShouldThrow(IStage stage)
9298
var webster = stage.Spotlight<Webster>();
9399

94100
await Given(webster).WasAbleTo(OpenTheUrl(testPage));
95-
await Given(webster).WasAbleTo(EnterTheText("2000").Into(delayTimer));
101+
await Given(webster).WasAbleTo(EnterTheText(GetDelayMilliseconds(webster).ToString()).Into(delayTimer));
96102
await When(webster).AttemptsTo(ClickOn(clickableButton));
97103

98-
Assert.That(async () => await Then(webster).Should(WaitUntil(displayText.Has().Text("Clicked, and 2000ms has elapsed")).ForAtMost(TimeSpan.FromMilliseconds(500))),
99-
Throws.InstanceOf<PerformableException>().And.InnerException.TypeOf<OpenQA.Selenium.WebDriverTimeoutException>());
104+
Assert.That(async () => await Then(webster).Should(WaitUntil(displayText.Has().Text($"Clicked, and {GetDelayMilliseconds(webster)}ms has elapsed"))
105+
.ForAtMost(TimeSpan.FromMilliseconds(GetInsufficientWaitMilliseconds(webster)))),
106+
Throws.InstanceOf<PerformableException>().And.InnerException.TypeOf<WebDriverTimeoutException>());
100107
}
101108

102109
[Test, Screenplay]
103110
public async Task WaitingForSufficientTimeUsingDefaultWaitAbilityShouldSucceed(IStage stage)
104111
{
105112
var webster = stage.Spotlight<Webster>();
106-
webster.IsAbleTo(new UseADefaultWaitTime(TimeSpan.FromMilliseconds(500)));
113+
webster.IsAbleTo(new UseADefaultWaitTime(TimeSpan.FromMilliseconds(GetSufficientWaitMilliseconds(webster))));
107114

108115
await Given(webster).WasAbleTo(OpenTheUrl(testPage));
109-
await Given(webster).WasAbleTo(EnterTheText("250").Into(delayTimer));
116+
await Given(webster).WasAbleTo(EnterTheText(GetDelayMilliseconds(webster).ToString()).Into(delayTimer));
110117
await When(webster).AttemptsTo(ClickOn(clickableButton));
111-
await Then(webster).Should(WaitUntil(displayText.Has().Text("Clicked, and 250ms has elapsed")));
118+
await Then(webster).Should(WaitUntil(displayText.Has().Text($"Clicked, and {GetDelayMilliseconds(webster)}ms has elapsed")));
112119
var contents = await Then(webster).Should(ReadFromTheElement(displayText).TheText());
113120

114-
Assert.That(contents, Is.EqualTo("Clicked, and 250ms has elapsed"));
121+
Assert.That(contents, Is.EqualTo($"Clicked, and {GetDelayMilliseconds(webster)}ms has elapsed"));
115122
}
116123

117124
[Test, Screenplay]
118125
public async Task WaitingForInsufficientTimeUsingDefaultWaitAbilityShouldThrow(IStage stage)
119126
{
120127
var webster = stage.Spotlight<Webster>();
121-
webster.IsAbleTo(new UseADefaultWaitTime(TimeSpan.FromMilliseconds(100)));
128+
webster.IsAbleTo(new UseADefaultWaitTime(TimeSpan.FromMilliseconds(GetInsufficientWaitMilliseconds(webster))));
122129

123130
await Given(webster).WasAbleTo(OpenTheUrl(testPage));
124-
await Given(webster).WasAbleTo(EnterTheText("2000").Into(delayTimer));
131+
await Given(webster).WasAbleTo(EnterTheText(GetDelayMilliseconds(webster).ToString()).Into(delayTimer));
125132
await When(webster).AttemptsTo(ClickOn(clickableButton));
126133

127-
Assert.That(async () => await Then(webster).Should(WaitUntil(displayText.Has().Text("Clicked, and 2000ms has elapsed"))),
128-
Throws.InstanceOf<PerformableException>().And.InnerException.TypeOf<OpenQA.Selenium.WebDriverTimeoutException>());
134+
Assert.That(async () => await Then(webster).Should(WaitUntil(displayText.Has().Text($"Clicked, and {GetDelayMilliseconds(webster)}ms has elapsed"))),
135+
Throws.InstanceOf<PerformableException>().And.InnerException.TypeOf<WebDriverTimeoutException>());
129136
}
130137

131138
[Test, Screenplay]
@@ -134,12 +141,12 @@ public async Task WaitingForSufficientTimeWithoutAPredicateShouldSucceed(IStage
134141
var webster = stage.Spotlight<Webster>();
135142

136143
await Given(webster).WasAbleTo(OpenTheUrl(testPage));
137-
await Given(webster).WasAbleTo(EnterTheText("250").Into(delayTimer));
144+
await Given(webster).WasAbleTo(EnterTheText(GetDelayMilliseconds(webster).ToString()).Into(delayTimer));
138145
await When(webster).AttemptsTo(ClickOn(clickableButton));
139-
await Then(webster).Should(WaitFor(TimeSpan.FromMilliseconds(300)));
146+
await Then(webster).Should(WaitFor(TimeSpan.FromMilliseconds(GetSufficientWaitMilliseconds(webster))));
140147
var contents = await Then(webster).Should(ReadFromTheElement(displayText).TheText());
141148

142-
Assert.That(contents, Is.EqualTo("Clicked, and 250ms has elapsed"));
149+
Assert.That(contents, Is.EqualTo($"Clicked, and {GetDelayMilliseconds(webster)}ms has elapsed"));
143150
}
144151

145152
[Test, Screenplay]
@@ -148,11 +155,11 @@ public async Task WaitingForInsufficientTimeWithoutAPredicateShouldYieldIncorrec
148155
var webster = stage.Spotlight<Webster>();
149156

150157
await Given(webster).WasAbleTo(OpenTheUrl(testPage));
151-
await Given(webster).WasAbleTo(EnterTheText("250").Into(delayTimer));
158+
await Given(webster).WasAbleTo(EnterTheText(GetDelayMilliseconds(webster).ToString()).Into(delayTimer));
152159
await When(webster).AttemptsTo(ClickOn(clickableButton));
153-
await Then(webster).Should(WaitFor(TimeSpan.FromMilliseconds(10)));
160+
await Then(webster).Should(WaitFor(TimeSpan.FromMilliseconds(GetInsufficientWaitMilliseconds(webster))));
154161
var contents = await Then(webster).Should(ReadFromTheElement(displayText).TheText());
155162

156-
Assert.That(contents, Is.Not.EqualTo("Clicked, and 250ms has elapsed"));
163+
Assert.That(contents, Is.Not.EqualTo($"Clicked, and {GetDelayMilliseconds(webster)}ms has elapsed"));
157164
}
158165
}

Tests/CSF.Screenplay.Selenium.Tests/Tasks/ClickAndWaitForDocumentReadyTests.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Linq;
23
using CSF.Screenplay.Performables;
34
using CSF.Screenplay.Selenium.Elements;
45
using OpenQA.Selenium;
@@ -15,6 +16,8 @@ static readonly ITarget
1516
link = new ElementId("clickable"),
1617
displayText = new ElementId("textContent");
1718

19+
static readonly string[] ignoredBrowsers = ["chrome", "edge"];
20+
1821
[Test, Screenplay]
1922
public async Task PerformAsAsyncShouldWaitSoItCanGetTheAppropriateContent(IStage stage)
2023
{
@@ -33,12 +36,12 @@ public async Task PerformAsAsyncShouldThrowIfWeDontWaitLongEnough(IStage stage)
3336
var webster = stage.Spotlight<Webster>();
3437
var ability = webster.GetAbility<BrowseTheWeb>();
3538

36-
if(ability.DriverOptions.BrowserName == "chrome")
37-
Assert.Pass("This test cannot meaningfully be run on a Chrome browser, because it always waits for the page load; treating as an implicit pass");
39+
if(ignoredBrowsers.Contains(ability.DriverOptions.BrowserName))
40+
Assert.Pass("This test cannot meaningfully be run on a Chrome or Edge browser, because they always wait for the page load. Treating this test as an implicit pass.");
3841

3942
await Given(webster).WasAbleTo(OpenTheUrl(startPage));
4043

41-
Assert.That(async () => await When(webster).AttemptsTo(ClickOn(link).AndWaitForANewPageToLoad(TimeSpan.FromMilliseconds(200))),
44+
Assert.That(async () => await When(webster).AttemptsTo(ClickOn(link).AndWaitForANewPageToLoad(TimeSpan.FromMilliseconds(100))),
4245
Throws.InstanceOf<PerformableException>().And.InnerException.InstanceOf<WebDriverException>());
4346
}
4447
}

0 commit comments

Comments
 (0)