using FluentAssertions; using Workflow.Application.Form.Derivation; using Workflow.Application.Form.Relation; using Xunit; namespace BuildFlow.Workflow.Tests.Form; public class FormRelationActionTests { [Fact] public async Task DeriveAsync_WhitelistedAction_ExecutesRegisteredHandler() { var action = new ReserveCreditAction(); var service = new FormValueDerivationService([new SupplierResolver()], [action]); var instanceId = Guid.NewGuid(); await service.DeriveAsync( RelationActionSchema, """{"supplier":{"id":"supplier-1"}}""", new FormDerivationContext(null, instanceId, null), CancellationToken.None); action.Calls.Should().Be(1); action.LastContext!.InstanceId.Should().Be(instanceId); action.LastContext.SourceCode.Should().Be("supplier"); action.LastContext.ActionCode.Should().Be("reserveCredit"); } [Fact] public async Task DeriveAsync_WhitelistedAction_ThrowsWhenActionMissing() { var service = new FormValueDerivationService([new SupplierResolver()], []); var act = () => service.DeriveAsync( RelationActionSchema, """{"supplier":{"id":"supplier-1"}}""", new FormDerivationContext(null, Guid.NewGuid(), null), CancellationToken.None); await act.Should().ThrowAsync() .WithMessage("*关联动作*supplier:reserveCredit*未注册*"); } private sealed class ReserveCreditAction : IFormRelationActionHandler { public string SourceCode => "supplier"; public string ActionCode => "reserveCredit"; public int Calls { get; private set; } public FormRelationActionContext? LastContext { get; private set; } public Task ExecuteAsync(FormRelationActionContext context, CancellationToken ct) { Calls++; LastContext = context; return Task.CompletedTask; } } private sealed class SupplierResolver : IFormRelationResolver { public string SourceCode => "supplier"; public Task ResolveAsync( FormRelationResolveRequest request, CancellationToken ct) => Task.FromResult(new FormRelationResolveResult( request.Id, "华东供应商", new Dictionary { ["name"] = "华东供应商" })); } private const string RelationActionSchema = """ { "type": "object", "properties": { "supplier": { "type": "object", "title": "供应商", "x-component": "RelationPicker", "x-field-kind": "relation", "x-relation": { "sourceCode": "supplier", "idField": "id", "labelField": "name", "snapshotFields": ["name"], "updatePolicy": "whitelistedAction", "actionCode": "reserveCredit" } } } } """; }