xiangning 6c110b579a refactor(dependencies): 移除未使用的域实体引用
- 从文件模块的多部分上传处理器中移除未使用的实体引用
- 从即时通讯模块的群组成员处理器中移除未使用的实体引用
- 从RAG模块的AI模型配置中移除未使用的实体引用
- 从监控模块的告警规则配置中移除未使用的实体引用
- 从平台模块的角色权限处理器中移除未使用的实体引用
- 从脚本模块的执行日志实体引用中进行清理
- 从多个基础设施配置类中移除未使用的依赖项
- 优化测试文件中的导入声明,移除不必要的引用
2026-07-19 14:09:47 +08:00

173 lines
7.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using BuildFlow.Platform.Domain.Entities.Menu;
using BuildFlow.Platform.Application.Menus.Commands;
using BuildFlow.Platform.Application.Menus.Handlers;
using BuildFlow.Platform.Application.Menus.Queries;
using BuildFlow.Platform.Domain.Entities.Role;
using BuildFlow.Platform.Domain.Entities.User;
using BuildFlow.Platform.Domain.Entities.UserRole;
using BuildFlow.Platform.Domain.Enums;
using BuildFlow.Platform.Infrastructure.Persistence;
using BuildFlow.Shared.Domain.Exceptions;
using FluentAssertions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace BuildFlow.Platform.Tests.Menus;
/// <summary>
/// 菜单管理测试。约束菜单主键使用 int64,并保证拖拽排序按 long Id 落库。
/// </summary>
public class MenuSortTests
{
[Fact]
public void MenuIdentifier_ShouldUseInt64()
{
typeof(MenuEntity).GetProperty(nameof(MenuEntity.Id))!.PropertyType.Should().Be(typeof(long));
typeof(MenuEntity).GetProperty(nameof(MenuEntity.ParentId))!.PropertyType.Should().Be(typeof(long?));
}
public async Task SortMenusCommand_ShouldUpdateMenusByInt64Ids()
await using var db = BuildInMemoryDb();
db.Menus.AddRange(
BuildMenu(1, "root", null, 0),
BuildMenu(2, "child-a", 1, 0),
BuildMenu(3, "child-b", 1, 1));
await db.SaveChangesAsync();
var handler = new SortMenusCommandHandler(db);
var affected = await handler.Handle(
new SortMenusCommand(
[
new MenuSortItem(2, null, 1),
new MenuSortItem(3, null, 0),
]),
CancellationToken.None);
affected.Should().Be(2);
var childA = await db.Menus.SingleAsync(m => m.Id == 2);
var childB = await db.Menus.SingleAsync(m => m.Id == 3);
childA.ParentId.Should().BeNull();
childA.Order.Should().Be(1);
childB.ParentId.Should().BeNull();
childB.Order.Should().Be(0);
public async Task SortMenusCommand_ShouldRejectMovingMenuUnderDescendant()
BuildMenu(2, "child", 1, 0),
BuildMenu(3, "grand-child", 2, 0));
var act = () => handler.Handle(
new SortMenusCommand([new MenuSortItem(1, 3, 0)]),
await act.Should().ThrowAsync<BusinessException>()
.WithMessage("不能将菜单移动到自己的子菜单下面");
public async Task GetAllMenusQuery_ShouldExposeBuildFlowFormRuntimeMetadata()
var userId = Guid.NewGuid();
var roleId = Guid.NewGuid();
var formId = Guid.NewGuid();
db.Users.Add(new UserEntity
{
Id = userId,
Username = "admin",
Email = "admin@buildflow.local",
PasswordHash = "hash",
CreatedBy = "test",
UpdatedBy = "test",
OperatorIP = "127.0.0.1",
});
db.Roles.Add(new RoleEntity
Id = roleId,
Name = "Admin",
db.UserRoles.Add(new UserRoleEntity
UserId = userId,
RoleId = roleId,
db.Menus.Add(BuildMenu(
100,
"expense.request",
null,
0,
renderType: MenuRenderTypeEnum.BuildFlowForm,
formDefinitionId: formId,
runtimeViewMode: MenuRuntimeViewModeEnum.List));
var handler = new GetAllMenusQueryHandler(db);
var routes = await handler.Handle(new GetAllMenusQuery(userId.ToString()), CancellationToken.None);
var route = routes.Should().ContainSingle().Subject;
route.Component.Should().Be("/buildflow/runtime/index");
route.Meta.RenderType.Should().Be("BuildFlowForm");
route.Meta.FormDefinitionId.Should().Be(formId);
route.Meta.RuntimeViewMode.Should().Be("List");
public async Task GetAllMenusQuery_ShouldHideRestrictedMenuWithoutVisibleForbidden()
Username = "viewer",
Email = "viewer@buildflow.local",
Name = "Viewer",
db.Menus.Add(BuildMenu(200, "finance.expense", null, 0, authority: "Admin"));
routes.Should().BeEmpty();
public async Task GetAllMenusQuery_ShouldReturnForbiddenVisibleMenuOnlyForUnauthorizedUser()
var viewerId = Guid.NewGuid();
var adminId = Guid.NewGuid();
var viewerRoleId = Guid.NewGuid();
var adminRoleId = Guid.NewGuid();
db.Users.AddRange(
new UserEntity
{
Id = viewerId,
Username = "viewer",
Email = "viewer@buildflow.local",
PasswordHash = "hash",
CreatedBy = "test",
UpdatedBy = "test",
OperatorIP = "127.0.0.1",
},
Id = adminId,
Username = "admin",
Email = "admin@buildflow.local",
});
db.Roles.AddRange(
new RoleEntity
Id = viewerRoleId,
Name = "Viewer",
Id = adminRoleId,
Name = "Admin",
db.UserRoles.AddRange(
new UserRoleEntity
UserId = viewerId,
RoleId = viewerRoleId,
UserId = adminId,
RoleId = adminRoleId,
200,
"finance.expense",
authority: "Admin",
menuVisibleWithForbidden: true));
var viewerRoutes = await handler.Handle(new GetAllMenusQuery(viewerId.ToString()), CancellationToken.None);
var adminRoutes = await handler.Handle(new GetAllMenusQuery(adminId.ToString()), CancellationToken.None);
var viewerRoute = viewerRoutes.Should().ContainSingle().Subject;
viewerRoute.Meta.Authority.Should().Equal("Admin");
viewerRoute.Meta.MenuVisibleWithForbidden.Should().BeTrue();
var adminRoute = adminRoutes.Should().ContainSingle().Subject;
adminRoute.Meta.Authority.Should().Equal("Admin");
adminRoute.Meta.MenuVisibleWithForbidden.Should().BeNull();
private static PlatformDbContext BuildInMemoryDb()
var services = new ServiceCollection();
services.AddDbContext<PlatformDbContext>(o => o.UseInMemoryDatabase($"platform-menu-{Guid.NewGuid()}"));
return services.BuildServiceProvider().GetRequiredService<PlatformDbContext>();
private static MenuEntity BuildMenu(
long id,
string code,
long? parentId,
int order,
MenuRenderTypeEnum renderType = MenuRenderTypeEnum.Route,
Guid? formDefinitionId = null,
MenuRuntimeViewModeEnum runtimeViewMode = MenuRuntimeViewModeEnum.List,
string? authority = null,
bool menuVisibleWithForbidden = false)
=> new()
Id = id,
Code = code,
Name = code.Replace(".", "-", StringComparison.Ordinal),
Path = $"/{code}",
ParentId = parentId,
Title = code,
Order = order,
RenderType = renderType,
FormDefinitionId = formDefinitionId,
RuntimeViewMode = runtimeViewMode,
Authority = authority,
MenuVisibleWithForbidden = menuVisibleWithForbidden,
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow,
};
}