namespace GmRelay.Bot.Tests.Web; public sealed class PortfolioSessionDeletionSourceTests { [Fact] public async Task SharedDeleteSessionHandler_ShouldUnpublishLinkedPortfolioCardBeforeDeletingSession() { var source = NormalizeSql(await ReadRepositoryFileAsync( "src/GmRelay.Shared/Features/Sessions/ListSessions/DeleteSessionHandler.cs")); const string unpublish = "UPDATE portfolio_games pg SET is_public = false, updated_at = now() FROM portfolio_game_sessions pgs WHERE pgs.portfolio_game_id = pg.id AND pgs.session_id = @SessionId AND pg.is_public = true"; Assert.Contains(unpublish, source, StringComparison.Ordinal); Assert.True( source.IndexOf(unpublish, StringComparison.Ordinal) < source.IndexOf("DELETE FROM sessions WHERE id = @Id", StringComparison.Ordinal), "Linked public portfolio cards must be unpublished before deleting the session."); } [Fact] public async Task DiscordDeleteSessionHandler_ShouldUnpublishOnlyCardsFromTheInteractionGuildBeforeDeletingSession() { var source = NormalizeSql(await ReadRepositoryFileAsync( "src/GmRelay.DiscordBot/Features/Sessions/DiscordDeleteSessionHandler.cs")); const string unpublish = "UPDATE portfolio_games pg SET is_public = false, updated_at = now() FROM portfolio_game_sessions pgs JOIN sessions s ON s.id = pgs.session_id JOIN game_groups g ON g.id = s.group_id WHERE pgs.portfolio_game_id = pg.id AND s.id = @SessionId AND g.platform = 'Discord' AND g.external_group_id = @GuildId AND pg.is_public = true"; Assert.Contains(unpublish, source, StringComparison.Ordinal); Assert.True( source.IndexOf(unpublish, StringComparison.Ordinal) < source.IndexOf("DELETE FROM sessions s", StringComparison.Ordinal), "Discord cards must be unpublished before deleting the session."); } private static string NormalizeSql(string sql) { return string.Join(' ', sql.Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries)) .Replace("( ", "(", StringComparison.Ordinal) .Replace(" )", ")", StringComparison.Ordinal); } private static async Task ReadRepositoryFileAsync(string relativePath) { var directory = new DirectoryInfo(AppContext.BaseDirectory); while (directory is not null) { var candidate = Path.Combine(directory.FullName, relativePath); if (File.Exists(candidate)) { return await File.ReadAllTextAsync(candidate); } directory = directory.Parent; } throw new FileNotFoundException($"Could not locate repository file '{relativePath}'."); } }