convert to blazor server side render

This commit is contained in:
2025-12-24 16:43:51 -06:00
parent 357c3d9932
commit dcbf8a3ac3
215 changed files with 1867 additions and 2350 deletions

View File

@@ -1,114 +1,105 @@
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Shogi.Identity;
using System.Net.Http.Json;
using System.Text.Json;
namespace Shogi.AcceptanceTests.TestSetup;
/// <summary>
/// Acceptance Test fixture for tests which assert features for Microsoft accounts.
/// Integration test fixture using WebApplicationFactory for in-process testing.
/// </summary>
public class AatTestFixture : IAsyncLifetime, IDisposable
public class AatTestFixture : WebApplicationFactory<Program>, IAsyncLifetime
{
protected static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web);
private readonly string testAccountPassword;
private bool disposedValue;
private const string TestPassword = "TestPassword123!";
public AatTestFixture()
public HttpClient HttpClient { get; private set; } = null!;
public HttpClient OtherHttpClient { get; private set; } = null!;
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
this.Configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddJsonFile("appsettings.Development.json", optional: true)
.Build();
builder.UseEnvironment("Development");
var baseUrl = this.Configuration["ServiceUrl"] ?? throw new InvalidOperationException();
this.HttpClient = new HttpClient
builder.ConfigureServices(services =>
{
BaseAddress = new Uri(baseUrl, UriKind.Absolute)
};
this.OtherHttpClient = new HttpClient
{
BaseAddress = new Uri(baseUrl, UriKind.Absolute)
};
// Remove the existing DbContext registration
var descriptor = services.SingleOrDefault(
d => d.ServiceType == typeof(DbContextOptions<ApplicationDbContext>));
this.testAccountPassword = this.Configuration["TestUserPassword"]!;
if (string.IsNullOrWhiteSpace(this.testAccountPassword))
{
throw new InvalidOperationException("TestUserPassword is not configured.");
}
}
public IConfiguration Configuration { get; private set; }
public HttpClient HttpClient { get; }
public HttpClient OtherHttpClient { get; }
protected async Task LoginToTestAccounts()
{
var response = await this.HttpClient.PostAsJsonAsync(
RelativeUri("login"),
new
if (descriptor != null)
{
email = "aat-account",
password = this.testAccountPassword,
},
options: SerializerOptions);
services.Remove(descriptor);
}
response.IsSuccessStatusCode.Should().BeTrue(because: "The test account should exist. If it does not, use the /Account/TestAccount route to create it.");
var bearerToken = (await response.Content.ReadFromJsonAsync<LoginResponse>())?.AccessToken;
this.HttpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", bearerToken);
response = await this.HttpClient.PostAsJsonAsync(
RelativeUri("login"),
new
// Add in-memory database for testing
services.AddDbContext<ApplicationDbContext>(options =>
{
email = "aat-account-2",
password = this.testAccountPassword,
},
options: SerializerOptions);
options.UseInMemoryDatabase("IntegrationTestDb_" + Guid.NewGuid().ToString());
});
response.IsSuccessStatusCode.Should().BeTrue(because: "The test account should exist. If it does not, use the /Account/TestAccount route to create it.");
bearerToken = (await response.Content.ReadFromJsonAsync<LoginResponse>())?.AccessToken;
this.OtherHttpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", bearerToken);
// Ensure the database is created and seeded
var sp = services.BuildServiceProvider();
using var scope = sp.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
db.Database.EnsureCreated();
});
}
public async Task InitializeAsync()
{
await this.LoginToTestAccounts();
this.HttpClient = this.CreateClient();
this.OtherHttpClient = this.CreateClient();
await this.SetupTestAccountsAndLogin();
}
protected virtual void Dispose(bool disposing)
private async Task SetupTestAccountsAndLogin()
{
if (!this.disposedValue)
{
if (disposing)
{
this.HttpClient.Dispose();
}
// Register and login first test account
await RegisterAndLogin(this.HttpClient, "aat-account@test.com", TestPassword);
this.disposedValue = true;
// Register and login second test account
await RegisterAndLogin(this.OtherHttpClient, "aat-account-2@test.com", TestPassword);
}
private static async Task RegisterAndLogin(HttpClient client, string email, string password)
{
// Try to register (may already exist)
await client.PostAsJsonAsync(
new Uri("register", UriKind.Relative),
new { email, password },
options: SerializerOptions);
// Login
var loginResponse = await client.PostAsJsonAsync(
new Uri("login", UriKind.Relative),
new { email, password },
options: SerializerOptions);
if (loginResponse.IsSuccessStatusCode)
{
var tokenResponse = await loginResponse.Content.ReadFromJsonAsync<LoginResponse>(SerializerOptions);
if (tokenResponse?.AccessToken != null)
{
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", tokenResponse.AccessToken);
}
}
}
public Task DisposeAsync()
async Task IAsyncLifetime.DisposeAsync()
{
this.Dispose(true);
return Task.CompletedTask;
this.HttpClient?.Dispose();
this.OtherHttpClient?.Dispose();
await base.DisposeAsync();
}
public void Dispose()
{
this.Dispose(disposing: true);
GC.SuppressFinalize(this);
}
protected static Uri RelativeUri(string s) => new(s, UriKind.Relative);
private class LoginResponse
{
public string AccessToken { get; set; } = string.Empty;
}
}