From 77faa3f5c6a63fc42c8f5637d3d25ef2e631e356 Mon Sep 17 00:00:00 2001 From: Hammond Date: Fri, 20 Mar 2026 21:29:16 +0700 Subject: [PATCH 1/2] fix(ci-tests): always enable fake email in integration host config --- .../PostgresWebApplicationFactory.cs | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/CleanArchitecture.IntegrationTests/Infrastructure/PostgresWebApplicationFactory.cs b/tests/CleanArchitecture.IntegrationTests/Infrastructure/PostgresWebApplicationFactory.cs index 8657a62..84689b8 100644 --- a/tests/CleanArchitecture.IntegrationTests/Infrastructure/PostgresWebApplicationFactory.cs +++ b/tests/CleanArchitecture.IntegrationTests/Infrastructure/PostgresWebApplicationFactory.cs @@ -34,21 +34,21 @@ public PostgresWebApplicationFactory() protected override void ConfigureWebHost(IWebHostBuilder builder) { - if (_useTestcontainers && TryEnsureContainer()) + builder.ConfigureAppConfiguration((context, config) => { - _connectionString = BuildConnectionString(_container!); + var settings = new Dictionary + { + ["EmailSettings:UseFakeEmail"] = "true" + }; - builder.ConfigureAppConfiguration((context, config) => + if (_useTestcontainers && TryEnsureContainer()) { - var settings = new Dictionary - { - ["ConnectionStrings:DefaultConnection"] = _connectionString, - ["EmailSettings:UseFakeEmail"] = "true" - }; - - config.AddInMemoryCollection(settings); - }); - } + _connectionString = BuildConnectionString(_container!); + settings["ConnectionStrings:DefaultConnection"] = _connectionString; + } + + config.AddInMemoryCollection(settings); + }); builder.ConfigureTestServices(services => { From e2ca3b9cb568813a6be9874eb971a39eb3aea60c Mon Sep 17 00:00:00 2001 From: Hammond Date: Fri, 20 Mar 2026 22:20:09 +0700 Subject: [PATCH 2/2] fix(tests): make fake-email token extraction resilient in integration suite --- .../Controllers/IdentityIntegrationTests.cs | 20 ++++++++++++++++++- .../AuthenticationTestHelper.cs | 20 ++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/tests/CleanArchitecture.IntegrationTests/Controllers/IdentityIntegrationTests.cs b/tests/CleanArchitecture.IntegrationTests/Controllers/IdentityIntegrationTests.cs index f26952f..1ff3177 100644 --- a/tests/CleanArchitecture.IntegrationTests/Controllers/IdentityIntegrationTests.cs +++ b/tests/CleanArchitecture.IntegrationTests/Controllers/IdentityIntegrationTests.cs @@ -5,6 +5,7 @@ using System.Text.RegularExpressions; using FluentAssertions; using CleanArchitecture.IntegrationTests.Infrastructure; +using Identity.Application.Services; using Identity.Infrastructure.Services; using Microsoft.AspNetCore.WebUtilities; @@ -49,7 +50,7 @@ private static AuthPayload ExtractAuthPayload(string jsonContent) private static (string userId, string token) ExtractUserIdAndTokenFromLastEmail(string recipient) { - var message = FakeEmailService.GetLastMessage(recipient); + var message = WaitForLastMessage(recipient, timeoutMs: 3000, pollMs: 100); message.Should().NotBeNull("Expected an email to be sent"); var link = ExtractFirstLink(message!.TextBody); @@ -65,6 +66,23 @@ private static (string userId, string token) ExtractUserIdAndTokenFromLastEmail( return (userId, token); } + private static EmailMessage? WaitForLastMessage(string recipient, int timeoutMs, int pollMs) + { + var start = DateTime.UtcNow; + while ((DateTime.UtcNow - start).TotalMilliseconds < timeoutMs) + { + var message = FakeEmailService.GetLastMessage(recipient); + if (message != null) + { + return message; + } + + Thread.Sleep(pollMs); + } + + return null; + } + private static string ExtractFirstLink(string text) { var match = Regex.Match(text, @"https?://\S+"); diff --git a/tests/CleanArchitecture.IntegrationTests/Infrastructure/AuthenticationTestHelper.cs b/tests/CleanArchitecture.IntegrationTests/Infrastructure/AuthenticationTestHelper.cs index 8db8c87..68ee96b 100644 --- a/tests/CleanArchitecture.IntegrationTests/Infrastructure/AuthenticationTestHelper.cs +++ b/tests/CleanArchitecture.IntegrationTests/Infrastructure/AuthenticationTestHelper.cs @@ -3,6 +3,7 @@ using System.Text.Json; using System.Text.RegularExpressions; using FluentAssertions; +using Identity.Application.Services; using Identity.Infrastructure.Services; using Microsoft.AspNetCore.WebUtilities; @@ -69,7 +70,7 @@ public static async Task AuthenticateAsync(HttpClient client) private static (string userId, string token) ExtractUserIdAndTokenFromLastEmail(string recipient) { - var message = FakeEmailService.GetLastMessage(recipient); + var message = WaitForLastMessage(recipient, timeoutMs: 3000, pollMs: 100); message.Should().NotBeNull("Expected an email to be sent"); var link = ExtractFirstLink(message!.TextBody); @@ -85,6 +86,23 @@ private static (string userId, string token) ExtractUserIdAndTokenFromLastEmail( return (userId, token); } + private static EmailMessage? WaitForLastMessage(string recipient, int timeoutMs, int pollMs) + { + var start = DateTime.UtcNow; + while ((DateTime.UtcNow - start).TotalMilliseconds < timeoutMs) + { + var message = FakeEmailService.GetLastMessage(recipient); + if (message != null) + { + return message; + } + + Thread.Sleep(pollMs); + } + + return null; + } + private static string ExtractFirstLink(string text) { var match = Regex.Match(text, @"https?://\S+");