Auto-indexing service and GraphQL API for AT Protocol Records quickslice.slices.network/
atproto gleam graphql
at main 170 lines 5.2 kB view raw
1/// Tests for strongRef resolution in nested object types 2/// 3/// Verifies that com.atproto.repo.strongRef refs in "others" object definitions 4/// (like #replyRef) resolve to ComAtprotoRepoStrongRef, not String 5import gleam/dict 6import gleam/list 7import gleam/option.{None, Some} 8import gleeunit/should 9import lexicon_graphql/internal/graphql/object_builder 10import lexicon_graphql/internal/lexicon/registry 11import lexicon_graphql/types 12import swell/schema 13 14/// Test that strongRef fields in nested objects resolve to object type, not String 15/// This reproduces the bug: app.bsky.feed.post#replyRef.parent should be 16/// ComAtprotoRepoStrongRef, not String 17pub fn strongref_in_nested_object_resolves_to_object_type_test() { 18 // Create com.atproto.repo.strongRef lexicon (main-level object type) 19 let strongref_lexicon = 20 types.Lexicon( 21 id: "com.atproto.repo.strongRef", 22 defs: types.Defs( 23 main: Some( 24 types.RecordDef(type_: "object", key: None, properties: [ 25 #( 26 "uri", 27 types.Property( 28 type_: "string", 29 required: True, 30 format: Some("at-uri"), 31 ref: None, 32 refs: None, 33 items: None, 34 ), 35 ), 36 #( 37 "cid", 38 types.Property( 39 type_: "string", 40 required: True, 41 format: Some("cid"), 42 ref: None, 43 refs: None, 44 items: None, 45 ), 46 ), 47 ]), 48 ), 49 others: dict.new(), 50 ), 51 ) 52 53 // Create a post lexicon with #replyRef that references strongRef 54 let post_lexicon = 55 types.Lexicon( 56 id: "app.bsky.feed.post", 57 defs: types.Defs( 58 main: Some( 59 types.RecordDef(type_: "record", key: Some("tid"), properties: [ 60 #( 61 "text", 62 types.Property( 63 type_: "string", 64 required: True, 65 format: None, 66 ref: None, 67 refs: None, 68 items: None, 69 ), 70 ), 71 #( 72 "reply", 73 types.Property( 74 type_: "ref", 75 required: False, 76 format: None, 77 ref: Some("#replyRef"), 78 refs: None, 79 items: None, 80 ), 81 ), 82 ]), 83 ), 84 others: dict.from_list([ 85 #( 86 "replyRef", 87 types.Object( 88 types.ObjectDef( 89 type_: "object", 90 required_fields: ["parent", "root"], 91 properties: [ 92 #( 93 "parent", 94 types.Property( 95 type_: "ref", 96 required: True, 97 format: None, 98 ref: Some("com.atproto.repo.strongRef"), 99 refs: None, 100 items: None, 101 ), 102 ), 103 #( 104 "root", 105 types.Property( 106 type_: "ref", 107 required: True, 108 format: None, 109 ref: Some("com.atproto.repo.strongRef"), 110 refs: None, 111 items: None, 112 ), 113 ), 114 ], 115 ), 116 ), 117 ), 118 ]), 119 ), 120 ) 121 122 // Build registry and object types 123 let reg = registry.from_lexicons([strongref_lexicon, post_lexicon]) 124 let object_types = object_builder.build_all_object_types(reg, None, None) 125 126 // The strongRef type should exist 127 let strongref_type_result = 128 dict.get(object_types, "com.atproto.repo.strongRef") 129 should.be_ok(strongref_type_result) 130 131 // The replyRef type should exist 132 let reply_ref_result = dict.get(object_types, "app.bsky.feed.post#replyRef") 133 should.be_ok(reply_ref_result) 134 135 // Check the replyRef type's parent field is ComAtprotoRepoStrongRef, not String 136 case reply_ref_result { 137 Ok(reply_ref_type) -> { 138 let type_name = schema.type_name(reply_ref_type) 139 should.equal(type_name, "AppBskyFeedPostReplyRef") 140 141 // Get the fields and find "parent" 142 let fields = schema.get_fields(reply_ref_type) 143 let parent_field = 144 list.find(fields, fn(f) { schema.field_name(f) == "parent" }) 145 146 case parent_field { 147 Ok(field) -> { 148 // The field type should be ComAtprotoRepoStrongRef, not String 149 let field_type = schema.field_type(field) 150 151 // Unwrap NonNull wrapper to get inner type 152 let inner_type = case schema.inner_type(field_type) { 153 Some(t) -> t 154 None -> field_type 155 } 156 157 let inner_type_name = schema.type_name(inner_type) 158 159 // Should NOT be "String" 160 should.not_equal(inner_type_name, "String") 161 162 // Should be "ComAtprotoRepoStrongRef" 163 should.equal(inner_type_name, "ComAtprotoRepoStrongRef") 164 } 165 Error(_) -> should.fail() 166 } 167 } 168 Error(_) -> should.fail() 169 } 170}