XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEWorkflow

【WinUI】XFE基于windows的工作流

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Text.Json;
using System.Text.Json.Nodes;
using XFEExtension.NetCore.XUnit.Assertions;
using XFEExtension.NetCore.XUnit.Attributes;
using XFEWorkflow.Abstractions;
using XFEWorkflow.Core.Runtime;
using XFEWorkflow.Infrastructure.Storage;

namespace XFEWorkflow.Test;

[TestFixture]
public sealed class ReadableJsonTests
{
    private const string Characters = "中文,。𠮷 🌚😀🐟 👨‍👩‍👧‍👦 👩🏽‍💻 👍🏽 🇨🇳 1️⃣ ❤️ é";

    [TestCase(false)]
    [TestCase(true)]
    public void DisplayKeepsChineseSupplementaryCharactersAndWholeEmojiSequences(bool indented)
    {
        var original = new JsonObject { [Characters] = Characters, ["array"] = new JsonArray(Characters, null, true, 12) };
        var text = original.Display(indented);
        Assert.Contains(Characters, text); Assert.False(text.Contains("\\u"));
        Assert.True(JsonNode.DeepEquals(original, JsonNode.Parse(text)));
        var serialized = WorkflowJson.SerializeDisplay(new { DisplayName = Characters }, indented);
        Assert.Contains(Characters, serialized); Assert.Equal(Characters, JsonNode.Parse(serialized)!["displayName"]!.GetValue<string>());
        Assert.Contains("\\u", JsonSerializer.Serialize(original, WorkflowJson.Options));
    }

    [Test]
    public void LiteralEscapeTextQuotesBackslashesAndControlsRoundTripWithoutUnescapingUserContent()
    {
        var values = new[] { @"\u4e2d", @"\uD83D\uDE00", @"\\u4e2d", @"\\\u4e2d", "\\🌚", "\\\\🌚", "\"引号😀\"\\路径", "\n\r\t\b\f\0\u001f", "\u007f\u0085", "<>&中文🌚" };
        foreach (var value in values)
        {
            var original = new JsonObject { [value] = value };
            var text = original.Display();
            Assert.True(JsonNode.DeepEquals(original, JsonNode.Parse(text)), text);
            Assert.Equal(value, JsonValue.Create(value).Text());
        }
        Assert.Equal("{\"literal\":\"\\\\u4e2d\"}", new JsonObject { ["literal"] = @"\u4e2d" }.Display());
        Assert.Contains("\\n", new JsonObject { ["line"] = "\n" }.Display());
    }

    [Test]
    public void TextAndConversionNodesUseReadableJsonWithoutChangingOriginalTextOrTypes()
    {
        var value = new JsonObject { ["name"] = Characters, ["literal"] = @"\u4e2d" };
        Assert.Contains(Characters, value.Text());
        foreach (var target in new[] { "string", "json" })
        {
            var converted = WorkflowConversions.Convert(value, target)!.GetValue<string>();
            Assert.Contains(Characters, converted); Assert.True(JsonNode.DeepEquals(value, JsonNode.Parse(converted)));
        }
        var literal = "  原文\n" + Characters + @" \uD83D\uDE00 $var ¥var  ";
        Assert.Equal(literal, WorkflowConversions.Convert(JsonValue.Create(literal), "string")!.GetValue<string>());
        Assert.Equal(literal, JsonNode.Parse(WorkflowConversions.Convert(JsonValue.Create(literal), "json")!.GetValue<string>())!.GetValue<string>());
        Assert.Equal("null", ((JsonNode?)null).Display()); Assert.Equal("", ((JsonNode?)null).Text());
        Assert.Equal("null", WorkflowConversions.Convert(null, "json")!.GetValue<string>());
    }

    [Test]
    public void ManagedSecretsAreRedactedInBothEscapedAndReadableJsonIncludingEmojiAndControls()
    {
        const string secret = "密钥🌚👩🏽‍💻\"\\\nvalue";
        var redactor = new SecretRedactor(); redactor.Add(secret);
        var payload = new JsonObject { ["nested"] = new JsonObject { ["secret"] = secret }, ["safe"] = Characters };
        foreach (var json in new[] { payload.ToJsonString(), payload.Display(), WorkflowJson.SerializeDisplay(payload) })
        {
            var redacted = JsonNode.Parse(redactor.Redact(json))!;
            Assert.Equal("***", redacted["nested"]!["secret"]!.GetValue<string>());
            Assert.Equal(Characters, redacted["safe"]!.GetValue<string>());
        }
        Assert.Equal("***", redactor.Redact(secret)); Assert.Equal(secret, payload["nested"]!["secret"]!.GetValue<string>());
    }

    [Test]
    public async Task JsonLogExportsKeepChineseEmojiMetadataAndLiteralEscapesInUtf8()
    {
        await using var workspace = new TestWorkspace();
        var entry = new WorkflowLogEntry { LogText = new JsonObject { ["name"] = Characters, ["literal"] = @"\u4e2d" }.Display(), WorkflowName = "工作流 " + Characters };
        var path = Path.Combine(workspace.Paths.Temp, "日志.json");
        await WorkflowLogExporter.ExportAsync(path, [entry], "json", false, new());
        var text = await File.ReadAllTextAsync(path); Assert.Contains(Characters, text); Assert.False(text.Contains("\\uD83"));
        var restored = JsonSerializer.Deserialize<List<WorkflowLogEntry>>(text, WorkflowJson.Options)!.Single();
        Assert.Equal(entry.LogText, restored.LogText); Assert.Equal(entry.WorkflowName, restored.WorkflowName);
        Assert.Equal(@"\u4e2d", JsonNode.Parse(restored.LogText)!["literal"]!.GetValue<string>());
    }
}