Enforce E2E test prerequisites when building individual solutions only (#11642)

* Fixes multiple issues that happened due to the E2E tests not running on the CI
* Enforces prerequisites for E2E tests on the CI and when building projects with E2E tests.
* Re-enables the E2E tests for templates.
This commit is contained in:
Javier Calvarro Nelson 2019-06-29 01:04:36 +02:00 committed by GitHub
parent f7de3da7a1
commit 1480b99866
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 211 additions and 125 deletions

View File

@ -28,7 +28,7 @@
<PropertyGroup>
<RunCommand>dotnet</RunCommand>
<_BlazorCliLocation>$(MSBuildThisFileDirectory)../../DevServer/src/bin/$(Configuration)/netcoreapp3.0/blazor-devserver.dll</_BlazorCliLocation>
<RunArguments>exec &quot;$(_BlazorCliLocation)&quot; serve &quot;$(MSBuildProjectDirectory)/$(OutputPath)$(TargetFileName)&quot; $(AdditionalRunArguments)</RunArguments>
<RunArguments>exec &quot;$(_BlazorCliLocation)&quot; serve --applicationpath &quot;$(MSBuildProjectDirectory)/$(OutputPath)$(TargetFileName)&quot; $(AdditionalRunArguments)</RunArguments>
</PropertyGroup>
<ItemGroup>

View File

@ -1,11 +1,9 @@
// 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 System;
using System.IO;
using System.Runtime.Versioning;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.CommandLineUtils;
using Microsoft.Extensions.Hosting;
namespace Microsoft.AspNetCore.Blazor.DevServer.Commands
{
@ -23,28 +21,11 @@ namespace Microsoft.AspNetCore.Blazor.DevServer.Commands
HelpOption("-?|-h|--help");
ApplicationPath = new CommandArgument()
{
Description = "Path to the client application dll",
MultipleValues = false,
Name = "<PATH>",
ShowInHelpText = true
};
Arguments.Add(ApplicationPath);
OnExecute(Execute);
}
public CommandArgument ApplicationPath { get; private set; }
private int Execute()
{
if (string.IsNullOrWhiteSpace(ApplicationPath.Value))
{
throw new InvalidOperationException($"Invalid value for parameter '{nameof(ApplicationPath)}'. Value supplied: '{ApplicationPath.Value}'");
}
Server.Startup.ApplicationAssembly = ApplicationPath.Value;
Server.Program.BuildWebHost(RemainingArguments.ToArray()).Run();
return 0;
}

View File

@ -19,6 +19,7 @@
<Reference Include="Microsoft.AspNetCore.ResponseCompression" />
<Reference Include="Microsoft.AspNetCore" />
<Reference Include="Microsoft.Extensions.CommandLineUtils.Sources" />
<Reference Include="Microsoft.Extensions.Hosting" />
</ItemGroup>
<!-- Pack settings -->

View File

@ -1,8 +1,15 @@
// 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.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
namespace Microsoft.AspNetCore.Blazor.DevServer.Server
{
@ -18,12 +25,24 @@ namespace Microsoft.AspNetCore.Blazor.DevServer.Server
/// <summary>
/// Intended for framework test use only.
/// </summary>
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseConfiguration(new ConfigurationBuilder()
.AddCommandLine(args)
.Build())
.UseStartup<Startup>()
.Build();
public static IHost BuildWebHost(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureHostConfiguration(cb => {
var applicationPath = args.SkipWhile(a => a != "--applicationpath").Skip(1).FirstOrDefault();
var name = Path.ChangeExtension(applicationPath,".StaticWebAssets.xml");
if (name != null)
{
cb.AddInMemoryCollection(new Dictionary<string, string>
{
[WebHostDefaults.StaticWebAssetsKey] = name
});
}
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStaticWebAssets();
webBuilder.UseStartup<Startup>();
}).Build();
}
}

View File

@ -17,7 +17,12 @@ namespace Microsoft.AspNetCore.Blazor.DevServer.Server
{
internal class Startup
{
public static string ApplicationAssembly { get; set; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
@ -35,7 +40,7 @@ namespace Microsoft.AspNetCore.Blazor.DevServer.Server
public void Configure(IApplicationBuilder app, IWebHostEnvironment environment, IConfiguration configuration)
{
var applicationAssemblyFullPath = ResolveApplicationAssemblyFullPath(environment);
var applicationAssemblyFullPath = ResolveApplicationAssemblyFullPath();
app.UseDeveloperExceptionPage();
app.UseResponseCompression();
@ -54,15 +59,22 @@ namespace Microsoft.AspNetCore.Blazor.DevServer.Server
});
}
private static string ResolveApplicationAssemblyFullPath(IWebHostEnvironment environment)
private string ResolveApplicationAssemblyFullPath()
{
var applicationAssemblyFullPath = Path.Combine(environment.ContentRootPath, ApplicationAssembly);
if (!File.Exists(applicationAssemblyFullPath))
const string applicationPathKey = "applicationpath";
var configuredApplicationPath = Configuration.GetValue<string>(applicationPathKey);
if (string.IsNullOrEmpty(configuredApplicationPath))
{
throw new InvalidOperationException($"Application assembly not found at {applicationAssemblyFullPath}.");
throw new InvalidOperationException($"No value was supplied for the required option '{applicationPathKey}'.");
}
return applicationAssemblyFullPath;
var resolvedApplicationPath = Path.GetFullPath(configuredApplicationPath);
if (!File.Exists(resolvedApplicationPath))
{
throw new InvalidOperationException($"Application assembly not found at {resolvedApplicationPath}.");
}
return resolvedApplicationPath;
}
private static void EnableConfiguredPathbase(IApplicationBuilder app, IConfiguration configuration)

View File

@ -2,6 +2,6 @@
<PropertyGroup>
<_BlazorDevServerDll>$(MSBuildThisFileDirectory)../tools/blazor-devserver.dll</_BlazorDevServerDll>
<RunCommand>dotnet</RunCommand>
<RunArguments>&quot;$(_BlazorDevServerDll)&quot; serve &quot;$(MSBuildProjectDirectory)/$(OutputPath)$(TargetFileName)&quot;</RunArguments>
<RunArguments>&quot;$(_BlazorDevServerDll)&quot; serve --applicationpath &quot;$(MSBuildProjectDirectory)/$(OutputPath)$(TargetFileName)&quot;</RunArguments>
</PropertyGroup>
</Project>

View File

@ -1,3 +1,3 @@
@ECHO OFF
SET RepoRoot=%~dp0..\..
%RepoRoot%\build.cmd -projects %~dp0**\*.*proj %*
%RepoRoot%\build.cmd -projects %~dp0**\*.*proj "/p:EnforceE2ETestPrerequisites=true" %*

View File

@ -4,4 +4,4 @@ set -euo pipefail
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
repo_root="$DIR/../.."
"$repo_root/build.sh" --projects "$DIR/**/*.*proj" "$@"
"$repo_root/build.sh" --projects "$DIR/**/*.*proj" "/p:EnforceE2ETestPrerequisites=true" "$@"

View File

@ -2,7 +2,13 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using DevHostServerProgram = Microsoft.AspNetCore.Blazor.DevServer.Server.Program;
namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures
@ -22,7 +28,8 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures
{
"--urls", "http://127.0.0.1:0",
"--contentroot", ContentRoot,
"--pathbase", PathBase
"--pathbase", PathBase,
"--applicationpath", typeof(TProgram).Assembly.Location,
};
if (!string.IsNullOrEmpty(Environment))
@ -31,7 +38,29 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures
args.Add(Environment);
}
return DevHostServerProgram.BuildWebHost(args.ToArray());
return new FakeWebHost(DevHostServerProgram.BuildWebHost(args.ToArray()));
}
private class FakeWebHost : IWebHost
{
private readonly IHost _realHost;
public FakeWebHost(IHost realHost)
{
_realHost = realHost;
}
public IFeatureCollection ServerFeatures => ((IServer)_realHost.Services.GetService(typeof(IServer))).Features;
public IServiceProvider Services => _realHost.Services;
public void Dispose() => _realHost.Dispose();
public void Start() => _realHost.Start();
public Task StartAsync(CancellationToken cancellationToken = default) => _realHost.StartAsync();
public Task StopAsync(CancellationToken cancellationToken = default) => _realHost.StopAsync();
}
}
}

View File

@ -7,10 +7,7 @@
<TargetFramework>netcoreapp3.0</TargetFramework>
<TestGroupName>Components.E2ETests</TestGroupName>
<!--
Temporarily disabled until this runs on macOS
-->
<SkipTests Condition="'$(SeleniumE2ETestsSupported)' != 'true'">true</SkipTests>
<SkipTests>true</SkipTests>
<!-- https://github.com/aspnet/AspNetCore/issues/6857 -->
<BuildHelixPayload>false</BuildHelixPayload>

View File

@ -5,33 +5,39 @@
<title>Basic test app</title>
<base href="/subdir/" />
<link href="style.css" rel="stylesheet" />
<!-- Used by ExternalContentPackage -->
<link href="_content/TestContentPackage/styles.css" rel="stylesheet" />
</head>
<body>
<root>Loading...</root>
<root>Loading...</root>
<!-- Used for testing interop scenarios between JS and .NET -->
<script src="js/jsinteroptests.js"></script>
<!-- Used for testing interop scenarios between JS and .NET -->
<script src="js/jsinteroptests.js"></script>
<script>
// Used by ElementRefComponent
function setElementValue(element, newValue) {
element.value = newValue;
return element.value;
}
<script>
// Used by ElementRefComponent
function setElementValue(element, newValue) {
element.value = newValue;
return element.value;
}
function uriHelperNavigate() {
Blazor.navigateTo('/subdir/some-path');
}
function uriHelperNavigate() {
Blazor.navigateTo('/subdir/some-path');
}
(function () {
// Load either blazor.webassembly.js or blazor.server.js depending
// on the hash part of the URL. This is just to give a way for the
// test runner to make the selection.
var src = location.hash === '#server'
? 'blazor.server.js'
: 'blazor.webassembly.js';
document.write('<script src="_framework/' + src + '"><' + '/script>');
})();
</script>
(function () {
// Load either blazor.webassembly.js or blazor.server.js depending
// on the hash part of the URL. This is just to give a way for the
// test runner to make the selection.
var src = location.hash === '#server'
? 'blazor.server.js'
: 'blazor.webassembly.js';
document.write('<script src="_framework/' + src + '"><' + '/script>');
})();
</script>
<!-- Used by ExternalContentPackage -->
<script src="_content/TestContentPackage/prompt.js"></script>
</body>
</html>

View File

@ -4,19 +4,9 @@
<TargetFramework>netstandard2.0</TargetFramework>
<OutputType>library</OutputType>
<RazorLangVersion>3.0</RazorLangVersion>
<StaticWebAssetBasePath>_content/TestContentPackage</StaticWebAssetBasePath>
</PropertyGroup>
<ItemGroup>
<!-- .js files will be referenced via <script> tags -->
<EmbeddedResource Include="content\**\*.js" LogicalName="blazor:js:%(RecursiveDir)%(Filename)%(Extension)" />
<!-- .css files will be referenced via <link rel='Stylesheet'> tags -->
<EmbeddedResource Include="content\**\*.css" LogicalName="blazor:css:%(RecursiveDir)%(Filename)%(Extension)" />
<!-- Any other files will be included in the 'dist' output but without any tags referencing them -->
<EmbeddedResource Include="content\**" Exclude="**\*.js;**\*.css" LogicalName="blazor:file:%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Components" />
</ItemGroup>

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -19,6 +19,7 @@ namespace TestServer
.AddCommandLine(args)
.Build())
.UseStartup<TStartup>()
.UseStaticWebAssets()
.Build();
}
}

View File

@ -1,10 +1,7 @@
using BasicTestApp;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Components.Server;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
@ -63,6 +60,7 @@ namespace TestServer
// Mount the server-side Blazor app on /subdir
app.Map("/subdir", subdirApp =>
{
subdirApp.UseStaticFiles();
subdirApp.UseClientSideBlazorFiles<BasicTestApp.Startup>();
subdirApp.UseRouting();

View File

@ -211,7 +211,7 @@ namespace Microsoft.AspNetCore
{
if (ctx.HostingEnvironment.IsDevelopment())
{
StaticWebAssetsLoader.UseStaticWebAssets(ctx.HostingEnvironment);
StaticWebAssetsLoader.UseStaticWebAssets(ctx.HostingEnvironment, ctx.Configuration);
}
});
builder.UseKestrel((builderContext, options) =>

View File

@ -121,6 +121,7 @@ namespace Microsoft.AspNetCore.Hosting
public static readonly string ServerUrlsKey;
public static readonly string ShutdownTimeoutKey;
public static readonly string StartupAssemblyKey;
public static readonly string StaticWebAssetsKey;
public static readonly string SuppressStatusMessagesKey;
public static readonly string WebRootKey;
}

View File

@ -21,5 +21,6 @@ namespace Microsoft.AspNetCore.Hosting
public static readonly string SuppressStatusMessagesKey = "suppressStatusMessages";
public static readonly string ShutdownTimeoutKey = "shutdownTimeoutSeconds";
public static readonly string StaticWebAssetsKey = "staticWebAssets";
}
}

View File

@ -82,7 +82,7 @@ namespace Microsoft.AspNetCore.Hosting.StaticWebAssets
public partial class StaticWebAssetsLoader
{
public StaticWebAssetsLoader() { }
public static void UseStaticWebAssets(Microsoft.AspNetCore.Hosting.IWebHostEnvironment environment) { }
public static void UseStaticWebAssets(Microsoft.AspNetCore.Hosting.IWebHostEnvironment environment, Microsoft.Extensions.Configuration.IConfiguration configuration) { }
}
}
namespace Microsoft.Extensions.Hosting

View File

@ -7,6 +7,7 @@ using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.FileProviders;
namespace Microsoft.AspNetCore.Hosting.StaticWebAssets
@ -21,10 +22,11 @@ namespace Microsoft.AspNetCore.Hosting.StaticWebAssets
/// <summary>
/// Configure the <see cref="IWebHostEnvironment"/> to use static web assets.
/// </summary>
/// <param name="environment"></param>
public static void UseStaticWebAssets(IWebHostEnvironment environment)
/// <param name="environment">The application <see cref="IWebHostEnvironment"/>.</param>
/// <param name="configuration">The host <see cref="IConfiguration"/>.</param>
public static void UseStaticWebAssets(IWebHostEnvironment environment, IConfiguration configuration)
{
using (var manifest = ResolveManifest(environment))
using (var manifest = ResolveManifest(environment, configuration))
{
if (manifest != null)
{
@ -54,13 +56,13 @@ namespace Microsoft.AspNetCore.Hosting.StaticWebAssets
}
}
internal static Stream ResolveManifest(IWebHostEnvironment environment)
internal static Stream ResolveManifest(IWebHostEnvironment environment, IConfiguration configuration)
{
try
{
var assembly = Assembly.Load(environment.ApplicationName);
var filePath = Path.Combine(Path.GetDirectoryName(GetAssemblyLocation(assembly)), $"{environment.ApplicationName}.StaticWebAssets.xml");
var manifestPath = configuration.GetValue<string>(WebHostDefaults.StaticWebAssetsKey);
var filePath = manifestPath ?? ResolveRelativeToAssembly(environment);
if (File.Exists(filePath))
{
return File.OpenRead(filePath);
@ -79,6 +81,12 @@ namespace Microsoft.AspNetCore.Hosting.StaticWebAssets
}
}
private static string ResolveRelativeToAssembly(IWebHostEnvironment environment)
{
var assembly = Assembly.Load(environment.ApplicationName);
return Path.Combine(Path.GetDirectoryName(GetAssemblyLocation(assembly)), $"{environment.ApplicationName}.StaticWebAssets.xml");
}
internal static string GetAssemblyLocation(Assembly assembly)
{
if (Uri.TryCreate(assembly.CodeBase, UriKind.Absolute, out var result) &&

View File

@ -189,7 +189,7 @@ namespace Microsoft.AspNetCore.Hosting
{
builder.ConfigureAppConfiguration((context, configBuilder) =>
{
StaticWebAssetsLoader.UseStaticWebAssets(context.HostingEnvironment);
StaticWebAssetsLoader.UseStaticWebAssets(context.HostingEnvironment, context.Configuration);
});
return builder;

View File

@ -2,10 +2,13 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using Xunit;
namespace Microsoft.AspNetCore.Hosting.StaticWebAssets
@ -72,12 +75,39 @@ namespace Microsoft.AspNetCore.Hosting.StaticWebAssets
};
// Act
var manifest = StaticWebAssetsLoader.ResolveManifest(environment);
var manifest = StaticWebAssetsLoader.ResolveManifest(environment, new ConfigurationBuilder().Build());
// Assert
Assert.Equal(expectedManifest, new StreamReader(manifest).ReadToEnd());
}
[Fact]
public void ResolveManifest_UsesConfigurationKey_WhenProvided()
{
// Arrange
var expectedManifest = @"<StaticWebAssets Version=""1.0"">
<ContentRoot Path=""/Path"" BasePath=""/BasePath"" />
</StaticWebAssets>
";
var path = Path.ChangeExtension(new Uri(typeof(StaticWebAssetsLoader).Assembly.CodeBase).LocalPath, ".StaticWebAssets.xml");
var environment = new HostingEnvironment()
{
ApplicationName = "NonExistingDll"
};
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string>() {
[WebHostDefaults.StaticWebAssetsKey] = path
}).Build();
// Act
var manifest = StaticWebAssetsLoader.ResolveManifest(environment, configuration);
// Assert
Assert.Equal(expectedManifest, new StreamReader(manifest).ReadToEnd());
}
private Stream CreateManifest(string manifestContent)
{
return new MemoryStream(Encoding.UTF8.GetBytes(manifestContent));

View File

@ -28,8 +28,8 @@ export class FetchData extends Component {
</thead>
<tbody>
{forecasts.map(forecast =>
<tr key={forecast.dateFormatted}>
<td>{forecast.dateFormatted}</td>
<tr key={forecast.date}>
<td>{forecast.date}</td>
<td>{forecast.temperatureC}</td>
<td>{forecast.temperatureF}</td>
<td>{forecast.summary}</td>

View File

@ -52,8 +52,8 @@ class FetchData extends React.PureComponent<WeatherForecastProps> {
</thead>
<tbody>
{this.props.forecasts.map((forecast: WeatherForecastsStore.WeatherForecast) =>
<tr key={forecast.dateFormatted}>
<td>{forecast.dateFormatted}</td>
<tr key={forecast.date}>
<td>{forecast.date}</td>
<td>{forecast.temperatureC}</td>
<td>{forecast.temperatureF}</td>
<td>{forecast.summary}</td>

View File

@ -11,7 +11,7 @@ export interface WeatherForecastsState {
}
export interface WeatherForecast {
dateFormatted: string;
date: string;
temperatureC: number;
temperatureF: number;
summary: string;

View File

@ -1,3 +1,3 @@
@ECHO OFF
SET RepoRoot=%~dp0..\..
%RepoRoot%\build.cmd -projects %~dp0**\*.*proj %*
%RepoRoot%\build.cmd -projects %~dp0**\*.*proj "/p:EnforceE2ETestPrerequisites=true" %*

View File

@ -4,4 +4,4 @@ set -euo pipefail
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
repo_root="$DIR/../.."
"$repo_root/build.sh" --projects "$DIR/**/*.*proj" "$@"
"$repo_root/build.sh" --projects "$DIR/**/*.*proj" "/p:EnforceE2ETestPrerequisites=true" "$@"

View File

@ -184,7 +184,8 @@ namespace Templates.Test.Helpers
var environment = new Dictionary<string, string>
{
["ASPNETCORE_URLS"] = _urls,
["ASPNETCORE_ENVIRONMENT"] = "Development"
["ASPNETCORE_ENVIRONMENT"] = "Development",
["ASPNETCORE_Kestrel__EndpointDefaults__Protocols"] = "Http1"
};
var projectDll = Path.Combine(TemplateBuildDir, $"{ProjectName}.dll");
@ -196,6 +197,7 @@ namespace Templates.Test.Helpers
var environment = new Dictionary<string, string>
{
["ASPNETCORE_URLS"] = _urls,
["ASPNETCORE_Kestrel__EndpointDefaults__Protocols"] = "Http1"
};
var projectDll = $"{ProjectName}.dll";

View File

@ -3,6 +3,7 @@
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
@ -78,7 +79,10 @@ namespace Microsoft.AspNetCore.E2ETesting
var opts = new ChromeOptions();
// Comment this out if you want to watch or interact with the browser (e.g., for debugging)
opts.AddArgument("--headless");
if (!Debugger.IsAttached)
{
opts.AddArgument("--headless");
}
// Log errors
opts.SetLoggingPreference(LogType.Browser, LogLevel.All);

View File

@ -3,8 +3,16 @@
<_DefaultProjectFilter>$(MSBuildProjectDirectory)\..\..</_DefaultProjectFilter>
<DefaultItemExcludes>$(DefaultItemExcludes);node_modules\**</DefaultItemExcludes>
<SeleniumProcessTrackingFolder Condition="'$(SeleniumProcessTrackingFolder)' == ''">$([MSBuild]::EnsureTrailingSlash('$(RepoRoot)'))artifacts\tmp\selenium\</SeleniumProcessTrackingFolder>
<SeleniumE2ETestsSupported Condition="'$(SeleniumE2ETestsSupported)' == '' and '$(TargetArchitecture)' != 'arm' and '$(OS)' == 'Windows_NT' and '$(BuildJava)' == 'true'">true</SeleniumE2ETestsSupported>
<EnforcePrerequisites Condition="'$(SeleniumE2ETestsSupported)' == 'true' and '$(EnforcePrerequisites)' == ''">true</EnforcePrerequisites>
<SeleniumE2ETestsSupported Condition="'$(SeleniumE2ETestsSupported)' == '' and '$(TargetArchitecture)' != 'arm' and '$(OS)' == 'Windows_NT'">true</SeleniumE2ETestsSupported>
<!-- We want to enforce prerequisites when we build from the CI or within Visual Studio -->
<EnforcedE2EBuildEnvironment Condition="'$(ContinuousIntegrationBuild)' == 'true' or '$(BuildingInsideVisualStudio)' == 'true'">true</EnforcedE2EBuildEnvironment>
<!-- If not explicitly set, enforce E2E test prerequisites when the platform is supported and we are building on the CI or visual studio -->
<EnforceE2ETestPrerequisites Condition="'$(SeleniumE2ETestsSupported)' == 'true' and $(EnforcedE2EBuildEnvironment) == 'true' and '$(EnforceE2ETestPrerequisites)' == ''">true</EnforceE2ETestPrerequisites>
<!-- Never enforce E2E test prerequisites if the platform is not supported -->
<EnforceE2ETestPrerequisites Condition="'$(SeleniumE2ETestsSupported)' != 'true'">false</EnforceE2ETestPrerequisites>
<!-- WebDriver is not strong-named, so this test project cannot be strong named either. -->
<SignAssembly>false</SignAssembly>

View File

@ -7,7 +7,7 @@
<Target Name="EnsureNodeJSRestored" Condition="'$(SeleniumE2ETestsSupported)' == 'true'" BeforeTargets="Build">
<Message Text="Running yarn install on $(MSBuildProjectFile)" Importance="High" />
<Message Condition="'$(EnforcePrerequisites)' == ''"
<Message Condition="'$(EnforceE2ETestPrerequisites)' != 'true'"
Importance="High"
Text="Prerequisites were not enforced at build time. Running Yarn or the E2E tests might fail as a result. Check /src/Shared/E2ETesting/Readme.md for instructions." />
@ -17,13 +17,13 @@
<Target
Name="WarnSeleniumNotSupported"
BeforeTargets="Build"
Condition="'$(SeleniumE2ETestsSupported)' == ''">
Condition="'$(SeleniumE2ETestsSupported)' != 'true'">
<Message Importance="High" Text="Selenium tests are not supported for OS '$(OS)' and architecture '$(TargetArchitecture)'." />
</Target>
<!-- Running prerequisites -->
<Target Name="EnsurePrerequisites" Condition="'$(EnforcePrerequisites)' == 'true'" BeforeTargets="EnsureNodeJSRestored">
<Target Name="EnsurePrerequisites" Condition="'$(EnforceE2ETestPrerequisites)' == 'true'" BeforeTargets="EnsureNodeJSRestored">
<PropertyGroup>
<_PackageJson>$(MSBuildProjectDirectory)\package.json</_PackageJson>
</PropertyGroup>

View File

@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.E2ETesting
private static IMessageSink _diagnosticsMessageSink;
// 1h 30 min
private static int SeleniumProcessTimeout = 5400;
private static int SeleniumProcessTimeout = 3600;
public SeleniumStandaloneServer(IMessageSink diagnosticsMessageSink)
{
@ -64,13 +64,9 @@ namespace Microsoft.AspNetCore.E2ETesting
public static async Task<SeleniumStandaloneServer> GetInstanceAsync(ITestOutputHelper output)
{
await _semaphore.WaitAsync();
try
{
if (Instance == null)
{
}
await _semaphore.WaitAsync();
if (Instance._process == null)
{
// No process was started, meaning the instance wasn't initialized.
@ -139,7 +135,7 @@ namespace Microsoft.AspNetCore.E2ETesting
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, args) => ProcessCleanup(process, pidFilePath);
// AppDomain.CurrentDomain.ProcessExit += (sender, args) => ProcessCleanup(process, pidFilePath);
// Log
void LogOutput(object sender, DataReceivedEventArgs e)
@ -183,7 +179,7 @@ namespace Microsoft.AspNetCore.E2ETesting
output = null;
logOutput.CompleteAdding();
var exitCodeString = process.HasExited ? process.ExitCode.ToString() : "Process has not yet exited.";
var message = @$"Failed to launch the server.
var message = $@"Failed to launch the server.
ExitCode: {exitCodeString}
Captured output lines:
{string.Join(Environment.NewLine, logOutput.GetConsumingEnumerable())}.";
@ -211,19 +207,20 @@ Captured output lines:
private static void ProcessCleanup(Process process, string pidFilePath)
{
if (process?.HasExited == false)
{
try
{
process?.KillTree(TimeSpan.FromSeconds(10));
process?.Dispose();
}
catch
{
}
}
try
{
if (process?.HasExited == false)
{
try
{
process?.KillTree(TimeSpan.FromSeconds(10));
process?.Dispose();
}
catch
{
// Ignore errors here since we can't do anything
}
}
if (pidFilePath != null && File.Exists(pidFilePath))
{
File.Delete(pidFilePath);
@ -231,6 +228,7 @@ Captured output lines:
}
catch
{
// Ignore errors here since we can't do anything
}
}