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 { 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{ ["Demo:Enabled"]="true",["Logging:LogLevel:Default"]="Warning", ["AMap:WebServiceKey"]="",["AMap:BrowserKey"]="",["AMap:JsSecurityCode"]="" })); builder.ConfigureServices(services=>{ services.RemoveAll();services.RemoveAll>(); services.RemoveAll>(); services.AddDbContext(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 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 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{ ["__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 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 Json(HttpResponseMessage response) { var raw=await response.Content.ReadAsStringAsync(); Assert.True(response.IsSuccessStatusCode,"HTTP "+(int)response.StatusCode+": "+raw); return JsonDocument.Parse(raw).RootElement.Clone(); } }