def test_fragment_select_field_not_in_fragment(ds): fragment = DSLFragment("test").on(ds.Character) with pytest.raises( GraphQLError, match="Invalid field for <DSLFragment test>: <DSLField Droid::primaryFunction>", ): fragment.select(ds.Droid.primaryFunction)
def test_fragment_with_name_changed(ds): fragment = DSLFragment("ABC") assert str(fragment) == "...ABC" fragment.name = "DEF" assert str(fragment) == "...DEF"
def test_fragments(ds): query = """fragment NameAndAppearances on Character { name appearsIn } { hero { ...NameAndAppearances } }""" name_and_appearances = ( DSLFragment("NameAndAppearances") .on(ds.Character) .select(ds.Character.name, ds.Character.appearsIn) ) query_dsl = DSLQuery(ds.Query.hero.select(name_and_appearances)) document = dsl_gql(name_and_appearances, query_dsl) print(print_ast(document)) assert query == print_ast(document)
def test_fragment_without_type_condition_error(ds): # We create a fragment without using the .on(type_condition) method name_and_appearances = DSLFragment("NameAndAppearances") # If we try to use this fragment, gql generates an error with pytest.raises( AttributeError, match=r"Missing type condition. Please use .on\(type_condition\) method", ): dsl_gql(name_and_appearances) with pytest.raises( AttributeError, match=r"Missing type condition. Please use .on\(type_condition\) method", ): DSLFragment("NameAndAppearances").select( ds.Character.name, ds.Character.appearsIn )
def get_introspection_query_ast( descriptions: bool = True, specified_by_url: bool = False, directive_is_repeatable: bool = False, schema_description: bool = False, type_recursion_level: int = 7, ) -> DocumentNode: """Get a query for introspection as a document using the DSL module. Equivalent to the get_introspection_query function from graphql-core but using the DSL module and allowing to select the recursion level. Optionally, you can exclude descriptions, include specification URLs, include repeatability of directives, and specify whether to include the schema description as well. """ ds = DSLSchema(GraphQLSchema()) fragment_FullType = DSLFragment("FullType").on(ds.__Type) fragment_InputValue = DSLFragment("InputValue").on(ds.__InputValue) fragment_TypeRef = DSLFragment("TypeRef").on(ds.__Type) schema = DSLMetaField("__schema") if descriptions and schema_description: schema.select(ds.__Schema.description) schema.select( ds.__Schema.queryType.select(ds.__Type.name), ds.__Schema.mutationType.select(ds.__Type.name), ds.__Schema.subscriptionType.select(ds.__Type.name), ) schema.select(ds.__Schema.types.select(fragment_FullType)) directives = ds.__Schema.directives.select(ds.__Directive.name) if descriptions: directives.select(ds.__Directive.description) if directive_is_repeatable: directives.select(ds.__Directive.isRepeatable) directives.select( ds.__Directive.locations, ds.__Directive.args.select(fragment_InputValue), ) schema.select(directives) fragment_FullType.select( ds.__Type.kind, ds.__Type.name, ) if descriptions: fragment_FullType.select(ds.__Type.description) if specified_by_url: fragment_FullType.select(ds.__Type.specifiedByURL) fields = ds.__Type.fields(includeDeprecated=True).select(ds.__Field.name) if descriptions: fields.select(ds.__Field.description) fields.select( ds.__Field.args.select(fragment_InputValue), ds.__Field.type.select(fragment_TypeRef), ds.__Field.isDeprecated, ds.__Field.deprecationReason, ) enum_values = ds.__Type.enumValues(includeDeprecated=True).select( ds.__EnumValue.name ) if descriptions: enum_values.select(ds.__EnumValue.description) enum_values.select( ds.__EnumValue.isDeprecated, ds.__EnumValue.deprecationReason, ) fragment_FullType.select( fields, ds.__Type.inputFields.select(fragment_InputValue), ds.__Type.interfaces.select(fragment_TypeRef), enum_values, ds.__Type.possibleTypes.select(fragment_TypeRef), ) fragment_InputValue.select(ds.__InputValue.name) if descriptions: fragment_InputValue.select(ds.__InputValue.description) fragment_InputValue.select( ds.__InputValue.type.select(fragment_TypeRef), ds.__InputValue.defaultValue, ) fragment_TypeRef.select( ds.__Type.kind, ds.__Type.name, ) if type_recursion_level >= 1: current_field = ds.__Type.ofType.select(ds.__Type.kind, ds.__Type.name) fragment_TypeRef.select(current_field) for _ in repeat(None, type_recursion_level - 1): new_oftype = ds.__Type.ofType.select(ds.__Type.kind, ds.__Type.name) current_field.select(new_oftype) current_field = new_oftype query = DSLQuery(schema) query.name = "IntrospectionQuery" dsl_query = dsl_gql(query, fragment_FullType, fragment_InputValue, fragment_TypeRef) return dsl_query
def test_invalid_meta_field_selection(ds): DSLQuery(DSLMetaField("__typename")) DSLQuery(DSLMetaField("__schema")) DSLQuery(DSLMetaField("__type")) metafield = DSLMetaField("__typename") assert metafield.name == "__typename" # alias does not work metafield.alias("test") assert metafield.name == "__typename" with pytest.raises(GraphQLError): DSLMetaField("__invalid_meta_field") DSLMutation(DSLMetaField("__typename")) with pytest.raises(GraphQLError): DSLMutation(DSLMetaField("__schema")) with pytest.raises(GraphQLError): DSLMutation(DSLMetaField("__type")) with pytest.raises(GraphQLError): DSLSubscription(DSLMetaField("__typename")) with pytest.raises(GraphQLError): DSLSubscription(DSLMetaField("__schema")) with pytest.raises(GraphQLError): DSLSubscription(DSLMetaField("__type")) fragment = DSLFragment("blah") with pytest.raises(AttributeError): fragment.select(DSLMetaField("__typename")) fragment.on(ds.Character) fragment.select(DSLMetaField("__typename")) with pytest.raises(GraphQLError): fragment.select(DSLMetaField("__schema")) with pytest.raises(GraphQLError): fragment.select(DSLMetaField("__type")) ds.Query.hero.select(DSLMetaField("__typename")) with pytest.raises(GraphQLError): ds.Query.hero.select(DSLMetaField("__schema")) with pytest.raises(GraphQLError): ds.Query.hero.select(DSLMetaField("__type"))
def test_dsl_nested_query_with_fragment(ds): query = """fragment NameAndAppearances on Character { name appearsIn } query NestedQueryWithFragment { hero { ...NameAndAppearances friends { ...NameAndAppearances friends { ...NameAndAppearances } } } }""" name_and_appearances = ( DSLFragment("NameAndAppearances") .on(ds.Character) .select(ds.Character.name, ds.Character.appearsIn) ) query_dsl = DSLQuery( ds.Query.hero.select( name_and_appearances, ds.Character.friends.select( name_and_appearances, ds.Character.friends.select(name_and_appearances) ), ) ) document = dsl_gql(name_and_appearances, NestedQueryWithFragment=query_dsl) print(print_ast(document)) assert query == print_ast(document) # Same thing, but incrementaly name_and_appearances = DSLFragment("NameAndAppearances") name_and_appearances.on(ds.Character) name_and_appearances.select(ds.Character.name) name_and_appearances.select(ds.Character.appearsIn) level_2 = ds.Character.friends level_2.select(name_and_appearances) level_1 = ds.Character.friends level_1.select(name_and_appearances) level_1.select(level_2) hero = ds.Query.hero hero.select(name_and_appearances) hero.select(level_1) query_dsl = DSLQuery(hero) document = dsl_gql(name_and_appearances, NestedQueryWithFragment=query_dsl) print(print_ast(document)) assert query == print_ast(document)
def test_fragments_repr(ds): assert repr(DSLInlineFragment()) == "<DSLInlineFragment>" assert repr(DSLInlineFragment().on(ds.Droid)) == "<DSLInlineFragment on Droid>" assert repr(DSLFragment("fragment_1")) == "<DSLFragment fragment_1>" assert repr(DSLFragment("fragment_2").on(ds.Droid)) == "<DSLFragment fragment_2>"