using System.Text.Json; using Xunit; namespace Admin.NET.Plugin.AiDOP.Tests.S8; /// /// S8NotificationLogQueryService.MapToDto payload 解析契约(S8-NOTIFY-AUDIT-LOG-API-1) /// MapToDto 是 private;此处复刻相同解析逻辑作等价契约测试。 /// public class S8NotificationLogPayloadParseTests { private static (bool? success, bool? recovered, int? targetCount, string? error) ParsePayload(string? payload) { if (string.IsNullOrWhiteSpace(payload)) return (null, null, null, null); try { using var doc = JsonDocument.Parse(payload); var root = doc.RootElement; bool? success = null; if (root.TryGetProperty("success", out var sv) && (sv.ValueKind == JsonValueKind.True || sv.ValueKind == JsonValueKind.False)) success = sv.GetBoolean(); bool? recovered = null; if (root.TryGetProperty("recovered", out var rv) && (rv.ValueKind == JsonValueKind.True || rv.ValueKind == JsonValueKind.False)) recovered = rv.GetBoolean(); int? targetCount = null; if (root.TryGetProperty("targetCount", out var tc) && tc.ValueKind == JsonValueKind.Number) targetCount = tc.GetInt32(); string? error = null; if (root.TryGetProperty("error", out var ev) && ev.ValueKind == JsonValueKind.String) error = ev.GetString(); return (success, recovered, targetCount, error); } catch { return (null, null, null, null); } } [Fact] public void CreatedPayload_ParsesAllFields() { var json = "{\"title\":\"T\",\"recovered\":false,\"success\":true,\"targetCount\":3,\"error\":null}"; var (success, recovered, targetCount, error) = ParsePayload(json); Assert.True(success); Assert.False(recovered); Assert.Equal(3, targetCount); Assert.Null(error); } [Fact] public void RecoveredPayload_RecoveredTrue() { var json = "{\"recovered\":true,\"success\":true,\"targetCount\":1,\"error\":null}"; var (success, recovered, targetCount, _) = ParsePayload(json); Assert.True(success); Assert.True(recovered); Assert.Equal(1, targetCount); } [Fact] public void FailedPush_SuccessFalse_ErrorPresent() { var json = "{\"recovered\":false,\"success\":false,\"targetCount\":0,\"error\":\"channel_disabled_by_config\"}"; var (success, recovered, _, error) = ParsePayload(json); Assert.False(success); Assert.False(recovered); Assert.Equal("channel_disabled_by_config", error); } [Fact] public void NullPayload_ReturnsAllNull() { var (success, recovered, targetCount, error) = ParsePayload(null); Assert.Null(success); Assert.Null(recovered); Assert.Null(targetCount); Assert.Null(error); } [Fact] public void InvalidJson_ReturnsAllNull_NoBoomNoThrow() { var (success, recovered, targetCount, error) = ParsePayload("not-json{{{"); Assert.Null(success); Assert.Null(recovered); Assert.Null(targetCount); Assert.Null(error); } [Fact] public void TruncatedPayload_ReturnsAllNull() { var (success, recovered, targetCount, error) = ParsePayload("{\"recovered\":true,\"success\":tru..."); Assert.Null(success); Assert.Null(recovered); Assert.Null(targetCount); Assert.Null(error); } }