using System.Net;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.RegularExpressions;
using EARSystem.Infrastructure;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace EARSystem.Tests;
public class AppFactory : WebApplicationFactory<Program>
{
private readonly SqliteConnection connection = new("Data Source=:memory:");
public AppFactory() => connection.Open();
protected override void ConfigureWebHost(IWebHostBuilder builder) {
builder.UseEnvironment("Testing");
builder.ConfigureAppConfiguration((_,config)=>config.AddInMemoryCollection(new Dictionary<string,string?>{
["Demo:Enabled"]="true",["Logging:LogLevel:Default"]="Warning",
["AMap:WebServiceKey"]="",["AMap:BrowserKey"]="",["AMap:JsSecurityCode"]=""
}));
builder.ConfigureServices(services=>{
services.RemoveAll<AppDbContext>();services.RemoveAll<DbContextOptions<AppDbContext>>();
services.RemoveAll<IDbContextOptionsConfiguration<AppDbContext>>();
services.AddDbContext<AppDbContext>(o=>o.UseSqlite(connection));
});
}
public HttpClient Browser() => CreateClient(new(){BaseAddress=new Uri("https://localhost"),AllowAutoRedirect=false,HandleCookies=true});
protected override void Dispose(bool disposing) {base.Dispose(disposing);if(disposing)connection.Dispose();}
}
public static class BrowserHelpers
{
public static async Task<string> Token(HttpClient client,string path="/Account/Login") {
var response=await client.GetAsync(path);
response.EnsureSuccessStatusCode();
var html=await response.Content.ReadAsStringAsync();
var match=Regex.Match(html,"name=\"__RequestVerificationToken\"[^>]*value=\"([^\"]+)\"");
Assert.True(match.Success,"Antiforgery token missing");
return WebUtility.HtmlDecode(match.Groups[1].Value);
}
public static async Task<string> Register(HttpClient client) {
var token=await Token(client);
var email=Guid.NewGuid().ToString("N")+"@test.local";
var response=await client.PostAsync("/Account/Register",new FormUrlEncodedContent(new Dictionary<string,string>{
["__RequestVerificationToken"]=token,["DisplayName"]="测试用户",["Email"]=email,
["Password"]="TestPassword!42",["ConfirmPassword"]="TestPassword!42"
}));
Assert.Equal(HttpStatusCode.Redirect,response.StatusCode);
return await Token(client,"/Diary");
}
public static async Task<HttpResponseMessage> Send(HttpClient client,string token,string url,HttpMethod method,object? body=null) {
var request=new HttpRequestMessage(method,url);
request.Headers.Add("X-CSRF-TOKEN",token);
if(body!=null)request.Content=JsonContent.Create(body);
return await client.SendAsync(request);
}
public static async Task<JsonElement> Json(HttpResponseMessage response) {
var raw=await response.Content.ReadAsStringAsync();
Assert.True(response.IsSuccessStatusCode,"HTTP "+(int)response.StatusCode+": "+raw);
return JsonDocument.Parse(raw).RootElement.Clone();
}
}
using System.Net;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.RegularExpressions;
using EARSystem.Infrastructure;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace EARSystem.Tests;
public class AppFactory : WebApplicationFactory<Program>
{
private readonly SqliteConnection connection = new("Data Source=:memory:");
public AppFactory() => connection.Open();
protected override void ConfigureWebHost(IWebHostBuilder builder) {
builder.UseEnvironment("Testing");
builder.ConfigureAppConfiguration((_,config)=>config.AddInMemoryCollection(new Dictionary<string,string?>{
["Demo:Enabled"]="true",["Logging:LogLevel:Default"]="Warning",
["AMap:WebServiceKey"]="",["AMap:BrowserKey"]="",["AMap:JsSecurityCode"]=""
}));
builder.ConfigureServices(services=>{
services.RemoveAll<AppDbContext>();services.RemoveAll<DbContextOptions<AppDbContext>>();
services.RemoveAll<IDbContextOptionsConfiguration<AppDbContext>>();
services.AddDbContext<AppDbContext>(o=>o.UseSqlite(connection));
});
}
public HttpClient Browser() => CreateClient(new(){BaseAddress=new Uri("https://localhost"),AllowAutoRedirect=false,HandleCookies=true});
protected override void Dispose(bool disposing) {base.Dispose(disposing);if(disposing)connection.Dispose();}
}
public static class BrowserHelpers
{
public static async Task<string> Token(HttpClient client,string path="/Account/Login") {
var response=await client.GetAsync(path);
response.EnsureSuccessStatusCode();
var html=await response.Content.ReadAsStringAsync();
var match=Regex.Match(html,"name=\"__RequestVerificationToken\"[^>]*value=\"([^\"]+)\"");
Assert.True(match.Success,"Antiforgery token missing");
return WebUtility.HtmlDecode(match.Groups[1].Value);
}
public static async Task<string> Register(HttpClient client) {
var token=await Token(client);
var email=Guid.NewGuid().ToString("N")+"@test.local";
var response=await client.PostAsync("/Account/Register",new FormUrlEncodedContent(new Dictionary<string,string>{
["__RequestVerificationToken"]=token,["DisplayName"]="测试用户",["Email"]=email,
["Password"]="TestPassword!42",["ConfirmPassword"]="TestPassword!42"
}));
Assert.Equal(HttpStatusCode.Redirect,response.StatusCode);
return await Token(client,"/Diary");
}
public static async Task<HttpResponseMessage> Send(HttpClient client,string token,string url,HttpMethod method,object? body=null) {
var request=new HttpRequestMessage(method,url);
request.Headers.Add("X-CSRF-TOKEN",token);
if(body!=null)request.Content=JsonContent.Create(body);
return await client.SendAsync(request);
}
public static async Task<JsonElement> Json(HttpResponseMessage response) {
var raw=await response.Content.ReadAsStringAsync();
Assert.True(response.IsSuccessStatusCode,"HTTP "+(int)response.StatusCode+": "+raw);
return JsonDocument.Parse(raw).RootElement.Clone();
}
}