๐ŸŒŠ A GraphQL implementation in Gleam

test: add introspection test for union possibleTypes

Verifies that introspecting a union type correctly returns all
possible types in the possibleTypes field. This test would have
caught the bug fixed in 49fac31.

Changed files
+100
test
+100
test/introspection_test.gleam
··· 722 } 723 |> should.be_true 724 }
··· 722 } 723 |> should.be_true 724 } 725 + 726 + /// Test: Union type introspection returns possibleTypes 727 + /// Verifies that introspecting a union type correctly returns all possible types 728 + pub fn union_type_possible_types_test() { 729 + // Create object types that will be part of the union 730 + let post_type = 731 + schema.object_type("Post", "A blog post", [ 732 + schema.field("title", schema.string_type(), "Post title", fn(_ctx) { 733 + Ok(value.String("test")) 734 + }), 735 + ]) 736 + 737 + let comment_type = 738 + schema.object_type("Comment", "A comment", [ 739 + schema.field("text", schema.string_type(), "Comment text", fn(_ctx) { 740 + Ok(value.String("test")) 741 + }), 742 + ]) 743 + 744 + // Type resolver for the union 745 + let type_resolver = fn(_ctx: schema.Context) -> Result(String, String) { 746 + Ok("Post") 747 + } 748 + 749 + // Create union type 750 + let search_result_union = 751 + schema.union_type( 752 + "SearchResult", 753 + "A search result", 754 + [post_type, comment_type], 755 + type_resolver, 756 + ) 757 + 758 + // Create query type that uses the union 759 + let query_type = 760 + schema.object_type("Query", "Root query type", [ 761 + schema.field( 762 + "search", 763 + schema.list_type(search_result_union), 764 + "Search results", 765 + fn(_ctx) { Ok(value.List([])) }, 766 + ), 767 + ]) 768 + 769 + let test_schema = schema.schema(query_type, None) 770 + 771 + // Query for union type's possibleTypes 772 + let query = 773 + "{ __type(name: \"SearchResult\") { name kind possibleTypes { name } } }" 774 + 775 + let result = executor.execute(query, test_schema, schema.context(None)) 776 + 777 + should.be_ok(result) 778 + |> fn(response) { 779 + case response { 780 + executor.Response(data: value.Object(fields), errors: []) -> { 781 + case list.key_find(fields, "__type") { 782 + Ok(value.Object(type_fields)) -> { 783 + // Check it's a UNION 784 + let is_union = case list.key_find(type_fields, "kind") { 785 + Ok(value.String("UNION")) -> True 786 + _ -> False 787 + } 788 + 789 + // Check possibleTypes contains both Post and Comment 790 + let has_possible_types = case 791 + list.key_find(type_fields, "possibleTypes") 792 + { 793 + Ok(value.List(possible_types)) -> { 794 + let names = 795 + list.filter_map(possible_types, fn(pt) { 796 + case pt { 797 + value.Object(pt_fields) -> { 798 + case list.key_find(pt_fields, "name") { 799 + Ok(value.String(name)) -> Ok(name) 800 + _ -> Error(Nil) 801 + } 802 + } 803 + _ -> Error(Nil) 804 + } 805 + }) 806 + 807 + // Should have exactly 2 possible types: Comment and Post 808 + list.length(names) == 2 809 + && list.contains(names, "Post") 810 + && list.contains(names, "Comment") 811 + } 812 + _ -> False 813 + } 814 + 815 + is_union && has_possible_types 816 + } 817 + _ -> False 818 + } 819 + } 820 + _ -> False 821 + } 822 + } 823 + |> should.be_true 824 + }