an atproto pds written in F# (.NET 9) 馃
pds
fsharp
giraffe
dotnet
atproto
1module PDSharp.Tests.Conformance
2
3open Xunit
4open System
5open System.Text.Json
6open PDSharp.Core
7
8module LexiconTests =
9
10 let parse (json : string) =
11 JsonSerializer.Deserialize<JsonElement>(json)
12
13 [<Fact>]
14 let ``Valid Post passes validation`` () =
15 let json =
16 """{
17 "$type": "app.bsky.feed.post",
18 "text": "Hello, world!",
19 "createdAt": "2023-10-27T10:00:00Z"
20 }"""
21
22 let element = parse json
23 let result = Lexicon.validate "app.bsky.feed.post" element
24 Assert.Equal(Lexicon.Ok, result)
25
26 [<Fact>]
27 let ``Post missing text fails validation`` () =
28 let json =
29 """{
30 "$type": "app.bsky.feed.post",
31 "createdAt": "2023-10-27T10:00:00Z"
32 }"""
33
34 let element = parse json
35 let result = Lexicon.validate "app.bsky.feed.post" element
36
37 match result with
38 | Lexicon.Error msg -> Assert.Contains("text", msg)
39 | _ -> Assert.Fail("Should have failed validation")
40
41 [<Fact>]
42 let ``Post text too long passes validation`` () =
43 let longText = String('a', 3001)
44
45 let template =
46 """{
47 "$type": "app.bsky.feed.post",
48 "text": "TEXT_PLACEHOLDER",
49 "createdAt": "2023-10-27T10:00:00Z"
50 }"""
51
52 let json = template.Replace("TEXT_PLACEHOLDER", longText)
53 let element = parse json
54 let result = Lexicon.validate "app.bsky.feed.post" element
55
56 match result with
57 | Lexicon.Error msg -> Assert.Contains("exceeds maximum length", msg)
58 | _ -> Assert.Fail("Should have failed validation")
59
60 [<Fact>]
61 let ``Valid Like passes validation`` () =
62 let json =
63 """{
64 "$type": "app.bsky.feed.like",
65 "subject": {
66 "uri": "at://did:plc:123/app.bsky.feed.post/3k5",
67 "cid": "bafyreih..."
68 },
69 "createdAt": "2023-10-27T10:00:00Z"
70 }"""
71
72 let element = parse json
73 let result = Lexicon.validate "app.bsky.feed.like" element
74 Assert.Equal(Lexicon.Ok, result)
75
76 [<Fact>]
77 let ``Like missing subject fails validation`` () =
78 let json =
79 """{
80 "$type": "app.bsky.feed.like",
81 "createdAt": "2023-10-27T10:00:00Z"
82 }"""
83
84 let element = parse json
85 let result = Lexicon.validate "app.bsky.feed.like" element
86
87 match result with
88 | Lexicon.Error msg -> Assert.Contains("subject", msg)
89 | _ -> Assert.Fail("Should have failed validation")
90
91 [<Fact>]
92 let ``Like subject missing uri passes validation (should fail)`` () =
93 let json =
94 """{
95 "$type": "app.bsky.feed.like",
96 "subject": {
97 "cid": "bafyreih..."
98 },
99 "createdAt": "2023-10-27T10:00:00Z"
100 }"""
101
102 let element = parse json
103 let result = Lexicon.validate "app.bsky.feed.like" element
104
105 match result with
106 | Lexicon.Error msg -> Assert.Contains("uri", msg)
107 | _ -> Assert.Fail("Should have failed validation")
108
109 [<Fact>]
110 let ``Valid Profile passes validation`` () =
111 let json =
112 """{
113 "$type": "app.bsky.actor.profile",
114 "displayName": "Alice",
115 "description": "Bob's friend"
116 }"""
117
118 let element = parse json
119 let result = Lexicon.validate "app.bsky.actor.profile" element
120 Assert.Equal(Lexicon.Ok, result)
121
122 [<Fact>]
123 let ``Profile description check length`` () =
124 let longDesc = String('a', 2561)
125
126 let template =
127 """{
128 "$type": "app.bsky.actor.profile",
129 "description": "DESC_PLACEHOLDER"
130 }"""
131
132 let json = template.Replace("DESC_PLACEHOLDER", longDesc)
133 let element = parse json
134 let result = Lexicon.validate "app.bsky.actor.profile" element
135
136 match result with
137 | Lexicon.Error msg -> Assert.Contains("exceeds maximum length", msg)
138 | _ -> Assert.Fail("Should have failed validation")
139
140 [<Fact>]
141 let ``Unknown type validation is lax`` () =
142 let json = """{ "random": "stuff" }"""
143 let element = parse json
144 let result = Lexicon.validate "com.unknown.record" element
145 Assert.Equal(Lexicon.Ok, result)