Cleanup some infrastructure pieces in Components
This commit is contained in:
parent
ebb7f3ade3
commit
c8319ece2a
|
|
@ -1,20 +1,23 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// 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;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Threading;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Testing;
|
||||||
|
using Microsoft.Extensions.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure
|
namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure
|
||||||
{
|
{
|
||||||
class SeleniumStandaloneServer
|
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;
|
private static SeleniumStandaloneServer _instance;
|
||||||
|
|
||||||
public Uri Uri { get; }
|
public Uri Uri { get; }
|
||||||
|
|
@ -40,15 +43,30 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure
|
||||||
var port = FindAvailablePort();
|
var port = FindAvailablePort();
|
||||||
Uri = new UriBuilder("http", "localhost", port, "/wd/hub").Uri;
|
Uri = new UriBuilder("http", "localhost", port, "/wd/hub").Uri;
|
||||||
|
|
||||||
var process = Process.Start(new ProcessStartInfo
|
var psi = new ProcessStartInfo
|
||||||
{
|
{
|
||||||
FileName = "npm",
|
FileName = "npm",
|
||||||
Arguments = $"run selenium-standalone start -- -- -port {port}",
|
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) =>
|
AppDomain.CurrentDomain.ProcessExit += (sender, e) =>
|
||||||
{
|
{
|
||||||
if (!process.HasExited)
|
if (!process.HasExited)
|
||||||
|
|
@ -57,34 +75,56 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure
|
||||||
process.Dispose();
|
process.Dispose();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
private void PollUntilProcessStarted()
|
void LogOutput(object sender, DataReceivedEventArgs e)
|
||||||
{
|
|
||||||
var timeoutAt = DateTime.Now.AddSeconds(30);
|
|
||||||
Exception lastException = null;
|
|
||||||
while (true)
|
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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();
|
throw new InvalidOperationException($"Failed to start selenium sever. {Environment.NewLine}{output}", ex.GetBaseException());
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures
|
||||||
|
|
||||||
public override void Dispose()
|
public override void Dispose()
|
||||||
{
|
{
|
||||||
_serverToDispose.Dispose();
|
_serverToDispose?.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
/// <reference path="../../../../../src/microsoft.jsinterop/javascriptruntime/dist/microsoft.jsinterop.d.ts" />
|
|
||||||
|
|
||||||
// We'll store the results from the tests here
|
// We'll store the results from the tests here
|
||||||
var results = {};
|
var results = {};
|
||||||
var assemblyName = 'BasicTestApp';
|
var assemblyName = 'BasicTestApp';
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||||
|
|
||||||
|
<!-- Reference targets and props from Components.Build package -->
|
||||||
|
<Import Project="..\..\..\Build\src\ReferenceFromSource.props" />
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<ReferenceBlazorBuildLocally>true</ReferenceBlazorBuildLocally>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<!-- Reference targets and props from Components.Build package -->
|
||||||
|
<Import Project="..\..\..\Build\src\ReferenceFromSource.props" />
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<OutputType>library</OutputType>
|
<OutputType>library</OutputType>
|
||||||
<ReferenceBlazorBuildLocally>true</ReferenceBlazorBuildLocally>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
@ -22,6 +24,4 @@
|
||||||
<Reference Include="Microsoft.NET.Sdk.Razor" PrivateAssets="All" />
|
<Reference Include="Microsoft.NET.Sdk.Razor" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<!-- In real content packages, use a <PackageReference> to Microsoft.AspNetCore.Blazor.Build instead. -->
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue