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:
N. Taylor Mullen 2016-01-08 16:32:32 -08:00
parent ddce8a4dbc
commit dbb69ef952
6 changed files with 285 additions and 34 deletions

View File

@ -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(">");
}
}
}

View File

@ -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.

View File

@ -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>

View File

@ -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;
}
}
}

View File

@ -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>

View File

@ -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>