馃寠 A GraphQL implementation in Gleam
at main 5.8 kB view raw
1/// Tests for GraphQL Schema (Type System) 2/// 3/// GraphQL spec Section 3 - Type System 4/// Defines types, fields, and schema structure 5import gleam/option.{None} 6import gleeunit/should 7import swell/schema 8import swell/value 9 10// Type system tests 11pub fn create_scalar_type_test() { 12 let string_type = schema.string_type() 13 should.equal(schema.type_name(string_type), "String") 14} 15 16pub fn create_object_type_test() { 17 let user_type = 18 schema.object_type("User", "A user in the system", [ 19 schema.field("id", schema.id_type(), "User ID", fn(_ctx) { 20 Ok(value.String("123")) 21 }), 22 schema.field("name", schema.string_type(), "User name", fn(_ctx) { 23 Ok(value.String("Alice")) 24 }), 25 ]) 26 27 should.equal(schema.type_name(user_type), "User") 28} 29 30pub fn create_non_null_type_test() { 31 let non_null_string = schema.non_null(schema.string_type()) 32 should.be_true(schema.is_non_null(non_null_string)) 33} 34 35pub fn create_list_type_test() { 36 let list_of_strings = schema.list_type(schema.string_type()) 37 should.be_true(schema.is_list(list_of_strings)) 38} 39 40pub fn create_schema_test() { 41 let query_type = 42 schema.object_type("Query", "Root query type", [ 43 schema.field("hello", schema.string_type(), "Hello field", fn(_ctx) { 44 Ok(value.String("world")) 45 }), 46 ]) 47 48 let graphql_schema = schema.schema(query_type, None) 49 should.equal(schema.query_type(graphql_schema), query_type) 50} 51 52pub fn field_with_arguments_test() { 53 let user_field = 54 schema.field_with_args( 55 "user", 56 schema.string_type(), 57 "Get user by ID", 58 [schema.argument("id", schema.id_type(), "User ID", None)], 59 fn(_ctx) { Ok(value.String("Alice")) }, 60 ) 61 62 should.equal(schema.field_name(user_field), "user") 63} 64 65pub fn enum_type_test() { 66 let role_enum = 67 schema.enum_type("Role", "User role", [ 68 schema.enum_value("ADMIN", "Administrator"), 69 schema.enum_value("USER", "Regular user"), 70 ]) 71 72 should.equal(schema.type_name(role_enum), "Role") 73} 74 75pub fn scalar_types_exist_test() { 76 // Built-in scalar types 77 let _string = schema.string_type() 78 let _int = schema.int_type() 79 let _float = schema.float_type() 80 let _boolean = schema.boolean_type() 81 let _id = schema.id_type() 82 83 should.be_true(True) 84} 85 86// Union type tests 87pub fn create_union_type_test() { 88 let post_type = 89 schema.object_type("Post", "A blog post", [ 90 schema.field("title", schema.string_type(), "Post title", fn(_ctx) { 91 Ok(value.String("Hello")) 92 }), 93 ]) 94 95 let comment_type = 96 schema.object_type("Comment", "A comment", [ 97 schema.field("text", schema.string_type(), "Comment text", fn(_ctx) { 98 Ok(value.String("Nice post")) 99 }), 100 ]) 101 102 let type_resolver = fn(_ctx: schema.Context) -> Result(String, String) { 103 Ok("Post") 104 } 105 106 let union_type = 107 schema.union_type( 108 "SearchResult", 109 "A search result", 110 [post_type, comment_type], 111 type_resolver, 112 ) 113 114 should.equal(schema.type_name(union_type), "SearchResult") 115 should.be_true(schema.is_union(union_type)) 116} 117 118pub fn union_possible_types_test() { 119 let post_type = 120 schema.object_type("Post", "A blog post", [ 121 schema.field("title", schema.string_type(), "Post title", fn(_ctx) { 122 Ok(value.String("Hello")) 123 }), 124 ]) 125 126 let comment_type = 127 schema.object_type("Comment", "A comment", [ 128 schema.field("text", schema.string_type(), "Comment text", fn(_ctx) { 129 Ok(value.String("Nice post")) 130 }), 131 ]) 132 133 let type_resolver = fn(_ctx: schema.Context) -> Result(String, String) { 134 Ok("Post") 135 } 136 137 let union_type = 138 schema.union_type( 139 "SearchResult", 140 "A search result", 141 [post_type, comment_type], 142 type_resolver, 143 ) 144 145 let possible_types = schema.get_possible_types(union_type) 146 should.equal(possible_types, [post_type, comment_type]) 147} 148 149pub fn resolve_union_type_test() { 150 let post_type = 151 schema.object_type("Post", "A blog post", [ 152 schema.field("title", schema.string_type(), "Post title", fn(_ctx) { 153 Ok(value.String("Hello")) 154 }), 155 ]) 156 157 let comment_type = 158 schema.object_type("Comment", "A comment", [ 159 schema.field("text", schema.string_type(), "Comment text", fn(_ctx) { 160 Ok(value.String("Nice post")) 161 }), 162 ]) 163 164 // Type resolver that examines the __typename field in the data 165 let type_resolver = fn(ctx: schema.Context) -> Result(String, String) { 166 case ctx.data { 167 None -> Error("No data") 168 option.Some(value.Object(fields)) -> { 169 case fields { 170 [#("__typename", value.String(type_name)), ..] -> Ok(type_name) 171 _ -> Error("No __typename field") 172 } 173 } 174 _ -> Error("Data is not an object") 175 } 176 } 177 178 let union_type = 179 schema.union_type( 180 "SearchResult", 181 "A search result", 182 [post_type, comment_type], 183 type_resolver, 184 ) 185 186 // Create context with data that has __typename 187 let data = 188 value.Object([ 189 #("__typename", value.String("Post")), 190 #("title", value.String("Test")), 191 ]) 192 let ctx = schema.context(option.Some(data)) 193 let result = schema.resolve_union_type(union_type, ctx) 194 195 case result { 196 Ok(resolved_type) -> should.equal(schema.type_name(resolved_type), "Post") 197 Error(_) -> should.be_true(False) 198 } 199} 200 201pub fn union_type_kind_test() { 202 let post_type = 203 schema.object_type("Post", "A blog post", [ 204 schema.field("title", schema.string_type(), "Post title", fn(_ctx) { 205 Ok(value.String("Hello")) 206 }), 207 ]) 208 209 let type_resolver = fn(_ctx: schema.Context) -> Result(String, String) { 210 Ok("Post") 211 } 212 213 let union_type = 214 schema.union_type( 215 "SearchResult", 216 "A search result", 217 [post_type], 218 type_resolver, 219 ) 220 221 should.equal(schema.type_kind(union_type), "UNION") 222}