Auto-indexing service and GraphQL API for AT Protocol Records quickslice.slices.network/
atproto gleam graphql
at main 201 lines 5.1 kB view raw
1/// Tests for GraphQL-WS protocol implementation 2/// 3/// Tests the GraphQL-WS (WebSocket) protocol message handling 4import gleam/dict 5import gleam/option.{Some} 6import gleeunit 7import gleeunit/should 8import graphql/ws 9 10pub fn main() { 11 gleeunit.main() 12} 13 14// Test: Parse connection_init message 15pub fn parse_connection_init_test() { 16 let json_str = 17 "{\"type\":\"connection_init\",\"payload\":{\"Authorization\":\"Bearer token123\"}}" 18 19 case ws.parse_message(json_str) { 20 Ok(ws.ConnectionInit(payload)) -> { 21 case dict.get(payload, "Authorization") { 22 Ok("Bearer token123") -> should.be_true(True) 23 _ -> should.fail() 24 } 25 } 26 _ -> should.fail() 27 } 28} 29 30// Test: Parse connection_init without payload 31pub fn parse_connection_init_no_payload_test() { 32 let json_str = "{\"type\":\"connection_init\"}" 33 34 case ws.parse_message(json_str) { 35 Ok(ws.ConnectionInit(payload)) -> { 36 dict.size(payload) 37 |> should.equal(0) 38 } 39 _ -> should.fail() 40 } 41} 42 43// Test: Parse subscribe message 44pub fn parse_subscribe_message_test() { 45 let json_str = 46 "{\"id\":\"1\",\"type\":\"subscribe\",\"payload\":{\"query\":\"subscription { postCreated { text } }\"}}" 47 48 case ws.parse_message(json_str) { 49 Ok(ws.Subscribe(id, query, _vars)) -> { 50 id |> should.equal("1") 51 query |> should.equal("subscription { postCreated { text } }") 52 } 53 _ -> should.fail() 54 } 55} 56 57// Test: Parse subscribe message with variables 58pub fn parse_subscribe_with_variables_test() { 59 let json_str = 60 "{\"id\":\"1\",\"type\":\"subscribe\",\"payload\":{\"query\":\"subscription { postCreated { text } }\",\"variables\":\"{}\"}}" 61 62 case ws.parse_message(json_str) { 63 Ok(ws.Subscribe(id, query, vars)) -> { 64 id |> should.equal("1") 65 query |> should.equal("subscription { postCreated { text } }") 66 vars |> should.equal(Some("{}")) 67 } 68 _ -> should.fail() 69 } 70} 71 72// Test: Parse ping message 73pub fn parse_ping_message_test() { 74 let json_str = "{\"type\":\"ping\"}" 75 76 case ws.parse_message(json_str) { 77 Ok(ws.Ping) -> should.be_true(True) 78 _ -> should.fail() 79 } 80} 81 82// Test: Parse pong message 83pub fn parse_pong_message_test() { 84 let json_str = "{\"type\":\"pong\"}" 85 86 case ws.parse_message(json_str) { 87 Ok(ws.Pong) -> should.be_true(True) 88 _ -> should.fail() 89 } 90} 91 92// Test: Parse complete message 93pub fn parse_complete_message_test() { 94 let json_str = "{\"id\":\"1\",\"type\":\"complete\"}" 95 96 case ws.parse_message(json_str) { 97 Ok(ws.Complete(id)) -> { 98 id |> should.equal("1") 99 } 100 _ -> should.fail() 101 } 102} 103 104// Test: Format connection_ack message 105pub fn format_connection_ack_test() { 106 let message = ws.ConnectionAck 107 108 let json_str = ws.format_message(message) 109 110 // Should produce valid JSON with type "connection_ack" 111 json_str |> should.equal("{\"type\":\"connection_ack\"}") 112} 113 114// Test: Format next message with data 115pub fn format_next_message_test() { 116 let data_json = "{\"data\":{\"postCreated\":{\"text\":\"Hello\"}}}" 117 118 let message = ws.Next("1", data_json) 119 120 let json_str = ws.format_message(message) 121 122 // Should contain id, type "next", and payload 123 json_str 124 |> should.equal( 125 "{\"id\":\"1\",\"type\":\"next\",\"payload\":" <> data_json <> "}", 126 ) 127} 128 129// Test: Format error message 130pub fn format_error_message_test() { 131 let message = ws.ErrorMessage("1", "Syntax error") 132 133 let json_str = ws.format_message(message) 134 135 // Should contain id, type "error", and payload with message 136 json_str 137 |> should.equal( 138 "{\"id\":\"1\",\"type\":\"error\",\"payload\":[{\"message\":\"Syntax error\"}]}", 139 ) 140} 141 142// Test: Format error message with quotes 143pub fn format_error_message_with_quotes_test() { 144 let message = ws.ErrorMessage("1", "Field \"text\" not found") 145 146 let json_str = ws.format_message(message) 147 148 // Should escape quotes in error message 149 json_str 150 |> should.equal( 151 "{\"id\":\"1\",\"type\":\"error\",\"payload\":[{\"message\":\"Field \\\"text\\\" not found\"}]}", 152 ) 153} 154 155// Test: Format complete message 156pub fn format_complete_message_test() { 157 let message = ws.Complete("1") 158 159 let json_str = ws.format_message(message) 160 161 json_str |> should.equal("{\"id\":\"1\",\"type\":\"complete\"}") 162} 163 164// Test: Format pong message 165pub fn format_pong_message_test() { 166 let message = ws.Pong 167 168 let json_str = ws.format_message(message) 169 170 json_str |> should.equal("{\"type\":\"pong\"}") 171} 172 173// Test: Invalid JSON should return error 174pub fn parse_invalid_json_test() { 175 let json_str = "not valid json" 176 177 case ws.parse_message(json_str) { 178 Error(_) -> should.be_true(True) 179 Ok(_) -> should.fail() 180 } 181} 182 183// Test: Unknown message type should return error 184pub fn parse_unknown_type_test() { 185 let json_str = "{\"type\":\"unknown_message_type\"}" 186 187 case ws.parse_message(json_str) { 188 Error(_) -> should.be_true(True) 189 Ok(_) -> should.fail() 190 } 191} 192 193// Test: Missing required fields should return error 194pub fn parse_subscribe_missing_id_test() { 195 let json_str = "{\"type\":\"subscribe\",\"payload\":{}}" 196 197 case ws.parse_message(json_str) { 198 Error(_) -> should.be_true(True) 199 Ok(_) -> should.fail() 200 } 201}