An ATProto Lexicon validator for Gleam.
at main 5.6 kB view raw
1import gleam/json 2import gleeunit 3import gleeunit/should 4import honk/validation/context 5import honk/validation/primary/procedure 6 7pub fn main() { 8 gleeunit.main() 9} 10 11// Test valid procedure input (object) 12pub fn valid_procedure_input_object_test() { 13 let schema = 14 json.object([ 15 #("type", json.string("procedure")), 16 #( 17 "input", 18 json.object([ 19 #("encoding", json.string("application/json")), 20 #( 21 "schema", 22 json.object([ 23 #("type", json.string("object")), 24 #("required", json.array([json.string("text")], fn(x) { x })), 25 #( 26 "properties", 27 json.object([ 28 #( 29 "text", 30 json.object([ 31 #("type", json.string("string")), 32 #("maxLength", json.int(300)), 33 ]), 34 ), 35 #( 36 "langs", 37 json.object([ 38 #("type", json.string("array")), 39 #( 40 "items", 41 json.object([#("type", json.string("string"))]), 42 ), 43 ]), 44 ), 45 ]), 46 ), 47 ]), 48 ), 49 ]), 50 ), 51 ]) 52 53 let data = 54 json.object([ 55 #("text", json.string("Hello world")), 56 #("langs", json.array([json.string("en")], fn(x) { x })), 57 ]) 58 59 let assert Ok(ctx) = context.builder() |> context.build() 60 procedure.validate_data(data, schema, ctx) |> should.be_ok 61} 62 63// Test invalid: missing required field 64pub fn invalid_procedure_missing_required_test() { 65 let schema = 66 json.object([ 67 #("type", json.string("procedure")), 68 #( 69 "input", 70 json.object([ 71 #("encoding", json.string("application/json")), 72 #( 73 "schema", 74 json.object([ 75 #("type", json.string("object")), 76 #("required", json.array([json.string("text")], fn(x) { x })), 77 #( 78 "properties", 79 json.object([ 80 #("text", json.object([#("type", json.string("string"))])), 81 ]), 82 ), 83 ]), 84 ), 85 ]), 86 ), 87 ]) 88 89 let data = json.object([#("description", json.string("No text field"))]) 90 91 let assert Ok(ctx) = context.builder() |> context.build() 92 procedure.validate_data(data, schema, ctx) |> should.be_error 93} 94 95// Test procedure with no input 96pub fn valid_procedure_no_input_test() { 97 let schema = json.object([#("type", json.string("procedure"))]) 98 99 let data = json.object([]) 100 101 let assert Ok(ctx) = context.builder() |> context.build() 102 procedure.validate_data(data, schema, ctx) |> should.be_ok 103} 104 105// Test valid output validation 106pub fn valid_procedure_output_test() { 107 let schema = 108 json.object([ 109 #("type", json.string("procedure")), 110 #( 111 "output", 112 json.object([ 113 #("encoding", json.string("application/json")), 114 #( 115 "schema", 116 json.object([ 117 #("type", json.string("object")), 118 #( 119 "properties", 120 json.object([ 121 #("uri", json.object([#("type", json.string("string"))])), 122 #("cid", json.object([#("type", json.string("string"))])), 123 ]), 124 ), 125 ]), 126 ), 127 ]), 128 ), 129 ]) 130 131 let data = 132 json.object([ 133 #("uri", json.string("at://did:plc:abc/app.bsky.feed.post/123")), 134 #("cid", json.string("bafyreiabc123")), 135 ]) 136 137 let assert Ok(ctx) = context.builder() |> context.build() 138 procedure.validate_output_data(data, schema, ctx) |> should.be_ok 139} 140 141// Test invalid output data 142pub fn invalid_procedure_output_wrong_type_test() { 143 let schema = 144 json.object([ 145 #("type", json.string("procedure")), 146 #( 147 "output", 148 json.object([ 149 #("encoding", json.string("application/json")), 150 #( 151 "schema", 152 json.object([ 153 #("type", json.string("object")), 154 #( 155 "properties", 156 json.object([ 157 #("count", json.object([#("type", json.string("integer"))])), 158 ]), 159 ), 160 ]), 161 ), 162 ]), 163 ), 164 ]) 165 166 let data = json.object([#("count", json.string("not-a-number"))]) 167 168 let assert Ok(ctx) = context.builder() |> context.build() 169 procedure.validate_output_data(data, schema, ctx) |> should.be_error 170} 171 172// Test procedure with union input 173pub fn valid_procedure_union_input_test() { 174 let schema = 175 json.object([ 176 #("type", json.string("procedure")), 177 #( 178 "input", 179 json.object([ 180 #("encoding", json.string("application/json")), 181 #( 182 "schema", 183 json.object([ 184 #("type", json.string("union")), 185 #( 186 "refs", 187 json.array( 188 [json.string("#typeA"), json.string("#typeB")], 189 fn(x) { x }, 190 ), 191 ), 192 ]), 193 ), 194 ]), 195 ), 196 ]) 197 198 let data = json.object([#("$type", json.string("#typeA"))]) 199 200 let assert Ok(ctx) = context.builder() |> context.build() 201 // This will fail because union needs the actual definitions 202 // but it tests that we're dispatching correctly 203 case procedure.validate_data(data, schema, ctx) { 204 Ok(_) -> Ok(Nil) 205 Error(_) -> Ok(Nil) 206 } 207 |> should.be_ok 208}