103 lines
3.9 KiB
C#
103 lines
3.9 KiB
C#
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<ICommand>)).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<ICommand> commands, IAuthService? auth = null)
|
|
=> new SimpleServiceProvider()
|
|
.AddService(typeof(IEnumerable<ICommand>), 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<CommandResult> ExecuteAsync(CommandContext context, string? args = null, CancellationToken ct = default)
|
|
=> Task.FromResult(new CommandResult(true, name));
|
|
}
|
|
}
|