128 lines
4.5 KiB
C#
128 lines
4.5 KiB
C#
using FluentAssertions;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Workflow.Application.BuildFlow.Buttons.Commands;
|
||
using Workflow.Application.BuildFlow.Buttons.Handlers;
|
||
using Workflow.Application.BuildFlow.Buttons.Services;
|
||
using Workflow.Application.BuildFlow.CustomFunctions.Commands;
|
||
using Workflow.Application.BuildFlow.CustomFunctions.Handlers;
|
||
using Workflow.Application.BuildFlow.CustomFunctions.Services;
|
||
using Workflow.Domain.Entities;
|
||
using Workflow.Domain.Enums;
|
||
using Xunit;
|
||
|
||
namespace BuildFlow.Workflow.Tests.BuildFlow;
|
||
|
||
/// <summary>
|
||
/// 按钮动作链测试,约束按钮配置驱动后端动作执行,而不是前端写死行为。
|
||
/// </summary>
|
||
public class BuildFlowButtonActionTests
|
||
{
|
||
[Fact]
|
||
public async Task CreateButtonDefinition_PersistsActionMetadata()
|
||
{
|
||
await using var db = TestDbFactory.Create();
|
||
var handler = new CreateBuildFlowButtonDefinitionCommandHandler(db);
|
||
|
||
var button = await handler.Handle(
|
||
new CreateBuildFlowButtonDefinitionCommand(
|
||
null,
|
||
null,
|
||
null,
|
||
null,
|
||
"submit",
|
||
"提交",
|
||
"send",
|
||
BuildFlowButtonPlacement.FormToolbar,
|
||
"form:submit",
|
||
null,
|
||
null,
|
||
"""{"title":"确认提交?"}""",
|
||
"""[]""",
|
||
10),
|
||
CancellationToken.None);
|
||
|
||
button.Code.Should().Be("submit");
|
||
button.PermissionCode.Should().Be("form:submit");
|
||
button.Status.Should().Be(BuildFlowMetadataStatus.Draft);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task ExecuteAsync_RunFunctionAction_ReturnsFunctionResultAndWritesLog()
|
||
{
|
||
await using var db = TestDbFactory.Create();
|
||
var function = await CreatePublishedFunctionAsync(db);
|
||
var button = CreateButton(function.Id);
|
||
db.BuildFlowButtons.Add(button);
|
||
await db.SaveChangesAsync();
|
||
|
||
var executor = new BuildFlowButtonActionExecutor(
|
||
db,
|
||
new CustomFunctionExecutionService(db));
|
||
|
||
var result = await executor.ExecuteAsync(
|
||
button.Id,
|
||
"""{"amount":1200}""",
|
||
CancellationToken.None);
|
||
|
||
result.Success.Should().BeTrue();
|
||
result.Results.Should().ContainSingle().Which.ResultJson.Should().Be("\"high\"");
|
||
(await db.BuildFlowActionExecutionLogs.CountAsync()).Should().Be(1);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task ExecuteAsync_WhenActionFails_DoesNotPersistActionLog()
|
||
{
|
||
await using var db = TestDbFactory.Create();
|
||
var button = CreateButton(Guid.NewGuid());
|
||
db.BuildFlowButtons.Add(button);
|
||
await db.SaveChangesAsync();
|
||
|
||
var executor = new BuildFlowButtonActionExecutor(
|
||
db,
|
||
new CustomFunctionExecutionService(db));
|
||
|
||
var act = () => executor.ExecuteAsync(button.Id, "{}", CancellationToken.None);
|
||
|
||
await act.Should().ThrowAsync<BusinessException>();
|
||
(await db.BuildFlowActionExecutionLogs.CountAsync()).Should().Be(0);
|
||
}
|
||
|
||
private static async Task<CustomFunction> CreatePublishedFunctionAsync(WorkflowDbContext db)
|
||
{
|
||
var createHandler = new CreateCustomFunctionCommandHandler(db);
|
||
var publishHandler = new PublishCustomFunctionCommandHandler(db);
|
||
var function = await createHandler.Handle(
|
||
new CreateCustomFunctionCommand(
|
||
"button-amount-level",
|
||
"按钮金额分级",
|
||
null,
|
||
"((System.Text.Json.JsonElement)Variables[\"amount\"]).GetDecimal() > 1000 ? \"high\" : \"normal\"",
|
||
null,
|
||
null,
|
||
5000),
|
||
CancellationToken.None);
|
||
await publishHandler.Handle(new PublishCustomFunctionCommand(function.Id), CancellationToken.None);
|
||
return await db.CustomFunctions.FindAsync(function.Id) ?? throw new InvalidOperationException();
|
||
}
|
||
|
||
private static BuildFlowButtonDefinition CreateButton(Guid functionId)
|
||
=> new()
|
||
{
|
||
Id = Guid.NewGuid(),
|
||
Code = "submit-and-run",
|
||
Label = "提交并计算",
|
||
Placement = BuildFlowButtonPlacement.FormToolbar,
|
||
Status = BuildFlowMetadataStatus.Published,
|
||
ActionsJson = $$"""
|
||
[
|
||
{
|
||
"type": "runFunction",
|
||
"target": "{{functionId}}",
|
||
"params": { "amount": "$input.amount" },
|
||
"runPolicy": "stopOnFailure"
|
||
}
|
||
]
|
||
""",
|
||
};
|
||
}
|