using System.Collections.ObjectModel; using System.Text; using System.Text.Json; using StevanFreeborn.Atproto.IdentityResolver.Json; namespace StevanFreeborn.Atproto.IdentityResolver.Tests.Unit; public sealed class StringToCollectionConverterTests { private readonly StringToCollectionConverter _converter = new(); private readonly JsonSerializerOptions _options = new(); private Collection? ReadJson(string json) { var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(json)); reader.Read(); return _converter.Read(ref reader, typeof(Collection), _options); } private string WriteJson(Collection value) { using var stream = new MemoryStream(); using var writer = new Utf8JsonWriter(stream); _converter.Write(writer, value, _options); return Encoding.UTF8.GetString(stream.ToArray()); } [Fact] public void Read_WhenJsonTokenIsNull_ItShouldReturnEmptyCollection() { var result = ReadJson("null"); result.Should().NotBeNull(); result.Should().BeEmpty(); } [Fact] public void Read_WhenJsonTokenIsString_ItShouldReturnCollectionWithSingleString() { var result = ReadJson("\"https://w3id.org/did/v1\""); result.Should().NotBeNull(); result.Should().ContainSingle().Which.Should().Be("https://w3id.org/did/v1"); } [Fact] public void Read_WhenJsonTokenIsEmptyString_ItShouldReturnCollectionWithEmptyString() { var result = ReadJson("\"\""); result.Should().NotBeNull(); result.Should().ContainSingle().Which.Should().Be(string.Empty); } [Fact] public void Read_WhenJsonTokenIsArrayOfStrings_ItShouldReturnCollectionWithAllStrings() { var result = ReadJson("[\"https://w3id.org/did/v1\",\"https://w3id.org/security/suites/ed25519-2020/v1\"]"); result.Should().NotBeNull(); result.Should().HaveCount(2); result.Should().ContainInOrder("https://w3id.org/did/v1", "https://w3id.org/security/suites/ed25519-2020/v1"); } [Fact] public void Read_WhenJsonTokenIsEmptyArray_ItShouldReturnEmptyCollection() { var result = ReadJson("[]"); result.Should().NotBeNull(); result.Should().BeEmpty(); } [Theory] [InlineData("123", "Number")] [InlineData("true", "True")] [InlineData("false", "False")] [InlineData("{\"key\":\"value\"}", "StartObject")] public void Read_WhenJsonTokenIsUnexpectedType_ItShouldThrowJsonException(string json, string expectedToken) { var act = () => ReadJson(json); var e = act.Should().Throw(); e.WithMessage($"Unexpected token type '{expectedToken}' when deserializing Collection."); } [Fact] public void Write_WhenCollectionContainsMultipleStrings_ItShouldSerializeAsJsonArray() { var collection = new Collection { "https://w3id.org/did/v1", "https://w3id.org/security/suites/ed25519-2020/v1" }; var json = WriteJson(collection); json.Should().Be("[\"https://w3id.org/did/v1\",\"https://w3id.org/security/suites/ed25519-2020/v1\"]"); } [Fact] public void Write_WhenCollectionContainsSingleString_ItShouldSerializeAsJsonArray() { var collection = new Collection { "https://w3id.org/did/v1" }; var json = WriteJson(collection); json.Should().Be("[\"https://w3id.org/did/v1\"]"); } [Fact] public void Write_WhenCollectionIsEmpty_ItShouldSerializeAsEmptyJsonArray() { var collection = new Collection(); var json = WriteJson(collection); json.Should().Be("[]"); } }