191 lines
6.5 KiB
C#
191 lines
6.5 KiB
C#
using BuildFlow.Platform.Application.Permissions.Commands;
|
|
using BuildFlow.Platform.Application.Permissions.DTOs;
|
|
using BuildFlow.Platform.Application.Permissions.Handlers;
|
|
using BuildFlow.Platform.Application.Permissions.Queries;
|
|
using BuildFlow.Platform.Domain.Entities;
|
|
using BuildFlow.Platform.Infrastructure.Persistence;
|
|
using BuildFlow.Shared.Domain.Exceptions;
|
|
using FluentAssertions;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Xunit;
|
|
|
|
namespace BuildFlow.Platform.Tests.Permissions;
|
|
|
|
/// <summary>
|
|
/// [SOP-PLATFORM] 权限管理全 Handler 覆盖测试。
|
|
/// 覆盖:Create / Update / Delete / GetList / GetById / GetTree。
|
|
/// 飞书矩阵: platform/Permissions 子域(6 Handler 零覆盖→全补)
|
|
/// </summary>
|
|
public class PermissionHandlerTests
|
|
{
|
|
private static PlatformDbContext CreateDb([System.Runtime.CompilerServices.CallerMemberName] string name = "")
|
|
=> PlatformTestDb.CreateDbContext(name);
|
|
|
|
private static Permission NewPermission(string code, string? group = "TestGroup")
|
|
=> PlatformTestDb.WithAudit(new Permission
|
|
{
|
|
Name = $"权限_{code}",
|
|
Code = code,
|
|
Description = "desc",
|
|
Group = group
|
|
});
|
|
|
|
[Fact]
|
|
public async Task Create_Valid_ReturnsDto()
|
|
{
|
|
var db = CreateDb();
|
|
var handler = new CreatePermissionCommandHandler(db);
|
|
|
|
var result = await handler.Handle(
|
|
new CreatePermissionCommand("创建用户", "user:create", "描述", "UserManagement"),
|
|
CancellationToken.None);
|
|
|
|
result.Code.Should().Be("user:create");
|
|
result.Name.Should().Be("创建用户");
|
|
(await db.Permissions.CountAsync()).Should().Be(1);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Create_DuplicateCode_ThrowsBusiness()
|
|
{
|
|
var db = CreateDb();
|
|
db.Permissions.Add(NewPermission("user:create"));
|
|
await db.SaveChangesAsync();
|
|
var handler = new CreatePermissionCommandHandler(db);
|
|
|
|
var act = async () => await handler.Handle(
|
|
new CreatePermissionCommand("重复", "user:create", null, null), CancellationToken.None);
|
|
|
|
await act.Should().ThrowAsync<BusinessException>("Code 唯一,重复应拒绝");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Update_Existing_OverwritesNullableFields()
|
|
{
|
|
var db = CreateDb();
|
|
var p = NewPermission("user:read");
|
|
db.Permissions.Add(p);
|
|
await db.SaveChangesAsync();
|
|
var handler = new UpdatePermissionCommandHandler(db);
|
|
|
|
var result = await handler.Handle(
|
|
new UpdatePermissionCommand(p.Id, "新名称", "新描述", "NewGroup"), CancellationToken.None);
|
|
|
|
result.Name.Should().Be("新名称");
|
|
result.Description.Should().Be("新描述");
|
|
result.Group.Should().Be("NewGroup");
|
|
result.Code.Should().Be("user:read", "Code 不可改");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Update_NonExistent_ThrowsNotFound()
|
|
{
|
|
var db = CreateDb();
|
|
var handler = new UpdatePermissionCommandHandler(db);
|
|
|
|
var act = async () => await handler.Handle(
|
|
new UpdatePermissionCommand(Guid.NewGuid(), "x", null, null), CancellationToken.None);
|
|
|
|
await act.Should().ThrowAsync<NotFoundException>();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Delete_Existing_RemovesAndUnlinksRoles()
|
|
{
|
|
var db = CreateDb();
|
|
var p = NewPermission("user:delete");
|
|
var role = PlatformTestDb.WithAudit(new Role { Name = "Admin" });
|
|
var link = new RolePermission { Role = role, Permission = p };
|
|
db.Permissions.Add(p);
|
|
db.Roles.Add(role);
|
|
db.RolePermissions.Add(link);
|
|
await db.SaveChangesAsync();
|
|
var handler = new DeletePermissionCommandHandler(db);
|
|
|
|
await handler.Handle(new DeletePermissionCommand(p.Id), CancellationToken.None);
|
|
|
|
(await db.Permissions.AnyAsync(x => x.Id == p.Id)).Should().BeFalse("软删后不可见");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Delete_NonExistent_ThrowsNotFound()
|
|
{
|
|
var db = CreateDb();
|
|
var handler = new DeletePermissionCommandHandler(db);
|
|
|
|
var act = async () => await handler.Handle(new DeletePermissionCommand(Guid.NewGuid()), CancellationToken.None);
|
|
|
|
await act.Should().ThrowAsync<NotFoundException>();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetList_ReturnsAll()
|
|
{
|
|
var db = CreateDb();
|
|
db.Permissions.AddRange(NewPermission("p1"), NewPermission("p2"));
|
|
await db.SaveChangesAsync();
|
|
var handler = new GetPermissionListQueryHandler(db);
|
|
|
|
var result = await handler.Handle(new GetPermissionListQuery(), CancellationToken.None);
|
|
|
|
result.Should().HaveCount(2);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetById_Existing_ReturnsDto()
|
|
{
|
|
var db = CreateDb();
|
|
var p = NewPermission("user:read");
|
|
db.Permissions.Add(p);
|
|
await db.SaveChangesAsync();
|
|
var handler = new GetPermissionByIdQueryHandler(db);
|
|
|
|
var result = await handler.Handle(new GetPermissionByIdQuery(p.Id), CancellationToken.None);
|
|
|
|
result.Code.Should().Be("user:read");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetById_NonExistent_ThrowsNotFound()
|
|
{
|
|
var db = CreateDb();
|
|
var handler = new GetPermissionByIdQueryHandler(db);
|
|
|
|
var act = async () => await handler.Handle(new GetPermissionByIdQuery(Guid.NewGuid()), CancellationToken.None);
|
|
|
|
await act.Should().ThrowAsync<NotFoundException>();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetTree_GroupsByGroupField()
|
|
{
|
|
var db = CreateDb();
|
|
db.Permissions.AddRange(
|
|
NewPermission("a:1", "GroupA"),
|
|
NewPermission("a:2", "GroupA"),
|
|
NewPermission("b:1", "GroupB"));
|
|
await db.SaveChangesAsync();
|
|
var handler = new GetPermissionTreeQueryHandler(db);
|
|
|
|
var tree = await handler.Handle(new GetPermissionTreeQuery(), CancellationToken.None);
|
|
|
|
tree.Should().HaveCount(2);
|
|
tree.First(g => g.Group == "GroupA").Permissions.Should().HaveCount(2);
|
|
tree.First(g => g.Group == "GroupB").Permissions.Should().HaveCount(1);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetTree_NullGroup_GoesToUngrouped()
|
|
{
|
|
var db = CreateDb();
|
|
db.Permissions.Add(NewPermission("no:group", null));
|
|
await db.SaveChangesAsync();
|
|
var handler = new GetPermissionTreeQueryHandler(db);
|
|
|
|
var tree = await handler.Handle(new GetPermissionTreeQuery(), CancellationToken.None);
|
|
|
|
tree.Should().ContainSingle();
|
|
tree[0].Group.Should().Be("未分组");
|
|
}
|
|
}
|