diff --git a/src/Components/test/E2ETest/Infrastructure/SeleniumStandaloneServer.cs b/src/Components/test/E2ETest/Infrastructure/SeleniumStandaloneServer.cs
index 752b0ce5c8..e263e4e5ea 100644
--- a/src/Components/test/E2ETest/Infrastructure/SeleniumStandaloneServer.cs
+++ b/src/Components/test/E2ETest/Infrastructure/SeleniumStandaloneServer.cs
@@ -1,20 +1,23 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-using Microsoft.Extensions.Internal;
using System;
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Net.Sockets;
-using System.Threading;
+using System.Runtime.InteropServices;
+using System.Text;
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Testing;
+using Microsoft.Extensions.Internal;
namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure
{
class SeleniumStandaloneServer
{
- private static object _instanceCreationLock = new object();
+ private static readonly TimeSpan Timeout = TimeSpan.FromSeconds(30);
+ private static readonly object _instanceCreationLock = new object();
private static SeleniumStandaloneServer _instance;
public Uri Uri { get; }
@@ -40,15 +43,30 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure
var port = FindAvailablePort();
Uri = new UriBuilder("http", "localhost", port, "/wd/hub").Uri;
- var process = Process.Start(new ProcessStartInfo
+ var psi = new ProcessStartInfo
{
FileName = "npm",
Arguments = $"run selenium-standalone start -- -- -port {port}",
- UseShellExecute = true,
- });
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ };
- PollUntilProcessStarted();
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ psi.FileName = "cmd";
+ psi.Arguments = $"/c npm {psi.Arguments}";
+ }
+ var process = Process.Start(psi);
+
+ var builder = new StringBuilder();
+ process.OutputDataReceived += LogOutput;
+ process.ErrorDataReceived += LogOutput;
+
+ process.BeginOutputReadLine();
+ process.BeginErrorReadLine();
+
+ // The Selenium sever has to be up for the entirety of the tests and is only shutdown when the application (i.e. the test) exits.
AppDomain.CurrentDomain.ProcessExit += (sender, e) =>
{
if (!process.HasExited)
@@ -57,34 +75,56 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure
process.Dispose();
}
};
- }
- private void PollUntilProcessStarted()
- {
- var timeoutAt = DateTime.Now.AddSeconds(30);
- Exception lastException = null;
- while (true)
+ void LogOutput(object sender, DataReceivedEventArgs e)
{
- if (DateTime.Now > timeoutAt)
+ lock (builder)
{
- throw new TimeoutException($"The selenium server instance did not start accepting requests at {Uri} before the timeout occurred. The last exception was: {lastException?.ToString() ?? "NULL"}");
+ builder.AppendLine(e.Data);
+ }
+ }
+
+ var waitForStart = Task.Run(async () =>
+ {
+ var httpClient = new HttpClient
+ {
+ Timeout = TimeSpan.FromSeconds(1),
+ };
+
+ while (true)
+ {
+ try
+ {
+ var responseTask = httpClient.GetAsync(Uri);
+
+ var response = await responseTask;
+ if (response.StatusCode == HttpStatusCode.OK)
+ {
+ return;
+ }
+ }
+ catch (OperationCanceledException)
+ {
+
+ }
+ await Task.Delay(1000);
+
+ }
+ });
+
+ try
+ {
+ waitForStart.TimeoutAfter(Timeout).Wait();
+ }
+ catch (Exception ex)
+ {
+ string output;
+ lock (builder)
+ {
+ output = builder.ToString();
}
- var httpClient = new HttpClient();
- try
- {
- var timeoutAfter1Second = new CancellationTokenSource(3000);
- var response = httpClient.GetAsync(
- Uri, timeoutAfter1Second.Token).Result;
- response.EnsureSuccessStatusCode();
- return;
- }
- catch (Exception ex)
- {
- lastException = ex;
- }
-
- Thread.Sleep(1000);
+ throw new InvalidOperationException($"Failed to start selenium sever. {Environment.NewLine}{output}", ex.GetBaseException());
}
}
diff --git a/src/Components/test/E2ETest/Infrastructure/ServerFixtures/ToggleExecutionModeServerFixture.cs b/src/Components/test/E2ETest/Infrastructure/ServerFixtures/ToggleExecutionModeServerFixture.cs
index 3a2f908509..9fb9863f60 100644
--- a/src/Components/test/E2ETest/Infrastructure/ServerFixtures/ToggleExecutionModeServerFixture.cs
+++ b/src/Components/test/E2ETest/Infrastructure/ServerFixtures/ToggleExecutionModeServerFixture.cs
@@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures
public override void Dispose()
{
- _serverToDispose.Dispose();
+ _serverToDispose?.Dispose();
}
}
}
diff --git a/src/Components/test/testassets/BasicTestApp/wwwroot/js/jsinteroptests.js b/src/Components/test/testassets/BasicTestApp/wwwroot/js/jsinteroptests.js
index 10882d9e61..97a7b0118b 100644
--- a/src/Components/test/testassets/BasicTestApp/wwwroot/js/jsinteroptests.js
+++ b/src/Components/test/testassets/BasicTestApp/wwwroot/js/jsinteroptests.js
@@ -1,5 +1,3 @@
-///
-
// We'll store the results from the tests here
var results = {};
var assemblyName = 'BasicTestApp';
diff --git a/src/Components/test/testassets/ComponentsApp.App/ComponentsApp.App.csproj b/src/Components/test/testassets/ComponentsApp.App/ComponentsApp.App.csproj
index 7819d3b088..e845bc60d4 100644
--- a/src/Components/test/testassets/ComponentsApp.App/ComponentsApp.App.csproj
+++ b/src/Components/test/testassets/ComponentsApp.App/ComponentsApp.App.csproj
@@ -1,8 +1,10 @@
+
+
+
netstandard2.0
- true
diff --git a/src/Components/test/testassets/TestContentPackage/TestContentPackage.csproj b/src/Components/test/testassets/TestContentPackage/TestContentPackage.csproj
index 7ef3a85690..f61c27f865 100644
--- a/src/Components/test/testassets/TestContentPackage/TestContentPackage.csproj
+++ b/src/Components/test/testassets/TestContentPackage/TestContentPackage.csproj
@@ -1,9 +1,11 @@
+
+
+
netstandard2.0
library
- true
@@ -22,6 +24,4 @@
-
-