using Xunit; using FluentAssertions; using NSubstitute; using System; using FreeCode.Core.Models; using FreeCode.Core.Enums; using CoreTaskStatus = FreeCode.Core.Enums.TaskStatus; namespace FreeCode.Tests.Unit.Models; public sealed class CompanionAndEnumTests { [Fact] public void Companion_HoldsConstructorValues() { var companion = new Companion(Species.Cat, Eye.Blue, Hat.Crown, Rarity.Legendary, "Mochi"); companion.Species.Should().Be(Species.Cat); companion.Eye.Should().Be(Eye.Blue); companion.Hat.Should().Be(Hat.Crown); companion.Rarity.Should().Be(Rarity.Legendary); companion.Name.Should().Be("Mochi"); } [Fact] public void Companion_UsesValueEquality() { var left = new Companion(Species.Fox, Eye.Gold, Hat.Cap, Rarity.Rare, "Nova"); var right = new Companion(Species.Fox, Eye.Gold, Hat.Cap, Rarity.Rare, "Nova"); left.Should().Be(right); } [Fact] public void Companion_IsNotEqualWhenNameDiffers() { var left = new Companion(Species.Fox, Eye.Gold, Hat.Cap, Rarity.Rare, "Nova"); var right = new Companion(Species.Fox, Eye.Gold, Hat.Cap, Rarity.Rare, "Luna"); left.Should().NotBe(right); } [Fact] public void Companion_AllowsEmptyName() { var companion = new Companion(Species.Owl, Eye.Green, Hat.None, Rarity.Common, string.Empty); companion.Name.Should().BeEmpty(); } [Fact] public void Companion_NameCanBeObservedThroughAConsumerSubstitute() { var companion = new Companion(Species.Dog, Eye.Red, Hat.Bowler, Rarity.Epic, "Pico"); var observer = new CompanionObserver(companion); observer.Current.Name.Should().Be("Pico"); } [Theory] [InlineData(Species.Cat)] [InlineData(Species.Dog)] [InlineData(Species.Fox)] [InlineData(Species.Owl)] public void Companion_SupportsEachSpecies(Species species) { var companion = new Companion(species, Eye.Blue, Hat.None, Rarity.Common, "Test"); companion.Species.Should().Be(species); } [Theory] [InlineData(Eye.Blue)] [InlineData(Eye.Green)] [InlineData(Eye.Gold)] [InlineData(Eye.Red)] public void Companion_SupportsEachEye(Eye eye) { var companion = new Companion(Species.Cat, eye, Hat.None, Rarity.Common, "Test"); companion.Eye.Should().Be(eye); } [Theory] [InlineData(Hat.None)] [InlineData(Hat.Bowler)] [InlineData(Hat.Cap)] [InlineData(Hat.Crown)] public void Companion_SupportsEachHat(Hat hat) { var companion = new Companion(Species.Cat, Eye.Blue, hat, Rarity.Common, "Test"); companion.Hat.Should().Be(hat); } [Theory] [InlineData(Rarity.Common)] [InlineData(Rarity.Uncommon)] [InlineData(Rarity.Rare)] [InlineData(Rarity.Epic)] [InlineData(Rarity.Legendary)] public void Companion_SupportsEachRarity(Rarity rarity) { var companion = new Companion(Species.Cat, Eye.Blue, Hat.None, rarity, "Test"); companion.Rarity.Should().Be(rarity); } [Theory] [InlineData(MessageRole.User, 0)] [InlineData(MessageRole.Assistant, 1)] [InlineData(MessageRole.System, 2)] [InlineData(MessageRole.Tool, 3)] public void MessageRole_EnumValues_AreStable(MessageRole value, int expected) { ((int)value).Should().Be(expected); } [Theory] [InlineData(PermissionMode.Default, 0)] [InlineData(PermissionMode.Plan, 1)] [InlineData(PermissionMode.AutoAccept, 2)] [InlineData(PermissionMode.BypassPermissions, 3)] public void PermissionMode_EnumValues_AreStable(PermissionMode value, int expected) { ((int)value).Should().Be(expected); } [Theory] [InlineData(ToolCategory.FileSystem, 0)] [InlineData(ToolCategory.Shell, 1)] [InlineData(ToolCategory.Agent, 2)] [InlineData(ToolCategory.Web, 3)] [InlineData(ToolCategory.Lsp, 4)] [InlineData(ToolCategory.Mcp, 5)] [InlineData(ToolCategory.UserInteraction, 6)] [InlineData(ToolCategory.Todo, 7)] [InlineData(ToolCategory.Task, 8)] [InlineData(ToolCategory.PlanMode, 9)] [InlineData(ToolCategory.AgentSwarm, 10)] [InlineData(ToolCategory.Worktree, 11)] [InlineData(ToolCategory.Config, 12)] public void ToolCategory_EnumValues_AreStable(ToolCategory value, int expected) { ((int)value).Should().Be(expected); } [Theory] [InlineData(ApiProviderType.Anthropic, 0)] [InlineData(ApiProviderType.OpenAICodex, 1)] [InlineData(ApiProviderType.AwsBedrock, 2)] [InlineData(ApiProviderType.GoogleVertex, 3)] [InlineData(ApiProviderType.AnthropicFoundry, 4)] public void ApiProviderType_EnumValues_AreStable(ApiProviderType value, int expected) { ((int)value).Should().Be(expected); } [Theory] [InlineData(CoreTaskStatus.Pending, 0)] [InlineData(CoreTaskStatus.Running, 1)] [InlineData(CoreTaskStatus.Completed, 2)] [InlineData(CoreTaskStatus.Failed, 3)] [InlineData(CoreTaskStatus.Stopped, 4)] public void TaskStatus_EnumValues_AreStable(CoreTaskStatus value, int expected) { ((int)value).Should().Be(expected); } [Theory] [InlineData(BridgeStatus.Idle, 0)] [InlineData(BridgeStatus.Registered, 1)] [InlineData(BridgeStatus.Attached, 2)] public void BridgeStatus_EnumValues_AreStable(BridgeStatus value, int expected) { ((int)value).Should().Be(expected); } [Theory] [InlineData(ConfigScope.Local, 0)] [InlineData(ConfigScope.User, 1)] [InlineData(ConfigScope.Project, 2)] [InlineData(ConfigScope.Dynamic, 3)] [InlineData(ConfigScope.Enterprise, 4)] [InlineData(ConfigScope.ClaudeAi, 5)] [InlineData(ConfigScope.Managed, 6)] public void ConfigScope_EnumValues_AreStable(ConfigScope value, int expected) { ((int)value).Should().Be(expected); } [Theory] [InlineData(BackgroundTaskType.LocalShell, 0)] [InlineData(BackgroundTaskType.LocalAgent, 1)] [InlineData(BackgroundTaskType.RemoteAgent, 2)] [InlineData(BackgroundTaskType.InProcessTeammate, 3)] [InlineData(BackgroundTaskType.LocalWorkflow, 4)] [InlineData(BackgroundTaskType.MonitorMcp, 5)] [InlineData(BackgroundTaskType.Dream, 6)] public void BackgroundTaskType_EnumValues_AreStable(BackgroundTaskType value, int expected) { ((int)value).Should().Be(expected); } [Theory] [InlineData(Species.Cat, 0)] [InlineData(Species.Dog, 1)] [InlineData(Species.Fox, 2)] [InlineData(Species.Owl, 3)] public void Species_EnumValues_AreStable(Species value, int expected) { ((int)value).Should().Be(expected); } [Theory] [InlineData(Eye.Blue, 0)] [InlineData(Eye.Green, 1)] [InlineData(Eye.Gold, 2)] [InlineData(Eye.Red, 3)] public void Eye_EnumValues_AreStable(Eye value, int expected) { ((int)value).Should().Be(expected); } [Theory] [InlineData(Hat.None, 0)] [InlineData(Hat.Bowler, 1)] [InlineData(Hat.Cap, 2)] [InlineData(Hat.Crown, 3)] public void Hat_EnumValues_AreStable(Hat value, int expected) { ((int)value).Should().Be(expected); } [Theory] [InlineData(Rarity.Common, 0)] [InlineData(Rarity.Uncommon, 1)] [InlineData(Rarity.Rare, 2)] [InlineData(Rarity.Epic, 3)] [InlineData(Rarity.Legendary, 4)] public void Rarity_EnumValues_AreStable(Rarity value, int expected) { ((int)value).Should().Be(expected); } public interface ICompanionObserver { Companion Current { get; } } private sealed class CompanionObserver(Companion current) : ICompanionObserver { public Companion Current { get; } = current; } }