Type-safe GraphQL client generator for Gleam
1import birdie
2import gleam/dict
3import gleam/option.{None, Some}
4import squall/internal/codegen
5import squall/internal/graphql_ast
6import squall/internal/schema
7
8// Test: Generate simple query function
9pub fn generate_simple_query_test() {
10 let query_source =
11 "
12 query GetUser {
13 user {
14 id
15 name
16 }
17 }
18 "
19
20 let assert Ok(operation) = graphql_ast.parse(query_source)
21
22 // Create mock schema with user type
23 let user_fields = [
24 schema.Field(
25 "id",
26 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
27 [],
28 None,
29 ),
30 schema.Field("name", schema.NamedType("String", schema.Scalar), [], None),
31 ]
32
33 let mock_schema =
34 schema.Schema(
35 Some("Query"),
36 None,
37 None,
38 dict.from_list([
39 #("User", schema.ObjectType("User", user_fields, None)),
40 #(
41 "Query",
42 schema.ObjectType(
43 "Query",
44 [
45 schema.Field(
46 "user",
47 schema.NamedType("User", schema.Object),
48 [],
49 None,
50 ),
51 ],
52 None,
53 ),
54 ),
55 ]),
56 )
57
58 let result =
59 codegen.generate_operation(
60 "get_user",
61 query_source,
62 operation,
63 mock_schema,
64 "",
65 )
66
67 case result {
68 Ok(code) -> {
69 code
70 |> birdie.snap(title: "Simple query function generation")
71 }
72 Error(_) -> Nil
73 }
74}
75
76// Test: Generate query with variables
77pub fn generate_query_with_variables_test() {
78 let query_source =
79 "
80 query GetUser($id: ID!) {
81 user(id: $id) {
82 id
83 name
84 }
85 }
86 "
87
88 let assert Ok(operation) = graphql_ast.parse(query_source)
89
90 let user_fields = [
91 schema.Field(
92 "id",
93 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
94 [],
95 None,
96 ),
97 schema.Field("name", schema.NamedType("String", schema.Scalar), [], None),
98 ]
99
100 let mock_schema =
101 schema.Schema(
102 Some("Query"),
103 None,
104 None,
105 dict.from_list([
106 #("User", schema.ObjectType("User", user_fields, None)),
107 #(
108 "Query",
109 schema.ObjectType(
110 "Query",
111 [
112 schema.Field(
113 "user",
114 schema.NamedType("User", schema.Object),
115 [
116 schema.InputValue(
117 "id",
118 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
119 None,
120 ),
121 ],
122 None,
123 ),
124 ],
125 None,
126 ),
127 ),
128 ]),
129 )
130
131 let result =
132 codegen.generate_operation(
133 "get_user",
134 query_source,
135 operation,
136 mock_schema,
137 "",
138 )
139
140 case result {
141 Ok(code) -> {
142 code
143 |> birdie.snap(title: "Query with variables function generation")
144 }
145 Error(_) -> Nil
146 }
147}
148
149// Test: Generate query with nested types
150pub fn generate_query_with_nested_types_test() {
151 let query_source =
152 "
153 query GetCharacter($id: ID!) {
154 character(id: $id) {
155 id
156 name
157 status
158 }
159 }
160 "
161
162 let assert Ok(operation) = graphql_ast.parse(query_source)
163
164 let character_fields = [
165 schema.Field(
166 "id",
167 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
168 [],
169 None,
170 ),
171 schema.Field(
172 "name",
173 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
174 [],
175 None,
176 ),
177 schema.Field(
178 "status",
179 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
180 [],
181 None,
182 ),
183 ]
184
185 let mock_schema =
186 schema.Schema(
187 Some("Query"),
188 None,
189 None,
190 dict.from_list([
191 #("Character", schema.ObjectType("Character", character_fields, None)),
192 #(
193 "Query",
194 schema.ObjectType(
195 "Query",
196 [
197 schema.Field(
198 "character",
199 schema.NamedType("Character", schema.Object),
200 [
201 schema.InputValue(
202 "id",
203 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
204 None,
205 ),
206 ],
207 None,
208 ),
209 ],
210 None,
211 ),
212 ),
213 ]),
214 )
215
216 let result =
217 codegen.generate_operation(
218 "get_character",
219 query_source,
220 operation,
221 mock_schema,
222 "",
223 )
224
225 case result {
226 Ok(code) -> {
227 code
228 |> birdie.snap(title: "Query with nested types generation")
229 }
230 Error(_) -> Nil
231 }
232}
233
234// Test: Generate mutation function
235pub fn generate_mutation_test() {
236 let mutation_source =
237 "
238 mutation CreateUser($name: String!) {
239 createUser(name: $name) {
240 id
241 name
242 }
243 }
244 "
245
246 let assert Ok(operation) = graphql_ast.parse(mutation_source)
247
248 let user_fields = [
249 schema.Field(
250 "id",
251 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
252 [],
253 None,
254 ),
255 schema.Field(
256 "name",
257 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
258 [],
259 None,
260 ),
261 ]
262
263 let mock_schema =
264 schema.Schema(
265 Some("Query"),
266 Some("Mutation"),
267 None,
268 dict.from_list([
269 #("User", schema.ObjectType("User", user_fields, None)),
270 #(
271 "Mutation",
272 schema.ObjectType(
273 "Mutation",
274 [
275 schema.Field(
276 "createUser",
277 schema.NamedType("User", schema.Object),
278 [
279 schema.InputValue(
280 "name",
281 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
282 None,
283 ),
284 ],
285 None,
286 ),
287 ],
288 None,
289 ),
290 ),
291 ]),
292 )
293
294 let result =
295 codegen.generate_operation(
296 "create_user",
297 mutation_source,
298 operation,
299 mock_schema,
300 "",
301 )
302
303 case result {
304 Ok(code) -> {
305 code
306 |> birdie.snap(title: "Mutation function generation")
307 }
308 Error(_) -> Nil
309 }
310}
311
312// Test: Generate type with reserved keywords
313pub fn generate_with_reserved_keywords_test() {
314 let query_source =
315 "
316 query GetItem {
317 item {
318 id
319 type
320 case
321 let
322 }
323 }
324 "
325
326 let assert Ok(operation) = graphql_ast.parse(query_source)
327
328 let item_fields = [
329 schema.Field(
330 "id",
331 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
332 [],
333 None,
334 ),
335 schema.Field("type", schema.NamedType("String", schema.Scalar), [], None),
336 schema.Field("case", schema.NamedType("String", schema.Scalar), [], None),
337 schema.Field("let", schema.NamedType("String", schema.Scalar), [], None),
338 ]
339
340 let mock_schema =
341 schema.Schema(
342 Some("Query"),
343 None,
344 None,
345 dict.from_list([
346 #("Item", schema.ObjectType("Item", item_fields, None)),
347 #(
348 "Query",
349 schema.ObjectType(
350 "Query",
351 [
352 schema.Field(
353 "item",
354 schema.NamedType("Item", schema.Object),
355 [],
356 None,
357 ),
358 ],
359 None,
360 ),
361 ),
362 ]),
363 )
364
365 let result =
366 codegen.generate_operation(
367 "get_item",
368 query_source,
369 operation,
370 mock_schema,
371 "",
372 )
373
374 case result {
375 Ok(code) -> {
376 code
377 |> birdie.snap(title: "Type with reserved keywords")
378 }
379 Error(_) -> Nil
380 }
381}
382
383// Test: Generate query with inline scalar arguments
384pub fn generate_inline_scalar_arguments_test() {
385 let query_source =
386 "
387 query GetCharacter {
388 character(id: 1) {
389 id
390 name
391 }
392 }
393 "
394
395 let assert Ok(operation) = graphql_ast.parse(query_source)
396
397 let character_fields = [
398 schema.Field(
399 "id",
400 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
401 [],
402 None,
403 ),
404 schema.Field(
405 "name",
406 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
407 [],
408 None,
409 ),
410 ]
411
412 let mock_schema =
413 schema.Schema(
414 Some("Query"),
415 None,
416 None,
417 dict.from_list([
418 #("Character", schema.ObjectType("Character", character_fields, None)),
419 #(
420 "Query",
421 schema.ObjectType(
422 "Query",
423 [
424 schema.Field(
425 "character",
426 schema.NamedType("Character", schema.Object),
427 [
428 schema.InputValue(
429 "id",
430 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
431 None,
432 ),
433 ],
434 None,
435 ),
436 ],
437 None,
438 ),
439 ),
440 ]),
441 )
442
443 let result =
444 codegen.generate_operation(
445 "get_character",
446 query_source,
447 operation,
448 mock_schema,
449 "",
450 )
451
452 case result {
453 Ok(code) -> {
454 code
455 |> birdie.snap(title: "Query with inline scalar arguments")
456 }
457 Error(_) -> Nil
458 }
459}
460
461// Test: Generate query with inline object arguments
462pub fn generate_inline_object_arguments_test() {
463 let query_source =
464 "
465 query GetCharacters {
466 characters(filter: { name: \"rick\", status: \"alive\" }) {
467 results {
468 id
469 name
470 }
471 }
472 }
473 "
474
475 let assert Ok(operation) = graphql_ast.parse(query_source)
476
477 let character_fields = [
478 schema.Field(
479 "id",
480 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
481 [],
482 None,
483 ),
484 schema.Field(
485 "name",
486 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
487 [],
488 None,
489 ),
490 ]
491
492 let characters_result_fields = [
493 schema.Field(
494 "results",
495 schema.ListType(schema.NamedType("Character", schema.Object)),
496 [],
497 None,
498 ),
499 ]
500
501 let mock_schema =
502 schema.Schema(
503 Some("Query"),
504 None,
505 None,
506 dict.from_list([
507 #("Character", schema.ObjectType("Character", character_fields, None)),
508 #(
509 "CharactersResult",
510 schema.ObjectType("CharactersResult", characters_result_fields, None),
511 ),
512 #(
513 "Query",
514 schema.ObjectType(
515 "Query",
516 [
517 schema.Field(
518 "characters",
519 schema.NamedType("CharactersResult", schema.Object),
520 [
521 schema.InputValue(
522 "filter",
523 schema.NamedType("FilterInput", schema.InputObject),
524 None,
525 ),
526 ],
527 None,
528 ),
529 ],
530 None,
531 ),
532 ),
533 ]),
534 )
535
536 let result =
537 codegen.generate_operation(
538 "get_characters",
539 query_source,
540 operation,
541 mock_schema,
542 "",
543 )
544
545 case result {
546 Ok(code) -> {
547 code
548 |> birdie.snap(title: "Query with inline object arguments")
549 }
550 Error(_) -> Nil
551 }
552}
553
554// Test: Generate query with inline array arguments
555pub fn generate_inline_array_arguments_test() {
556 let query_source =
557 "
558 query GetEpisodes {
559 episodesByIds(ids: [1, 2, 3]) {
560 id
561 name
562 }
563 }
564 "
565
566 let assert Ok(operation) = graphql_ast.parse(query_source)
567
568 let episode_fields = [
569 schema.Field(
570 "id",
571 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
572 [],
573 None,
574 ),
575 schema.Field(
576 "name",
577 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
578 [],
579 None,
580 ),
581 ]
582
583 let mock_schema =
584 schema.Schema(
585 Some("Query"),
586 None,
587 None,
588 dict.from_list([
589 #("Episode", schema.ObjectType("Episode", episode_fields, None)),
590 #(
591 "Query",
592 schema.ObjectType(
593 "Query",
594 [
595 schema.Field(
596 "episodesByIds",
597 schema.ListType(schema.NamedType("Episode", schema.Object)),
598 [
599 schema.InputValue(
600 "ids",
601 schema.ListType(
602 schema.NonNullType(schema.NamedType("Int", schema.Scalar)),
603 ),
604 None,
605 ),
606 ],
607 None,
608 ),
609 ],
610 None,
611 ),
612 ),
613 ]),
614 )
615
616 let result =
617 codegen.generate_operation(
618 "get_episodes",
619 query_source,
620 operation,
621 mock_schema,
622 "",
623 )
624
625 case result {
626 Ok(code) -> {
627 code
628 |> birdie.snap(title: "Query with inline array arguments")
629 }
630 Error(_) -> Nil
631 }
632}
633
634// Test: Generate query with multiple root fields and mixed argument types
635pub fn generate_multiple_root_fields_test() {
636 let query_source =
637 "
638 query MultiQuery {
639 characters(page: 2, filter: { name: \"rick\" }) {
640 info {
641 count
642 }
643 results {
644 name
645 }
646 }
647 location(id: 1) {
648 id
649 }
650 episodesByIds(ids: [1, 2]) {
651 id
652 }
653 }
654 "
655
656 let assert Ok(operation) = graphql_ast.parse(query_source)
657
658 let character_fields = [
659 schema.Field("name", schema.NamedType("String", schema.Scalar), [], None),
660 ]
661
662 let info_fields = [
663 schema.Field("count", schema.NamedType("Int", schema.Scalar), [], None),
664 ]
665
666 let characters_result_fields = [
667 schema.Field("info", schema.NamedType("Info", schema.Object), [], None),
668 schema.Field(
669 "results",
670 schema.ListType(schema.NamedType("Character", schema.Object)),
671 [],
672 None,
673 ),
674 ]
675
676 let location_fields = [
677 schema.Field("id", schema.NamedType("ID", schema.Scalar), [], None),
678 ]
679
680 let episode_fields = [
681 schema.Field("id", schema.NamedType("ID", schema.Scalar), [], None),
682 ]
683
684 let mock_schema =
685 schema.Schema(
686 Some("Query"),
687 None,
688 None,
689 dict.from_list([
690 #("Character", schema.ObjectType("Character", character_fields, None)),
691 #("Info", schema.ObjectType("Info", info_fields, None)),
692 #(
693 "CharactersResult",
694 schema.ObjectType("CharactersResult", characters_result_fields, None),
695 ),
696 #("Location", schema.ObjectType("Location", location_fields, None)),
697 #("Episode", schema.ObjectType("Episode", episode_fields, None)),
698 #(
699 "Query",
700 schema.ObjectType(
701 "Query",
702 [
703 schema.Field(
704 "characters",
705 schema.NamedType("CharactersResult", schema.Object),
706 [
707 schema.InputValue(
708 "page",
709 schema.NamedType("Int", schema.Scalar),
710 None,
711 ),
712 schema.InputValue(
713 "filter",
714 schema.NamedType("FilterInput", schema.InputObject),
715 None,
716 ),
717 ],
718 None,
719 ),
720 schema.Field(
721 "location",
722 schema.NamedType("Location", schema.Object),
723 [
724 schema.InputValue(
725 "id",
726 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
727 None,
728 ),
729 ],
730 None,
731 ),
732 schema.Field(
733 "episodesByIds",
734 schema.ListType(schema.NamedType("Episode", schema.Object)),
735 [
736 schema.InputValue(
737 "ids",
738 schema.ListType(
739 schema.NonNullType(schema.NamedType("Int", schema.Scalar)),
740 ),
741 None,
742 ),
743 ],
744 None,
745 ),
746 ],
747 None,
748 ),
749 ),
750 ]),
751 )
752
753 let result =
754 codegen.generate_operation(
755 "multi_query",
756 query_source,
757 operation,
758 mock_schema,
759 "",
760 )
761
762 case result {
763 Ok(code) -> {
764 code
765 |> birdie.snap(
766 title: "Query with multiple root fields and mixed arguments",
767 )
768 }
769 Error(_) -> Nil
770 }
771}
772
773// Test: Generate mutation with InputObject variable
774pub fn generate_mutation_with_input_object_test() {
775 let mutation_source =
776 "
777 mutation UpdateProfile($input: ProfileInput!) {
778 updateProfile(input: $input) {
779 id
780 displayName
781 }
782 }
783 "
784
785 let assert Ok(operation) = graphql_ast.parse(mutation_source)
786
787 // Define InputObject type in schema
788 let profile_input_fields = [
789 schema.InputValue(
790 "displayName",
791 schema.NamedType("String", schema.Scalar),
792 None,
793 ),
794 schema.InputValue(
795 "description",
796 schema.NamedType("String", schema.Scalar),
797 None,
798 ),
799 ]
800
801 let profile_fields = [
802 schema.Field(
803 "id",
804 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
805 [],
806 None,
807 ),
808 schema.Field(
809 "displayName",
810 schema.NamedType("String", schema.Scalar),
811 [],
812 None,
813 ),
814 ]
815
816 let mock_schema =
817 schema.Schema(
818 Some("Query"),
819 Some("Mutation"),
820 None,
821 dict.from_list([
822 #("Profile", schema.ObjectType("Profile", profile_fields, None)),
823 #(
824 "ProfileInput",
825 schema.InputObjectType("ProfileInput", profile_input_fields, None),
826 ),
827 #(
828 "Mutation",
829 schema.ObjectType(
830 "Mutation",
831 [
832 schema.Field(
833 "updateProfile",
834 schema.NamedType("Profile", schema.Object),
835 [
836 schema.InputValue(
837 "input",
838 schema.NonNullType(schema.NamedType(
839 "ProfileInput",
840 schema.InputObject,
841 )),
842 None,
843 ),
844 ],
845 None,
846 ),
847 ],
848 None,
849 ),
850 ),
851 ]),
852 )
853
854 let result =
855 codegen.generate_operation(
856 "update_profile",
857 mutation_source,
858 operation,
859 mock_schema,
860 "",
861 )
862
863 case result {
864 Ok(code) -> {
865 code
866 |> birdie.snap(title: "Mutation with InputObject variable")
867 }
868 Error(_) -> Nil
869 }
870}
871
872// Test: Generate mutation with nested InputObject types
873pub fn generate_mutation_with_nested_input_object_test() {
874 let mutation_source =
875 "
876 mutation UpdateProfile($input: ProfileInput!) {
877 updateProfile(input: $input) {
878 id
879 displayName
880 }
881 }
882 "
883
884 let assert Ok(operation) = graphql_ast.parse(mutation_source)
885
886 // Define nested InputObject types
887 let blob_input_fields = [
888 schema.InputValue(
889 "data",
890 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
891 None,
892 ),
893 schema.InputValue(
894 "mimeType",
895 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
896 None,
897 ),
898 ]
899
900 let profile_input_fields = [
901 schema.InputValue(
902 "displayName",
903 schema.NamedType("String", schema.Scalar),
904 None,
905 ),
906 schema.InputValue(
907 "avatar",
908 schema.NamedType("BlobInput", schema.InputObject),
909 None,
910 ),
911 schema.InputValue(
912 "interests",
913 schema.ListType(
914 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
915 ),
916 None,
917 ),
918 ]
919
920 let profile_fields = [
921 schema.Field(
922 "id",
923 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
924 [],
925 None,
926 ),
927 schema.Field(
928 "displayName",
929 schema.NamedType("String", schema.Scalar),
930 [],
931 None,
932 ),
933 ]
934
935 let mock_schema =
936 schema.Schema(
937 Some("Query"),
938 Some("Mutation"),
939 None,
940 dict.from_list([
941 #("Profile", schema.ObjectType("Profile", profile_fields, None)),
942 #(
943 "ProfileInput",
944 schema.InputObjectType("ProfileInput", profile_input_fields, None),
945 ),
946 #(
947 "BlobInput",
948 schema.InputObjectType("BlobInput", blob_input_fields, None),
949 ),
950 #(
951 "Mutation",
952 schema.ObjectType(
953 "Mutation",
954 [
955 schema.Field(
956 "updateProfile",
957 schema.NamedType("Profile", schema.Object),
958 [
959 schema.InputValue(
960 "input",
961 schema.NonNullType(schema.NamedType(
962 "ProfileInput",
963 schema.InputObject,
964 )),
965 None,
966 ),
967 ],
968 None,
969 ),
970 ],
971 None,
972 ),
973 ),
974 ]),
975 )
976
977 let result =
978 codegen.generate_operation(
979 "update_profile",
980 mutation_source,
981 operation,
982 mock_schema,
983 "",
984 )
985
986 case result {
987 Ok(code) -> {
988 code
989 |> birdie.snap(title: "Mutation with nested InputObject types")
990 }
991 Error(_) -> Nil
992 }
993}
994
995// Test: Generate query with all non-nullable fields (no Option import needed)
996pub fn generate_query_with_all_non_nullable_fields_test() {
997 let query_source =
998 "
999 query GetProduct {
1000 product {
1001 id
1002 name
1003 price
1004 }
1005 }
1006 "
1007
1008 let assert Ok(operation) = graphql_ast.parse(query_source)
1009
1010 // Create mock schema with all non-nullable fields
1011 let product_fields = [
1012 schema.Field(
1013 "id",
1014 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
1015 [],
1016 None,
1017 ),
1018 schema.Field(
1019 "name",
1020 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
1021 [],
1022 None,
1023 ),
1024 schema.Field(
1025 "price",
1026 schema.NonNullType(schema.NamedType("Float", schema.Scalar)),
1027 [],
1028 None,
1029 ),
1030 ]
1031
1032 let mock_schema =
1033 schema.Schema(
1034 Some("Query"),
1035 None,
1036 None,
1037 dict.from_list([
1038 #("Product", schema.ObjectType("Product", product_fields, None)),
1039 #(
1040 "Query",
1041 schema.ObjectType(
1042 "Query",
1043 [
1044 schema.Field(
1045 "product",
1046 schema.NonNullType(schema.NamedType("Product", schema.Object)),
1047 [],
1048 None,
1049 ),
1050 ],
1051 None,
1052 ),
1053 ),
1054 ]),
1055 )
1056
1057 let result =
1058 codegen.generate_operation(
1059 "get_product",
1060 query_source,
1061 operation,
1062 mock_schema,
1063 "",
1064 )
1065
1066 case result {
1067 Ok(code) -> {
1068 code
1069 |> birdie.snap(
1070 title: "Query with all non-nullable fields (no Option import)",
1071 )
1072 }
1073 Error(_) -> Nil
1074 }
1075}
1076
1077// Test: Generate query with JSON scalar field
1078pub fn generate_query_with_json_scalar_test() {
1079 let query_source =
1080 "
1081 query GetProfile {
1082 profile {
1083 id
1084 displayName
1085 metadata
1086 }
1087 }
1088 "
1089
1090 let assert Ok(operation) = graphql_ast.parse(query_source)
1091
1092 // Create mock schema with JSON scalar field
1093 let profile_fields = [
1094 schema.Field(
1095 "id",
1096 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
1097 [],
1098 None,
1099 ),
1100 schema.Field(
1101 "displayName",
1102 schema.NamedType("String", schema.Scalar),
1103 [],
1104 None,
1105 ),
1106 schema.Field("metadata", schema.NamedType("JSON", schema.Scalar), [], None),
1107 ]
1108
1109 let mock_schema =
1110 schema.Schema(
1111 Some("Query"),
1112 None,
1113 None,
1114 dict.from_list([
1115 #("Profile", schema.ObjectType("Profile", profile_fields, None)),
1116 #(
1117 "Query",
1118 schema.ObjectType(
1119 "Query",
1120 [
1121 schema.Field(
1122 "profile",
1123 schema.NamedType("Profile", schema.Object),
1124 [],
1125 None,
1126 ),
1127 ],
1128 None,
1129 ),
1130 ),
1131 ]),
1132 )
1133
1134 let result =
1135 codegen.generate_operation(
1136 "get_profile",
1137 query_source,
1138 operation,
1139 mock_schema,
1140 "",
1141 )
1142
1143 case result {
1144 Ok(code) -> {
1145 code
1146 |> birdie.snap(title: "Query with JSON scalar field")
1147 }
1148 Error(_) -> Nil
1149 }
1150}
1151
1152// Test: Generate mutation with JSON scalar in InputObject
1153pub fn generate_mutation_with_json_input_field_test() {
1154 let mutation_source =
1155 "
1156 mutation UpdateSettings($input: SettingsInput!) {
1157 updateSettings(input: $input) {
1158 id
1159 metadata
1160 }
1161 }
1162 "
1163
1164 let assert Ok(operation) = graphql_ast.parse(mutation_source)
1165
1166 // Define InputObject type with JSON field
1167 let settings_input_fields = [
1168 schema.InputValue("metadata", schema.NamedType("JSON", schema.Scalar), None),
1169 schema.InputValue(
1170 "displayName",
1171 schema.NamedType("String", schema.Scalar),
1172 None,
1173 ),
1174 ]
1175
1176 let settings_fields = [
1177 schema.Field(
1178 "id",
1179 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
1180 [],
1181 None,
1182 ),
1183 schema.Field("metadata", schema.NamedType("JSON", schema.Scalar), [], None),
1184 ]
1185
1186 let mock_schema =
1187 schema.Schema(
1188 Some("Query"),
1189 Some("Mutation"),
1190 None,
1191 dict.from_list([
1192 #("Settings", schema.ObjectType("Settings", settings_fields, None)),
1193 #(
1194 "SettingsInput",
1195 schema.InputObjectType("SettingsInput", settings_input_fields, None),
1196 ),
1197 #(
1198 "Mutation",
1199 schema.ObjectType(
1200 "Mutation",
1201 [
1202 schema.Field(
1203 "updateSettings",
1204 schema.NamedType("Settings", schema.Object),
1205 [
1206 schema.InputValue(
1207 "input",
1208 schema.NonNullType(schema.NamedType(
1209 "SettingsInput",
1210 schema.InputObject,
1211 )),
1212 None,
1213 ),
1214 ],
1215 None,
1216 ),
1217 ],
1218 None,
1219 ),
1220 ),
1221 ]),
1222 )
1223
1224 let result =
1225 codegen.generate_operation(
1226 "update_settings",
1227 mutation_source,
1228 operation,
1229 mock_schema,
1230 "",
1231 )
1232
1233 case result {
1234 Ok(code) -> {
1235 code
1236 |> birdie.snap(title: "Mutation with JSON scalar in InputObject")
1237 }
1238 Error(_) -> Nil
1239 }
1240}
1241
1242// Test: Generate mutation with optional InputObject fields (tests Some/None serializer)
1243pub fn generate_mutation_with_optional_input_fields_test() {
1244 let mutation_source =
1245 "
1246 mutation CreateProfile($input: ProfileInput!) {
1247 createProfile(input: $input) {
1248 id
1249 displayName
1250 description
1251 }
1252 }
1253 "
1254
1255 let assert Ok(operation) = graphql_ast.parse(mutation_source)
1256
1257 // Define InputObject type with optional fields (nullable in GraphQL)
1258 let profile_input_fields = [
1259 schema.InputValue(
1260 "displayName",
1261 schema.NamedType("String", schema.Scalar),
1262 None,
1263 ),
1264 schema.InputValue(
1265 "description",
1266 schema.NamedType("String", schema.Scalar),
1267 None,
1268 ),
1269 schema.InputValue("avatar", schema.NamedType("JSON", schema.Scalar), None),
1270 ]
1271
1272 let profile_fields = [
1273 schema.Field(
1274 "id",
1275 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
1276 [],
1277 None,
1278 ),
1279 schema.Field(
1280 "displayName",
1281 schema.NamedType("String", schema.Scalar),
1282 [],
1283 None,
1284 ),
1285 schema.Field(
1286 "description",
1287 schema.NamedType("String", schema.Scalar),
1288 [],
1289 None,
1290 ),
1291 ]
1292
1293 let mock_schema =
1294 schema.Schema(
1295 Some("Query"),
1296 Some("Mutation"),
1297 None,
1298 dict.from_list([
1299 #("Profile", schema.ObjectType("Profile", profile_fields, None)),
1300 #(
1301 "ProfileInput",
1302 schema.InputObjectType("ProfileInput", profile_input_fields, None),
1303 ),
1304 #(
1305 "Mutation",
1306 schema.ObjectType(
1307 "Mutation",
1308 [
1309 schema.Field(
1310 "createProfile",
1311 schema.NamedType("Profile", schema.Object),
1312 [
1313 schema.InputValue(
1314 "input",
1315 schema.NonNullType(schema.NamedType(
1316 "ProfileInput",
1317 schema.InputObject,
1318 )),
1319 None,
1320 ),
1321 ],
1322 None,
1323 ),
1324 ],
1325 None,
1326 ),
1327 ),
1328 ]),
1329 )
1330
1331 let result =
1332 codegen.generate_operation(
1333 "create_profile",
1334 mutation_source,
1335 operation,
1336 mock_schema,
1337 "",
1338 )
1339
1340 case result {
1341 Ok(code) -> {
1342 code
1343 |> birdie.snap(
1344 title: "Mutation with optional InputObject fields (imports Some, None)",
1345 )
1346 }
1347 Error(_) -> Nil
1348 }
1349}
1350
1351// Test: Generate query with optional response fields only (should not import Some, None)
1352pub fn generate_query_with_optional_response_fields_test() {
1353 let query_source =
1354 "
1355 query GetProfile {
1356 profile {
1357 id
1358 displayName
1359 description
1360 }
1361 }
1362 "
1363
1364 let assert Ok(operation) = graphql_ast.parse(query_source)
1365
1366 // Create mock schema with optional response fields
1367 let profile_fields = [
1368 schema.Field(
1369 "id",
1370 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
1371 [],
1372 None,
1373 ),
1374 schema.Field(
1375 "displayName",
1376 schema.NamedType("String", schema.Scalar),
1377 [],
1378 None,
1379 ),
1380 schema.Field(
1381 "description",
1382 schema.NamedType("String", schema.Scalar),
1383 [],
1384 None,
1385 ),
1386 ]
1387
1388 let mock_schema =
1389 schema.Schema(
1390 Some("Query"),
1391 None,
1392 None,
1393 dict.from_list([
1394 #("Profile", schema.ObjectType("Profile", profile_fields, None)),
1395 #(
1396 "Query",
1397 schema.ObjectType(
1398 "Query",
1399 [
1400 schema.Field(
1401 "profile",
1402 schema.NamedType("Profile", schema.Object),
1403 [],
1404 None,
1405 ),
1406 ],
1407 None,
1408 ),
1409 ),
1410 ]),
1411 )
1412
1413 let result =
1414 codegen.generate_operation(
1415 "get_profile",
1416 query_source,
1417 operation,
1418 mock_schema,
1419 "",
1420 )
1421
1422 case result {
1423 Ok(code) -> {
1424 code
1425 |> birdie.snap(
1426 title: "Query with optional response fields (no Some, None imports)",
1427 )
1428 }
1429 Error(_) -> Nil
1430 }
1431}
1432
1433// Test: Generate response serializer for simple type
1434pub fn generate_response_serializer_simple_test() {
1435 let query_source =
1436 "
1437 query GetUser {
1438 user {
1439 id
1440 name
1441 }
1442 }
1443 "
1444
1445 let assert Ok(operation) = graphql_ast.parse(query_source)
1446
1447 // Create mock schema with user type
1448 let user_fields = [
1449 schema.Field(
1450 "id",
1451 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
1452 [],
1453 None,
1454 ),
1455 schema.Field(
1456 "name",
1457 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
1458 [],
1459 None,
1460 ),
1461 ]
1462
1463 let mock_schema =
1464 schema.Schema(
1465 Some("Query"),
1466 None,
1467 None,
1468 dict.from_list([
1469 #("User", schema.ObjectType("User", user_fields, None)),
1470 #(
1471 "Query",
1472 schema.ObjectType(
1473 "Query",
1474 [
1475 schema.Field(
1476 "user",
1477 schema.NamedType("User", schema.Object),
1478 [],
1479 None,
1480 ),
1481 ],
1482 None,
1483 ),
1484 ),
1485 ]),
1486 )
1487
1488 let result =
1489 codegen.generate_operation(
1490 "get_user",
1491 query_source,
1492 operation,
1493 mock_schema,
1494 "",
1495 )
1496
1497 case result {
1498 Ok(code) -> {
1499 code
1500 |> birdie.snap(title: "Response serializer for simple type")
1501 }
1502 Error(_) -> Nil
1503 }
1504}
1505
1506// Test: Generate response serializer with optional fields
1507pub fn generate_response_serializer_with_optional_fields_test() {
1508 let query_source =
1509 "
1510 query GetUser {
1511 user {
1512 id
1513 name
1514 email
1515 }
1516 }
1517 "
1518
1519 let assert Ok(operation) = graphql_ast.parse(query_source)
1520
1521 // Create mock schema with optional fields
1522 let user_fields = [
1523 schema.Field(
1524 "id",
1525 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
1526 [],
1527 None,
1528 ),
1529 schema.Field("name", schema.NamedType("String", schema.Scalar), [], None),
1530 schema.Field("email", schema.NamedType("String", schema.Scalar), [], None),
1531 ]
1532
1533 let mock_schema =
1534 schema.Schema(
1535 Some("Query"),
1536 None,
1537 None,
1538 dict.from_list([
1539 #("User", schema.ObjectType("User", user_fields, None)),
1540 #(
1541 "Query",
1542 schema.ObjectType(
1543 "Query",
1544 [
1545 schema.Field(
1546 "user",
1547 schema.NamedType("User", schema.Object),
1548 [],
1549 None,
1550 ),
1551 ],
1552 None,
1553 ),
1554 ),
1555 ]),
1556 )
1557
1558 let result =
1559 codegen.generate_operation(
1560 "get_user",
1561 query_source,
1562 operation,
1563 mock_schema,
1564 "",
1565 )
1566
1567 case result {
1568 Ok(code) -> {
1569 code
1570 |> birdie.snap(title: "Response serializer with optional fields")
1571 }
1572 Error(_) -> Nil
1573 }
1574}
1575
1576// Test: Generate response serializer with nested types
1577pub fn generate_response_serializer_with_nested_types_test() {
1578 let query_source =
1579 "
1580 query GetUser {
1581 user {
1582 id
1583 name
1584 location {
1585 city
1586 country
1587 }
1588 }
1589 }
1590 "
1591
1592 let assert Ok(operation) = graphql_ast.parse(query_source)
1593
1594 // Create mock schema with nested types
1595 let location_fields = [
1596 schema.Field("city", schema.NamedType("String", schema.Scalar), [], None),
1597 schema.Field("country", schema.NamedType("String", schema.Scalar), [], None),
1598 ]
1599
1600 let user_fields = [
1601 schema.Field(
1602 "id",
1603 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
1604 [],
1605 None,
1606 ),
1607 schema.Field(
1608 "name",
1609 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
1610 [],
1611 None,
1612 ),
1613 schema.Field(
1614 "location",
1615 schema.NamedType("Location", schema.Object),
1616 [],
1617 None,
1618 ),
1619 ]
1620
1621 let mock_schema =
1622 schema.Schema(
1623 Some("Query"),
1624 None,
1625 None,
1626 dict.from_list([
1627 #("Location", schema.ObjectType("Location", location_fields, None)),
1628 #("User", schema.ObjectType("User", user_fields, None)),
1629 #(
1630 "Query",
1631 schema.ObjectType(
1632 "Query",
1633 [
1634 schema.Field(
1635 "user",
1636 schema.NamedType("User", schema.Object),
1637 [],
1638 None,
1639 ),
1640 ],
1641 None,
1642 ),
1643 ),
1644 ]),
1645 )
1646
1647 let result =
1648 codegen.generate_operation(
1649 "get_user",
1650 query_source,
1651 operation,
1652 mock_schema,
1653 "",
1654 )
1655
1656 case result {
1657 Ok(code) -> {
1658 code
1659 |> birdie.snap(title: "Response serializer with nested types")
1660 }
1661 Error(_) -> Nil
1662 }
1663}
1664
1665// Test: Generate response serializer with lists
1666pub fn generate_response_serializer_with_lists_test() {
1667 let query_source =
1668 "
1669 query GetUsers {
1670 users {
1671 id
1672 name
1673 }
1674 }
1675 "
1676
1677 let assert Ok(operation) = graphql_ast.parse(query_source)
1678
1679 // Create mock schema with list type
1680 let user_fields = [
1681 schema.Field(
1682 "id",
1683 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
1684 [],
1685 None,
1686 ),
1687 schema.Field(
1688 "name",
1689 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
1690 [],
1691 None,
1692 ),
1693 ]
1694
1695 let mock_schema =
1696 schema.Schema(
1697 Some("Query"),
1698 None,
1699 None,
1700 dict.from_list([
1701 #("User", schema.ObjectType("User", user_fields, None)),
1702 #(
1703 "Query",
1704 schema.ObjectType(
1705 "Query",
1706 [
1707 schema.Field(
1708 "users",
1709 schema.ListType(schema.NamedType("User", schema.Object)),
1710 [],
1711 None,
1712 ),
1713 ],
1714 None,
1715 ),
1716 ),
1717 ]),
1718 )
1719
1720 let result =
1721 codegen.generate_operation(
1722 "get_users",
1723 query_source,
1724 operation,
1725 mock_schema,
1726 "",
1727 )
1728
1729 case result {
1730 Ok(code) -> {
1731 code
1732 |> birdie.snap(title: "Response serializer with lists")
1733 }
1734 Error(_) -> Nil
1735 }
1736}
1737
1738// Test: Generate response serializer with all scalar types
1739pub fn generate_response_serializer_with_all_scalars_test() {
1740 let query_source =
1741 "
1742 query GetProduct {
1743 product {
1744 id
1745 name
1746 price
1747 inStock
1748 rating
1749 metadata
1750 }
1751 }
1752 "
1753
1754 let assert Ok(operation) = graphql_ast.parse(query_source)
1755
1756 // Create mock schema with all scalar types
1757 let product_fields = [
1758 schema.Field(
1759 "id",
1760 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
1761 [],
1762 None,
1763 ),
1764 schema.Field(
1765 "name",
1766 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
1767 [],
1768 None,
1769 ),
1770 schema.Field(
1771 "price",
1772 schema.NonNullType(schema.NamedType("Float", schema.Scalar)),
1773 [],
1774 None,
1775 ),
1776 schema.Field(
1777 "inStock",
1778 schema.NonNullType(schema.NamedType("Boolean", schema.Scalar)),
1779 [],
1780 None,
1781 ),
1782 schema.Field(
1783 "rating",
1784 schema.NonNullType(schema.NamedType("Int", schema.Scalar)),
1785 [],
1786 None,
1787 ),
1788 schema.Field("metadata", schema.NamedType("JSON", schema.Scalar), [], None),
1789 ]
1790
1791 let mock_schema =
1792 schema.Schema(
1793 Some("Query"),
1794 None,
1795 None,
1796 dict.from_list([
1797 #("Product", schema.ObjectType("Product", product_fields, None)),
1798 #(
1799 "Query",
1800 schema.ObjectType(
1801 "Query",
1802 [
1803 schema.Field(
1804 "product",
1805 schema.NamedType("Product", schema.Object),
1806 [],
1807 None,
1808 ),
1809 ],
1810 None,
1811 ),
1812 ),
1813 #("JSON", schema.ScalarType("JSON", None)),
1814 ]),
1815 )
1816
1817 let result =
1818 codegen.generate_operation(
1819 "get_product",
1820 query_source,
1821 operation,
1822 mock_schema,
1823 "",
1824 )
1825
1826 case result {
1827 Ok(code) -> {
1828 code
1829 |> birdie.snap(title: "Response serializer with all scalar types")
1830 }
1831 Error(_) -> Nil
1832 }
1833}
1834
1835// Test: Generate query with simple fragment spread
1836pub fn generate_query_with_fragment_spread_test() {
1837 let query_source =
1838 "
1839 fragment UserFields on User {
1840 id
1841 name
1842 email
1843 }
1844
1845 query GetUser {
1846 user {
1847 ...UserFields
1848 createdAt
1849 }
1850 }
1851 "
1852
1853 let assert Ok(document) = graphql_ast.parse_document(query_source)
1854 let assert Ok(operation) = graphql_ast.get_main_operation(document)
1855 let fragments = graphql_ast.get_fragment_definitions(document)
1856
1857 // Create mock schema
1858 let user_fields = [
1859 schema.Field(
1860 "id",
1861 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
1862 [],
1863 None,
1864 ),
1865 schema.Field("name", schema.NamedType("String", schema.Scalar), [], None),
1866 schema.Field("email", schema.NamedType("String", schema.Scalar), [], None),
1867 schema.Field(
1868 "createdAt",
1869 schema.NamedType("String", schema.Scalar),
1870 [],
1871 None,
1872 ),
1873 ]
1874
1875 let mock_schema =
1876 schema.Schema(
1877 Some("Query"),
1878 None,
1879 None,
1880 dict.from_list([
1881 #("User", schema.ObjectType("User", user_fields, None)),
1882 #(
1883 "Query",
1884 schema.ObjectType(
1885 "Query",
1886 [
1887 schema.Field(
1888 "user",
1889 schema.NamedType("User", schema.Object),
1890 [],
1891 None,
1892 ),
1893 ],
1894 None,
1895 ),
1896 ),
1897 ]),
1898 )
1899
1900 let result =
1901 codegen.generate_operation_with_fragments(
1902 "get_user",
1903 query_source,
1904 operation,
1905 fragments,
1906 mock_schema,
1907 "",
1908 )
1909
1910 case result {
1911 Ok(code) -> {
1912 code
1913 |> birdie.snap(title: "Query with simple fragment spread")
1914 }
1915 Error(_) -> Nil
1916 }
1917}
1918
1919// Test: Generate query with enum field in response
1920pub fn generate_query_with_enum_field_test() {
1921 let query_source =
1922 "
1923 query GetCharacter {
1924 character {
1925 id
1926 name
1927 status
1928 }
1929 }
1930 "
1931
1932 let assert Ok(operation) = graphql_ast.parse(query_source)
1933
1934 // Create mock schema with enum type
1935 let character_fields = [
1936 schema.Field(
1937 "id",
1938 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
1939 [],
1940 None,
1941 ),
1942 schema.Field(
1943 "name",
1944 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
1945 [],
1946 None,
1947 ),
1948 schema.Field(
1949 "status",
1950 schema.NonNullType(schema.NamedType("CharacterStatus", schema.Enum)),
1951 [],
1952 None,
1953 ),
1954 ]
1955
1956 let mock_schema =
1957 schema.Schema(
1958 Some("Query"),
1959 None,
1960 None,
1961 dict.from_list([
1962 #("Character", schema.ObjectType("Character", character_fields, None)),
1963 #(
1964 "CharacterStatus",
1965 schema.EnumType("CharacterStatus", ["Alive", "Dead", "unknown"], None),
1966 ),
1967 #(
1968 "Query",
1969 schema.ObjectType(
1970 "Query",
1971 [
1972 schema.Field(
1973 "character",
1974 schema.NamedType("Character", schema.Object),
1975 [],
1976 None,
1977 ),
1978 ],
1979 None,
1980 ),
1981 ),
1982 ]),
1983 )
1984
1985 let result =
1986 codegen.generate_operation(
1987 "get_character",
1988 query_source,
1989 operation,
1990 mock_schema,
1991 "",
1992 )
1993
1994 case result {
1995 Ok(code) -> {
1996 code
1997 |> birdie.snap(title: "Query with enum field in response")
1998 }
1999 Error(_) -> Nil
2000 }
2001}
2002
2003// Test: Generate mutation with enum variable
2004pub fn generate_mutation_with_enum_variable_test() {
2005 let mutation_source =
2006 "
2007 mutation FilterCharacters($status: CharacterStatus!) {
2008 filterCharacters(status: $status) {
2009 id
2010 name
2011 status
2012 }
2013 }
2014 "
2015
2016 let assert Ok(operation) = graphql_ast.parse(mutation_source)
2017
2018 let character_fields = [
2019 schema.Field(
2020 "id",
2021 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
2022 [],
2023 None,
2024 ),
2025 schema.Field(
2026 "name",
2027 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
2028 [],
2029 None,
2030 ),
2031 schema.Field(
2032 "status",
2033 schema.NonNullType(schema.NamedType("CharacterStatus", schema.Enum)),
2034 [],
2035 None,
2036 ),
2037 ]
2038
2039 let mock_schema =
2040 schema.Schema(
2041 Some("Query"),
2042 Some("Mutation"),
2043 None,
2044 dict.from_list([
2045 #("Character", schema.ObjectType("Character", character_fields, None)),
2046 #(
2047 "CharacterStatus",
2048 schema.EnumType("CharacterStatus", ["Alive", "Dead", "unknown"], None),
2049 ),
2050 #(
2051 "Mutation",
2052 schema.ObjectType(
2053 "Mutation",
2054 [
2055 schema.Field(
2056 "filterCharacters",
2057 schema.ListType(schema.NamedType("Character", schema.Object)),
2058 [
2059 schema.InputValue(
2060 "status",
2061 schema.NonNullType(schema.NamedType(
2062 "CharacterStatus",
2063 schema.Enum,
2064 )),
2065 None,
2066 ),
2067 ],
2068 None,
2069 ),
2070 ],
2071 None,
2072 ),
2073 ),
2074 ]),
2075 )
2076
2077 let result =
2078 codegen.generate_operation(
2079 "filter_characters",
2080 mutation_source,
2081 operation,
2082 mock_schema,
2083 "",
2084 )
2085
2086 case result {
2087 Ok(code) -> {
2088 code
2089 |> birdie.snap(title: "Mutation with enum variable")
2090 }
2091 Error(_) -> Nil
2092 }
2093}
2094
2095// Test: Generate mutation with enum in InputObject
2096pub fn generate_mutation_with_enum_in_input_object_test() {
2097 let mutation_source =
2098 "
2099 mutation CreateCharacter($input: CharacterInput!) {
2100 createCharacter(input: $input) {
2101 id
2102 name
2103 status
2104 }
2105 }
2106 "
2107
2108 let assert Ok(operation) = graphql_ast.parse(mutation_source)
2109
2110 // Define InputObject with enum field
2111 let character_input_fields = [
2112 schema.InputValue(
2113 "name",
2114 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
2115 None,
2116 ),
2117 schema.InputValue(
2118 "status",
2119 schema.NonNullType(schema.NamedType("CharacterStatus", schema.Enum)),
2120 None,
2121 ),
2122 schema.InputValue(
2123 "species",
2124 schema.NamedType("String", schema.Scalar),
2125 None,
2126 ),
2127 ]
2128
2129 let character_fields = [
2130 schema.Field(
2131 "id",
2132 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
2133 [],
2134 None,
2135 ),
2136 schema.Field(
2137 "name",
2138 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
2139 [],
2140 None,
2141 ),
2142 schema.Field(
2143 "status",
2144 schema.NonNullType(schema.NamedType("CharacterStatus", schema.Enum)),
2145 [],
2146 None,
2147 ),
2148 ]
2149
2150 let mock_schema =
2151 schema.Schema(
2152 Some("Query"),
2153 Some("Mutation"),
2154 None,
2155 dict.from_list([
2156 #("Character", schema.ObjectType("Character", character_fields, None)),
2157 #(
2158 "CharacterStatus",
2159 schema.EnumType("CharacterStatus", ["Alive", "Dead", "unknown"], None),
2160 ),
2161 #(
2162 "CharacterInput",
2163 schema.InputObjectType("CharacterInput", character_input_fields, None),
2164 ),
2165 #(
2166 "Mutation",
2167 schema.ObjectType(
2168 "Mutation",
2169 [
2170 schema.Field(
2171 "createCharacter",
2172 schema.NamedType("Character", schema.Object),
2173 [
2174 schema.InputValue(
2175 "input",
2176 schema.NonNullType(schema.NamedType(
2177 "CharacterInput",
2178 schema.InputObject,
2179 )),
2180 None,
2181 ),
2182 ],
2183 None,
2184 ),
2185 ],
2186 None,
2187 ),
2188 ),
2189 ]),
2190 )
2191
2192 let result =
2193 codegen.generate_operation(
2194 "create_character",
2195 mutation_source,
2196 operation,
2197 mock_schema,
2198 "",
2199 )
2200
2201 case result {
2202 Ok(code) -> {
2203 code
2204 |> birdie.snap(title: "Mutation with enum in InputObject")
2205 }
2206 Error(_) -> Nil
2207 }
2208}
2209
2210// Test: Generate query with optional enum field
2211pub fn generate_query_with_optional_enum_field_test() {
2212 let query_source =
2213 "
2214 query GetCharacter {
2215 character {
2216 id
2217 name
2218 status
2219 gender
2220 }
2221 }
2222 "
2223
2224 let assert Ok(operation) = graphql_ast.parse(query_source)
2225
2226 // Create mock schema with optional enum field
2227 let character_fields = [
2228 schema.Field(
2229 "id",
2230 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
2231 [],
2232 None,
2233 ),
2234 schema.Field(
2235 "name",
2236 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
2237 [],
2238 None,
2239 ),
2240 schema.Field(
2241 "status",
2242 schema.NonNullType(schema.NamedType("CharacterStatus", schema.Enum)),
2243 [],
2244 None,
2245 ),
2246 schema.Field("gender", schema.NamedType("Gender", schema.Enum), [], None),
2247 ]
2248
2249 let mock_schema =
2250 schema.Schema(
2251 Some("Query"),
2252 None,
2253 None,
2254 dict.from_list([
2255 #("Character", schema.ObjectType("Character", character_fields, None)),
2256 #(
2257 "CharacterStatus",
2258 schema.EnumType("CharacterStatus", ["Alive", "Dead", "unknown"], None),
2259 ),
2260 #(
2261 "Gender",
2262 schema.EnumType("Gender", ["Male", "Female", "Genderless"], None),
2263 ),
2264 #(
2265 "Query",
2266 schema.ObjectType(
2267 "Query",
2268 [
2269 schema.Field(
2270 "character",
2271 schema.NamedType("Character", schema.Object),
2272 [],
2273 None,
2274 ),
2275 ],
2276 None,
2277 ),
2278 ),
2279 ]),
2280 )
2281
2282 let result =
2283 codegen.generate_operation(
2284 "get_character",
2285 query_source,
2286 operation,
2287 mock_schema,
2288 "",
2289 )
2290
2291 case result {
2292 Ok(code) -> {
2293 code
2294 |> birdie.snap(title: "Query with optional enum field")
2295 }
2296 Error(_) -> Nil
2297 }
2298}
2299
2300// Test: Generate mutation with optional enum in InputObject
2301pub fn generate_mutation_with_optional_enum_in_input_test() {
2302 let mutation_source =
2303 "
2304 mutation UpdateCharacter($input: CharacterUpdateInput!) {
2305 updateCharacter(input: $input) {
2306 id
2307 name
2308 status
2309 }
2310 }
2311 "
2312
2313 let assert Ok(operation) = graphql_ast.parse(mutation_source)
2314
2315 // Define InputObject with optional enum field
2316 let character_update_input_fields = [
2317 schema.InputValue(
2318 "id",
2319 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
2320 None,
2321 ),
2322 schema.InputValue("name", schema.NamedType("String", schema.Scalar), None),
2323 schema.InputValue(
2324 "status",
2325 schema.NamedType("CharacterStatus", schema.Enum),
2326 None,
2327 ),
2328 ]
2329
2330 let character_fields = [
2331 schema.Field(
2332 "id",
2333 schema.NonNullType(schema.NamedType("ID", schema.Scalar)),
2334 [],
2335 None,
2336 ),
2337 schema.Field(
2338 "name",
2339 schema.NonNullType(schema.NamedType("String", schema.Scalar)),
2340 [],
2341 None,
2342 ),
2343 schema.Field(
2344 "status",
2345 schema.NonNullType(schema.NamedType("CharacterStatus", schema.Enum)),
2346 [],
2347 None,
2348 ),
2349 ]
2350
2351 let mock_schema =
2352 schema.Schema(
2353 Some("Query"),
2354 Some("Mutation"),
2355 None,
2356 dict.from_list([
2357 #("Character", schema.ObjectType("Character", character_fields, None)),
2358 #(
2359 "CharacterStatus",
2360 schema.EnumType("CharacterStatus", ["Alive", "Dead", "unknown"], None),
2361 ),
2362 #(
2363 "CharacterUpdateInput",
2364 schema.InputObjectType(
2365 "CharacterUpdateInput",
2366 character_update_input_fields,
2367 None,
2368 ),
2369 ),
2370 #(
2371 "Mutation",
2372 schema.ObjectType(
2373 "Mutation",
2374 [
2375 schema.Field(
2376 "updateCharacter",
2377 schema.NamedType("Character", schema.Object),
2378 [
2379 schema.InputValue(
2380 "input",
2381 schema.NonNullType(schema.NamedType(
2382 "CharacterUpdateInput",
2383 schema.InputObject,
2384 )),
2385 None,
2386 ),
2387 ],
2388 None,
2389 ),
2390 ],
2391 None,
2392 ),
2393 ),
2394 ]),
2395 )
2396
2397 let result =
2398 codegen.generate_operation(
2399 "update_character",
2400 mutation_source,
2401 operation,
2402 mock_schema,
2403 "",
2404 )
2405
2406 case result {
2407 Ok(code) -> {
2408 code
2409 |> birdie.snap(title: "Mutation with optional enum in InputObject")
2410 }
2411 Error(_) -> Nil
2412 }
2413}