iOS client for Grain
grain.social
ios
photography
atproto
1@testable import Grain
2import XCTest
3
4final class FacetCodingTests: XCTestCase {
5 private let decoder = JSONDecoder()
6 private let encoder = JSONEncoder()
7
8 // MARK: - Decoding
9
10 func testDecodeMention() throws {
11 let json = Data("""
12 {"$type": "app.bsky.richtext.facet#mention", "did": "did:plc:abc123"}
13 """.utf8)
14 let feature = try decoder.decode(FacetFeature.self, from: json)
15 if case let .mention(did) = feature {
16 XCTAssertEqual(did, "did:plc:abc123")
17 } else {
18 XCTFail("Expected mention, got \(feature)")
19 }
20 }
21
22 func testDecodeLink() throws {
23 let json = Data("""
24 {"$type": "app.bsky.richtext.facet#link", "uri": "https://example.com"}
25 """.utf8)
26 let feature = try decoder.decode(FacetFeature.self, from: json)
27 if case let .link(uri) = feature {
28 XCTAssertEqual(uri, "https://example.com")
29 } else {
30 XCTFail("Expected link, got \(feature)")
31 }
32 }
33
34 func testDecodeTag() throws {
35 let json = Data("""
36 {"$type": "app.bsky.richtext.facet#tag", "tag": "photography"}
37 """.utf8)
38 let feature = try decoder.decode(FacetFeature.self, from: json)
39 if case let .tag(tag) = feature {
40 XCTAssertEqual(tag, "photography")
41 } else {
42 XCTFail("Expected tag, got \(feature)")
43 }
44 }
45
46 func testDecodeUnknownTypeThrows() {
47 let json = Data("""
48 {"$type": "app.bsky.richtext.facet#unknown", "data": "stuff"}
49 """.utf8)
50 XCTAssertThrowsError(try decoder.decode(FacetFeature.self, from: json))
51 }
52
53 // MARK: - Encoding round-trips
54
55 func testMentionRoundTrip() throws {
56 let original = FacetFeature.mention(did: "did:plc:xyz")
57 let data = try encoder.encode(original)
58 let decoded = try decoder.decode(FacetFeature.self, from: data)
59 if case let .mention(did) = decoded {
60 XCTAssertEqual(did, "did:plc:xyz")
61 } else {
62 XCTFail("Round-trip failed")
63 }
64 }
65
66 func testLinkRoundTrip() throws {
67 let original = FacetFeature.link(uri: "https://grain.social")
68 let data = try encoder.encode(original)
69 let decoded = try decoder.decode(FacetFeature.self, from: data)
70 if case let .link(uri) = decoded {
71 XCTAssertEqual(uri, "https://grain.social")
72 } else {
73 XCTFail("Round-trip failed")
74 }
75 }
76
77 func testTagRoundTrip() throws {
78 let original = FacetFeature.tag(tag: "streetphoto")
79 let data = try encoder.encode(original)
80 let decoded = try decoder.decode(FacetFeature.self, from: data)
81 if case let .tag(tag) = decoded {
82 XCTAssertEqual(tag, "streetphoto")
83 } else {
84 XCTFail("Round-trip failed")
85 }
86 }
87
88 // MARK: - Full Facet
89
90 func testDecodeFacetWithFeatures() throws {
91 let json = Data("""
92 {
93 "index": {"byteStart": 0, "byteEnd": 10},
94 "features": [
95 {"$type": "app.bsky.richtext.facet#mention", "did": "did:plc:test"}
96 ]
97 }
98 """.utf8)
99 let facet = try decoder.decode(Facet.self, from: json)
100 XCTAssertEqual(facet.index.byteStart, 0)
101 XCTAssertEqual(facet.index.byteEnd, 10)
102 XCTAssertEqual(facet.features.count, 1)
103 }
104}