diff --git a/db.ssmssln b/db.ssmssln
index b05ef5e9..52d89ac2 100644
--- a/db.ssmssln
+++ b/db.ssmssln
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# SQL Server Management Studio Solution File, Format Version 14.00
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{4F2E2C19-372F-40D8-9FA7-9D2138C6997A}") = "db", "db\db.ssmssqlproj", "{3107E538-B771-4F20-A68F-E7B9827FCBE6}"
+Project("{4F2E2C19-372F-40D8-9FA7-9D2138C6997A}") = "db", "src\db\db.ssmssqlproj", "{3107E538-B771-4F20-A68F-E7B9827FCBE6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/src/apicaller.core/apicaller.core.csproj b/src/apicaller.core/apicaller.core.csproj
index 481e3593..c26d2934 100644
--- a/src/apicaller.core/apicaller.core.csproj
+++ b/src/apicaller.core/apicaller.core.csproj
@@ -6,12 +6,12 @@
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/src/apiservice.core/Controllers/Makefile b/src/apiservice.core/Controllers/Makefile
index 33bbc379..f91e3546 100644
--- a/src/apiservice.core/Controllers/Makefile
+++ b/src/apiservice.core/Controllers/Makefile
@@ -10,7 +10,7 @@ Accesscode_sm.dot: Accesscode.sm
Accesscode_sm.png: Accesscode_sm.dot
dot -T png -o Accesscode_sm.png Accesscode_sm.dot
- xcopy /D /F /Y Accesscode_sm.png ..\..\doc\img
+ xcopy /D /F /Y Accesscode_sm.png ..\..\..\doc\img
clean:
-del Accesscode_sm.cs
diff --git a/src/apiservice.core/apiservice.core.csproj b/src/apiservice.core/apiservice.core.csproj
index 96552692..5c8b3642 100644
--- a/src/apiservice.core/apiservice.core.csproj
+++ b/src/apiservice.core/apiservice.core.csproj
@@ -15,17 +15,17 @@
-
-
-
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/src/apitest.core/apitest.core.csproj b/src/apitest.core/apitest.core.csproj
index 258c47ca..688c8d46 100644
--- a/src/apitest.core/apitest.core.csproj
+++ b/src/apitest.core/apitest.core.csproj
@@ -9,7 +9,7 @@
-
+
all
diff --git a/src/asp.core/Startup.cs b/src/asp.core/Startup.cs
index 32ee1579..f07d605a 100644
--- a/src/asp.core/Startup.cs
+++ b/src/asp.core/Startup.cs
@@ -54,6 +54,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.UseDeveloperExceptionPage(); // always for this demo
app.UseExceptionHandler("/Error/Error");
app.UseMiddleware(); // Global.asax
+ app.UseMiddleware();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseSession();
diff --git a/src/asp.webforms/Web.config b/src/asp.webforms/Web.config
index 1600f455..454dbc61 100644
--- a/src/asp.webforms/Web.config
+++ b/src/asp.webforms/Web.config
@@ -6,20 +6,17 @@
-
+
-
+
-
-
+
@@ -47,18 +44,12 @@
-
+
-
-
+
+
\ No newline at end of file
diff --git a/src/asp.webforms/asp.webforms.csproj b/src/asp.webforms/asp.webforms.csproj
index c04338ad..c569518b 100644
--- a/src/asp.webforms/asp.webforms.csproj
+++ b/src/asp.webforms/asp.webforms.csproj
@@ -46,8 +46,8 @@
4
-
- ..\..\packages\AjaxControlToolkit.19.1.0\lib\net40\AjaxControlToolkit.dll
+
+ ..\..\packages\AjaxControlToolkit.20.1.0\lib\net40\AjaxControlToolkit.dll
..\..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.dll
diff --git a/src/asp.webforms/packages.config b/src/asp.webforms/packages.config
index c2e710be..a906121f 100644
--- a/src/asp.webforms/packages.config
+++ b/src/asp.webforms/packages.config
@@ -1,6 +1,6 @@
-
+
diff --git a/src/asp.websharper.spa.fs/Startup.fs b/src/asp.websharper.spa.fs/Startup.fs
index 6244ec4d..4e2ee08d 100644
--- a/src/asp.websharper.spa.fs/Startup.fs
+++ b/src/asp.websharper.spa.fs/Startup.fs
@@ -33,7 +33,8 @@ type Startup private () =
member this.Configure(app: IApplicationBuilder, env: IWebHostEnvironment) =
if (env.IsDevelopment()) then
WebSharper.Web.Remoting.DisableCsrfProtection() |> ignore // Prevent HTTP 403 errors in GUI tests
- app.UseDeveloperExceptionPage() |> ignore
+ app.UseDeveloperExceptionPage()
+ .UseMiddleware() |> ignore
else
app.UseHttpsRedirection()
.UseHsts() |> ignore
diff --git a/src/asp.websharper.spa.fs/wwwroot/triptych.html b/src/asp.websharper.spa.fs/wwwroot/triptych.html
index adb88062..1b819763 100644
--- a/src/asp.websharper.spa.fs/wwwroot/triptych.html
+++ b/src/asp.websharper.spa.fs/wwwroot/triptych.html
@@ -13,6 +13,8 @@
}
.calc-box {
+ position: relative;
+ z-index: 1;
border: 1px solid black;
border-radius: 10px;
padding: 30px;
diff --git a/src/asp.websharper.spa/Startup.cs b/src/asp.websharper.spa/Startup.cs
index ef2802a6..33719b21 100644
--- a/src/asp.websharper.spa/Startup.cs
+++ b/src/asp.websharper.spa/Startup.cs
@@ -8,7 +8,6 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
-using Microsoft.Net.Http.Headers;
using System;
using WebSharper.AspNetCore;
@@ -51,7 +50,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
if (env.IsDevelopment())
{
WebSharper.Web.Remoting.DisableCsrfProtection(); // Prevent HTTP 403 errors in GUI tests
- app.UseDeveloperExceptionPage();
+ app.UseDeveloperExceptionPage()
+ .UseMiddleware();
}
else
{
diff --git a/src/asp.websharper.spa/wwwroot/triptych.html b/src/asp.websharper.spa/wwwroot/triptych.html
index adb88062..1b819763 100644
--- a/src/asp.websharper.spa/wwwroot/triptych.html
+++ b/src/asp.websharper.spa/wwwroot/triptych.html
@@ -13,6 +13,8 @@
}
.calc-box {
+ position: relative;
+ z-index: 1;
border: 1px solid black;
border-radius: 10px;
padding: 30px;
diff --git a/src/asplib.core/asplib.core.csproj b/src/asplib.core/asplib.core.csproj
index 0aacfbd5..f2ffe5b8 100644
--- a/src/asplib.core/asplib.core.csproj
+++ b/src/asplib.core/asplib.core.csproj
@@ -19,11 +19,11 @@
-
+
-
-
-
+
+
+
diff --git a/src/asplib.websharper/Remoting/RequestQuerySessionMiddleware.cs b/src/asplib.websharper/Remoting/RequestQuerySessionMiddleware.cs
index 07038877..946394ef 100644
--- a/src/asplib.websharper/Remoting/RequestQuerySessionMiddleware.cs
+++ b/src/asplib.websharper/Remoting/RequestQuerySessionMiddleware.cs
@@ -1,9 +1,9 @@
using asplib.Model;
using Microsoft.AspNetCore.Http;
+using System;
using System.Collections.Generic;
-using System.Threading.Tasks;
using System.Net;
-using System;
+using System.Threading.Tasks;
namespace asplib.Remoting
{
diff --git a/src/asptest.websharper.spa.fs/Calculator/CalculateTest.cs b/src/asptest.websharper.spa.fs/Calculator/CalculateTest.cs
index 879eb2c9..0a662731 100644
--- a/src/asptest.websharper.spa.fs/Calculator/CalculateTest.cs
+++ b/src/asptest.websharper.spa.fs/Calculator/CalculateTest.cs
@@ -2,10 +2,12 @@
using iselenium;
using NUnit.Framework;
using OpenQA.Selenium;
+using OpenQA.Selenium.IE;
using static asplib.View.TagHelper;
namespace asptest.Calculator
{
+ [TestFixture(typeof(InternetExplorerDriver))]
public class CalculateTest : CalculatorTestBase
where TWebDriver : IWebDriver, new()
{
diff --git a/src/asptest.websharper.spa.fs/Calculator/FibonacciTest.cs b/src/asptest.websharper.spa.fs/Calculator/FibonacciTest.cs
index 461d2f9c..59779673 100644
--- a/src/asptest.websharper.spa.fs/Calculator/FibonacciTest.cs
+++ b/src/asptest.websharper.spa.fs/Calculator/FibonacciTest.cs
@@ -43,7 +43,7 @@ public void VerifyFibonacciSums()
// Check the correctness of the Fibonacci sequence in the calculator GUI
// Delete the current sum and recalculate it from the sequence
- this.Click(Id(CalculatorDoc.ClrButton));
+ this.Click(Id(CalculatorDoc.ClrButton), wait: 15);
this.Click(Id(CalculatorDoc.AddButton));
this.AssertPoll(() => this.Stack.ElementAt(0), () => Is.EqualTo(sum));
diff --git a/src/asptest.websharper.spa.fs/Calculator/WithSessionTest.cs b/src/asptest.websharper.spa.fs/Calculator/WithSessionTest.cs
index 2d13633a..ce875c49 100644
--- a/src/asptest.websharper.spa.fs/Calculator/WithSessionTest.cs
+++ b/src/asptest.websharper.spa.fs/Calculator/WithSessionTest.cs
@@ -48,23 +48,22 @@ private void Reload()
[Test]
public void AddWithPersistenceTest()
{
- this.Navigate("/");
- this.Click("EnterButton");
+ this.Click(Id(CalculatorDoc.EnterButton));
this.AssertPoll(() => this.State, () => Is.EqualTo(CalculatorContext.Map1.Enter));
this.Reload();
this.Write(Id(CalculatorDoc.OperandTextbox), "2");
- this.Click("EnterButton");
+ this.Click(Id(CalculatorDoc.EnterButton));
this.AssertPoll(() => this.State, () => Is.EqualTo(CalculatorContext.Map1.Calculate));
this.Reload();
- this.Click("EnterButton");
+ this.Click(Id(CalculatorDoc.EnterButton));
this.AssertPoll(() => this.State, () => Is.EqualTo(CalculatorContext.Map1.Enter));
this.Reload();
this.Write(Id(CalculatorDoc.OperandTextbox), "3");
- this.Click("EnterButton");
+ this.Click(Id(CalculatorDoc.EnterButton));
this.AssertPoll(() => this.State, () => Is.EqualTo(CalculatorContext.Map1.Calculate));
var before = this.Stack.Count;
this.Reload();
- this.Click("AddButton");
+ this.Click(Id(CalculatorDoc.AddButton));
this.AssertAddFinalState(before);
this.Reload();
}
diff --git a/src/asptest.websharper.spa.fs/TriptychTest.cs b/src/asptest.websharper.spa.fs/TriptychTest.cs
index b87424fe..134a87b4 100644
--- a/src/asptest.websharper.spa.fs/TriptychTest.cs
+++ b/src/asptest.websharper.spa.fs/TriptychTest.cs
@@ -17,10 +17,23 @@ namespace asptest
public class TriptychTest : CalculatorTestBase
where TWebDriver : IWebDriver, new()
{
+ public override void OneTimeSetUpBrowser()
+ {
+ base.OneTimeSetUpBrowser();
+ driver.Manage().Window.Size = new System.Drawing.Size(1450, 1000);
+ }
+
+ [OneTimeSetUp]
+ public void DistinctPages()
+ {
+ this.samePageDefault = false;
+ }
+
[SetUp]
- public void UnsetStorage()
+ public void ReloadUnsetStorage()
{
- StorageImplementation.SessionStorage = null;
+ this.Navigate("/");
+ StorageImplementation.SessionStorage = null; // defaults to ViewState (DOM)
}
[TearDown]
@@ -36,47 +49,50 @@ public void ClearStorage()
[Test]
public void NavigateTriptychTest()
{
+ this.AssertPoll(() => this.Html(), () => Does.Contain("Session Storage: ViewState")); // init view
this.Click(Id(CalculatorDoc.StorageLink));
this.AssertTriptychHtml();
}
- ///
- /// Assert the presence of the three calculators superficially by text.
- ///
- private void AssertTriptychHtml()
- {
- Assert.Multiple(() =>
- {
- // Assert from bottom to top to ensure the page has been fully rendered on the client
- this.AssertPoll(() => this.Html(), () => Does.Contain("Session Storage: Database"));
- this.AssertPoll(() => this.Html(), () => Does.Contain("Session Storage: Session"));
- this.AssertPoll(() => this.Html(), () => Does.Contain("Session Storage: ViewState"));
- });
- }
-
[Test]
public void CircumambulateStorageTypes()
{
+ this.AssertPoll(() => this.Html(), () => Does.Contain("Session Storage: ViewState")); // init view
this.Click(Id(CalculatorDoc.StorageLink));
this.AssertTriptychHtml();
this.Click(Id(TriptychDoc.DatabaseDoc, CalculatorDoc.StorageLink));
- this.Navigate("/"); // Reload, as static StorageImplementation.SessionStorage is set too late in F#
+ this.driver.Navigate().Refresh(); // only in the F# port
+ // Poll SessionStorage first, this.Html() is ambiguous and succeeds too early (still on the triptych)
this.AssertPoll(() => this.ViewModel.SessionStorage, () => Is.EqualTo(Storage.Database));
this.AssertPoll(() => this.Html(), () => Does.Contain("Session Storage: Database"));
this.Click(Id(CalculatorDoc.StorageLink));
this.AssertTriptychHtml();
this.Click(Id(TriptychDoc.SessionDoc, CalculatorDoc.StorageLink));
- this.Navigate("/");
+ this.driver.Navigate().Refresh();
this.AssertPoll(() => this.ViewModel.SessionStorage, () => Is.EqualTo(Storage.Session));
this.AssertPoll(() => this.Html(), () => Does.Contain("Session Storage: Session"));
this.Click(Id(CalculatorDoc.StorageLink));
this.AssertTriptychHtml();
this.Click(Id(TriptychDoc.ViewStateDoc, CalculatorDoc.StorageLink));
- this.Navigate("/");
+ this.driver.Navigate().Refresh();
this.AssertPoll(() => this.ViewModel.SessionStorage, () => Is.EqualTo(Storage.ViewState));
this.AssertPoll(() => this.Html(), () => Does.Contain("Session Storage: ViewState"));
}
+
+ ///
+ /// Assert the presence of the three calculators superficially by text.
+ ///
+ private void AssertTriptychHtml()
+ {
+ Assert.Multiple(() =>
+ {
+ // Assert from bottom to top to ensure the page has been fully rendered on the client
+ this.AssertPoll(() => this.Html(), () => Does.Contain("Session Storage: Database"));
+ this.AssertPoll(() => this.Html(), () => Does.Contain("Session Storage: Session"));
+ this.AssertPoll(() => this.Html(), () => Does.Contain("Session Storage: ViewState"));
+ });
+ }
}
}
\ No newline at end of file
diff --git a/src/asptest.websharper.spa/Calculator/FibonacciTest.cs b/src/asptest.websharper.spa/Calculator/FibonacciTest.cs
index 32c212ee..fdf24de0 100644
--- a/src/asptest.websharper.spa/Calculator/FibonacciTest.cs
+++ b/src/asptest.websharper.spa/Calculator/FibonacciTest.cs
@@ -43,7 +43,7 @@ public void VerifyFibonacciSums()
// Check the correctness of the Fibonacci sequence in the calculator GUI
// Delete the current sum and recalculate it from the sequence
- this.Click(Id(CalculatorDoc.ClrButton));
+ this.Click(Id(CalculatorDoc.ClrButton), wait: 15);
this.Click(Id(CalculatorDoc.AddButton));
this.AssertPoll(() => this.Stack.ElementAt(0), () => Is.EqualTo(sum));
diff --git a/src/asptest.websharper.spa/TriptychTest.cs b/src/asptest.websharper.spa/TriptychTest.cs
index 5dc68f08..95d06713 100644
--- a/src/asptest.websharper.spa/TriptychTest.cs
+++ b/src/asptest.websharper.spa/TriptychTest.cs
@@ -17,10 +17,23 @@ namespace asptest
public class TriptychTest : CalculatorTestBase
where TWebDriver : IWebDriver, new()
{
+ public override void OneTimeSetUpBrowser()
+ {
+ base.OneTimeSetUpBrowser();
+ driver.Manage().Window.Size = new System.Drawing.Size(1450, 1000);
+ }
+
+ [OneTimeSetUp]
+ public void DistinctPages()
+ {
+ this.samePageDefault = false;
+ }
+
[SetUp]
- public void UnsetStorage()
+ public void ReloadUnsetStorage()
{
- StorageImplementation.SessionStorage = null; // defaults to ViewState
+ this.Navigate("/");
+ StorageImplementation.SessionStorage = null; // defaults to ViewState (DOM)
}
[TearDown]
@@ -36,27 +49,15 @@ public void ClearStorage()
[Test]
public void NavigateTriptychTest()
{
+ this.AssertPoll(() => this.Html(), () => Does.Contain("Session Storage: ViewState")); // init view
this.Click(Id(CalculatorDoc.StorageLink));
this.AssertTriptychHtml();
}
- ///
- /// Assert the presence of the three calculators superficially by text.
- ///
- private void AssertTriptychHtml()
- {
- Assert.Multiple(() =>
- {
- // Assert from bottom to top to ensure the page has been fully rendered on the client
- this.AssertPoll(() => this.Html(), () => Does.Contain("Session Storage: Database"));
- this.AssertPoll(() => this.Html(), () => Does.Contain("Session Storage: Session"));
- this.AssertPoll(() => this.Html(), () => Does.Contain("Session Storage: ViewState"));
- });
- }
-
[Test]
public void CircumambulateStorageTypes()
{
+ this.AssertPoll(() => this.Html(), () => Does.Contain("Session Storage: ViewState")); // init view
this.Click(Id(CalculatorDoc.StorageLink));
this.AssertTriptychHtml();
this.Click(Id(TriptychDoc.DatabaseDoc, CalculatorDoc.StorageLink));
@@ -76,5 +77,19 @@ public void CircumambulateStorageTypes()
this.AssertPoll(() => this.ViewModel.SessionStorage, () => Is.EqualTo(Storage.ViewState));
this.AssertPoll(() => this.Html(), () => Does.Contain("Session Storage: ViewState"));
}
+
+ ///
+ /// Assert the presence of the three calculators superficially by text.
+ ///
+ private void AssertTriptychHtml()
+ {
+ Assert.Multiple(() =>
+ {
+ // Assert from bottom to top to ensure the page has been fully rendered on the client
+ this.AssertPoll(() => this.Html(), () => Does.Contain("Session Storage: Database"));
+ this.AssertPoll(() => this.Html(), () => Does.Contain("Session Storage: Session"));
+ this.AssertPoll(() => this.Html(), () => Does.Contain("Session Storage: ViewState"));
+ });
+ }
}
}
\ No newline at end of file
diff --git a/src/asptestrunner.core/Runner.cs b/src/asptestrunner.core/Runner.cs
index 2ba3458c..182bce35 100644
--- a/src/asptestrunner.core/Runner.cs
+++ b/src/asptestrunner.core/Runner.cs
@@ -27,6 +27,7 @@ public void TearDown()
public void RunTests()
{
this.Navigate("/");
+ this.driver.Navigate().Refresh();
this.ClickID("testButton");
this.AssertTestsOK();
}
diff --git a/src/asptestrunner.core/asptestrunner.core.csproj b/src/asptestrunner.core/asptestrunner.core.csproj
index 3b567989..fc240a02 100644
--- a/src/asptestrunner.core/asptestrunner.core.csproj
+++ b/src/asptestrunner.core/asptestrunner.core.csproj
@@ -20,6 +20,8 @@
+
+
diff --git a/src/asptestrunner.websharper.spa/CSharpRunner.cs b/src/asptestrunner.websharper.spa/CSharpRunner.cs
index 9f2ec587..76a2ab62 100644
--- a/src/asptestrunner.websharper.spa/CSharpRunner.cs
+++ b/src/asptestrunner.websharper.spa/CSharpRunner.cs
@@ -27,9 +27,10 @@ public void TearDown()
[Test]
public void RunTests()
{
- this.Navigate("/", delay: 7000); // server not yet ready on 1st run
+ this.Navigate("/", delay: 7000); // server not yet ready on 1st run
+ this.driver.Navigate().Refresh(); // and the page sometimes doesn't load the 1st time
this.AssertPoll(() => this.GetHTMLElementById("testButton").Displayed, () => Is.True);
- this.Click("testButton");
+ this.Click("testButton", awaitRemoved: false);
this.AssertTestsOK();
}
}
diff --git a/src/asptestrunner.websharper.spa/FSharpRunner.cs b/src/asptestrunner.websharper.spa/FSharpRunner.cs
index f680cb02..2cf17f39 100644
--- a/src/asptestrunner.websharper.spa/FSharpRunner.cs
+++ b/src/asptestrunner.websharper.spa/FSharpRunner.cs
@@ -27,9 +27,10 @@ public void TearDown()
[Test]
public void RunTests()
{
- this.Navigate("/", delay: 7000); // server not yet ready on 1st run
+ this.Navigate("/", delay: 7000); // server not yet ready on 1st run
+ this.driver.Navigate().Refresh(); // and the page sometimes doesn't load the 1st time
this.AssertPoll(() => this.GetHTMLElementById("testButton").Displayed, () => Is.True);
- this.Click("testButton");
+ this.Click("testButton", awaitRemoved: false);
this.AssertTestsOK();
}
}
diff --git a/src/asptestrunner.websharper.spa/appsettings.json b/src/asptestrunner.websharper.spa/appsettings.json
index 6ed652d5..36b4b02f 100644
--- a/src/asptestrunner.websharper.spa/appsettings.json
+++ b/src/asptestrunner.websharper.spa/appsettings.json
@@ -4,6 +4,6 @@
"ServerFSharp": "..\\..\\..\\..\\asp.websharper.spa.fs\\bin\\Debug\\netcoreapp3.1\\asp.websharper.spa.fs.exe",
"RootCFharp": "..\\..\\..\\..\\asp.websharper.spa.fs",
"Port": "5000",
- "RequestTimeout": "350",
+ "RequestTimeout": "1000",
"ServerStartTimeout": "10"
}
\ No newline at end of file
diff --git a/src/asptestrunner.websharper.spa/asptestrunner.websharper.spa.csproj b/src/asptestrunner.websharper.spa/asptestrunner.websharper.spa.csproj
index 14d98b0f..c9cca7e7 100644
--- a/src/asptestrunner.websharper.spa/asptestrunner.websharper.spa.csproj
+++ b/src/asptestrunner.websharper.spa/asptestrunner.websharper.spa.csproj
@@ -22,6 +22,10 @@
+
+
+
+
diff --git a/src/iselenium.core/ISeleniumExtension.cs b/src/iselenium.core/ISeleniumExtension.cs
index e73ef937..5101a91c 100644
--- a/src/iselenium.core/ISeleniumExtension.cs
+++ b/src/iselenium.core/ISeleniumExtension.cs
@@ -10,18 +10,19 @@ public static class SeleniumExtension
/// Click the HTML element (usually a Button) with the given id and
/// index and wait for the response when expectPostBack is true (default).
///
- /// HTML id attribute of the element to click on
- /// Whether to expect a GET/POST request to the server from the click
- /// Whether to expect a WebForms style PostBack to the same page with the same HTML element
- /// Expected StatusCofe of the response
- /// Optional delay time in milliseconds before clicking the element
- /// Optional pause time in milliseconds after IE claims DocumentComplete
+ /// HTML id attribute of the element to click on
+ /// Whether to expect a GET/POST request to the server from the click
+ /// Whether to expect a WebForms style PostBack to the same page with the same HTML element
+ /// Whether to wait for the HTML element to disappear (in an SPA)
+ /// Expected StatusCofe of the response
+ /// Optional delay time in milliseconds before clicking the element
+ /// Optional pause time in milliseconds after IE claims DocumentComplete
public static void Click(this ISelenium inst, string id, int index = 0,
- bool expectRequest = true, bool samePage = false,
+ bool expectRequest = true, bool samePage = false, bool awaitRemoved = false,
int expectedStatusCode = 200, int delay = 0, int pause = 0)
{
SeleniumExtensionBase.ClickID(inst, id, index,
- expectRequest: expectRequest, samePage: samePage,
+ expectRequest: expectRequest, samePage: samePage, awaitRemoved: awaitRemoved,
expectedStatusCode: expectedStatusCode, delay: delay, pause: pause);
}
diff --git a/src/iselenium.core/NoCacheMiddleware.cs b/src/iselenium.core/NoCacheMiddleware.cs
new file mode 100644
index 00000000..421bdc0d
--- /dev/null
+++ b/src/iselenium.core/NoCacheMiddleware.cs
@@ -0,0 +1,30 @@
+using Microsoft.AspNetCore.Http;
+using Microsoft.Net.Http.Headers;
+using System.Threading.Tasks;
+
+namespace iselenium
+{
+ // https://support.microsoft.com/en-us/help/234067/how-to-prevent-caching-in-internet-explorer
+ // But even this does not stop IE from getting 304 responses and the test runner still requires two loads.
+
+ ///
+ /// Send no-cache and expires headers
+ ///
+ public class NoCacheMiddleware
+ {
+ protected readonly RequestDelegate _next;
+
+ public NoCacheMiddleware(RequestDelegate next)
+ {
+ _next = next;
+ }
+
+ public async Task Invoke(HttpContext context)
+ {
+ context.Response.Headers[HeaderNames.CacheControl] = "no-cache";
+ context.Response.Headers[HeaderNames.Pragma] = "no-cache";
+ context.Response.Headers[HeaderNames.Expires] = "-1";
+ await _next(context);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/iselenium.core/SpaTest.cs b/src/iselenium.core/SpaTest.cs
index 26ffc5c5..69bc9059 100644
--- a/src/iselenium.core/SpaTest.cs
+++ b/src/iselenium.core/SpaTest.cs
@@ -16,6 +16,21 @@ namespace iselenium
public abstract class SpaTest : SeleniumTest
where TWebDriver : IWebDriver, new()
{
+ ///
+ /// Globally set the awaitRemove: default for Click(), as simple SPA
+ /// pages (as the minimal one) don't require awaitRemove: true, but
+ /// complex ones on almost every clickable element.
+ ///
+ protected bool awaitRemovedDefault = true;
+
+ ///
+ /// Globally set the samePage: default for Click(). True if the
+ /// interaction with a single page with static elements is tested, false
+ /// if the test jumps around several pages.
+ /// Relevant if awaitRemovedDefault is true.
+ ///
+ protected bool samePageDefault = true;
+
///
/// Start the browser and poll the root directory to be available (SPAs
/// are known to have a long startup time)
@@ -58,6 +73,7 @@ public string Html(int wait = 0)
return SeleniumExtensionBase.Html(this, wait: (wait == 0) ? SeleniumExtensionBase.RequestTimeout : wait);
}
+ ///
/// Click the HTML element (usually a Button) with the given id and
/// index, don't wait for a response as expectRequest defaults to false for an SPA,
/// but wait RequestTimeout seconds for the element to appear.
@@ -66,17 +82,20 @@ public string Html(int wait = 0)
/// Index of the element collection with that id, defaults to 0
/// Whether to expect a GET/POST request to the server from the click
/// Whether to expect a WebForms style PostBack to the same page with the same HTML element
+ /// Whether to wait for the HTML element to disappear (in an SPA)
/// Expected StatusCofe of the response
/// Optional delay time in milliseconds before clicking the element
/// Optional pause time in milliseconds after IE claims DocumentComplete
/// Explicit WebDriverWait in seconds for the element to appear
public void Click(string id, int index = 0,
- bool expectRequest = false, bool samePage = false,
+ bool expectRequest = false, bool? samePage = null, bool? awaitRemoved = null,
int expectedStatusCode = 200, int delay = 0, int pause = 0, int wait = 0)
{
+ var doAwaitRemoved = awaitRemoved ?? this.awaitRemovedDefault;
+ var onSamePage = samePage ?? this.samePageDefault;
SeleniumExtensionBase.ClickID(this, id, index,
- expectRequest: expectRequest, samePage: samePage,
- expectedStatusCode: expectedStatusCode,
+ expectRequest: expectRequest, samePage: onSamePage,
+ awaitRemoved: doAwaitRemoved, expectedStatusCode: expectedStatusCode,
delay: delay, pause: pause,
wait: (wait == 0) ? SeleniumExtensionBase.RequestTimeout : wait);
}
diff --git a/src/iselenium.webforms/ISeleniumExtension.cs b/src/iselenium.webforms/ISeleniumExtension.cs
index 4db36ac7..4f09b925 100644
--- a/src/iselenium.webforms/ISeleniumExtension.cs
+++ b/src/iselenium.webforms/ISeleniumExtension.cs
@@ -30,13 +30,16 @@ public static class SeleniumExtension
///
/// Member name path to the control starting at the main control
/// Whether to expect a server request from the click
+ /// Whether the PostBack stays on the same page with the same HTML element
/// Expected StatusCofe of the response
/// Optional delay time in milliseconds before clicking the element
/// Optional pause time in milliseconds after IE claims DocumentComplete
- public static void Click(this ISelenium inst, string path, bool expectPostBack = true, int expectedStatusCode = 200, int delay = 0, int pause = 0)
+ public static void Click(this ISelenium inst, string path, bool expectPostBack = true, bool samePage = false,
+ int expectedStatusCode = 200, int delay = 0, int pause = 0)
{
var button = GetControl(inst, path);
- SeleniumExtensionBase.ClickID(inst, button.ClientID, expectRequest: expectPostBack, samePage: false,
+ SeleniumExtensionBase.ClickID(inst, button.ClientID,
+ expectRequest: expectPostBack, samePage: samePage,
expectedStatusCode: expectedStatusCode, delay: delay, pause: pause);
}
@@ -46,13 +49,16 @@ public static void Click(this ISelenium inst, string path, bool expectPostBack =
///
/// The ASP.NET control to click on
/// Whether to expect a server request from the click
+ /// Whether the PostBack stays on the same page with the same HTML element
/// Expected StatusCode of the response
/// Optional delay time in milliseconds before clicking the element
/// Optional pause time in milliseconds after IE claims DocumentComplete
- public static void Click(this ISelenium inst, Control control, bool expectPostBack = true, int expectedStatusCode = 200, int delay = 0, int pause = 0)
+ public static void Click(this ISelenium inst, Control control, bool expectPostBack = true, bool samePage = false,
+ int expectedStatusCode = 200, int delay = 0, int pause = 0)
{
- var button = GetHTMLElement(inst, control.ClientID);
- SeleniumExtensionBase.Click(inst, button, expectPostBack, expectedStatusCode, delay, pause);
+ SeleniumExtensionBase.ClickID(inst, control.ClientID,
+ expectRequest: expectPostBack, samePage: samePage,
+ expectedStatusCode: expectedStatusCode, delay: delay, pause: pause);
}
///
@@ -81,7 +87,7 @@ public static void Select(this ISelenium inst, string path, string value, bool e
else if (list.Items[idx].Value == value)
{
string itemID = String.Format("{0}_{1}", list.ClientID, idx);
- SeleniumExtensionBase.ClickID(inst, itemID, expectRequest: expectPostBack, samePage: true,
+ SeleniumExtensionBase.ClickID(inst, itemID, expectRequest: expectPostBack, samePage: !expectPostBack,
expectedStatusCode: expectedStatusCode, delay: delay, pause: pause);
break;
}
diff --git a/src/iselenium/ISeleniumExtensionBase.cs b/src/iselenium/ISeleniumExtensionBase.cs
index a3d64072..6f6234fc 100644
--- a/src/iselenium/ISeleniumExtensionBase.cs
+++ b/src/iselenium/ISeleniumExtensionBase.cs
@@ -74,7 +74,7 @@ public static void SetUpBrowser(this ISeleniumBase inst)
///
/// [OneTimeTearDown]
- /// Quit Internet Explorer
+ /// Quit the browser
///
public static void TearDownBrowser(this ISeleniumBase inst)
{
@@ -167,18 +167,19 @@ public static void AssertTestsOK(this ISeleniumBase inst)
///
/// HTML name attribute of the element to click on
/// Whether to expect a GET/POST request to the server from the click
- /// Whether to expect a WebForms style PostBack to the same page
+ /// Whether to expect a WebForms style PostBack to the same page with the same HTML element
+ /// Whether to wait for the HTML element to disappear (in an SPA)
/// Expected StatusCofe of the response
/// Optional delay time in milliseconds before clicking the element
/// Optional pause time in milliseconds after IE claims DocumentComplete
/// Explicit WebDriverWait in seconds for the element to appear
public static void ClickName(this ISeleniumBase inst, string name, int index = 0,
- bool expectRequest = true, bool samePage = false,
+ bool expectRequest = true, bool samePage = false, bool awaitRemoved = false,
int expectedStatusCode = 200, int delay = 0, int pause = 0, int wait = 0)
{
var button = GetHTMLElementByName(inst, name, index, wait: wait);
- Click(inst, button, expectRequest: expectRequest, delay: delay, pause: pause);
- if (expectRequest && samePage)
+ Click(button, awaitRemoved, delay, pause);
+ if ((expectRequest || awaitRemoved) && samePage)
{
new WebDriverWait(inst.driver, TimeSpan.FromSeconds(RequestTimeout))
.Until(drv => drv.FindElement(By.Name(name)).Displayed);
@@ -193,20 +194,20 @@ public static void AssertTestsOK(this ISeleniumBase inst)
/// HTML id attribute of the element to click on
/// Index of the element collection with that id, defaults to 0
/// Whether to expect a GET/POST request to the server from the click
- /// Whether to expect a WebForms style PostBack to the same page
+ /// Whether to expect a WebForms style PostBack to the same page with the same HTML element
+ /// Whether to wait for the HTML element to disappear (in an SPA)
/// Expected StatusCofe of the response///
/// Optional delay time in milliseconds before clicking the element
/// Optional pause time in milliseconds after IE claims DocumentComplete
/// Explicit WebDriverWait in seconds for the element to appear
public static void ClickID(this ISeleniumBase inst, string id, int index = 0,
- bool expectRequest = true, bool samePage = false,
+ bool expectRequest = true, bool samePage = false, bool awaitRemoved = false,
int expectedStatusCode = 200, int delay = 0, int pause = 0,
int wait = 0)
{
var button = GetHTMLElementById(inst, id, index, wait: wait);
- Click(inst, button, expectRequest: expectRequest, expectedStatusCode: expectedStatusCode,
- delay: delay, pause: pause);
- if (expectRequest && samePage)
+ Click(button, awaitRemoved, delay, pause);
+ if ((expectRequest || awaitRemoved) && samePage)
{
new WebDriverWait(inst.driver, TimeSpan.FromSeconds(RequestTimeout))
.Until(drv => drv.FindElement(By.Id(id)).Displayed);
@@ -215,24 +216,22 @@ public static void AssertTestsOK(this ISeleniumBase inst)
}
///
- /// Click on the HTML element and wait for the response when expectRequest is true.
+ /// Click on the HTML element
///
/// The HTML element itself
- /// Whether to expect a GET/POST request to the server from the click
+ /// Whether to wait for the HTML element to disappear (in an SPA)
/// Expected StatusCofe of the response///
/// Optional delay time in milliseconds before clicking the element
/// Optional pause time in milliseconds after IE claims DocumentComplete
- public static void Click(this ISeleniumBase inst, IWebElement element, bool expectRequest = true,
- int expectedStatusCode = 200, int delay = 0, int pause = 0)
+ private static void Click(IWebElement element, bool awaitRemoved, int delay, int pause)
{
Thread.Sleep(delay);
element.Click();
- if (expectRequest)
+ if (awaitRemoved)
{
- AwaitBeginRequest(element);
+ AwaitElementRemoved(element);
}
Thread.Sleep(pause);
- AssertStatusCode(inst, expectedStatusCode);
}
///
@@ -290,7 +289,7 @@ public static void AssertTestsOK(this ISeleniumBase inst)
}
else if (list[idx].GetAttribute("value") == value)
{
- ClickID(inst, id, idx, expectRequest: expectPostBack, samePage: true, expectedStatusCode: expectedStatusCode,
+ ClickID(inst, id, idx, expectRequest: expectPostBack, samePage: !expectPostBack, expectedStatusCode: expectedStatusCode,
delay: delay, pause: pause);
if (expectPostBack)
{
@@ -329,7 +328,7 @@ public static void AssertTestsOK(this ISeleniumBase inst)
}
else if (list[idx].GetAttribute("value") == value)
{
- ClickName(inst, name, idx, expectRequest: expectPostBack, samePage: true, expectedStatusCode: expectedStatusCode,
+ ClickName(inst, name, idx, expectRequest: expectPostBack, samePage: !expectPostBack, expectedStatusCode: expectedStatusCode,
delay: delay, pause: pause);
if (expectPostBack)
{
@@ -350,8 +349,7 @@ public static void AssertTestsOK(this ISeleniumBase inst)
///
public static IWebElement GetHTMLElementById(this ISeleniumBase inst, string id, int index = 0, int wait = 0)
{
- var elements = new WebDriverWait(inst.driver, TimeSpan.FromSeconds(wait))
- .Until(drv => drv.FindElements(By.Id(id)));
+ var elements = AwaitHTMLElements(inst, By.Id, id, wait);
if (elements.Count <= index)
{
throw new ArgumentException(String.Format(
@@ -369,8 +367,7 @@ public static IWebElement GetHTMLElementById(this ISeleniumBase inst, string id,
///
public static ReadOnlyCollection GetHTMLElementsByID(this ISeleniumBase inst, string id, int wait = 0)
{
- var elements = new WebDriverWait(inst.driver, TimeSpan.FromSeconds(wait))
- .Until(drv => drv.FindElements(By.Id(id)));
+ var elements = AwaitHTMLElements(inst, By.Id, id, wait);
if (elements.Count == 0)
{
throw new ArgumentException(String.Format("HTML input element with id='{0}' not found", id));
@@ -392,14 +389,12 @@ public static ReadOnlyCollection GetHTMLElementsByID(this ISelenium
///
public static IWebElement GetHTMLElementByName(this ISeleniumBase inst, string name, int index = 0, int wait = 0)
{
- var elements = new WebDriverWait(inst.driver, TimeSpan.FromSeconds(wait))
- .Until(drv => drv.FindElements(By.Name(name)));
+ var elements = AwaitHTMLElements(inst, By.Name, name, wait);
if (elements.Count <= index)
{
if (IIECompatible(inst))
{
- elements = new WebDriverWait(inst.driver, TimeSpan.FromSeconds(wait))
- .Until(drv => drv.FindElements(By.Id(name)));
+ elements = AwaitHTMLElements(inst, By.Id, name, wait);
if (elements.Count <= index)
{
throw new ArgumentException(String.Format(
@@ -423,8 +418,7 @@ public static IWebElement GetHTMLElementByName(this ISeleniumBase inst, string n
///
public static ReadOnlyCollection GetHTMLElementsByName(this ISeleniumBase inst, string name, int wait = 0)
{
- var elements = new WebDriverWait(inst.driver, TimeSpan.FromSeconds(wait))
- .Until(drv => drv.FindElements(By.Name(name)));
+ var elements = AwaitHTMLElements(inst, By.Name, name, wait);
if (elements.Count == 0)
{
throw new ArgumentException(String.Format("HTML input element with name='{0}' not found", name));
@@ -435,15 +429,46 @@ public static ReadOnlyCollection GetHTMLElementsByName(this ISeleni
}
}
+ ///
+ /// On Chrome, WebDriverWait might sometimes find an element during DOM
+ /// manipulation that has become stale. Ignore
+ /// StaleElementReferenceException and try again.
+ ///
+ /// delegate for By.Name(name) or By.Id(id)
+ /// argument for the selector
+ /// Explicit WebDriverWait for the elements
+ ///
+ public static ReadOnlyCollection AwaitHTMLElements(this ISeleniumBase inst,
+ Func selector,
+ string nameOrId, int wait)
+ {
+ var elements = new ReadOnlyCollection(Array.Empty());
+ for (int i = 0; i < RequestTimeout * 1000 / FAST_POLL_MILLISECONDS; i++)
+ {
+ try
+ {
+ elements = new WebDriverWait(inst.driver, TimeSpan.FromSeconds(wait))
+ .Until(drv => drv.FindElements(selector(nameOrId)));
+ if (elements.Count == 0)
+ return elements; // element not findable within WebDriverWait -> give up
+ var _ = elements[0].Displayed; // either the old one (throws) or the new one
+ return elements; // didn't throw -> return
+ }
+ catch (StaleElementReferenceException) { } // next try for the non-stale element
+ Thread.Sleep(FAST_POLL_MILLISECONDS);
+ }
+ return elements;
+ }
+
///
/// Explicitly wait for the element to disappear by rapidly polling
/// its visibility until the reference has become stale or the
/// RequestTimeout is exceeded.
///
- ///
- private static void AwaitBeginRequest(IWebElement element)
+ /// The HTML element that should disappear
+ private static void AwaitElementRemoved(IWebElement element)
{
- bool isPostBack = false;
+ bool isRemoved = false;
for (int i = 0; i < RequestTimeout * 1000 / FAST_POLL_MILLISECONDS; i++)
{
try
@@ -452,14 +477,16 @@ private static void AwaitBeginRequest(IWebElement element)
}
catch (StaleElementReferenceException)
{
- isPostBack = true;
+ isRemoved = true;
break;
}
Thread.Sleep(FAST_POLL_MILLISECONDS);
}
- if (!isPostBack)
+ if (!isRemoved)
{
- throw new TimeoutException(String.Format("PostBack took longer than {0}s", RequestTimeout));
+ throw new TimeoutException(String.Format(
+ "AwaitElementRemoved took longer than {0}s, if this is expected set awaitRemoved: false",
+ RequestTimeout));
}
}
diff --git a/src/iselenium/ISeleniumExtensionBaseAssertPoll.cs b/src/iselenium/ISeleniumExtensionBaseAssertPoll.cs
index b2f6ad82..5ced01e3 100644
--- a/src/iselenium/ISeleniumExtensionBaseAssertPoll.cs
+++ b/src/iselenium/ISeleniumExtensionBaseAssertPoll.cs
@@ -47,9 +47,26 @@ public static partial class SeleniumExtensionBase
/// The Type being compared.
/// An ActualValueDelegate returning the value to be tested
/// A Constraint expression to be applied
- public static void AssertPoll(this ISeleniumBase _, ActualValueDelegate del, Func expr)
+ /// Time in seconds to poll for the assertion to pass, overrides RequestTimeout
+ public static void AssertPoll(this ISeleniumBase _, ActualValueDelegate del,
+ Func expr, int? timeout = null)
{
- AssertPoll(del, expr, null, null);
+ AssertPoll(del, expr, null, timeout: timeout, null);
+ }
+
+ ///
+ /// Apply a constraint to a delegate. Returns without throwing an exception when inside a multiple assert block.
+ ///
+ /// The Type being compared.
+ /// An ActualValueDelegate returning the value to be tested
+ /// A Constraint expression to be applied
+ /// Exception message delegate
+ /// A Constraint expression to be applied
+ public static void AssertPoll(this ISeleniumBase _, ActualValueDelegate del,
+ Func expr, Func getExceptionMessage,
+ int? timeout = null)
+ {
+ AssertPoll(del, expr, getExceptionMessage, timeout: timeout);
}
///
@@ -60,9 +77,10 @@ public static void AssertPoll(this ISeleniumBase _, ActualValueDelegate
/// A Constraint expression to be applied
/// The message that will be displayed on failure
/// Arguments to be used in formatting the message
- public static void That(ActualValueDelegate del, Func expr, string message, params object[] args)
+ public static void That(ActualValueDelegate del, Func expr,
+ string message, params object[] args)
{
- AssertPoll(del, expr, message, args);
+ AssertPoll(del, expr, message, timeout: null, args);
}
///
@@ -86,15 +104,17 @@ public static void That(ActualValueDelegate del, Func(ActualValueDelegate del, Func expression, string message, params object[] args)
+ private static void AssertPoll(ActualValueDelegate del, Func expression,
+ string message, int? timeout = null, params object[] args)
{
- TryAssertPoll(del, expression);
+ TryAssertPoll(del, expression, timeout);
Assert.That(del, expression(), message, args);
}
- private static void AssertPoll(ActualValueDelegate del, Func expression, Func getExceptionMessage)
+ private static void AssertPoll(ActualValueDelegate del, Func expression,
+ Func getExceptionMessage, int? timeout = null)
{
- TryAssertPoll(del, expression);
+ TryAssertPoll(del, expression, timeout);
Assert.That(del, expression(), getExceptionMessage);
}
@@ -104,11 +124,15 @@ private static void AssertPoll(ActualValueDelegate del, Func
///
///
- /// whether the tess passed
- private static bool TryAssertPoll(ActualValueDelegate del, Func expression)
+ /// Overrides RequestTimeout
+ /// whether the test passed
+ private static bool TryAssertPoll(ActualValueDelegate del,
+ Func expression,
+ int? timeout)
{
+ int pollFor = timeout ?? RequestTimeout;
var constraint = expression().Resolve();
- for (int i = 0; i < RequestTimeout * 1000 / FAST_POLL_MILLISECONDS; i++)
+ for (int i = 0; i < pollFor * 1000 / FAST_POLL_MILLISECONDS; i++)
{
try
{
diff --git a/src/iselenium/ITestServerBase.cs b/src/iselenium/ITestServerBase.cs
index 97f07e96..5f4feef5 100644
--- a/src/iselenium/ITestServerBase.cs
+++ b/src/iselenium/ITestServerBase.cs
@@ -52,12 +52,18 @@ public static void StopServer(this ITestServerBase inst)
TestServerIPC.Dispose();
try
{
- if (inst != null)
+ if (inst.ServerProcess != null)
{
inst.ServerProcess.Kill();
+ inst.ServerProcess.WaitForExit();
}
}
catch { }
+ finally
+ {
+ inst.ServerProcess.Dispose();
+ inst.ServerProcess = null;
+ }
}
}
}
\ No newline at end of file
diff --git a/src/minimal.core/Startup.cs b/src/minimal.core/Startup.cs
index b5ec6182..3602889d 100644
--- a/src/minimal.core/Startup.cs
+++ b/src/minimal.core/Startup.cs
@@ -57,6 +57,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.UseDeveloperExceptionPage(); // always for this demo
app.UseExceptionHandler("/Error/Error");
app.UseMiddleware(); // Global.asax
+ app.UseMiddleware();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseSession();
diff --git a/src/minimal.websharper.spa/Startup.cs b/src/minimal.websharper.spa/Startup.cs
index 1812c0ed..051e4962 100644
--- a/src/minimal.websharper.spa/Startup.cs
+++ b/src/minimal.websharper.spa/Startup.cs
@@ -50,15 +50,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
//WebSharper.Web.Remoting.DisableCsrfProtection(); // HTTP 403 prevention not needed here
app.UseDeveloperExceptionPage()
.UseMiddleware()
- // https://support.microsoft.com/en-us/help/234067/how-to-prevent-caching-in-internet-explorer
- // But even this does not stop IE from sending 304 responses:
- .Use(async (httpContext, next) =>
- {
- httpContext.Response.Headers[HeaderNames.CacheControl] = "no-cache";
- httpContext.Response.Headers[HeaderNames.Pragma] = "no-cache";
- httpContext.Response.Headers[HeaderNames.Expires] = "-1";
- await next();
- })
+ .UseMiddleware()
.UseDefaultFiles()
.UseSession()
.UseMiddleware()
diff --git a/src/minimaltest.websharper.spa/WithStaticRemoteTest.cs b/src/minimaltest.websharper.spa/WithStaticRemoteTest.cs
index c18eb23a..f62b522d 100644
--- a/src/minimaltest.websharper.spa/WithStaticRemoteTest.cs
+++ b/src/minimaltest.websharper.spa/WithStaticRemoteTest.cs
@@ -9,13 +9,18 @@
namespace minimaltest
{
- //public class WithStaticRemoteTest : SpaTest // For TestFilter with 1 Browser
[TestFixture(typeof(ChromeDriver))]
[TestFixture(typeof(FirefoxDriver))] // at the speed of continental drift...
[TestFixture(typeof(InternetExplorerDriver))]
public class WithStaticRemoteTest : SpaTest
where TWebDriver : IWebDriver, new()
{
+ [OneTimeSetUp]
+ public void NoAwaitRemoved()
+ {
+ this.awaitRemovedDefault = false;
+ }
+
///
/// Typed accessor to the only model object in the app
///
diff --git a/src/minimaltest.websharper.spa/WithStorageRemoteTest.cs b/src/minimaltest.websharper.spa/WithStorageRemoteTest.cs
index 7bffdb52..82be7357 100644
--- a/src/minimaltest.websharper.spa/WithStorageRemoteTest.cs
+++ b/src/minimaltest.websharper.spa/WithStorageRemoteTest.cs
@@ -11,14 +11,17 @@
namespace minimaltest
{
- //public class WithStaticRemoteTest : SpaTest // For TestFilter with 1 Browser
- //public class WithStorageRemoteTest : SpaTest // does not work with FireFox
[TestFixture(typeof(ChromeDriver))]
[TestFixture(typeof(InternetExplorerDriver))]
public class WithStorageRemoteTest : SpaStorageTest
where TWebDriver : IWebDriver, new()
- //public class WithStorageRemoteTest : SpaTest
{
+ [OneTimeSetUp]
+ public void NoAwaitRemoved()
+ {
+ this.awaitRemovedDefault = false;
+ }
+
///
/// Typed accessor to the only model object in the app
///
diff --git a/src/minimaltestrunner.core/Runner.cs b/src/minimaltestrunner.core/Runner.cs
index 9a7c8422..98b03384 100644
--- a/src/minimaltestrunner.core/Runner.cs
+++ b/src/minimaltestrunner.core/Runner.cs
@@ -27,6 +27,7 @@ public void TearDown()
public void RunTests()
{
this.Navigate("/");
+ this.driver.Navigate().Refresh();
this.ClickID("testButton");
this.AssertTestsOK();
}
diff --git a/src/minimaltestrunner.websharper.spa/Runner.cs b/src/minimaltestrunner.websharper.spa/Runner.cs
index 1c004d41..2cbd5bff 100644
--- a/src/minimaltestrunner.websharper.spa/Runner.cs
+++ b/src/minimaltestrunner.websharper.spa/Runner.cs
@@ -26,8 +26,10 @@ public void TearDown()
[Test]
public void RunTests()
{
- this.Navigate("/", delay: 7000); // server not yet ready on 1st run
- this.Click("testButton");
+ this.Navigate("/", delay: 7000); // server not yet ready on 1st run
+ this.driver.Navigate().Refresh(); // and the page sometimes doesn't load the 1st time
+ this.AssertPoll(() => this.GetHTMLElementById("testButton").Displayed, () => Is.True);
+ this.Click("testButton", awaitRemoved: false);
this.AssertTestsOK();
}
}
diff --git a/src/minimaltestrunner.websharper.spa/minimaltestrunner.websharper.spa.csproj b/src/minimaltestrunner.websharper.spa/minimaltestrunner.websharper.spa.csproj
index c3912352..5d563dfe 100644
--- a/src/minimaltestrunner.websharper.spa/minimaltestrunner.websharper.spa.csproj
+++ b/src/minimaltestrunner.websharper.spa/minimaltestrunner.websharper.spa.csproj
@@ -23,6 +23,7 @@
+