This commit is contained in:
2025-10-27 21:39:50 -04:00
parent 31f723bea4
commit 2fecd5b315
22 changed files with 1198 additions and 14 deletions

View File

@@ -1,5 +1,6 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Prefab.Handler;
using Prefab.Web.Data;
@@ -50,7 +51,7 @@ public class PrefabCompositeFixture : IAsyncLifetime
catalogProject,
catalogPort,
overrides: null,
configureServices: ConfigureTestAuthentication);
configureServices: ConfigureCatalogServices);
await CatalogApi.InitializeAsync();
catalogAddress = CatalogApi.HttpAddress;
@@ -68,7 +69,7 @@ public class PrefabCompositeFixture : IAsyncLifetime
prefabProject,
prefabPort,
overrides,
ConfigureTestAuthentication);
ConfigureWebServices);
await PrefabWeb.InitializeAsync();
}
@@ -113,7 +114,7 @@ public class PrefabCompositeFixture : IAsyncLifetime
["Prefab__Catalog__Client__BaseAddress"] = catalogAddress?.ToString().TrimEnd('/') ?? string.Empty
};
private void ConfigureTestAuthentication(IServiceCollection services)
protected void ConfigureTestAuthentication(IServiceCollection services)
{
var descriptors = services.Where(d => d.ServiceType == typeof(AuthenticationStateProvider)).ToList();
foreach (var descriptor in descriptors)
@@ -125,6 +126,10 @@ public class PrefabCompositeFixture : IAsyncLifetime
services.AddSingleton<AuthenticationStateProvider>(_ => _authenticationProvider);
}
protected virtual void ConfigureCatalogServices(IServiceCollection services) => ConfigureTestAuthentication(services);
protected virtual void ConfigureWebServices(IServiceCollection services) => ConfigureTestAuthentication(services);
private static PrefabHarnessOptions ResolveDefaultOptions()
{
var modeEnv = Environment.GetEnvironmentVariable("PREFAB_TEST_MODE")?.Trim().ToLowerInvariant();
@@ -190,6 +195,79 @@ public sealed class PrefabCompositeFixture_InProcess : PrefabCompositeFixture
};
}
public sealed class PrefabCompositeFixture_BffProduct : PrefabCompositeFixture
{
private Prefab.Shared.Catalog.Products.IProductClient? _productClient;
private readonly Prefab.Shared.Catalog.Categories.ICategoryClient _categoryClient = new NullCategoryClient();
private readonly Prefab.Shared.Catalog.Products.IPriceQuoteClient _priceQuoteClient = new NullPriceQuoteClient();
public PrefabCompositeFixture_BffProduct()
: base(new PrefabHarnessOptions(
RunMode.DebugPersistent,
EnableAspireDashboard: true,
DisablePortRandomization: true))
{
}
public void UseProductClient(Prefab.Shared.Catalog.Products.IProductClient client)
{
_productClient = client ?? throw new ArgumentNullException(nameof(client));
}
protected override bool ShouldStartCatalog => false;
protected override IDictionary<string, string?> GetWebOverrides(Uri? catalogAddress) =>
new Dictionary<string, string?>
{
["Prefab__Catalog__Client__Transport"] = "InProcess"
};
protected override void ConfigureWebServices(IServiceCollection services)
{
base.ConfigureWebServices(services);
services.RemoveAll<Prefab.Shared.Catalog.IModuleClient>();
services.RemoveAll<Prefab.Shared.Catalog.Categories.ICategoryClient>();
services.RemoveAll<Prefab.Shared.Catalog.Products.IProductClient>();
services.RemoveAll<Prefab.Shared.Catalog.Products.IPriceQuoteClient>();
services.AddScoped<Prefab.Shared.Catalog.Categories.ICategoryClient>(_ => _categoryClient);
services.AddScoped<Prefab.Shared.Catalog.Products.IPriceQuoteClient>(_ => _priceQuoteClient);
services.AddScoped<Prefab.Shared.Catalog.Products.IProductClient>(_ =>
_productClient ?? throw new InvalidOperationException("Test product client has not been configured."));
services.AddScoped<Prefab.Shared.Catalog.IModuleClient>(sp =>
new Prefab.Catalog.ModuleClient(
sp.GetRequiredService<Prefab.Shared.Catalog.Categories.ICategoryClient>(),
sp.GetRequiredService<Prefab.Shared.Catalog.Products.IProductClient>(),
sp.GetRequiredService<Prefab.Shared.Catalog.Products.IPriceQuoteClient>()));
}
private sealed class NullCategoryClient : Prefab.Shared.Catalog.Categories.ICategoryClient
{
public Task<Prefab.Shared.Catalog.Categories.GetCategories.Response> GetCategories(
CancellationToken cancellationToken) =>
throw new NotSupportedException("Category retrieval is not configured for this test.");
public Task<Prefab.Shared.Catalog.Categories.CreateCategory.Response> CreateCategory(
Prefab.Shared.Catalog.Categories.CreateCategory.Request request,
CancellationToken cancellationToken) =>
throw new NotSupportedException("Category creation is not configured for this test.");
}
private sealed class NullPriceQuoteClient : Prefab.Shared.Catalog.Products.IPriceQuoteClient
{
public Task<Prefab.Shared.Catalog.Products.QuotePrice.Response> Quote(
Prefab.Shared.Catalog.Products.QuotePrice.Request request,
CancellationToken cancellationToken) =>
throw new NotSupportedException("Price quote client is not configured for this test.");
public Task<Prefab.Shared.Catalog.Products.QuotePrice.Response> QuotePrice(
Prefab.Shared.Catalog.Products.QuotePrice.Request request,
CancellationToken cancellationToken) =>
throw new NotSupportedException("Price quote client is not configured for this test.");
}
}
[CollectionDefinition("Prefab.Debug")]
public sealed class PrefabDebugCollection : ICollectionFixture<PrefabCompositeFixture_Debug>
{
@@ -204,3 +282,8 @@ public sealed class PrefabEphemeralCollection : ICollectionFixture<PrefabComposi
public sealed class PrefabInProcessCollection : ICollectionFixture<PrefabCompositeFixture_InProcess>
{
}
[CollectionDefinition("Prefab.BffProduct")]
public sealed class PrefabBffProductCollection : ICollectionFixture<PrefabCompositeFixture_BffProduct>
{
}