Add `TagHelperSample.Web` functional tests.
- Validated that each of `TagHelperSample.Web`s sites work properly. - Found that the `ConditionalCommentTagHelper` page wasn't working as intended due to never being updated after `TagHelperContent` encoding changes. - Added content verification for the `TagHelper/ConditionalComment` endpoint only since it's static HTML. #3530
This commit is contained in:
parent
ddce8a4dbc
commit
dbb69ef952
|
|
@ -23,15 +23,15 @@ namespace TagHelperSample.Web
|
|||
modeModifier = "--";
|
||||
}
|
||||
|
||||
output.PreContent.Append("<!");
|
||||
output.PreContent.Append(modeModifier);
|
||||
output.PreContent.Append("[if ");
|
||||
output.PreContent.Append(Condition);
|
||||
output.PreContent.Append("]>");
|
||||
output.PreContent.AppendHtml("<!");
|
||||
output.PreContent.AppendHtml(modeModifier);
|
||||
output.PreContent.AppendHtml("[if ");
|
||||
output.PreContent.AppendHtml(Condition);
|
||||
output.PreContent.AppendHtml("]>");
|
||||
|
||||
output.PostContent.Append("<![endif]");
|
||||
output.PostContent.Append(modeModifier);
|
||||
output.PostContent.Append(">");
|
||||
output.PostContent.AppendHtml("<![endif]");
|
||||
output.PostContent.AppendHtml(modeModifier);
|
||||
output.PostContent.AppendHtml(">");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,14 @@
|
|||
TagHelperSample.Web
|
||||
===
|
||||
This sample web project illustrates TagHelper use. Please build from root
|
||||
(`.\build.cmd` on Windows; `./build.sh` elsewhere) before using this site.
|
||||
(`.\build.cmd` on Windows; `./build.sh` elsewhere) before using this site.
|
||||
|
||||
### What this sample contains
|
||||
1. Creating, editing and viewing custom users with validation.
|
||||
1. `/` lists current users.
|
||||
2. `/Home/Create` create a new user.
|
||||
3. `/Home/Edit/{id:int}` edit a user.
|
||||
2. View Components and nested caching in views.
|
||||
1. `/Movies/` Current movie ratings and critic quotes. Click on the buttons on the page to update values in the side bar.
|
||||
3. Custom TagHelper to enable browser detection based content.
|
||||
1. `/TagHelper/ConditionalComment` Shows different content if your browser is IE7.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<add name="httpPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" />
|
||||
</handlers>
|
||||
<httpPlatform processPath="%DNX_PATH%" arguments="%DNX_ARGS%" forwardWindowsAuthToken="false" startupTimeLimit="3600" />
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
|
|
@ -1,8 +1,13 @@
|
|||
// 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.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Xunit;
|
||||
|
|
@ -18,44 +23,176 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
|
||||
public HttpClient Client { get; }
|
||||
|
||||
public static TheoryData<string> PathData
|
||||
[Fact]
|
||||
public async Task HomeController_Index_ReturnsExpectedContent()
|
||||
{
|
||||
// Arrange
|
||||
var expectedMediaType = MediaTypeHeaderValue.Parse("text/html; charset=utf-8");
|
||||
var outputFile = "compiler/resources/TagHelperSample.Web.Home.Index.html";
|
||||
var resourceAssembly = typeof(TagHelperSampleTest).GetTypeInfo().Assembly;
|
||||
var expectedContent = await ResourceFile.ReadResourceAsync(resourceAssembly, outputFile, sourceFile: false);
|
||||
|
||||
// Act
|
||||
var response = await Client.GetAsync("http://localhost/");
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal(expectedMediaType, response.Content.Headers.ContentType);
|
||||
|
||||
#if GENERATE_BASELINES
|
||||
ResourceFile.UpdateFile(resourceAssembly, outputFile, expectedContent, responseContent);
|
||||
#else
|
||||
Assert.Equal(expectedContent, responseContent, ignoreLineEndingDifferences: true);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public async Task HomeController_Create_Get_ReturnsSuccess()
|
||||
{
|
||||
// Act
|
||||
var response = await Client.GetAsync("http://localhost/Home/Create");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HomeController_Create_Post_ReturnsSuccess()
|
||||
{
|
||||
// Arrange
|
||||
var createBillyContent = CreateUserFormContent("Billy", "2000-11-30", 0, "hello");
|
||||
|
||||
// Act
|
||||
var response = await Client.PostAsync("http://localhost/Home/Create", createBillyContent);
|
||||
|
||||
// Assert
|
||||
AssertRedirectsToHome(response);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HomeController_Edit_Get_ReturnsSuccess()
|
||||
{
|
||||
// Arrange
|
||||
var createBillyContent = CreateUserFormContent("Billy", "2000-11-30", 0, "hello");
|
||||
var createBilly = await Client.PostAsync("http://localhost/Home/Create", createBillyContent);
|
||||
|
||||
// Guard
|
||||
AssertRedirectsToHome(createBilly);
|
||||
|
||||
// Act
|
||||
var response = await Client.GetAsync("http://localhost/Home/Edit/0");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HomeController_Edit_Post_ReturnsSuccess()
|
||||
{
|
||||
// Arrange
|
||||
var createBillyContent = CreateUserFormContent("Billy", "2000-11-30", 0, "hello");
|
||||
var changeBillyContent = CreateUserFormContent("Bobby", "1999-11-30", 1, "howdy");
|
||||
var createBilly = await Client.PostAsync("http://localhost/Home/Create", createBillyContent);
|
||||
|
||||
// Guard
|
||||
AssertRedirectsToHome(createBilly);
|
||||
|
||||
// Act
|
||||
var changeBilly = await Client.PostAsync("http://localhost/Home/Edit/0", changeBillyContent);
|
||||
|
||||
// Assert
|
||||
AssertRedirectsToHome(changeBilly);
|
||||
}
|
||||
|
||||
public static TheoryData MoviesControllerPageData
|
||||
{
|
||||
get
|
||||
{
|
||||
var data = new TheoryData<string>
|
||||
return new TheoryData<Func<HttpClient, Task<HttpResponseMessage>>>
|
||||
{
|
||||
"/Home/Create",
|
||||
"/Home/Create?Name=Billy&Blurb=hello&DateOfBirth=2000-11-30&YearsEmployeed=0",
|
||||
"/Home/Create?Name=Joe&Blurb=goodbye&DateOfBirth=1980-10-20&YearsEmployeed=1",
|
||||
"/Home/Edit/0",
|
||||
"/Home/Edit/0?Name=Bobby&Blurb=howdy&DateOfBirth=1999-11-30&YearsEmployeed=1",
|
||||
"/Home/Edit/0?Name=Bobby&Blurb=howdy&DateOfBirth=1999-11-30&YearsEmployeed=2",
|
||||
"/Home/Edit/1",
|
||||
"/Home/Edit/1?Name=Jack&Blurb=goodbye&DateOfBirth=1979-10-20&YearsEmployeed=4",
|
||||
async (client) => await client.GetAsync("http://localhost/Movies"),
|
||||
async (client) => await client.PostAsync(
|
||||
"http://localhost/Movies/UpdateMovieRatings",
|
||||
new FormUrlEncodedContent(Enumerable.Empty<KeyValuePair<string, string>>())),
|
||||
async (client) => await client.PostAsync(
|
||||
"http://localhost/Movies/UpdateCriticsQuotes",
|
||||
new FormUrlEncodedContent(Enumerable.Empty<KeyValuePair<string, string>>())),
|
||||
async (client) =>
|
||||
{
|
||||
await client.PostAsync(
|
||||
"http://localhost/Movies/UpdateCriticsQuotes",
|
||||
new FormUrlEncodedContent(Enumerable.Empty<KeyValuePair<string, string>>()));
|
||||
await client.PostAsync(
|
||||
"http://localhost/Movies/UpdateCriticsQuotes",
|
||||
new FormUrlEncodedContent(Enumerable.Empty<KeyValuePair<string, string>>()));
|
||||
|
||||
return await client.GetAsync("http://localhost/Movies/Index");
|
||||
}
|
||||
};
|
||||
|
||||
// Three paths hit aspnet/External#50 with Mono on Mac.
|
||||
if (!TestPlatformHelper.IsMac || !TestPlatformHelper.IsMono)
|
||||
{
|
||||
data.Add(string.Empty);
|
||||
data.Add("/");
|
||||
data.Add("/Home/Index");
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(PathData))]
|
||||
public async Task Home_Pages_ReturnSuccess(string path)
|
||||
[MemberData(nameof(MoviesControllerPageData))]
|
||||
public async Task MoviesController_Pages_ReturnSuccess(Func<HttpClient, Task<HttpResponseMessage>> requestPage)
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync("http://localhost" + path);
|
||||
// Act
|
||||
var response = await requestPage(Client);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(response);
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TagHelperController_ConditionalComment_ReturnsExpectedContent()
|
||||
{
|
||||
// Arrange
|
||||
var expectedMediaType = MediaTypeHeaderValue.Parse("text/html; charset=utf-8");
|
||||
var outputFile = "compiler/resources/TagHelperSample.Web.TagHelper.ConditionalComment.html";
|
||||
var resourceAssembly = typeof(TagHelperSampleTest).GetTypeInfo().Assembly;
|
||||
var expectedContent = await ResourceFile.ReadResourceAsync(resourceAssembly, outputFile, sourceFile: false);
|
||||
|
||||
// Act
|
||||
var response = await Client.GetAsync("http://localhost/TagHelper/ConditionalComment");
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal(expectedMediaType, response.Content.Headers.ContentType);
|
||||
|
||||
#if GENERATE_BASELINES
|
||||
ResourceFile.UpdateFile(resourceAssembly, outputFile, expectedContent, responseContent);
|
||||
#else
|
||||
Assert.Equal(expectedContent, responseContent, ignoreLineEndingDifferences: true);
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void AssertRedirectsToHome(HttpResponseMessage response)
|
||||
{
|
||||
Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
|
||||
var redirectLocations = response.Headers.GetValues("Location");
|
||||
var redirectsTo = Assert.Single(redirectLocations);
|
||||
Assert.Equal("/", redirectsTo, StringComparer.Ordinal);
|
||||
}
|
||||
|
||||
private static HttpContent CreateUserFormContent(
|
||||
string name,
|
||||
string dateOfBirth,
|
||||
int yearsEmployeed,
|
||||
string blurb)
|
||||
{
|
||||
var form = new List<KeyValuePair<string, string>>()
|
||||
{
|
||||
new KeyValuePair<string, string>("Name", name),
|
||||
new KeyValuePair<string, string>("DateOfBirth", dateOfBirth),
|
||||
new KeyValuePair<string, string>("YearsEmployeed", yearsEmployeed.ToString()),
|
||||
new KeyValuePair<string, string>("Blurb", blurb),
|
||||
};
|
||||
var content = new FormUrlEncodedContent(form);
|
||||
|
||||
return content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link href="/css/sub/blank.css" rel="stylesheet" data-test="value" />
|
||||
<link href="site.min.css" rel="stylesheet" data-test="value" />
|
||||
<meta name="x-stylesheet-fallback-test" content="" class="fallback-test" /><script>!function(a,b,c){var d,e=document,f=e.getElementsByTagName("SCRIPT"),g=f[f.length-1].previousElementSibling,h=e.defaultView&&e.defaultView.getComputedStyle?e.defaultView.getComputedStyle(g):g.currentStyle;if(h&&h[a]!==b)for(d=0;d<c.length;d++)e.write('<link rel="stylesheet" href="'+c[d]+'"/>')}("visibility","hidden",["\/site.css"]);</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
<script src="/originalXX.js">
|
||||
// 1. By removing the src attribute, the script below will execute and prevent fallback from running
|
||||
// 2. Alternatively fix the type in the value of the src attribute
|
||||
function foo() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
function bar() {
|
||||
document.write("<p>foo is from page</p>");
|
||||
}
|
||||
</script>
|
||||
<script>(window.foo||document.write("<script src=\"\/fallback.js\"><\/script>"));</script>
|
||||
|
||||
<script>bar();</script>
|
||||
|
||||
<h2>Index</h2>
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label for="z0__Name">Name</label>
|
||||
<input type="text" disabled="disabled" readonly="readonly" id="z0__Name" name="[0].Name" value="Billy" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="z0__DateOfBirth">DateOfBirth</label>
|
||||
<input type="date" disabled="disabled" readonly="readonly" data-val="true" data-val-required="The DateOfBirth field is required." id="z0__DateOfBirth" name="[0].DateOfBirth" value="2000-11-30" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="z0__YearsEmployeed">YearsEmployeed</label>
|
||||
<input type="number" disabled="disabled" readonly="readonly" data-val="true" data-val-required="The YearsEmployeed field is required." id="z0__YearsEmployeed" name="[0].YearsEmployeed" value="0" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="z0__Blurb">Blurb</label>
|
||||
<textarea rows="4" disabled="disabled" readonly="readonly" id="z0__Blurb" name="[0].Blurb">
|
||||
hello</textarea>
|
||||
</div>
|
||||
<p>
|
||||
<a href="/Home/Edit/0">Edit</a>
|
||||
</p>
|
||||
<div class="form-group">
|
||||
<label for="z1__Name">Name</label>
|
||||
<input type="text" disabled="disabled" readonly="readonly" id="z1__Name" name="[1].Name" value="Billy" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="z1__DateOfBirth">DateOfBirth</label>
|
||||
<input type="date" disabled="disabled" readonly="readonly" data-val="true" data-val-required="The DateOfBirth field is required." id="z1__DateOfBirth" name="[1].DateOfBirth" value="2000-11-30" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="z1__YearsEmployeed">YearsEmployeed</label>
|
||||
<input type="number" disabled="disabled" readonly="readonly" data-val="true" data-val-required="The YearsEmployeed field is required." id="z1__YearsEmployeed" name="[1].YearsEmployeed" value="0" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="z1__Blurb">Blurb</label>
|
||||
<textarea rows="4" disabled="disabled" readonly="readonly" id="z1__Blurb" name="[1].Blurb">
|
||||
hello</textarea>
|
||||
</div>
|
||||
<p>
|
||||
<a href="/Home/Edit/1">Edit</a>
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
<a href="/Home/Create">Create New</a>
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link href="/css/sub/blank.css" rel="stylesheet" data-test="value" />
|
||||
<link href="site.min.css" rel="stylesheet" data-test="value" />
|
||||
<meta name="x-stylesheet-fallback-test" content="" class="fallback-test" /><script>!function(a,b,c){var d,e=document,f=e.getElementsByTagName("SCRIPT"),g=f[f.length-1].previousElementSibling,h=e.defaultView&&e.defaultView.getComputedStyle?e.defaultView.getComputedStyle(g):g.currentStyle;if(h&&h[a]!==b)for(d=0;d<c.length;d++)e.write('<link rel="stylesheet" href="'+c[d]+'"/>')}("visibility","hidden",["\/site.css"]);</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<![if gt IE 7]>
|
||||
<p>Content visible to all browsers newer than Internet Explorer 7.</p>
|
||||
<![endif]>
|
||||
<!--[if IE 7]>
|
||||
<p>Content visible only to Internet Explorer 7 users.</p>
|
||||
<![endif]-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in New Issue