build-flow.api/tests/BuildFlow.Workflow.Tests/Form/GetFormComponentManifestQueryHandlerTests.cs
xiangning 74e99850e5 feat(workflow): 添加钉钉式节点级字段权限和依次审批功能
- 实现钉钉式节点级字段权限:从审批节点config解析fieldPermissions进行表单校验
- 添加依次审批模式支持:按顺序逐个创建审批任务并推进流程
- 扩展工作流定义实体:新增DefinitionTree字段存储钉式审批流树JSON
- 更新表单验证器:支持节点级字段权限配置影响必填校验逻辑
- 重构后台服务:修复OperationCanceledException处理防止进程崩溃
- 扩展脚本执行服务:支持加载各模块Application/Domain程序集
- 更新菜单配置:调整组件管理和脚本函数菜单顺序
- 完善工作流引擎:修复实例图加载和任务完成逻辑
2026-07-17 17:05:35 +08:00

120 lines
4.5 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 FluentAssertions;
using Xunit;
using Workflow.Application.Form.ComponentRegistry.DTOs;
using Workflow.Application.Form.ComponentRegistry.Handlers;
using Workflow.Application.Form.ComponentRegistry.Queries;
using Workflow.Domain.Entities;
using Workflow.Infrastructure.Persistence;
namespace BuildFlow.Workflow.Tests.Form;
/// <summary>
/// manifest handler 单元测试:验证后端元数据驱动的物料清单查询逻辑
/// (分组、排序、IsActive 过滤、轻量投影不含 SupportedProps)。
/// </summary>
public class GetFormComponentManifestQueryHandlerTests
{
private static WorkflowDbContext CreateDb(params FormComponentRegistry[] seeds)
{
var db = TestDbFactory.Create();
if (seeds.Length > 0)
{
db.FormComponentRegistries.AddRange(seeds);
db.SaveChanges();
}
return db;
}
private static FormComponentRegistry Seed(
string name,
string category,
int sortOrder,
bool active = true,
string supportedProps = "{\"basic\":[]}") => new()
{
Id = Guid.NewGuid(),
Name = name,
DisplayName = name + "显示名",
Category = category,
Icon = "lucide:test",
DefaultSchema = "{}",
SupportedProps = supportedProps,
IsActive = active,
SortOrder = sortOrder,
};
[Fact]
public async Task Returns_Groups_By_Category_Sorted_By_SortOrder()
{
// 跨分类、乱序插入,验证分组聚合 + 组内/组间排序
var db = CreateDb(
Seed("Select", "选择控件", 2),
Seed("Input", "基础输入", 1),
Seed("RadioGroup", "选择控件", 1),
Seed("Textarea", "基础输入", 2)
);
var handler = new GetFormComponentManifestQueryHandler(db);
var result = await handler.Handle(new GetFormComponentManifestQuery(), default);
// 分组顺序:基础输入(sortOrder min=1) 在 选择控件(min=1) 之前?同 min 时按出现稳定顺序
// 基础输入组内最小 sortOrder=1,选择控件组内最小=1,两者相等,稳定排序保持插入顺序
result.Groups.Should().HaveCount(2);
var basic = result.Groups.First(g => g.Title == "基础输入");
basic.Items.Select(i => i.Name).Should().Equal(["Input", "Textarea"]);
var select = result.Groups.First(g => g.Title == "选择控件");
select.Items.Select(i => i.Name).Should().Equal(["RadioGroup", "Select"]);
}
[Fact]
public async Task Filters_Out_Inactive_Components()
{
var db = CreateDb(
Seed("Input", "基础输入", 1, active: true),
Seed("Hidden", "基础输入", 2, active: false)
);
var handler = new GetFormComponentManifestQueryHandler(db);
var result = await handler.Handle(new GetFormComponentManifestQuery(), default);
result.Groups.Should().ContainSingle();
result.Groups[0].Items.Should().ContainSingle();
result.Groups[0].Items[0].Name.Should().Be("Input");
}
[Fact]
public async Task Projection_Excludes_SupportedProps()
{
// manifest 是轻量接口:物料面板不需要 SupportedProps(那是属性面板用的全量接口的职责)
var db = CreateDb(
Seed("Input", "基础输入", 1, supportedProps: "{\"basic\":[{\"key\":\"placeholder\"}]}")
);
var handler = new GetFormComponentManifestQueryHandler(db);
var result = await handler.Handle(new GetFormComponentManifestQuery(), default);
var item = result.Groups[0].Items[0];
// ComponentManifestItem 只应有这 6 个字段,不含 SupportedProps
item.Name.Should().Be("Input");
item.DisplayName.Should().Be("Input显示名");
item.Category.Should().Be("基础输入");
item.Icon.Should().Be("lucide:test");
item.DefaultSchema.Should().Be("{}");
item.SortOrder.Should().Be(1);
// 确认 DTO 类型本身没有 SupportedProps 字段(编译期保证,运行期额外断言属性集)
item.GetType().GetProperties().Select(p => p.Name)
.Should().NotContain("SupportedProps");
}
[Fact]
public async Task Returns_Empty_When_No_Active_Components()
{
var db = CreateDb(Seed("Hidden", "x", 1, active: false));
var handler = new GetFormComponentManifestQueryHandler(db);
var result = await handler.Handle(new GetFormComponentManifestQuery(), default);
result.Groups.Should().BeEmpty();
}
}