using Xunit; using FluentAssertions; using NSubstitute; using FreeCode.Commands; using FreeCode.Core.Enums; using FreeCode.Core.Interfaces; using FreeCode.Core.Models; using FreeCode.Tests.Unit.Helpers; namespace FreeCode.Tests.Unit.Commands; public sealed class CommandRegistryTests { [Fact] public async Task GetCommandsAsync_ReturnsRegisteredCommandsSortedByCategoryThenName() { var registry = new CommandRegistry(CreateServices([ new TestCommand("zeta", CommandCategory.Local), new TestCommand("alpha", CommandCategory.Prompt), new TestCommand("beta", CommandCategory.Prompt) ])); var commands = await registry.GetCommandsAsync(); commands.Select(x => x.Name).Should().Equal("alpha", "beta", "zeta"); } [Fact] public async Task GetCommandsAsync_CachesDiscoveredCommands() { var services = CreateServices([new TestCommand("alpha", CommandCategory.Prompt)]); var registry = new CommandRegistry(services); _ = await registry.GetCommandsAsync(); _ = await registry.GetCommandsAsync(); services.GetCallCount(typeof(IEnumerable)).Should().Be(1); } [Fact] public async Task GetEnabledCommandsAsync_FiltersDisabledCommands() { var registry = new CommandRegistry(CreateServices([ new TestCommand("enabled", CommandCategory.Prompt), new TestCommand("disabled", CommandCategory.Prompt, enabled: false) ])); var commands = await registry.GetEnabledCommandsAsync(); commands.Select(x => x.Name).Should().Equal("enabled"); } [Fact] public async Task GetEnabledCommandsAsync_ExcludesRequiresAuthCommandsWhenUnauthenticated() { var auth = new StubAuthService { IsAuthenticated = false }; var registry = new CommandRegistry(CreateServices([ new TestCommand("public", CommandCategory.Prompt), new TestCommand("private", CommandCategory.Prompt, availability: CommandAvailability.RequiresAuth) ], auth)); var commands = await registry.GetEnabledCommandsAsync(); commands.Select(x => x.Name).Should().Equal("public"); } [Fact] public async Task GetEnabledCommandsAsync_IncludesCommandsAllowedByAuthCapabilities() { var auth = new StubAuthService { IsAuthenticated = true, IsClaudeAiUser = true, IsInternalUser = true }; var registry = new CommandRegistry(CreateServices([ new TestCommand("auth", CommandCategory.Prompt, availability: CommandAvailability.RequiresAuth), new TestCommand("claude", CommandCategory.Prompt, availability: CommandAvailability.ClaudeAiOnly), new TestCommand("internal", CommandCategory.Local, availability: CommandAvailability.InternalOnly) ], auth)); var commands = await registry.GetEnabledCommandsAsync(); commands.Select(x => x.Name).Should().Equal("auth", "claude", "internal"); } private static SimpleServiceProvider CreateServices(IEnumerable commands, IAuthService? auth = null) => new SimpleServiceProvider() .AddService(typeof(IEnumerable), commands.ToArray()) .AddService(typeof(IAuthService), auth); private sealed class TestCommand( string name, CommandCategory category, bool enabled = true, CommandAvailability availability = CommandAvailability.Always) : ICommand { public string Name => name; public string[]? Aliases => null; public string Description => name; public CommandCategory Category => category; public CommandAvailability Availability => availability; public bool IsEnabled() => enabled; public Task ExecuteAsync(CommandContext context, string? args = null, CancellationToken ct = default) => Task.FromResult(new CommandResult(true, name)); } }