GetOpenIdConfiguration_returns_ok against testing host

This commit is contained in:
Paul Schneider 2026-09-12 14:30:50 +01:00
commit 5b48e0bfdb
Signed by: notazof
GPG key ID: 1DD5D838E5343B06
5 changed files with 70 additions and 75 deletions

View file

@ -21,6 +21,45 @@ namespace Yavsc.Org.Tests
this._output = output; this._output = output;
} }
public HttpClient CreateHttpClient()
{
return new HttpClient(new BypassSslValidationHandler())
{
BaseAddress = new Uri(this._serverFixture.HttpsAuthority ?? throw new InvalidOperationException("Missing HttpsAuthority"))
};
}
/// <summary>
/// Issue a GET against <paramref name="relativePath"/> on the
/// in-memory test server. Returns the raw HttpResponseMessage
/// without following redirects — the test asserts on the first
/// hop, not the eventual page.
/// </summary>
protected static async Task<HttpResponseMessage> GetRaw(
HttpClient client, string relativePath)
{
Assert.NotNull(client);
var request = new HttpRequestMessage(HttpMethod.Get, relativePath);
return await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
}
/// <summary>
/// Smoke assertion: a GET on <paramref name="relativePath"/>
/// returns 2xx (page served) or 3xx (redirect to login) or
/// 401/403 (anonymous rejected by [Authorize]). Anything else
/// — 404 (route missing), 5xx (server crash), connection
/// refused (host not started) — fails the test.
/// </summary>
protected static async Task AssertResponds(
HttpClient client, string relativePath)
{
var response = await GetRaw(client, relativePath);
var status = (int)response.StatusCode;
Assert.True(
status >= 200 && status < 400 || status == 401 || status == 403,
$"GET {relativePath} returned {status} {response.StatusCode}, " +
"expected 2xx/3xx (page or redirect) or 401/403 (auth required).");
}
// FIXME write a scenario from an empty database [Fact] // FIXME write a scenario from an empty database [Fact]
public void GitClone() public void GitClone()
{ {

View file

@ -69,6 +69,29 @@ namespace Yavsc.Org.Tests
} }
[Fact]
public async Task GetSignin_returns_a_page()
{
using var client = new HttpClient(new BypassSslValidationHandler())
{
BaseAddress = new Uri(this._serverFixture.HttpsAuthority ?? throw new InvalidOperationException("Missing HttpsAuthority"))
};
await AssertResponds(client, "/signin");
}
[Fact]
public async Task GetOpenIdConfiguration_returns_ok()
{
using var client = _serverFixture.CreateHttpClient();
var response = await GetRaw(client, "/.well-known/openid-configuration");
var payload = await response.Content.ReadAsStringAsync();
Assert.True(
response.IsSuccessStatusCode,
$"GET /.well-known/openid-configuration returned {(int)response.StatusCode} {response.StatusCode}. Body: {payload}");
}
public static IEnumerable<object[]> GetLoginIntentData() public static IEnumerable<object[]> GetLoginIntentData()
{ {
return new object[][] { new object[] { "testuser", "test" } }; return new object[][] { new object[] { "testuser", "test" } };
@ -124,4 +147,5 @@ namespace Yavsc.Org.Tests
return true; return true;
} }
} }
} }

View file

@ -18,7 +18,7 @@ namespace Yavsc.Org.Tests.Smoke;
/// entire pipeline (routing + Razor + IdentityServer + EF + DI) /// entire pipeline (routing + Razor + IdentityServer + EF + DI)
/// is wired correctly end-to-end. /// is wired correctly end-to-end.
/// </summary> /// </summary>
public class AccountSmokeTests : SmokeTestBase, IClassFixture<TestWebApplicationFactory> public class AccountSmokeTests : IClassFixture<TestWebApplicationFactory>
{ {
private readonly TestWebApplicationFactory _factory; private readonly TestWebApplicationFactory _factory;
@ -27,24 +27,7 @@ public class AccountSmokeTests : SmokeTestBase, IClassFixture<TestWebApplication
_factory = factory; _factory = factory;
} }
[Fact]
public async Task GetSignin_returns_a_page()
{
using var client = _factory.CreateClient();
await AssertResponds(client, "/signin");
}
[Fact]
public async Task GetOpenIdConfiguration_returns_ok()
{
using var client = _factory.CreateClient();
var response = await GetRaw(client, "/.well-known/openid-configuration");
var payload = await response.Content.ReadAsStringAsync();
Assert.True(
response.IsSuccessStatusCode,
$"GET /.well-known/openid-configuration returned {(int)response.StatusCode} {response.StatusCode}. Body: {payload}");
}
[Fact] [Fact]
public async Task ResourceStore_get_all_resources_does_not_throw() public async Task ResourceStore_get_all_resources_does_not_throw()

View file

@ -1,52 +0,0 @@
namespace Yavsc.Org.Tests.Smoke;
/// <summary>
/// Base for the smoke tests covering the production hosts
/// (Yavsc.Org / Yavsc.Api / Yavsc.Blogs). One smoke test per
/// bounded context (BC): each test hits one GET endpoint and
/// asserts a 2xx or 3xx status, with no follow-up redirect.
/// Together they satisfy the 'Tests d'intégration smoke par BC'
/// item of Jalon 0 in <c>ROADMAP.md</c>.
///
/// Status code policy:
/// - 200 OK : endpoint serves a page.
/// - 302 / 301 : endpoint requires auth and redirects to login
/// (acceptable smoke signal: routing + middleware are wired).
/// - 401 / 403 : endpoint exists but rejects anonymous (acceptable
/// for API smoke tests where the smoke is "the host boots").
/// Anything else (404, 500, connection refused) is a failure.
/// </summary>
public abstract class SmokeTestBase
{
/// <summary>
/// Issue a GET against <paramref name="relativePath"/> on the
/// in-memory test server. Returns the raw HttpResponseMessage
/// without following redirects — the test asserts on the first
/// hop, not the eventual page.
/// </summary>
protected static async Task<HttpResponseMessage> GetRaw(
HttpClient client, string relativePath)
{
Assert.NotNull(client);
var request = new HttpRequestMessage(HttpMethod.Get, relativePath);
return await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
}
/// <summary>
/// Smoke assertion: a GET on <paramref name="relativePath"/>
/// returns 2xx (page served) or 3xx (redirect to login) or
/// 401/403 (anonymous rejected by [Authorize]). Anything else
/// — 404 (route missing), 5xx (server crash), connection
/// refused (host not started) — fails the test.
/// </summary>
protected static async Task AssertResponds(
HttpClient client, string relativePath)
{
var response = await GetRaw(client, relativePath);
var status = (int)response.StatusCode;
Assert.True(
status >= 200 && status < 400 || status == 401 || status == 403,
$"GET {relativePath} returned {status} {response.StatusCode}, " +
"expected 2xx/3xx (page or redirect) or 401/403 (auth required).");
}
}

View file

@ -78,6 +78,7 @@ public sealed class WebServerFixture : WebHostFixture
public RecordingSmtpClientFactory? SmtpClientFactory { get; private set; } public RecordingSmtpClientFactory? SmtpClientFactory { get; private set; }
public ILogger? Logger { get; internal set; } public ILogger? Logger { get; internal set; }
public string? HttpsAuthority => Addresses.FirstOrDefault(u => u.StartsWith("https:"));
protected override WebApplication BuildApp(WebApplicationBuilder builder) protected override WebApplication BuildApp(WebApplicationBuilder builder)
{ {
var authority = $"https://localhost:{_httpsPort}"; var authority = $"https://localhost:{_httpsPort}";