using FluentAssertions; using FreeCode.Core.Enums; using FreeCode.Core.Interfaces; using FreeCode.Services; using FreeCode.Tests.Unit.Helpers; using Xunit; namespace FreeCode.Tests.Unit.Services; public sealed class PermissionEngineTests { private readonly PermissionEngine _sut = new(); [Fact] public async Task CheckAsync_DefaultMode_AllowsReadOnlyTools() { var context = CreateContext(PermissionMode.Default, isReadOnly: true); var result = await _sut.CheckAsync("Read", new object(), context); result.IsAllowed.Should().BeTrue(); result.Reason.Should().BeNull(); } [Fact] public async Task CheckAsync_DefaultMode_DeniesNonReadOnlyTools() { var context = CreateContext(PermissionMode.Default, isReadOnly: false); var result = await _sut.CheckAsync("Write", new object(), context); result.IsAllowed.Should().BeFalse(); result.Reason.Should().Contain("requires confirmation"); } [Fact] public async Task CheckAsync_PlanMode_AllowsReadOnlyTools() { var context = CreateContext(PermissionMode.Plan, isReadOnly: true); var result = await _sut.CheckAsync("Read", new object(), context); result.IsAllowed.Should().BeTrue(); result.Reason.Should().BeNull(); } [Fact] public async Task CheckAsync_PlanMode_DeniesNonReadOnlyToolsWithReason() { var context = CreateContext(PermissionMode.Plan, isReadOnly: false); var result = await _sut.CheckAsync("Edit", new object(), context); result.IsAllowed.Should().BeFalse(); result.Reason.Should().Be("Tool 'Edit' is not allowed in plan mode."); } [Fact] public async Task CheckAsync_AutoAccept_AllowsAllTools() { var context = CreateContext(PermissionMode.AutoAccept, isReadOnly: false); var result = await _sut.CheckAsync("Bash", new object(), context); result.IsAllowed.Should().BeTrue(); } [Fact] public async Task CheckAsync_BypassPermissions_AllowsAllTools() { var context = CreateContext(PermissionMode.BypassPermissions, isReadOnly: false); var result = await _sut.CheckAsync("Bash", new object(), context); result.IsAllowed.Should().BeTrue(); } private static FreeCode.Core.Models.ToolExecutionContext CreateContext(PermissionMode mode, bool isReadOnly) { var tool = new StubTool { ReadOnlyFactory = _ => isReadOnly }; var services = new SimpleServiceProvider().AddService(typeof(ITool), tool); return TestHelper.CreateContext(permissionMode: mode, services: services); } }