forked from
slices.network/quickslice
Auto-indexing service and GraphQL API for AT Protocol Records
1/// Tests for array ref expansion in object types
2///
3/// Tests that array fields with refs properly resolve to object types.
4import gleam/dict
5import gleam/option
6import gleam/string
7import gleeunit/should
8import lexicon_graphql/schema/builder
9import lexicon_graphql/types
10import swell/introspection
11import swell/sdl
12
13/// Test that array fields in records with refs to object defs resolve correctly.
14/// This mirrors the pattern in array_type_test but verifies the full ref path.
15pub fn array_in_record_with_ref_to_object_test() {
16 // Similar to the existing array_of_refs_generates_object_list_type_test
17 // but uses a different lexicon to verify our changes work
18 let lexicon =
19 types.Lexicon(
20 id: "app.bsky.embed.images",
21 defs: types.Defs(
22 main: option.Some(
23 types.RecordDef(type_: "record", key: option.None, properties: [
24 #(
25 "images",
26 types.Property(
27 type_: "array",
28 required: True,
29 format: option.None,
30 ref: option.None,
31 refs: option.None,
32 items: option.Some(types.ArrayItems(
33 type_: "ref",
34 ref: option.Some("app.bsky.embed.images#image"),
35 refs: option.None,
36 )),
37 ),
38 ),
39 ]),
40 ),
41 others: dict.from_list([
42 #(
43 "image",
44 types.Object(
45 types.ObjectDef(type_: "object", required_fields: [], properties: [
46 #(
47 "alt",
48 types.Property(
49 type_: "string",
50 required: False,
51 format: option.None,
52 ref: option.None,
53 refs: option.None,
54 items: option.None,
55 ),
56 ),
57 ]),
58 ),
59 ),
60 ]),
61 ),
62 )
63
64 let result = builder.build_schema([lexicon])
65 should.be_ok(result)
66
67 case result {
68 Ok(schema_val) -> {
69 let all_types = introspection.get_all_schema_types(schema_val)
70 let serialized = sdl.print_types(all_types)
71
72 // The image type should exist
73 string.contains(serialized, "type AppBskyEmbedImagesImage")
74 |> should.be_true
75
76 // The image type should have the alt field
77 string.contains(serialized, "alt: String")
78 |> should.be_true
79 }
80 Error(_) -> should.fail()
81 }
82}
83
84/// Test that object types in "others" get properly built with their fields.
85/// This verifies the object_builder creates types from ObjectDef definitions.
86pub fn object_def_in_others_builds_correctly_test() {
87 // Create a record that references an object def in others
88 let lexicon =
89 types.Lexicon(
90 id: "social.grain.example",
91 defs: types.Defs(
92 main: option.Some(
93 types.RecordDef(type_: "record", key: option.None, properties: [
94 #(
95 "ratio",
96 types.Property(
97 type_: "ref",
98 required: False,
99 format: option.None,
100 ref: option.Some("social.grain.example#aspectRatio"),
101 refs: option.None,
102 items: option.None,
103 ),
104 ),
105 ]),
106 ),
107 others: dict.from_list([
108 #(
109 "aspectRatio",
110 types.Object(
111 types.ObjectDef(type_: "object", required_fields: [], properties: [
112 #(
113 "width",
114 types.Property(
115 type_: "integer",
116 required: True,
117 format: option.None,
118 ref: option.None,
119 refs: option.None,
120 items: option.None,
121 ),
122 ),
123 #(
124 "height",
125 types.Property(
126 type_: "integer",
127 required: True,
128 format: option.None,
129 ref: option.None,
130 refs: option.None,
131 items: option.None,
132 ),
133 ),
134 ]),
135 ),
136 ),
137 ]),
138 ),
139 )
140
141 let result = builder.build_schema([lexicon])
142 should.be_ok(result)
143
144 case result {
145 Ok(schema_val) -> {
146 let all_types = introspection.get_all_schema_types(schema_val)
147 let serialized = sdl.print_types(all_types)
148
149 // The aspectRatio type should exist
150 string.contains(serialized, "SocialGrainExampleAspectRatio")
151 |> should.be_true
152 }
153 Error(_) -> should.fail()
154 }
155}