Add E2E test support for starting ASP.NET sites

This commit is contained in:
Steve Sanderson 2017-12-05 23:49:24 +00:00
parent 1cef27bcff
commit 29a8a21ed3
14 changed files with 268 additions and 65 deletions

View File

@ -37,6 +37,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "mono", "mono", "{7B5CAAB1-A
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Blazor.Mono", "runtime\Microsoft.Blazor.Mono\Microsoft.Blazor.Mono.csproj", "{39FEC72D-AF52-47A3-B63D-7BF0E4335248}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoSanity", "samples\MonoSanity\MonoSanity.csproj", "{7C53BB6B-5906-4753-B507-C9FCC2F7E5B7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -55,6 +57,10 @@ Global
{39FEC72D-AF52-47A3-B63D-7BF0E4335248}.Debug|Any CPU.Build.0 = Debug|Any CPU
{39FEC72D-AF52-47A3-B63D-7BF0E4335248}.Release|Any CPU.ActiveCfg = Release|Any CPU
{39FEC72D-AF52-47A3-B63D-7BF0E4335248}.Release|Any CPU.Build.0 = Release|Any CPU
{7C53BB6B-5906-4753-B507-C9FCC2F7E5B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7C53BB6B-5906-4753-B507-C9FCC2F7E5B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7C53BB6B-5906-4753-B507-C9FCC2F7E5B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7C53BB6B-5906-4753-B507-C9FCC2F7E5B7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -63,6 +69,7 @@ Global
{4C7EE25B-E9C7-4CA3-8357-77ADF9AAD20A} = {F5FDD4E5-6A52-4A86-BE5E-5E42CB1DC8DA}
{7B5CAAB1-A3EB-44F7-87E3-A13ED89FC17D} = {B867E038-B3CE-43E3-9292-61568C46CDEB}
{39FEC72D-AF52-47A3-B63D-7BF0E4335248} = {B867E038-B3CE-43E3-9292-61568C46CDEB}
{7C53BB6B-5906-4753-B507-C9FCC2F7E5B7} = {F5FDD4E5-6A52-4A86-BE5E-5E42CB1DC8DA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {504DA352-6788-4DC0-8705-82167E72A4D3}

View File

@ -15,4 +15,8 @@
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\samples\MonoSanity\MonoSanity.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,29 @@
// 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.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using System;
using System.IO;
namespace Blazor.E2ETest.Infrastructure
{
public class AspNetServerFixture : ServerFixture
{
public string StartAndGetUrl(Type startupType)
{
var sampleSitePath = Path.Combine(
FindSolutionDir(),
"samples",
startupType.Assembly.GetName().Name);
var host = WebHost.CreateDefaultBuilder()
.UseStartup(startupType)
.UseContentRoot(sampleSitePath)
.UseUrls("http://127.0.0.1:0")
.Build();
return StartAndGetUrl(host);
}
}
}

View File

@ -0,0 +1,33 @@
// 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 OpenQA.Selenium;
using System;
using Xunit;
namespace Blazor.E2ETest.Infrastructure
{
public class AspNetSiteTestBase<TStartup>
: IClassFixture<BrowserFixture>, IClassFixture<AspNetServerFixture>
{
public IWebDriver Browser { get; }
private Uri _serverRootUri;
public AspNetSiteTestBase(
BrowserFixture browserFixture,
AspNetServerFixture serverFixture)
{
Browser = browserFixture.Browser;
var serverRootUriString = serverFixture.StartAndGetUrl(typeof(TStartup));
_serverRootUri = new Uri(serverRootUriString);
}
public void Navigate(string relativeUrl)
{
var absoluteUrl = new Uri(_serverRootUri, relativeUrl);
Browser.Navigate().GoToUrl(absoluteUrl);
}
}
}

View File

@ -0,0 +1,74 @@
// 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.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server.Features;
using System;
using System.IO;
using System.Linq;
using System.Threading;
namespace Blazor.E2ETest.Infrastructure
{
public abstract class ServerFixture : IDisposable
{
private IWebHost _host;
public void Dispose()
{
_host.StopAsync();
}
protected string StartAndGetUrl(IWebHost host)
{
_host = host;
return StartWebHostInBackgroundThread();
}
protected static string FindSolutionDir()
{
return FindClosestDirectoryContaining(
"Blazor.sln",
Path.GetDirectoryName(typeof(ServerFixture).Assembly.Location));
}
private static string FindClosestDirectoryContaining(
string filename,
string startDirectory)
{
var dir = startDirectory;
while (true)
{
if (File.Exists(Path.Combine(dir, filename)))
{
return dir;
}
dir = Directory.GetParent(dir)?.FullName;
if (string.IsNullOrEmpty(dir))
{
throw new FileNotFoundException(
$"Could not locate a file called '{filename}' in " +
$"directory '{startDirectory}' or any parent directory.");
}
}
}
private string StartWebHostInBackgroundThread()
{
var serverStarted = new ManualResetEvent(false);
new Thread(() =>
{
_host.Start();
serverStarted.Set();
}).Start();
serverStarted.WaitOne();
return _host.ServerFeatures
.Get<IServerAddressesFeature>()
.Addresses.Single();
}
}
}

View File

@ -1,51 +1,30 @@
// 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.Linq;
using System.Threading;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server.Features;
namespace Blazor.E2ETest.Infrastructure
{
public class StaticServerFixture : IDisposable
public class StaticServerFixture : ServerFixture
{
private IWebHost _host;
public string Start(string path)
public string StartAndGetUrl(string sampleSiteName)
{
_host = new WebHostBuilder()
var sampleSitePath = Path.Combine(
FindSolutionDir(),
"samples",
sampleSiteName);
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(path)
.UseContentRoot(sampleSitePath)
.UseWebRoot(string.Empty)
.UseStartup<Startup>()
.UseUrls("http://127.0.0.1:0")
.Build();
StartWebHostInBackgroundThread(_host);
return _host.ServerFeatures
.Get<IServerAddressesFeature>()
.Addresses.Single();
}
public void Dispose()
{
_host.StopAsync();
}
private static void StartWebHostInBackgroundThread(IWebHost host)
{
var serverStarted = new ManualResetEvent(false);
new Thread(() =>
{
host.Start();
serverStarted.Set();
}).Start();
serverStarted.WaitOne();
return StartAndGetUrl(host);
}
private class Startup

View File

@ -18,13 +18,12 @@ namespace Blazor.E2ETest.Infrastructure
public StaticSiteTestBase(
BrowserFixture browserFixture,
StaticServerFixture serverFixture,
string staticSitePath)
string sampleSiteName)
{
Browser = browserFixture.Browser;
// Start a static files web server for the specified directory
var staticSiteFullPath = Path.Combine(FindSolutionDir(), staticSitePath);
var serverRootUriString = serverFixture.Start(staticSiteFullPath);
var serverRootUriString = serverFixture.StartAndGetUrl(sampleSiteName);
_serverRootUri = new Uri(serverRootUriString);
}
@ -33,34 +32,5 @@ namespace Blazor.E2ETest.Infrastructure
var absoluteUrl = new Uri(_serverRootUri, relativeUrl);
Browser.Navigate().GoToUrl(absoluteUrl);
}
private string FindSolutionDir()
{
return FindClosestDirectoryContaining(
"Blazor.sln",
Path.GetDirectoryName(GetType().Assembly.Location));
}
private static string FindClosestDirectoryContaining(
string filename,
string startDirectory)
{
var dir = startDirectory;
while (true)
{
if (File.Exists(Path.Combine(dir, filename)))
{
return dir;
}
dir = Directory.GetParent(dir)?.FullName;
if (string.IsNullOrEmpty(dir))
{
throw new FileNotFoundException(
$"Could not locate a file called '{filename}' in " +
$"directory '{startDirectory}' or any parent directory.");
}
}
}
}
}

View File

@ -10,7 +10,7 @@ namespace Blazor.E2ETest.Tests
public class HelloWorldTest : StaticSiteTestBase
{
public HelloWorldTest(BrowserFixture browserFixture, StaticServerFixture serverFixture)
: base(browserFixture, serverFixture, @"samples\HelloWorld")
: base(browserFixture, serverFixture, "HelloWorld")
{
}

View File

@ -0,0 +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 Blazor.E2ETest.Infrastructure;
using Xunit;
namespace Blazor.E2ETest.Tests
{
public class MonoSanityTest : AspNetSiteTestBase<MonoSanity.Startup>
{
public MonoSanityTest(BrowserFixture browserFixture, AspNetServerFixture serverFixture)
: base(browserFixture, serverFixture)
{
}
[Fact]
public void HasTitle()
{
Navigate("/");
Assert.Equal("Mono sanity check", Browser.Title);
}
}
}

View File

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,21 @@
// 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.AspNetCore;
using Microsoft.AspNetCore.Hosting;
namespace MonoSanity
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
}

View File

@ -0,0 +1,27 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:50885/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"MonoSanity": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:50886/"
}
}
}

View File

@ -0,0 +1,17 @@
// 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.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
namespace MonoSanity
{
public class Startup
{
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseDeveloperExceptionPage();
app.UseFileServer();
}
}
}

View File

@ -0,0 +1,8 @@
<html>
<head>
<title>Mono sanity check</title>
</head>
<body>
<h1>Hello, world!</h1>
</body>
</html>