work-flow/tests/Workflow.Tests/Serialization/TimestampJsonConverterTests.cs
向宁 9f878286e7 feat: form versioning, notification center, scheduler and webhooks
- Add FormDefinitionVersion with compare/versions endpoints and schema differ
- Add Notification entity, endpoints and application features
- Add Scheduler (timeout) and WebhookDispatcher services
- Add FormDataValidator/FieldPermissionEvaluator/ReactionEvaluator
- Add workflow task mark-read, CC support and SystemUserContext
- Add EF migrations for form versions and notifications
- Add unit tests for form schema, notifications, scheduler and serialization
2026-06-14 15:03:11 +08:00

91 lines
3.4 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Text.Json;
using FluentAssertions;
using Workflow.Api.Serialization;
using Xunit;
namespace Workflow.Tests.Serialization;
/// <summary>
/// 验证统一数据规范DateTime / DateTimeOffset 序列化为 UTC 毫秒时间戳long
/// 这是第二期"后端数据规范统一"的核心契约 —— 后端只输出毫秒时间戳,时区/格式化交给前端。
/// </summary>
public class TimestampJsonConverterTests
{
private static JsonSerializerOptions BuildOptions() => new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Converters = { new TimestampDateTimeConverter(), new TimestampDateTimeOffsetConverter() }
};
private class SampleDto
{
public Guid Id { get; set; }
public DateTime CreatedAt { get; set; }
public DateTimeOffset? UpdatedAt { get; set; }
}
[Fact]
public void DateTime_serializes_to_millisecond_epoch_number()
{
// 固定时刻2026-06-14T03:30:00Z
var utc = new DateTime(2026, 6, 14, 3, 30, 0, DateTimeKind.Utc);
var expectedMs = new DateTimeOffset(utc, TimeSpan.Zero).ToUnixTimeMilliseconds();
var dto = new SampleDto { Id = Guid.NewGuid(), CreatedAt = utc };
var json = JsonSerializer.Serialize(dto, BuildOptions());
using var doc = JsonDocument.Parse(json);
doc.RootElement.GetProperty("createdAt").ValueKind.Should().Be(JsonValueKind.Number);
doc.RootElement.GetProperty("createdAt").GetInt64().Should().Be(expectedMs);
}
[Fact]
public void DateTimeOffset_serializes_to_millisecond_epoch_number()
{
var dto = new DateTimeOffset(2026, 1, 2, 3, 4, 5, TimeSpan.Zero);
var expectedMs = dto.ToUnixTimeMilliseconds();
var json = JsonSerializer.Serialize(new { t = dto }, BuildOptions());
using var doc = JsonDocument.Parse(json);
doc.RootElement.GetProperty("t").GetInt64().Should().Be(expectedMs);
}
[Fact]
public void Guid_serializes_as_string()
{
// 验证 ID 统一为字符串Guid 天然序列化为字符串,无需额外转换器)
var id = Guid.NewGuid();
var dto = new SampleDto { Id = id };
var json = JsonSerializer.Serialize(dto, BuildOptions());
using var doc = JsonDocument.Parse(json);
doc.RootElement.GetProperty("id").ValueKind.Should().Be(JsonValueKind.String);
doc.RootElement.GetProperty("id").GetGuid().Should().Be(id);
}
[Fact]
public void Deserializes_epoch_number_back_to_utc_dateTime()
{
var utc = new DateTime(2026, 6, 14, 3, 30, 0, DateTimeKind.Utc);
var ms = new DateTimeOffset(utc, TimeSpan.Zero).ToUnixTimeMilliseconds();
var json = $$"""{"id":"00000000-0000-0000-0000-000000000000","createdAt":{{ms}}}""";
var dto = JsonSerializer.Deserialize<SampleDto>(json, BuildOptions())!;
dto.CreatedAt.Should().Be(utc);
dto.CreatedAt.Kind.Should().Be(DateTimeKind.Utc);
}
[Fact]
public void Deserializes_legacy_iso_string_for_backward_compatibility()
{
// 旧客户端/旧数据可能仍是 ISO 字符串,必须能读回(向后兼容)
var json = """{"id":"00000000-0000-0000-0000-000000000000","createdAt":"2026-06-14T03:30:00Z"}""";
var dto = JsonSerializer.Deserialize<SampleDto>(json, BuildOptions())!;
dto.CreatedAt.Should().Be(new DateTime(2026, 6, 14, 3, 30, 0, DateTimeKind.Utc));
}
}