应文浩wenhao.ying@xiaobao100.com bce2612b64 feat: 完善具体实现
2026-04-06 15:25:34 +08:00

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));
}
}