- 实现钉钉式节点级字段权限:从审批节点config解析fieldPermissions进行表单校验 - 添加依次审批模式支持:按顺序逐个创建审批任务并推进流程 - 扩展工作流定义实体:新增DefinitionTree字段存储钉式审批流树JSON - 更新表单验证器:支持节点级字段权限配置影响必填校验逻辑 - 重构后台服务:修复OperationCanceledException处理防止进程崩溃 - 扩展脚本执行服务:支持加载各模块Application/Domain程序集 - 更新菜单配置:调整组件管理和脚本函数菜单顺序 - 完善工作流引擎:修复实例图加载和任务完成逻辑
120 lines
4.5 KiB
C#
120 lines
4.5 KiB
C#
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();
|
||
}
|
||
}
|