parent
237b19b2b9
commit
fefffd7751
|
|
@ -1,5 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>Invoke Node.js modules at runtime in ASP.NET Core applications.</Description>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
<RazorLangVersion Condition="'$(SupportPagesAndViews)' != 'True'">3.0</RazorLangVersion>
|
||||
<AddRazorSupportForMvc Condition="'$(SupportPagesAndViews)' == 'True'">true</AddRazorSupportForMvc>
|
||||
<RootNamespace Condition="'$(name)' != '$(name{-VALUE-FORMS-}safe_namespace)'">Company.RazorClassLibrary1</RootNamespace>
|
||||
<AddRazorSupportForMvc Condition="'$(SupportPagesAndViews)' == 'True'">true</AddRazorSupportForMvc>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition="'$(SupportPagesAndViews)' == 'True'">
|
||||
|
|
|
|||
|
|
@ -22,12 +22,14 @@ namespace Templates.Test
|
|||
|
||||
public ITestOutputHelper Output { get; }
|
||||
|
||||
[Fact]
|
||||
public async Task EmptyWebTemplateAsync()
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("F#")]
|
||||
public async Task EmptyWebTemplateAsync(string languageOverride)
|
||||
{
|
||||
Project = await ProjectFactory.GetOrCreateProject("empty", Output);
|
||||
Project = await ProjectFactory.GetOrCreateProject("empty" + (languageOverride == "F#" ? "fsharp" : "csharp"), Output);
|
||||
|
||||
var createResult = await Project.RunDotNetNewAsync("web");
|
||||
var createResult = await Project.RunDotNetNewAsync("web", language: languageOverride);
|
||||
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
|
||||
|
||||
var publishResult = await Project.RunDotNetPublishAsync();
|
||||
|
|
@ -43,8 +45,8 @@ namespace Templates.Test
|
|||
using (var aspNetProcess = Project.StartBuiltProjectAsync())
|
||||
{
|
||||
Assert.False(
|
||||
aspNetProcess.Process.HasExited,
|
||||
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
|
||||
aspNetProcess.Process.HasExited,
|
||||
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
|
||||
|
||||
await aspNetProcess.AssertOk("/");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Templates.Test.Helpers;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Templates.Test
|
||||
{
|
||||
public class GrpcTemplateTest
|
||||
{
|
||||
public GrpcTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output)
|
||||
{
|
||||
ProjectFactory = projectFactory;
|
||||
Output = output;
|
||||
}
|
||||
|
||||
public Project Project { get; set; }
|
||||
|
||||
public ProjectFactoryFixture ProjectFactory { get; }
|
||||
public ITestOutputHelper Output { get; }
|
||||
|
||||
[Fact(Skip = "https://github.com/aspnet/AspNetCore/issues/7973")]
|
||||
public async Task GrpcTemplate()
|
||||
{
|
||||
Project = await ProjectFactory.GetOrCreateProject("grpc", Output);
|
||||
|
||||
var createResult = await Project.RunDotNetNewAsync("grpc");
|
||||
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
|
||||
|
||||
var publishResult = await Project.RunDotNetPublishAsync();
|
||||
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
|
||||
|
||||
var buildResult = await Project.RunDotNetBuildAsync();
|
||||
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult));
|
||||
|
||||
using (var serverProcess = Project.StartBuiltServerAsync())
|
||||
{
|
||||
Assert.False(
|
||||
serverProcess.Process.HasExited,
|
||||
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built server", Project, serverProcess.Process));
|
||||
|
||||
using (var clientProcess = Project.StartBuiltClientAsync(serverProcess))
|
||||
{
|
||||
// Wait for the client to do its thing
|
||||
await Task.Delay(100);
|
||||
Assert.False(
|
||||
clientProcess.Process.HasExited,
|
||||
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built client", Project, clientProcess.Process));
|
||||
}
|
||||
}
|
||||
|
||||
using (var aspNetProcess = Project.StartPublishedServerAsync())
|
||||
{
|
||||
Assert.False(
|
||||
aspNetProcess.Process.HasExited,
|
||||
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published server", Project, aspNetProcess.Process));
|
||||
|
||||
using (var clientProcess = Project.StartPublishedClientAsync())
|
||||
{
|
||||
// Wait for the client to do its thing
|
||||
await Task.Delay(100);
|
||||
Assert.False(
|
||||
clientProcess.Process.HasExited,
|
||||
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built client", Project, clientProcess.Process));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,8 @@ using System.Linq;
|
|||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using AngleSharp.Dom.Html;
|
||||
using AngleSharp.Parser.Html;
|
||||
using Microsoft.AspNetCore.Certificates.Generation;
|
||||
using Microsoft.Extensions.CommandLineUtils;
|
||||
using OpenQA.Selenium;
|
||||
|
|
@ -21,17 +23,19 @@ namespace Templates.Test.Helpers
|
|||
public class AspNetProcess : IDisposable
|
||||
{
|
||||
private const string ListeningMessagePrefix = "Now listening on: ";
|
||||
private readonly Uri _listeningUri;
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly ITestOutputHelper _output;
|
||||
|
||||
internal readonly Uri ListeningUri;
|
||||
internal ProcessEx Process { get; }
|
||||
|
||||
public AspNetProcess(
|
||||
ITestOutputHelper output,
|
||||
string workingDirectory,
|
||||
string dllPath,
|
||||
IDictionary<string, string> environmentVariables)
|
||||
IDictionary<string, string> environmentVariables,
|
||||
bool published = true,
|
||||
bool hasListeningUri = true)
|
||||
{
|
||||
_output = output;
|
||||
_httpClient = new HttpClient(new HttpClientHandler()
|
||||
|
|
@ -48,18 +52,20 @@ namespace Templates.Test.Helpers
|
|||
var now = DateTimeOffset.Now;
|
||||
new CertificateManager().EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1));
|
||||
|
||||
|
||||
output.WriteLine("Running ASP.NET application...");
|
||||
|
||||
Process = ProcessEx.Run(output, workingDirectory, DotNetMuxer.MuxerPathOrDefault(), $"exec {dllPath}", envVars: environmentVariables);
|
||||
_listeningUri = GetListeningUri(output);
|
||||
var arguments = published ? $"exec {dllPath}" : "run";
|
||||
Process = ProcessEx.Run(output, workingDirectory, DotNetMuxer.MuxerPathOrDefault(), arguments, envVars: environmentVariables);
|
||||
if(hasListeningUri)
|
||||
{
|
||||
ListeningUri = GetListeningUri(output);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void VisitInBrowser(IWebDriver driver)
|
||||
{
|
||||
_output.WriteLine($"Opening browser at {_listeningUri}...");
|
||||
driver.Navigate().GoToUrl(_listeningUri);
|
||||
_output.WriteLine($"Opening browser at {ListeningUri}...");
|
||||
driver.Navigate().GoToUrl(ListeningUri);
|
||||
|
||||
if (driver is EdgeDriver)
|
||||
{
|
||||
|
|
@ -75,7 +81,7 @@ namespace Templates.Test.Helpers
|
|||
{
|
||||
_output.WriteLine($"Clicking on link '{continueLink.Text}' to skip invalid certificate error page.");
|
||||
continueLink.Click();
|
||||
driver.Navigate().GoToUrl(_listeningUri);
|
||||
driver.Navigate().GoToUrl(ListeningUri);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -85,6 +91,58 @@ namespace Templates.Test.Helpers
|
|||
}
|
||||
}
|
||||
|
||||
public async Task AssertPagesOk(IEnumerable<Page> pages)
|
||||
{
|
||||
foreach (var page in pages)
|
||||
{
|
||||
await AssertOk(page.Url);
|
||||
await ContainsLinks(page);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ContainsLinks(Page page)
|
||||
{
|
||||
var request = new HttpRequestMessage(
|
||||
HttpMethod.Get,
|
||||
new Uri(ListeningUri, page.Url));
|
||||
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
var parser = new HtmlParser();
|
||||
var html = await parser.ParseAsync(await response.Content.ReadAsStreamAsync());
|
||||
|
||||
foreach (IHtmlLinkElement styleSheet in html.GetElementsByTagName("link"))
|
||||
{
|
||||
Assert.Equal("stylesheet", styleSheet.Relation);
|
||||
await AssertOk(styleSheet.Href.Replace("about://", string.Empty));
|
||||
}
|
||||
foreach (var script in html.Scripts)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(script.Source))
|
||||
{
|
||||
await AssertOk(script.Source);
|
||||
}
|
||||
}
|
||||
|
||||
Assert.True(html.Links.Length == page.Links.Count(), $"Expected {page.Url} to have {page.Links.Count()} links but it had {html.Links.Length}");
|
||||
foreach ((var link, var expectedLink) in html.Links.Zip(page.Links, Tuple.Create))
|
||||
{
|
||||
IHtmlAnchorElement anchor = (IHtmlAnchorElement)link;
|
||||
if (string.Equals(anchor.Protocol, "about:"))
|
||||
{
|
||||
Assert.True(anchor.PathName.EndsWith(expectedLink), $"Expected next link on {page.Url} to be {expectedLink} but it was {anchor.PathName}.");
|
||||
await AssertOk(anchor.PathName);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.True(string.Equals(anchor.Href, expectedLink), $"Expected next link to be {expectedLink} but it was {anchor.Href}.");
|
||||
var result = await _httpClient.GetAsync(anchor.Href);
|
||||
Assert.True(IsSuccessStatusCode(result), $"{anchor.Href} is a broken link!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Uri GetListeningUri(ITestOutputHelper output)
|
||||
{
|
||||
// Wait until the app is accepting HTTP requests
|
||||
|
|
@ -113,6 +171,11 @@ namespace Templates.Test.Helpers
|
|||
}
|
||||
}
|
||||
|
||||
private bool IsSuccessStatusCode(HttpResponseMessage response)
|
||||
{
|
||||
return response.IsSuccessStatusCode || response.StatusCode == HttpStatusCode.Redirect;
|
||||
}
|
||||
|
||||
public Task AssertOk(string requestUrl)
|
||||
=> AssertStatusCode(requestUrl, HttpStatusCode.OK);
|
||||
|
||||
|
|
@ -121,14 +184,14 @@ namespace Templates.Test.Helpers
|
|||
|
||||
internal Task<HttpResponseMessage> SendRequest(string path)
|
||||
{
|
||||
return _httpClient.GetAsync(new Uri(_listeningUri, path));
|
||||
return _httpClient.GetAsync(new Uri(ListeningUri, path));
|
||||
}
|
||||
|
||||
public async Task AssertStatusCode(string requestUrl, HttpStatusCode statusCode, string acceptContentType = null)
|
||||
{
|
||||
var request = new HttpRequestMessage(
|
||||
HttpMethod.Get,
|
||||
new Uri(_listeningUri, requestUrl));
|
||||
new Uri(ListeningUri, requestUrl));
|
||||
|
||||
if (!string.IsNullOrEmpty(acceptContentType))
|
||||
{
|
||||
|
|
@ -136,7 +199,7 @@ namespace Templates.Test.Helpers
|
|||
}
|
||||
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
Assert.Equal(statusCode, response.StatusCode);
|
||||
Assert.True(statusCode == response.StatusCode, $"Expected {requestUrl} to have status '{statusCode}' but it was '{response.StatusCode}'.");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
@ -153,7 +216,7 @@ namespace Templates.Test.Helpers
|
|||
{
|
||||
if (!Process.HasExited)
|
||||
{
|
||||
result += $"(Listening on {_listeningUri.OriginalString}) PID: {Process.Id}";
|
||||
result += $"(Listening on {ListeningUri.OriginalString}) PID: {Process.Id}";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -164,4 +227,10 @@ namespace Templates.Test.Helpers
|
|||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public class Page
|
||||
{
|
||||
public string Url { get; set; }
|
||||
public IEnumerable<string> Links { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
namespace Templates.Test.Helpers
|
||||
{
|
||||
public static class PageUrls
|
||||
{
|
||||
public const string HomeUrl = "/";
|
||||
public const string PrivacyUrl = "/Privacy";
|
||||
public const string PrivacyFullUrl = "/Home/Privacy";
|
||||
public const string DocsUrl = "https://docs.microsoft.com/aspnet/core";
|
||||
public const string LoginUrl = "/Identity/Account/Login";
|
||||
public const string RegisterUrl = "/Identity/Account/Register";
|
||||
public const string ForgotPassword = "/Identity/Account/ForgotPassword";
|
||||
public const string ExternalArticle = "https://go.microsoft.com/fwlink/?LinkID=532715";
|
||||
}
|
||||
}
|
||||
|
|
@ -19,6 +19,8 @@ namespace Templates.Test.Helpers
|
|||
[DebuggerDisplay("{ToString(),nq}")]
|
||||
public class Project
|
||||
{
|
||||
private const string _urls = "http://127.0.0.1:0;https://127.0.0.1:0";
|
||||
|
||||
public const string DefaultFramework = "netcoreapp3.0";
|
||||
|
||||
public SemaphoreSlim DotNetNewLock { get; set; }
|
||||
|
|
@ -30,6 +32,12 @@ namespace Templates.Test.Helpers
|
|||
public string TemplateBuildDir => Path.Combine(TemplateOutputDir, "bin", "Debug", DefaultFramework);
|
||||
public string TemplatePublishDir => Path.Combine(TemplateOutputDir, "bin", "Release", DefaultFramework, "publish");
|
||||
|
||||
private string TemplateServerDir => Path.Combine(TemplateOutputDir, $"{ProjectName}.Server");
|
||||
private string TemplateClientDir => Path.Combine(TemplateOutputDir, $"{ProjectName}.Client");
|
||||
public string TemplateClientDebugDir => Path.Combine(TemplateClientDir, "bin", "Debug", DefaultFramework);
|
||||
public string TemplateClientReleaseDir => Path.Combine(TemplateClientDir, "bin", "Release", DefaultFramework, "publish");
|
||||
public string TemplateServerReleaseDir => Path.Combine(TemplateServerDir, "bin", "Release", DefaultFramework, "publish");
|
||||
|
||||
public ITestOutputHelper Output { get; set; }
|
||||
public IMessageSink DiagnosticsMessageSink { get; set; }
|
||||
|
||||
|
|
@ -127,11 +135,55 @@ namespace Templates.Test.Helpers
|
|||
}
|
||||
}
|
||||
|
||||
internal AspNetProcess StartBuiltServerAsync()
|
||||
{
|
||||
var environment = new Dictionary<string, string>
|
||||
{
|
||||
["ASPNETCORE_ENVIRONMENT"] = "Development"
|
||||
};
|
||||
|
||||
var projectDll = Path.Combine(TemplateServerDir, $"{ProjectName}.Server.dll");
|
||||
return new AspNetProcess(Output, TemplateServerDir, projectDll, environment, published: false);
|
||||
}
|
||||
|
||||
internal AspNetProcess StartBuiltClientAsync(AspNetProcess serverProcess)
|
||||
{
|
||||
var environment = new Dictionary<string, string>
|
||||
{
|
||||
["ASPNETCORE_ENVIRONMENT"] = "Development"
|
||||
};
|
||||
|
||||
var projectDll = Path.Combine(TemplateClientDebugDir, $"{ProjectName}.Client.dll {serverProcess.ListeningUri.Port}");
|
||||
return new AspNetProcess(Output, TemplateOutputDir, projectDll, environment, hasListeningUri: false);
|
||||
}
|
||||
|
||||
internal AspNetProcess StartPublishedServerAsync()
|
||||
{
|
||||
var environment = new Dictionary<string, string>
|
||||
{
|
||||
["ASPNETCORE_URLS"] = _urls,
|
||||
};
|
||||
|
||||
var projectDll = $"{ProjectName}.Server.dll";
|
||||
return new AspNetProcess(Output, TemplateServerReleaseDir, projectDll, environment);
|
||||
}
|
||||
|
||||
internal AspNetProcess StartPublishedClientAsync()
|
||||
{
|
||||
var environment = new Dictionary<string, string>
|
||||
{
|
||||
["ASPNETCORE_URLS"] = _urls,
|
||||
};
|
||||
|
||||
var projectDll = $"{ProjectName}.Client.dll";
|
||||
return new AspNetProcess(Output, TemplateClientReleaseDir, projectDll, environment);
|
||||
}
|
||||
|
||||
internal AspNetProcess StartBuiltProjectAsync()
|
||||
{
|
||||
var environment = new Dictionary<string, string>
|
||||
{
|
||||
["ASPNETCORE_URLS"] = $"http://127.0.0.1:0;https://127.0.0.1:0",
|
||||
["ASPNETCORE_URLS"] = _urls,
|
||||
["ASPNETCORE_ENVIRONMENT"] = "Development"
|
||||
};
|
||||
|
||||
|
|
@ -143,7 +195,7 @@ namespace Templates.Test.Helpers
|
|||
{
|
||||
var environment = new Dictionary<string, string>
|
||||
{
|
||||
["ASPNETCORE_URLS"] = $"http://127.0.0.1:0;https://127.0.0.1:0",
|
||||
["ASPNETCORE_URLS"] = _urls,
|
||||
};
|
||||
|
||||
var projectDll = $"{ProjectName}.dll";
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Templates.Test.Helpers;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
|
|
@ -55,14 +57,39 @@ namespace Templates.Test
|
|||
var buildResult = await Project.RunDotNetBuildAsync();
|
||||
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult));
|
||||
|
||||
IEnumerable<string> menuLinks = new List<string> {
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.PrivacyFullUrl
|
||||
};
|
||||
|
||||
if(languageOverride == null)
|
||||
{
|
||||
menuLinks = menuLinks.Append(PageUrls.PrivacyFullUrl);
|
||||
}
|
||||
var footerLinks = new string[] { PageUrls.PrivacyFullUrl };
|
||||
|
||||
var pages = new List<Page>
|
||||
{
|
||||
new Page
|
||||
{
|
||||
Url = PageUrls.HomeUrl,
|
||||
Links = menuLinks.Append(PageUrls.DocsUrl).Concat(footerLinks)
|
||||
},
|
||||
new Page
|
||||
{
|
||||
Url = PageUrls.PrivacyFullUrl,
|
||||
Links = menuLinks.Concat(footerLinks)
|
||||
}
|
||||
};
|
||||
|
||||
using (var aspNetProcess = Project.StartBuiltProjectAsync())
|
||||
{
|
||||
Assert.False(
|
||||
aspNetProcess.Process.HasExited,
|
||||
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
|
||||
|
||||
await aspNetProcess.AssertOk("/");
|
||||
await aspNetProcess.AssertOk("/Home/Privacy");
|
||||
await aspNetProcess.AssertPagesOk(pages);
|
||||
}
|
||||
|
||||
using (var aspNetProcess = Project.StartPublishedProjectAsync())
|
||||
|
|
@ -71,8 +98,7 @@ namespace Templates.Test
|
|||
aspNetProcess.Process.HasExited,
|
||||
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process));
|
||||
|
||||
await aspNetProcess.AssertOk("/");
|
||||
await aspNetProcess.AssertOk("/Home/Privacy");
|
||||
await aspNetProcess.AssertPagesOk(pages);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -110,18 +136,94 @@ namespace Templates.Test
|
|||
Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", Project, migrationsResult));
|
||||
Project.AssertEmptyMigration("mvc");
|
||||
|
||||
var pages = new List<Page> {
|
||||
new Page
|
||||
{
|
||||
Url = PageUrls.ForgotPassword,
|
||||
Links = new string [] {
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.RegisterUrl,
|
||||
PageUrls.LoginUrl,
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.PrivacyUrl
|
||||
}
|
||||
},
|
||||
new Page
|
||||
{
|
||||
Url = PageUrls.HomeUrl,
|
||||
Links = new string[] {
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.RegisterUrl,
|
||||
PageUrls.LoginUrl,
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.DocsUrl,
|
||||
PageUrls.PrivacyUrl
|
||||
}
|
||||
},
|
||||
new Page
|
||||
{
|
||||
Url = PageUrls.PrivacyFullUrl,
|
||||
Links = new string[] {
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.RegisterUrl,
|
||||
PageUrls.LoginUrl,
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.PrivacyUrl
|
||||
}
|
||||
},
|
||||
new Page
|
||||
{
|
||||
Url = PageUrls.LoginUrl,
|
||||
Links = new string[] {
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.RegisterUrl,
|
||||
PageUrls.LoginUrl,
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.ForgotPassword,
|
||||
PageUrls.RegisterUrl,
|
||||
PageUrls.ExternalArticle,
|
||||
PageUrls.PrivacyUrl }
|
||||
},
|
||||
new Page
|
||||
{
|
||||
Url = PageUrls.RegisterUrl,
|
||||
Links = new string [] {
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.RegisterUrl,
|
||||
PageUrls.LoginUrl,
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.ExternalArticle,
|
||||
PageUrls.PrivacyUrl
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using (var aspNetProcess = Project.StartBuiltProjectAsync())
|
||||
{
|
||||
await aspNetProcess.AssertOk("/");
|
||||
await aspNetProcess.AssertOk("/Identity/Account/Login");
|
||||
await aspNetProcess.AssertOk("/Home/Privacy");
|
||||
Assert.False(
|
||||
aspNetProcess.Process.HasExited,
|
||||
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
|
||||
|
||||
await aspNetProcess.AssertPagesOk(pages);
|
||||
}
|
||||
|
||||
using (var aspNetProcess = Project.StartPublishedProjectAsync())
|
||||
{
|
||||
await aspNetProcess.AssertOk("/");
|
||||
await aspNetProcess.AssertOk("/Identity/Account/Login");
|
||||
await aspNetProcess.AssertOk("/Home/Privacy");
|
||||
Assert.False(
|
||||
aspNetProcess.Process.HasExited,
|
||||
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process));
|
||||
|
||||
await aspNetProcess.AssertPagesOk(pages);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Templates.Test.Helpers;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Templates.Test
|
||||
{
|
||||
public class RazorClassLibraryTemplateTest
|
||||
{
|
||||
public RazorClassLibraryTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output)
|
||||
{
|
||||
ProjectFactory = projectFactory;
|
||||
Output = output;
|
||||
}
|
||||
|
||||
public Project Project { get; set; }
|
||||
|
||||
public ProjectFactoryFixture ProjectFactory { get; }
|
||||
public ITestOutputHelper Output { get; }
|
||||
|
||||
[Fact]
|
||||
public async Task RazorClassLibraryTemplateAsync()
|
||||
{
|
||||
Project = await ProjectFactory.GetOrCreateProject("razorclasslib", Output);
|
||||
|
||||
var createResult = await Project.RunDotNetNewAsync("razorclasslib");
|
||||
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
|
||||
|
||||
var publishResult = await Project.RunDotNetPublishAsync();
|
||||
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
|
||||
|
||||
// Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
|
||||
// The output from publish will go into bin/Release/netcoreapp3.0/publish and won't be affected by calling build
|
||||
// later, while the opposite is not true.
|
||||
|
||||
var buildResult = await Project.RunDotNetBuildAsync();
|
||||
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Templates.Test.Helpers;
|
||||
|
|
@ -31,8 +32,6 @@ namespace Templates.Test
|
|||
var createResult = await Project.RunDotNetNewAsync("razor");
|
||||
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("razor", Project, createResult));
|
||||
|
||||
AssertFileExists(Project.TemplateOutputDir, "Pages/Shared/_LoginPartial.cshtml", false);
|
||||
|
||||
var projectFileContents = ReadFile(Project.TemplateOutputDir, $"{Project.ProjectName}.csproj");
|
||||
Assert.DoesNotContain(".db", projectFileContents);
|
||||
Assert.DoesNotContain("Microsoft.EntityFrameworkCore.Tools", projectFileContents);
|
||||
|
|
@ -50,14 +49,39 @@ namespace Templates.Test
|
|||
var buildResult = await Project.RunDotNetBuildAsync();
|
||||
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, createResult));
|
||||
|
||||
var pages = new List<Page>
|
||||
{
|
||||
new Page
|
||||
{
|
||||
Url = PageUrls.HomeUrl,
|
||||
Links = new string[] {
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.DocsUrl,
|
||||
PageUrls.PrivacyUrl
|
||||
}
|
||||
},
|
||||
new Page
|
||||
{
|
||||
Url = PageUrls.PrivacyUrl,
|
||||
Links = new string[] {
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.PrivacyUrl }
|
||||
}
|
||||
};
|
||||
|
||||
using (var aspNetProcess = Project.StartBuiltProjectAsync())
|
||||
{
|
||||
Assert.False(
|
||||
aspNetProcess.Process.HasExited,
|
||||
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
|
||||
|
||||
await aspNetProcess.AssertOk("/");
|
||||
await aspNetProcess.AssertOk("/Privacy");
|
||||
await aspNetProcess.AssertPagesOk(pages);
|
||||
}
|
||||
|
||||
using (var aspNetProcess = Project.StartPublishedProjectAsync())
|
||||
|
|
@ -66,8 +90,7 @@ namespace Templates.Test
|
|||
aspNetProcess.Process.HasExited,
|
||||
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process));
|
||||
|
||||
await aspNetProcess.AssertOk("/");
|
||||
await aspNetProcess.AssertOk("/Privacy");
|
||||
await aspNetProcess.AssertPagesOk(pages);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -81,8 +104,6 @@ namespace Templates.Test
|
|||
var createResult = await Project.RunDotNetNewAsync("razor", auth: "Individual", useLocalDB: useLocalDB);
|
||||
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
|
||||
|
||||
AssertFileExists(Project.TemplateOutputDir, "Pages/Shared/_LoginPartial.cshtml", true);
|
||||
|
||||
var projectFileContents = ReadFile(Project.TemplateOutputDir, $"{Project.ProjectName}.csproj");
|
||||
if (!useLocalDB)
|
||||
{
|
||||
|
|
@ -103,39 +124,104 @@ namespace Templates.Test
|
|||
Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", Project, migrationsResult));
|
||||
Project.AssertEmptyMigration("razorpages");
|
||||
|
||||
var pages = new List<Page> {
|
||||
new Page
|
||||
{
|
||||
Url = PageUrls.ForgotPassword,
|
||||
Links = new string [] {
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.RegisterUrl,
|
||||
PageUrls.LoginUrl,
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.PrivacyUrl
|
||||
}
|
||||
},
|
||||
new Page
|
||||
{
|
||||
Url = PageUrls.HomeUrl,
|
||||
Links = new string[] {
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.RegisterUrl,
|
||||
PageUrls.LoginUrl,
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.DocsUrl,
|
||||
PageUrls.PrivacyUrl
|
||||
}
|
||||
},
|
||||
new Page
|
||||
{
|
||||
Url = PageUrls.PrivacyUrl,
|
||||
Links = new string[] {
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.RegisterUrl,
|
||||
PageUrls.LoginUrl,
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.PrivacyUrl
|
||||
}
|
||||
},
|
||||
new Page
|
||||
{
|
||||
Url = PageUrls.LoginUrl,
|
||||
Links = new string[] {
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.RegisterUrl,
|
||||
PageUrls.LoginUrl,
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.ForgotPassword,
|
||||
PageUrls.RegisterUrl,
|
||||
PageUrls.ExternalArticle,
|
||||
PageUrls.PrivacyUrl }
|
||||
},
|
||||
new Page
|
||||
{
|
||||
Url = PageUrls.RegisterUrl,
|
||||
Links = new string [] {
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.RegisterUrl,
|
||||
PageUrls.LoginUrl,
|
||||
PageUrls.HomeUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.PrivacyUrl,
|
||||
PageUrls.ExternalArticle,
|
||||
PageUrls.PrivacyUrl
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using (var aspNetProcess = Project.StartBuiltProjectAsync())
|
||||
{
|
||||
await aspNetProcess.AssertOk("/");
|
||||
await aspNetProcess.AssertOk("/Identity/Account/Login");
|
||||
await aspNetProcess.AssertOk("/Privacy");
|
||||
Assert.False(
|
||||
aspNetProcess.Process.HasExited,
|
||||
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
|
||||
|
||||
await aspNetProcess.AssertPagesOk(pages);
|
||||
}
|
||||
|
||||
using (var aspNetProcess = Project.StartPublishedProjectAsync())
|
||||
{
|
||||
await aspNetProcess.AssertOk("/");
|
||||
await aspNetProcess.AssertOk("/Identity/Account/Login");
|
||||
await aspNetProcess.AssertOk("/Privacy");
|
||||
Assert.False(
|
||||
aspNetProcess.Process.HasExited,
|
||||
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
|
||||
|
||||
await aspNetProcess.AssertPagesOk(pages);
|
||||
}
|
||||
}
|
||||
|
||||
private void AssertFileExists(string basePath, string path, bool shouldExist)
|
||||
|
||||
private string ReadFile(string basePath, string path)
|
||||
{
|
||||
var fullPath = Path.Combine(basePath, path);
|
||||
var doesExist = File.Exists(fullPath);
|
||||
|
||||
if (shouldExist)
|
||||
{
|
||||
Assert.True(doesExist, "Expected file to exist, but it doesn't: " + path);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.False(doesExist, "Expected file not to exist, but it does: " + path);
|
||||
}
|
||||
}
|
||||
|
||||
private string ReadFile(string basePath, string path)
|
||||
{
|
||||
AssertFileExists(basePath, path, shouldExist: true);
|
||||
Assert.True(doesExist, $"Expected file to exist, but it doesn't: {path}");
|
||||
return File.ReadAllText(Path.Combine(basePath, path));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,12 +22,14 @@ namespace Templates.Test
|
|||
|
||||
public Project Project { get; set; }
|
||||
|
||||
[Fact]
|
||||
public async Task WebApiTemplateAsync()
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("F#")]
|
||||
public async Task WebApiTemplateAsync(string languageOverride)
|
||||
{
|
||||
Project = await FactoryFixture.GetOrCreateProject("webapi", Output);
|
||||
Project = await FactoryFixture.GetOrCreateProject("webapi" + (languageOverride == "F#" ? "fsharp" : "csharp"), Output);
|
||||
|
||||
var createResult = await Project.RunDotNetNewAsync("webapi");
|
||||
var createResult = await Project.RunDotNetNewAsync("webapi", language: languageOverride);
|
||||
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
|
||||
|
||||
var publishResult = await Project.RunDotNetPublishAsync();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Templates.Test.Helpers;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Templates.Test
|
||||
{
|
||||
public class WorkerTemplateTest
|
||||
{
|
||||
public WorkerTemplateTest(ProjectFactoryFixture projectFactory, ITestOutputHelper output)
|
||||
{
|
||||
ProjectFactory = projectFactory;
|
||||
Output = output;
|
||||
}
|
||||
|
||||
public Project Project { get; set; }
|
||||
public ProjectFactoryFixture ProjectFactory { get; }
|
||||
public ITestOutputHelper Output { get; }
|
||||
|
||||
[Fact(Skip = "Microsoft.NET.Sdk.Worker isn't available yet")]
|
||||
public async Task WorkerTemplateAsync()
|
||||
{
|
||||
Project = await ProjectFactory.GetOrCreateProject("worker", Output);
|
||||
|
||||
var createResult = await Project.RunDotNetNewAsync("worker");
|
||||
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult));
|
||||
|
||||
var publishResult = await Project.RunDotNetPublishAsync();
|
||||
Assert.True(0 == publishResult.ExitCode, ErrorMessages.GetFailedProcessMessage("publish", Project, publishResult));
|
||||
|
||||
// Run dotnet build after publish. The reason is that one uses Config = Debug and the other uses Config = Release
|
||||
// The output from publish will go into bin/Release/netcoreapp3.0/publish and won't be affected by calling build
|
||||
// later, while the opposite is not true.
|
||||
|
||||
var buildResult = await Project.RunDotNetBuildAsync();
|
||||
Assert.True(0 == buildResult.ExitCode, ErrorMessages.GetFailedProcessMessage("build", Project, buildResult));
|
||||
|
||||
using (var aspNetProcess = Project.StartBuiltProjectAsync())
|
||||
{
|
||||
Assert.False(
|
||||
aspNetProcess.Process.HasExited,
|
||||
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
|
||||
}
|
||||
|
||||
using (var aspNetProcess = Project.StartPublishedProjectAsync())
|
||||
{
|
||||
Assert.False(
|
||||
aspNetProcess.Process.HasExited,
|
||||
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -370,7 +370,7 @@
|
|||
}
|
||||
},
|
||||
"web": {
|
||||
"None": {
|
||||
"CSharp": {
|
||||
"Template": "web",
|
||||
"Arguments": "new web",
|
||||
"Files": [
|
||||
|
|
@ -381,6 +381,18 @@
|
|||
"Properties/launchSettings.json"
|
||||
],
|
||||
"AuthOption": "None"
|
||||
},
|
||||
"FSharp": {
|
||||
"Template": "web",
|
||||
"Arguments": "new web --language F#",
|
||||
"Files": [
|
||||
"appsettings.Development.json",
|
||||
"appsettings.json",
|
||||
"Program.fs",
|
||||
"Startup.fs",
|
||||
"Properties/launchSettings.json"
|
||||
],
|
||||
"AuthOption": "None"
|
||||
}
|
||||
},
|
||||
"webapi": {
|
||||
|
|
@ -435,6 +447,18 @@
|
|||
"Properties/launchSettings.json"
|
||||
],
|
||||
"AuthOption": "Windows"
|
||||
},
|
||||
"FSharp": {
|
||||
"Template": "webapi",
|
||||
"Arguments": "new webapi --language F#",
|
||||
"Files": [
|
||||
"appsettings.Development.json",
|
||||
"appsettings.json",
|
||||
"Program.fs",
|
||||
"Startup.fs",
|
||||
"Controllers/ValuesController.fs",
|
||||
"Properties/launchSettings.json"
|
||||
]
|
||||
}
|
||||
},
|
||||
"mvc": {
|
||||
|
|
@ -864,6 +888,55 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"razorcomponents": {
|
||||
"None": {
|
||||
"Template": "razorcomponents",
|
||||
"Arguments": "new razorcomponents",
|
||||
"Files": [
|
||||
"Pages/_Imports.razor",
|
||||
"Pages/Counter.razor",
|
||||
"Pages/FetchData.razor",
|
||||
"Pages/_Host.cshtml",
|
||||
"Pages/Index.razor",
|
||||
"Shared/MainLayout.razor",
|
||||
"Shared/NavMenu.razor",
|
||||
"_Imports.razor",
|
||||
"App.razor",
|
||||
"Properties/launchSettings.json",
|
||||
"Data/WeatherForecast.cs",
|
||||
"Data/WeatherForecastService.cs",
|
||||
"wwwroot/css/bootstrap/bootstrap.min.css",
|
||||
"wwwroot/css/bootstrap/bootstrap.min.css.map",
|
||||
"wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css",
|
||||
"wwwroot/css/open-iconic/font/fonts/open-iconic.eot",
|
||||
"wwwroot/css/open-iconic/font/fonts/open-iconic.otf",
|
||||
"wwwroot/css/open-iconic/font/fonts/open-iconic.svg",
|
||||
"wwwroot/css/open-iconic/font/fonts/open-iconic.ttf",
|
||||
"wwwroot/css/open-iconic/font/fonts/open-iconic.woff",
|
||||
"wwwroot/css/open-iconic/FONT-LICENSE",
|
||||
"wwwroot/css/open-iconic/ICON-LICENSE",
|
||||
"wwwroot/css/open-iconic/README.md",
|
||||
"wwwroot/css/site.css",
|
||||
"appsettings.Development.json",
|
||||
"appsettings.json",
|
||||
"Program.cs",
|
||||
"Startup.cs"
|
||||
]
|
||||
}
|
||||
},
|
||||
"worker": {
|
||||
"None": {
|
||||
"Template": "worker",
|
||||
"Arguments": "new worker",
|
||||
"Files": [
|
||||
"Properties/launchSettings.json",
|
||||
"appsettings.Development.json",
|
||||
"appsettings.json",
|
||||
"Program.cs",
|
||||
"Worker.cs"
|
||||
]
|
||||
}
|
||||
},
|
||||
"angular": {
|
||||
"None": {
|
||||
"Template": "angular",
|
||||
|
|
|
|||
Loading…
Reference in New Issue