using System; using System.IO; namespace GmRelay.Bot.Tests.Discord; public sealed class DiscordProjectStructureTests { private static string GetRepoRoot() { var dir = AppContext.BaseDirectory; while (!string.IsNullOrEmpty(dir) && !File.Exists(Path.Combine(dir, "Directory.Build.props"))) { dir = Directory.GetParent(dir)?.FullName; } return dir ?? throw new InvalidOperationException("Could not find repo root"); } [Fact] public void Solution_ShouldIncludeDiscordWorkerProject() { var repoRoot = GetRepoRoot(); var solution = File.ReadAllText(Path.Combine(repoRoot, "GM-Relay.slnx")); Assert.Contains("src/GmRelay.DiscordBot/GmRelay.DiscordBot.csproj", solution); } [Fact] public void DiscordWorkerProject_ShouldExistWithoutTelegramDependency() { var repoRoot = GetRepoRoot(); var projectPath = Path.Combine(repoRoot, "src", "GmRelay.DiscordBot", "GmRelay.DiscordBot.csproj"); Assert.True(File.Exists(projectPath), "Discord worker project should exist."); var project = File.ReadAllText(projectPath); Assert.Contains("Microsoft.NET.Sdk.Worker", project); Assert.Contains("NetCord.Hosting", project); Assert.Contains("GmRelay.ServiceDefaults.csproj", project); Assert.Contains("GmRelay.Shared.csproj", project); Assert.DoesNotContain("Telegram.Bot", project); Assert.DoesNotContain("GmRelay.Bot.csproj", project); } [Fact] public void TelegramWorkerProject_ShouldNotReferenceNetCord() { var repoRoot = GetRepoRoot(); var project = File.ReadAllText(Path.Combine(repoRoot, "src", "GmRelay.Bot", "GmRelay.Bot.csproj")); Assert.DoesNotContain("NetCord", project, StringComparison.OrdinalIgnoreCase); } [Fact] public void RuntimeWiring_ShouldIncludeDiscordServiceWithoutCouplingTelegram() { var repoRoot = GetRepoRoot(); var compose = File.ReadAllText(Path.Combine(repoRoot, "compose.yaml")); var appHostProject = File.ReadAllText(Path.Combine(repoRoot, "src", "GmRelay.AppHost", "GmRelay.AppHost.csproj")); var appHostProgram = File.ReadAllText(Path.Combine(repoRoot, "src", "GmRelay.AppHost", "Program.cs")); var prChecks = File.ReadAllText(Path.Combine(repoRoot, ".gitea", "workflows", "pr-checks.yml")); var deploy = File.ReadAllText(Path.Combine(repoRoot, ".gitea", "workflows", "deploy.yml")); Assert.Contains("gmrelay-discord-bot:2.2.0", compose); Assert.Contains("Discord__Token=${DISCORD_BOT_TOKEN:?Set DISCORD_BOT_TOKEN in .env}", compose); Assert.Contains("src/GmRelay.DiscordBot/Dockerfile", deploy); Assert.Contains("DISCORD_BOT_TOKEN", deploy); Assert.Contains("dotnet build src/GmRelay.DiscordBot/GmRelay.DiscordBot.csproj --no-restore", prChecks); Assert.Contains("GmRelay.DiscordBot.csproj", appHostProject); Assert.Contains("Projects.GmRelay_DiscordBot", appHostProgram); } [Fact] public void Version_ShouldBeSynchronizedForDiscordFeatureRelease() { var repoRoot = GetRepoRoot(); Assert.Contains("2.2.0", File.ReadAllText(Path.Combine(repoRoot, "Directory.Build.props"))); Assert.Contains("VERSION: 2.2.0", File.ReadAllText(Path.Combine(repoRoot, ".gitea", "workflows", "deploy.yml"))); Assert.Contains("gmrelay-bot:2.2.0", File.ReadAllText(Path.Combine(repoRoot, "compose.yaml"))); Assert.Contains("gmrelay-web:2.2.0", File.ReadAllText(Path.Combine(repoRoot, "compose.yaml"))); Assert.Contains("gmrelay-discord-bot:2.2.0", File.ReadAllText(Path.Combine(repoRoot, "compose.yaml"))); Assert.Contains( "v2.2.0", File.ReadAllText(Path.Combine(repoRoot, "src", "GmRelay.Web", "Components", "Layout", "NavMenu.razor"))); } }