Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
211 changes: 197 additions & 14 deletions aspnetcore/test/integration-tests.md

Large diffs are not rendered by default.

210 changes: 196 additions & 14 deletions aspnetcore/test/integration-tests/includes/integration-tests9.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using System.Data.Common;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
using RazorPagesProject.Data;

namespace RazorPagesProject.Tests;

// <snippet1>
public class CustomWebApplicationFactory<TProgram>
: WebApplicationFactory<TProgram> where TProgram : class
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
var dbContextDescriptor = services.SingleOrDefault(
d => d.ServiceType ==
typeof(IDbContextOptionsConfiguration<ApplicationDbContext>));

services.Remove(dbContextDescriptor);

var dbConnectionDescriptor = services.SingleOrDefault(
d => d.ServiceType ==
typeof(DbConnection));

services.Remove(dbConnectionDescriptor);

// Create open SqliteConnection so EF won't automatically close it.
services.AddSingleton<DbConnection>(container =>
{
var connection = new SqliteConnection("DataSource=:memory:");
connection.Open();

return connection;
});

services.AddDbContext<ApplicationDbContext>((container, options) =>
{
var connection = container.GetRequiredService<DbConnection>();
options.UseSqlite(connection);
});
});

builder.UseEnvironment("Development");
}
}
// </snippet1>
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
using System.Net;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Text.Encodings.Web;
using AngleSharp.Html.Dom;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using RazorPagesProject.Services;
using RazorPagesProject.Tests.Helpers;

namespace RazorPagesProject.Tests.IntegrationTests;

[TestClass]
public class AuthTests
{

private static CustomWebApplicationFactory<Program> _factory;

[ClassInitialize]
public static void AssemblyInitialize(TestContext _)
{
_factory = new CustomWebApplicationFactory<Program>();
}

[ClassCleanup(ClassCleanupBehavior.EndOfClass)]
public static void AssemblyCleanup(TestContext _)
{
_factory.Dispose();
}

// <snippet1>
[TestMethod]
public async Task Get_GithubProfilePageCanGetAGithubUser()
{
// Arrange
void ConfigureTestServices(IServiceCollection services) =>
services.AddSingleton<IGithubClient>(new TestGithubClient());
var client = _factory
.WithWebHostBuilder(builder =>
builder.ConfigureTestServices(ConfigureTestServices))
.CreateClient();

// Act
var profile = await client.GetAsync("/GithubProfile");
Assert.AreEqual(HttpStatusCode.OK, profile.StatusCode);
var profileHtml = await HtmlHelpers.GetDocumentAsync(profile);

var profileWithUserName = await client.SendAsync(
(IHtmlFormElement)profileHtml.QuerySelector("#user-profile"),
new Dictionary<string, string> { ["Input_UserName"] = "user" });

// Assert
Assert.AreEqual(HttpStatusCode.OK, profileWithUserName.StatusCode);
var profileWithUserHtml =
await HtmlHelpers.GetDocumentAsync(profileWithUserName);
var userLogin = profileWithUserHtml.QuerySelector("#user-login");
Assert.AreEqual("user", userLogin.TextContent);
}

public class TestGithubClient : IGithubClient
{
public Task<GithubUser> GetUserAsync(string userName)
{
if (userName == "user")
{
return Task.FromResult(
new GithubUser
{
Login = "user",
Company = "Contoso Blockchain",
Name = "John Doe"
});
}
else
{
return Task.FromResult<GithubUser>(null);
}
}
}
// </snippet1>

// <snippet2>
[TestMethod]
public async Task Get_SecurePageRedirectsAnUnauthenticatedUser()
{
// Arrange
var client = _factory.CreateClient(
new WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false
});

// Act
var response = await client.GetAsync("/SecurePage");

// Assert
Assert.AreEqual(HttpStatusCode.Redirect, response.StatusCode);
StringAssert.StartsWith(response.Headers.Location.OriginalString, "http://localhost/Identity/Account/Login");
}
// </snippet2>

// <snippet3>
[TestMethod]
public async Task Get_SecurePageIsReturnedForAnAuthenticatedUser()
{
// Arrange
var client = _factory.WithWebHostBuilder(builder =>
{
builder.ConfigureTestServices(services =>
{
services.AddAuthentication(defaultScheme: "TestScheme")
.AddScheme<AuthenticationSchemeOptions, TestAuthHandler>(
"TestScheme", options => { });
});
})
.CreateClient(new WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false,
});

client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue(scheme: "TestScheme");

//Act
var response = await client.GetAsync("/SecurePage");

// Assert
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
// </snippet3>
}

// <snippet4>
public class TestAuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
public TestAuthHandler(IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger, UrlEncoder encoder)
: base(options, logger, encoder)
{
}

protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
var claims = new[] { new Claim(ClaimTypes.Name, "Test user") };
var identity = new ClaimsIdentity(claims, "Test");
var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, "TestScheme");

var result = AuthenticateResult.Success(ticket);

return Task.FromResult(result);
}
}
// </snippet4>
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
namespace RazorPagesProject.Tests.IntegrationTests;

// <snippet1>
[TestClass]
public class BasicTests
{
private static CustomWebApplicationFactory<Program> _factory;

[ClassInitialize]
public static void AssemblyInitialize(TestContext _)
{
_factory = new CustomWebApplicationFactory<Program>();
}

[ClassCleanup(ClassCleanupBehavior.EndOfClass)]
public static void AssemblyCleanup(TestContext _)
{
_factory.Dispose();
}

[TestMethod]
[DataRow("/")]
[DataRow("/Index")]
[DataRow("/About")]
[DataRow("/Privacy")]
[DataRow("/Contact")]
public async Task Get_EndpointsReturnSuccessAndCorrectContentType(string url)
{
// Arrange
var client = _factory.CreateClient();

// Act
var response = await client.GetAsync(url);

// Assert
response.EnsureSuccessStatusCode(); // Status Code 200-299
Assert.AreEqual("text/html; charset=utf-8",
response.Content.Headers.ContentType.ToString());
}
}
// </snippet1>
Loading