Add some initial functional tests for auth samples (#41)
This commit is contained in:
parent
baa979f5ad
commit
cc47426c77
|
|
@ -3,6 +3,7 @@
|
||||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Label="Package Versions">
|
<PropertyGroup Label="Package Versions">
|
||||||
|
<AngleSharpPackageVersion>0.9.9</AngleSharpPackageVersion>
|
||||||
<InternalAspNetCoreSdkPackageVersion>2.2.0-preview1-17042</InternalAspNetCoreSdkPackageVersion>
|
<InternalAspNetCoreSdkPackageVersion>2.2.0-preview1-17042</InternalAspNetCoreSdkPackageVersion>
|
||||||
<MicrosoftAspNetCoreAuthenticationCookiesPackageVersion>2.2.0-preview1-34066</MicrosoftAspNetCoreAuthenticationCookiesPackageVersion>
|
<MicrosoftAspNetCoreAuthenticationCookiesPackageVersion>2.2.0-preview1-34066</MicrosoftAspNetCoreAuthenticationCookiesPackageVersion>
|
||||||
<MicrosoftAspNetCoreAuthenticationFacebookPackageVersion>2.2.0-preview1-34066</MicrosoftAspNetCoreAuthenticationFacebookPackageVersion>
|
<MicrosoftAspNetCoreAuthenticationFacebookPackageVersion>2.2.0-preview1-34066</MicrosoftAspNetCoreAuthenticationFacebookPackageVersion>
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,12 @@
|
||||||
<form asp-controller="Account" asp-action="Signin" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post">
|
<form asp-controller="Account" asp-action="Signin" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post">
|
||||||
<div>
|
<div>
|
||||||
<label>User Name</label>
|
<label>User Name</label>
|
||||||
<input type="text" name="userName" />
|
<input id="UserName" type="text" name="userName" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label>Date of Birth (MM/DD/YYYY)</label>
|
<label>Date of Birth (MM/DD/YYYY)</label>
|
||||||
<input type="text" name="birthDate" />
|
<input id="DOB" type="text" name="birthDate" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -29,5 +29,6 @@
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" />
|
||||||
<PackageReference Include="xunit" Version="$(XunitPackageVersion)" />
|
<PackageReference Include="xunit" Version="$(XunitPackageVersion)" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitRunnerVisualStudioPackageVersion)" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitRunnerVisualStudioPackageVersion)" />
|
||||||
|
<PackageReference Include="AngleSharp" Version="$(AngleSharpPackageVersion)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
// 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.
|
// 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.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
@ -13,7 +15,7 @@ namespace AuthSamples.FunctionalTests
|
||||||
{
|
{
|
||||||
public CustomPolicyProviderTests(WebApplicationFactory<CustomPolicyProvider.Startup> fixture)
|
public CustomPolicyProviderTests(WebApplicationFactory<CustomPolicyProvider.Startup> fixture)
|
||||||
{
|
{
|
||||||
Client = fixture.CreateDefaultClient();
|
Client = fixture.CreateClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpClient Client { get; }
|
public HttpClient Client { get; }
|
||||||
|
|
@ -37,8 +39,70 @@ namespace AuthSamples.FunctionalTests
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
Assert.Equal("http://localhost/account/signin?ReturnUrl=%2FHome%2FMinimumAge10", response.Headers.Location.ToString());
|
Assert.Equal("http://localhost/account/signin?ReturnUrl=%2FHome%2FMinimumAge10", response.RequestMessage.RequestUri.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task MinimumAge10WorksIfOldEnough()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var signIn = await SignIn(Client, "Dude", DateTime.Now.Subtract(TimeSpan.FromDays(365 * 20)).ToShortDateString());
|
||||||
|
Assert.Equal(HttpStatusCode.OK, signIn.StatusCode);
|
||||||
|
|
||||||
|
var response = await Client.GetAsync("/Home/MinimumAge10");
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Contains("Welcome, Dude", content);
|
||||||
|
Assert.Contains("Welcome to a page restricted to users 10 or older", content);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task MinimumAge10FailsIfNotOldEnough()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var signIn = await SignIn(Client, "Dude", DateTime.Now.Subtract(TimeSpan.FromDays(365 * 5)).ToShortDateString());
|
||||||
|
Assert.Equal(HttpStatusCode.OK, signIn.StatusCode);
|
||||||
|
|
||||||
|
var response = await Client.GetAsync("/Home/MinimumAge10");
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Contains("Access Denied: Dude is not authorized to view this page.", content);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task MinimumAge50WorksIfOldEnough()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var signIn = await SignIn(Client, "Dude", DateTime.Now.Subtract(TimeSpan.FromDays(365 * 55)).ToShortDateString());
|
||||||
|
Assert.Equal(HttpStatusCode.OK, signIn.StatusCode);
|
||||||
|
|
||||||
|
var response = await Client.GetAsync("/Home/MinimumAge50");
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Contains("Welcome, Dude", content);
|
||||||
|
Assert.Contains("Welcome to a page restricted to users 50 or older", content);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task MinimumAge50FailsIfNotOldEnough()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var signIn = await SignIn(Client, "Dude", DateTime.Now.Subtract(TimeSpan.FromDays(365 * 20)).ToShortDateString());
|
||||||
|
Assert.Equal(HttpStatusCode.OK, signIn.StatusCode);
|
||||||
|
|
||||||
|
var response = await Client.GetAsync("/Home/MinimumAge50");
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Contains("Access Denied: Dude is not authorized to view this page.", content);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -49,8 +113,21 @@ namespace AuthSamples.FunctionalTests
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
Assert.Equal("http://localhost/account/signin?ReturnUrl=%2FHome%2FMinimumAge50", response.Headers.Location.ToString());
|
Assert.Equal("http://localhost/account/signin?ReturnUrl=%2FHome%2FMinimumAge50", response.RequestMessage.RequestUri.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static async Task<HttpResponseMessage> SignIn(HttpClient client, string userName, string dob)
|
||||||
|
{
|
||||||
|
var goToSignIn = await client.GetAsync("/account/signin");
|
||||||
|
var signIn = await TestAssert.IsHtmlDocumentAsync(goToSignIn);
|
||||||
|
|
||||||
|
var form = TestAssert.HasForm(signIn);
|
||||||
|
return await client.SendAsync(form, new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
["UserName"] = userName,
|
||||||
|
["DOB"] = dob,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
// 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.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using AngleSharp.Dom.Html;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace AuthSamples.FunctionalTests
|
||||||
|
{
|
||||||
|
public static class HttpClientExtensions
|
||||||
|
{
|
||||||
|
// Copied from Identity functionals
|
||||||
|
public static Task<HttpResponseMessage> SendAsync(
|
||||||
|
this HttpClient client,
|
||||||
|
IHtmlFormElement form,
|
||||||
|
IEnumerable<KeyValuePair<string, string>> formValues)
|
||||||
|
{
|
||||||
|
var submitElement = Assert.Single(form.QuerySelectorAll("[type=submit]"));
|
||||||
|
var submitButton = Assert.IsAssignableFrom<IHtmlElement>(submitElement);
|
||||||
|
|
||||||
|
return client.SendAsync(form, submitButton, formValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copied from Identity functionals
|
||||||
|
public static Task<HttpResponseMessage> SendAsync(
|
||||||
|
this HttpClient client,
|
||||||
|
IHtmlFormElement form,
|
||||||
|
IHtmlElement submitButton,
|
||||||
|
IEnumerable<KeyValuePair<string, string>> formValues)
|
||||||
|
{
|
||||||
|
foreach (var kvp in formValues)
|
||||||
|
{
|
||||||
|
var element = Assert.IsAssignableFrom<IHtmlInputElement>(form[kvp.Key]);
|
||||||
|
element.Value = kvp.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
var submit = form.GetSubmission(submitButton);
|
||||||
|
var target = (Uri)submit.Target;
|
||||||
|
if (submitButton.HasAttribute("formaction"))
|
||||||
|
{
|
||||||
|
var formaction = submitButton.GetAttribute("formaction");
|
||||||
|
target = new Uri(formaction, UriKind.Relative);
|
||||||
|
}
|
||||||
|
var submision = new HttpRequestMessage(new HttpMethod(submit.Method.ToString()), target)
|
||||||
|
{
|
||||||
|
Content = new StreamContent(submit.Body)
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var header in submit.Headers)
|
||||||
|
{
|
||||||
|
if (!submision.Headers.TryAddWithoutValidation(header.Key, header.Value))
|
||||||
|
{
|
||||||
|
submision.Content.Headers.TryAddWithoutValidation(header.Key, header.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return client.SendAsync(submision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
// 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.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using AngleSharp;
|
||||||
|
using AngleSharp.Dom;
|
||||||
|
using AngleSharp.Dom.Html;
|
||||||
|
using AngleSharp.Network;
|
||||||
|
using AngleSharp.Parser.Html;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace AuthSamples.FunctionalTests
|
||||||
|
{
|
||||||
|
// Merged HtmlAssert + ResponseAssert from Identity functional tests
|
||||||
|
public class TestAssert
|
||||||
|
{
|
||||||
|
public static IHtmlFormElement HasForm(IHtmlDocument document)
|
||||||
|
{
|
||||||
|
var form = Assert.Single(document.QuerySelectorAll("form"));
|
||||||
|
return Assert.IsAssignableFrom<IHtmlFormElement>(form);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IHtmlAnchorElement HasLink(string selector, IHtmlDocument document)
|
||||||
|
{
|
||||||
|
var element = Assert.Single(document.QuerySelectorAll(selector));
|
||||||
|
return Assert.IsAssignableFrom<IHtmlAnchorElement>(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static IEnumerable<IHtmlElement> HasElements(string selector, IHtmlDocument document)
|
||||||
|
{
|
||||||
|
var elements = document
|
||||||
|
.QuerySelectorAll(selector)
|
||||||
|
.OfType<IHtmlElement>()
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
Assert.NotEmpty(elements);
|
||||||
|
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IHtmlElement HasElement(string selector, IParentNode document)
|
||||||
|
{
|
||||||
|
var element = Assert.Single(document.QuerySelectorAll(selector));
|
||||||
|
return Assert.IsAssignableFrom<IHtmlElement>(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IHtmlFormElement HasForm(string selector, IParentNode document)
|
||||||
|
{
|
||||||
|
var form = Assert.Single(document.QuerySelectorAll(selector));
|
||||||
|
return Assert.IsAssignableFrom<IHtmlFormElement>(form);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static IHtmlHtmlElement IsHtmlFragment(string htmlMessage)
|
||||||
|
{
|
||||||
|
var synteticNode = $"<div>{htmlMessage}</div>";
|
||||||
|
var fragment = Assert.Single(new HtmlParser().ParseFragment(htmlMessage, context: null));
|
||||||
|
return Assert.IsAssignableFrom<IHtmlHtmlElement>(fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Uri IsRedirect(HttpResponseMessage responseMessage)
|
||||||
|
{
|
||||||
|
Assert.Equal(HttpStatusCode.Redirect, responseMessage.StatusCode);
|
||||||
|
return responseMessage.Headers.Location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<IHtmlDocument> IsHtmlDocumentAsync(HttpResponseMessage response)
|
||||||
|
{
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Equal("text/html", response.Content.Headers.ContentType.MediaType);
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
var document = await BrowsingContext.New()
|
||||||
|
.OpenAsync(ResponseFactory, CancellationToken.None);
|
||||||
|
return Assert.IsAssignableFrom<IHtmlDocument>(document);
|
||||||
|
|
||||||
|
void ResponseFactory(VirtualResponse htmlResponse)
|
||||||
|
{
|
||||||
|
htmlResponse
|
||||||
|
.Address(response.RequestMessage.RequestUri)
|
||||||
|
.Status(response.StatusCode);
|
||||||
|
|
||||||
|
MapHeaders(response.Headers);
|
||||||
|
MapHeaders(response.Content.Headers);
|
||||||
|
|
||||||
|
htmlResponse.Content(content);
|
||||||
|
|
||||||
|
void MapHeaders(HttpHeaders headers)
|
||||||
|
{
|
||||||
|
foreach (var header in headers)
|
||||||
|
{
|
||||||
|
foreach (var value in header.Value)
|
||||||
|
{
|
||||||
|
htmlResponse.Header(header.Key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void IsOK(HttpResponseMessage download)
|
||||||
|
{
|
||||||
|
Assert.Equal(HttpStatusCode.OK, download.StatusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue