A Gleam WebSocket consumer for AT Protocol Jetstream events.
at main 8.2 kB view raw
1import gleam/option 2import gleeunit 3import goose 4 5pub fn main() -> Nil { 6 gleeunit.main() 7} 8 9// Test build_url with default config (no filters) 10pub fn build_url_default_test() { 11 let config = goose.default_config() 12 let url = goose.build_url(config) 13 14 assert url 15 == "wss://jetstream2.us-east.bsky.network/subscribe?compress=false&requireHello=false" 16} 17 18// Test build_url with wanted collections 19pub fn build_url_with_collections_test() { 20 let config = 21 goose.JetstreamConfig( 22 endpoint: "wss://jetstream2.us-east.bsky.network/subscribe", 23 wanted_collections: ["app.bsky.feed.post", "app.bsky.feed.like"], 24 wanted_dids: [], 25 cursor: option.None, 26 max_message_size_bytes: option.None, 27 compress: False, 28 require_hello: False, 29 ) 30 let url = goose.build_url(config) 31 32 assert url 33 == "wss://jetstream2.us-east.bsky.network/subscribe?wantedCollections=app.bsky.feed.like&wantedCollections=app.bsky.feed.post&compress=false&requireHello=false" 34} 35 36// Test build_url with wanted DIDs 37pub fn build_url_with_dids_test() { 38 let config = 39 goose.JetstreamConfig( 40 endpoint: "wss://jetstream2.us-east.bsky.network/subscribe", 41 wanted_collections: [], 42 wanted_dids: ["did:plc:example123", "did:plc:example456"], 43 cursor: option.None, 44 max_message_size_bytes: option.None, 45 compress: False, 46 require_hello: False, 47 ) 48 let url = goose.build_url(config) 49 50 assert url 51 == "wss://jetstream2.us-east.bsky.network/subscribe?wantedDids=did:plc:example456&wantedDids=did:plc:example123&compress=false&requireHello=false" 52} 53 54// Test build_url with both collections and DIDs 55pub fn build_url_with_both_test() { 56 let config = 57 goose.JetstreamConfig( 58 endpoint: "wss://jetstream2.us-east.bsky.network/subscribe", 59 wanted_collections: ["app.bsky.feed.post"], 60 wanted_dids: ["did:plc:example123"], 61 cursor: option.None, 62 max_message_size_bytes: option.None, 63 compress: False, 64 require_hello: False, 65 ) 66 let url = goose.build_url(config) 67 68 assert url 69 == "wss://jetstream2.us-east.bsky.network/subscribe?wantedCollections=app.bsky.feed.post&wantedDids=did:plc:example123&compress=false&requireHello=false" 70} 71 72// Test build_url with cursor 73pub fn build_url_with_cursor_test() { 74 let config = 75 goose.JetstreamConfig( 76 endpoint: "wss://jetstream2.us-east.bsky.network/subscribe", 77 wanted_collections: [], 78 wanted_dids: [], 79 cursor: option.Some(1_234_567_890_123_456), 80 max_message_size_bytes: option.None, 81 compress: False, 82 require_hello: False, 83 ) 84 let url = goose.build_url(config) 85 86 assert url 87 == "wss://jetstream2.us-east.bsky.network/subscribe?cursor=1234567890123456&compress=false&requireHello=false" 88} 89 90// Test build_url with max_message_size_bytes 91pub fn build_url_with_max_size_test() { 92 let config = 93 goose.JetstreamConfig( 94 endpoint: "wss://jetstream2.us-east.bsky.network/subscribe", 95 wanted_collections: [], 96 wanted_dids: [], 97 cursor: option.None, 98 max_message_size_bytes: option.Some(1_048_576), 99 compress: False, 100 require_hello: False, 101 ) 102 let url = goose.build_url(config) 103 104 assert url 105 == "wss://jetstream2.us-east.bsky.network/subscribe?maxMessageSizeBytes=1048576&compress=false&requireHello=false" 106} 107 108// Test build_url with compress enabled 109pub fn build_url_with_compress_test() { 110 let config = 111 goose.JetstreamConfig( 112 endpoint: "wss://jetstream2.us-east.bsky.network/subscribe", 113 wanted_collections: [], 114 wanted_dids: [], 115 cursor: option.None, 116 max_message_size_bytes: option.None, 117 compress: True, 118 require_hello: False, 119 ) 120 let url = goose.build_url(config) 121 122 assert url 123 == "wss://jetstream2.us-east.bsky.network/subscribe?compress=true&requireHello=false" 124} 125 126// Test build_url with require_hello enabled 127pub fn build_url_with_require_hello_test() { 128 let config = 129 goose.JetstreamConfig( 130 endpoint: "wss://jetstream2.us-east.bsky.network/subscribe", 131 wanted_collections: [], 132 wanted_dids: [], 133 cursor: option.None, 134 max_message_size_bytes: option.None, 135 compress: False, 136 require_hello: True, 137 ) 138 let url = goose.build_url(config) 139 140 assert url 141 == "wss://jetstream2.us-east.bsky.network/subscribe?compress=false&requireHello=true" 142} 143 144// Test build_url with all options combined 145pub fn build_url_with_all_options_test() { 146 let config = 147 goose.JetstreamConfig( 148 endpoint: "wss://jetstream2.us-east.bsky.network/subscribe", 149 wanted_collections: ["app.bsky.feed.post"], 150 wanted_dids: ["did:plc:example123"], 151 cursor: option.Some(9_876_543_210), 152 max_message_size_bytes: option.Some(2_097_152), 153 compress: True, 154 require_hello: True, 155 ) 156 let url = goose.build_url(config) 157 158 assert url 159 == "wss://jetstream2.us-east.bsky.network/subscribe?wantedCollections=app.bsky.feed.post&wantedDids=did:plc:example123&cursor=9876543210&maxMessageSizeBytes=2097152&compress=true&requireHello=true" 160} 161 162// Test parsing a commit event (create operation with record) 163pub fn parse_commit_event_create_test() { 164 let json = 165 "{\"did\":\"did:plc:test123\",\"time_us\":1234567890,\"commit\":{\"rev\":\"abc123\",\"operation\":\"create\",\"collection\":\"app.bsky.feed.post\",\"rkey\":\"post123\",\"record\":{\"text\":\"Hello world\"},\"cid\":\"cid123\"}}" 166 167 let event = goose.parse_event(json) 168 169 case event { 170 goose.CommitEvent(did, time_us, commit) -> { 171 assert did == "did:plc:test123" 172 assert time_us == 1_234_567_890 173 assert commit.rev == "abc123" 174 assert commit.operation == "create" 175 assert commit.collection == "app.bsky.feed.post" 176 assert commit.rkey == "post123" 177 } 178 _ -> panic as "Expected CommitEvent" 179 } 180} 181 182// Test parsing a commit event (delete operation without record) 183pub fn parse_commit_event_delete_test() { 184 let json = 185 "{\"did\":\"did:plc:test456\",\"time_us\":9876543210,\"commit\":{\"rev\":\"xyz789\",\"operation\":\"delete\",\"collection\":\"app.bsky.feed.like\",\"rkey\":\"like456\"}}" 186 187 let event = goose.parse_event(json) 188 189 case event { 190 goose.CommitEvent(did, time_us, commit) -> { 191 assert did == "did:plc:test456" 192 assert time_us == 9_876_543_210 193 assert commit.rev == "xyz789" 194 assert commit.operation == "delete" 195 assert commit.collection == "app.bsky.feed.like" 196 assert commit.rkey == "like456" 197 } 198 _ -> panic as "Expected CommitEvent" 199 } 200} 201 202// Test parsing an identity event 203pub fn parse_identity_event_test() { 204 let json = 205 "{\"did\":\"did:plc:identity123\",\"time_us\":1111111111,\"identity\":{\"did\":\"did:plc:identity123\",\"handle\":\"alice.bsky.social\",\"seq\":42,\"time\":\"2024-01-01T00:00:00Z\"}}" 206 207 let event = goose.parse_event(json) 208 209 case event { 210 goose.IdentityEvent(did, time_us, identity) -> { 211 assert did == "did:plc:identity123" 212 assert time_us == 1_111_111_111 213 assert identity.did == "did:plc:identity123" 214 assert identity.handle == "alice.bsky.social" 215 assert identity.seq == 42 216 assert identity.time == "2024-01-01T00:00:00Z" 217 } 218 _ -> panic as "Expected IdentityEvent" 219 } 220} 221 222// Test parsing an account event 223pub fn parse_account_event_test() { 224 let json = 225 "{\"did\":\"did:plc:account789\",\"time_us\":2222222222,\"account\":{\"active\":true,\"did\":\"did:plc:account789\",\"seq\":99,\"time\":\"2024-01-02T00:00:00Z\"}}" 226 227 let event = goose.parse_event(json) 228 229 case event { 230 goose.AccountEvent(did, time_us, account) -> { 231 assert did == "did:plc:account789" 232 assert time_us == 2_222_222_222 233 assert account.active == True 234 assert account.did == "did:plc:account789" 235 assert account.seq == 99 236 assert account.time == "2024-01-02T00:00:00Z" 237 } 238 _ -> panic as "Expected AccountEvent" 239 } 240} 241 242// Test parsing unknown/invalid JSON 243pub fn parse_unknown_event_test() { 244 let json = "{\"unknown\":\"event\",\"type\":\"something\"}" 245 246 let event = goose.parse_event(json) 247 248 case event { 249 goose.UnknownEvent(raw) -> { 250 assert raw == json 251 } 252 _ -> panic as "Expected UnknownEvent" 253 } 254}