2026-07-24 08:57:03 +08:00

90 lines
2.9 KiB
C#

using BuildFlow.Shared.Domain.Errors;
using BuildFlow.Shared.Domain.Exceptions;
using FluentAssertions;
using System.Text.Json.Nodes;
using Workflow.Application.Form.Derivation;
using Workflow.Application.Form.Schema;
using Xunit;
namespace BuildFlow.Workflow.Tests.Performance;
/// <summary>
/// 预解析表单 Schema 在批量校验和派生中的复用测试。
/// </summary>
public class PreparedFormSchemaTests
{
[Fact]
public async Task PreparedSchemaCanBeReusedForValidationAndDerivation()
{
var prepared = PreparedFormSchema.Create(ComputedSchema);
var derivation = new FormValueDerivationService([], []);
var firstValidation = FormDataValidator.Validate(
prepared,
"""{"quantity":2,"unitPrice":10}""");
var first = await derivation.DeriveAsync(
prepared,
"""{"quantity":2,"unitPrice":10}""",
new FormDerivationContext(Guid.NewGuid(), Guid.NewGuid(), null),
CancellationToken.None);
var second = await derivation.DeriveAsync(
prepared,
"""{"quantity":3,"unitPrice":5}""",
new FormDerivationContext(Guid.NewGuid(), Guid.NewGuid(), null),
CancellationToken.None);
firstValidation.IsValid.Should().BeTrue();
ReadTotal(first.DataJson).Should().Be(20);
ReadTotal(second.DataJson).Should().Be(15);
prepared.Validation.Fields.Should().HaveCount(3);
}
[Fact]
public void InvalidSchemaCannotBePrepared()
{
var act = () => PreparedFormSchema.Create("""
{
"type": "object",
"properties": {
"supplier": {
"type": "object",
"x-component": "RelationPicker",
"x-field-kind": "relation",
"x-relation": { "idField": "id" }
}
}
}
""");
var exception = act.Should().Throw<BusinessException>().Which;
exception.Code.Should().Be(ErrorCode.InvalidParam);
}
private static decimal ReadTotal(string dataJson)
=> JsonNode.Parse(dataJson)!["total"]!.GetValue<decimal>();
private const string ComputedSchema = """
{
"type": "object",
"properties": {
"quantity": { "type": "number", "x-component": "InputNumber" },
"unitPrice": { "type": "number", "x-component": "InputNumber" },
"total": {
"type": "number",
"x-component": "InputNumber",
"x-field-kind": "computed",
"x-derived": {
"mode": "computed",
"writePolicy": "overwrite",
"expression": {
"operator": "multiply",
"left": { "type": "field", "path": "quantity" },
"right": { "type": "field", "path": "unitPrice" }
}
}
}
}
}
""";
}