Files
tiku-backend.net/Tiku.IntegrationTests/Api/TenantPublicEndpointTests.cs

166 lines
6.4 KiB
C#

using System.Net;
using System.Net.Http.Json;
using System.Text.Json;
using Tiku.Domain.Common;
using Tiku.Domain.Operations;
using Tiku.Domain.Tenancy;
namespace Tiku.IntegrationTests.Api;
public sealed class TenantPublicEndpointTests
{
[Fact]
public async Task Resolve_returns_public_tenant_configuration_by_tenant_code()
{
await using var factory = new ApiTestFactory();
var tenantId = Guid.NewGuid();
await SeedTenantAsync(factory, tenantId);
using var client = factory.CreateClient();
var response = await client.GetAsync("/api/tenant/resolve?tenantCode=master");
var document = await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync());
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal(tenantId.ToString(), document.RootElement.GetProperty("tenant").GetProperty("id").GetString());
Assert.Equal("升本刷题通", document.RootElement.GetProperty("branding").GetProperty("brandName").GetString());
Assert.True(document.RootElement.GetProperty("features").GetProperty("enableVocabulary").GetBoolean());
Assert.Equal("http://127.0.0.1:5173", document.RootElement.GetProperty("publicConfig").GetProperty("appUrl").GetString());
}
[Fact]
public async Task Resolve_returns_public_tenant_configuration_by_host()
{
await using var factory = new ApiTestFactory();
var tenantId = Guid.NewGuid();
await SeedTenantAsync(factory, tenantId);
using var client = factory.CreateClient();
var response = await client.GetAsync("/api/tenant/resolve?host=student.example.test");
var document = await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync());
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("student.example.test", document.RootElement.GetProperty("tenant").GetProperty("host").GetString());
}
[Fact]
public async Task Resolve_prefers_published_theme_config_over_branding_theme()
{
await using var factory = new ApiTestFactory();
var tenantId = Guid.NewGuid();
await SeedTenantAsync(factory, tenantId);
await factory.SeedAsync(new TenantThemeConfig
{
TenantId = tenantId,
Status = TenantThemeConfigStatus.Published,
ActiveTheme = JsonSerializer.SerializeToElement(new
{
color = "red"
}),
ActivePublicAssets = JsonSerializer.SerializeToElement(new
{
hero = "/hero.png"
})
});
using var client = factory.CreateClient();
var response = await client.GetAsync("/api/tenant/current-public?tenantCode=master");
var document = await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync());
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("red", document.RootElement.GetProperty("branding").GetProperty("theme").GetProperty("color").GetString());
Assert.Equal("/hero.png", document.RootElement.GetProperty("branding").GetProperty("publicAssets").GetProperty("hero").GetString());
}
[Fact]
public async Task Resolve_returns_not_found_for_unknown_tenant()
{
await using var factory = new ApiTestFactory();
using var client = factory.CreateClient();
var response = await client.GetAsync("/api/tenant/resolve?tenantCode=missing");
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
[Fact]
public async Task Health_returns_ok()
{
await using var factory = new ApiTestFactory();
using var client = factory.CreateClient();
var response = await client.GetAsync("/api/health");
var body = await response.Content.ReadFromJsonAsync<JsonElement>();
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("ok", body.GetProperty("status").GetString());
}
[Fact]
public async Task Cors_preflight_allows_configured_development_origin()
{
await using var factory = new ApiTestFactory();
using var client = factory.CreateClient();
using var request = new HttpRequestMessage(HttpMethod.Options, "/api/health");
request.Headers.Add("Origin", "http://localhost:5173");
request.Headers.Add("Access-Control-Request-Method", "GET");
var response = await client.SendAsync(request);
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
Assert.Equal("http://localhost:5173", response.Headers.GetValues("Access-Control-Allow-Origin").Single());
}
private static Task SeedTenantAsync(ApiTestFactory factory, Guid tenantId)
{
return factory.SeedAsync(
new Tenant
{
Id = tenantId,
Slug = "master",
Name = "升本刷题通",
Status = TenantStatus.Active,
Mode = TenantMode.PlatformOwned
},
new TenantDomain
{
TenantId = tenantId,
Host = "student.example.test",
DomainType = TenantDomainType.Custom,
Status = TenantDomainStatus.Active,
IsPrimary = true
},
new TenantBranding
{
TenantId = tenantId,
BrandName = "升本刷题通",
ShortName = "刷题通",
Slogan = "多租户专升本题库 SaaS",
LogoUrl = "https://example.test/logo.png",
FaviconUrl = "https://example.test/favicon.ico",
ServiceWechat = "service-wechat",
ServiceAccountName = "服务号",
Theme = JsonSerializer.SerializeToElement(new
{
color = "blue"
}),
PublicAssets = JsonDefaults.Object()
},
new TenantSettings
{
TenantId = tenantId,
FeatureFlags = JsonSerializer.SerializeToElement(new
{
enableVocabulary = true
}),
AdminFeatureFlags = JsonSerializer.SerializeToElement(new
{
enableTenantManagement = true
}),
PublicConfig = JsonSerializer.SerializeToElement(new
{
appUrl = "http://127.0.0.1:5173"
})
});
}
}