An ATProto Lexicon validator for Gleam.
1import gleam/json
2import gleeunit
3import gleeunit/should
4import honk/validation/context
5import honk/validation/primary/subscription
6
7pub fn main() {
8 gleeunit.main()
9}
10
11// Test valid subscription parameters
12pub fn valid_subscription_parameters_test() {
13 let schema =
14 json.object([
15 #("type", json.string("subscription")),
16 #(
17 "parameters",
18 json.object([
19 #("type", json.string("params")),
20 #(
21 "properties",
22 json.object([
23 #("cursor", json.object([#("type", json.string("integer"))])),
24 ]),
25 ),
26 ]),
27 ),
28 ])
29
30 let data = json.object([#("cursor", json.int(12_345))])
31
32 let assert Ok(ctx) = context.builder() |> context.build()
33 subscription.validate_data(data, schema, ctx) |> should.be_ok
34}
35
36// Test invalid: missing required parameter
37pub fn invalid_subscription_missing_required_test() {
38 let schema =
39 json.object([
40 #("type", json.string("subscription")),
41 #(
42 "parameters",
43 json.object([
44 #("type", json.string("params")),
45 #(
46 "properties",
47 json.object([
48 #("collection", json.object([#("type", json.string("string"))])),
49 ]),
50 ),
51 #("required", json.array([json.string("collection")], fn(x) { x })),
52 ]),
53 ),
54 ])
55
56 let data = json.object([])
57
58 let assert Ok(ctx) = context.builder() |> context.build()
59 subscription.validate_data(data, schema, ctx) |> should.be_error
60}
61
62// Test valid subscription with no parameters
63pub fn valid_subscription_no_parameters_test() {
64 let schema = json.object([#("type", json.string("subscription"))])
65
66 let data = json.object([])
67
68 let assert Ok(ctx) = context.builder() |> context.build()
69 subscription.validate_data(data, schema, ctx) |> should.be_ok
70}
71
72// Test invalid: parameters not an object
73pub fn invalid_subscription_not_object_test() {
74 let schema =
75 json.object([
76 #("type", json.string("subscription")),
77 #(
78 "parameters",
79 json.object([
80 #("type", json.string("params")),
81 #("properties", json.object([])),
82 ]),
83 ),
84 ])
85
86 let data = json.array([], fn(x) { x })
87
88 let assert Ok(ctx) = context.builder() |> context.build()
89 subscription.validate_data(data, schema, ctx) |> should.be_error
90}
91
92// Test message validation with union
93pub fn valid_subscription_message_test() {
94 let schema =
95 json.object([
96 #("type", json.string("subscription")),
97 #(
98 "message",
99 json.object([
100 #(
101 "schema",
102 json.object([
103 #("type", json.string("union")),
104 #(
105 "refs",
106 json.array(
107 [json.string("#commit"), json.string("#identity")],
108 fn(x) { x },
109 ),
110 ),
111 ]),
112 ),
113 ]),
114 ),
115 ])
116
117 let data = json.object([#("$type", json.string("#commit"))])
118
119 let assert Ok(ctx) = context.builder() |> context.build()
120 // This will likely fail due to missing definitions, but tests dispatch
121 case subscription.validate_message_data(data, schema, ctx) {
122 Ok(_) -> Ok(Nil)
123 Error(_) -> Ok(Nil)
124 }
125 |> should.be_ok
126}
127
128// Test parameter constraint violation
129pub fn invalid_subscription_constraint_violation_test() {
130 let schema =
131 json.object([
132 #("type", json.string("subscription")),
133 #(
134 "parameters",
135 json.object([
136 #("type", json.string("params")),
137 #(
138 "properties",
139 json.object([
140 #(
141 "limit",
142 json.object([
143 #("type", json.string("integer")),
144 #("maximum", json.int(100)),
145 ]),
146 ),
147 ]),
148 ),
149 ]),
150 ),
151 ])
152
153 let data = json.object([#("limit", json.int(200))])
154
155 let assert Ok(ctx) = context.builder() |> context.build()
156 subscription.validate_data(data, schema, ctx) |> should.be_error
157}
158
159// Test valid array parameter
160pub fn valid_subscription_array_parameter_test() {
161 let schema =
162 json.object([
163 #("type", json.string("subscription")),
164 #(
165 "parameters",
166 json.object([
167 #("type", json.string("params")),
168 #(
169 "properties",
170 json.object([
171 #(
172 "repos",
173 json.object([
174 #("type", json.string("array")),
175 #("items", json.object([#("type", json.string("string"))])),
176 ]),
177 ),
178 ]),
179 ),
180 ]),
181 ),
182 ])
183
184 let data =
185 json.object([
186 #(
187 "repos",
188 json.array(
189 [json.string("did:plc:abc"), json.string("did:plc:xyz")],
190 fn(x) { x },
191 ),
192 ),
193 ])
194
195 let assert Ok(ctx) = context.builder() |> context.build()
196 subscription.validate_data(data, schema, ctx) |> should.be_ok
197}