示例#1
0
    def builds_a_schema_with_an_enum():
        food_enum = GraphQLEnumType(
            "Food",
            {
                "VEGETABLES": GraphQLEnumValue(
                    1, description="Foods that are vegetables."
                ),
                "FRUITS": GraphQLEnumValue(2, description="Foods that are fruits."),
                "OILS": GraphQLEnumValue(3, description="Foods that are oils."),
                "DAIRY": GraphQLEnumValue(4, description="Foods that are dairy."),
                "MEAT": GraphQLEnumValue(5, description="Foods that are meat."),
            },
            description="Varieties of food stuffs",
        )

        schema = GraphQLSchema(
            GraphQLObjectType(
                "EnumFields",
                {
                    "food": GraphQLField(
                        food_enum,
                        args={
                            "kind": GraphQLArgument(
                                food_enum, description="what kind of food?"
                            )
                        },
                        description="Repeats the arg you give it",
                    )
                },
            )
        )

        introspection = introspection_from_schema(schema)
        client_schema = build_client_schema(introspection)
        second_introspection = introspection_from_schema(client_schema)

        hack_to_remove_standard_types(second_introspection)
        hack_to_remove_standard_types(introspection)
        assert second_introspection == introspection

        client_food_enum = client_schema.get_type("Food")

        # It's also an Enum type on the client.
        assert is_enum_type(client_food_enum)

        values = client_food_enum.values
        descriptions = {name: value.description for name, value in values.items()}
        assert descriptions == {
            "VEGETABLES": "Foods that are vegetables.",
            "FRUITS": "Foods that are fruits.",
            "OILS": "Foods that are oils.",
            "DAIRY": "Foods that are dairy.",
            "MEAT": "Foods that are meat.",
        }
        values = values.values()
        assert all(value.value is None for value in values)
        assert all(value.is_deprecated is False for value in values)
        assert all(value.deprecation_reason is None for value in values)
        assert all(value.ast_node is None for value in values)
示例#2
0
def check_schema(server_schema):
    """Test that the client side introspection gives the same result.

    Given a server's schema, a client may query that server with introspection,
    and use the result to produce a client-side representation of the schema by using
    `build_client_schema`. If the client then runs the introspection query against
    the client-side schema, it should get a result identical to what was returned
    by the server.
    """
    initial_introspection = introspection_from_schema(server_schema)
    client_schema = build_client_schema(initial_introspection)
    second_introspection = introspection_from_schema(client_schema)
    assert initial_introspection == second_introspection
    def uses_built_in_scalars_when_possible():
        custom_scalar = GraphQLScalarType('CustomScalar',
                                          serialize=lambda: None)

        schema = GraphQLSchema(
            GraphQLObjectType(
                'Scalars', {
                    'int': GraphQLField(GraphQLInt),
                    'float': GraphQLField(GraphQLFloat),
                    'string': GraphQLField(GraphQLString),
                    'boolean': GraphQLField(GraphQLBoolean),
                    'id': GraphQLField(GraphQLID),
                    'custom': GraphQLField(custom_scalar)
                }))

        check_schema(schema)

        introspection = introspection_from_schema(schema)
        client_schema = build_client_schema(introspection)

        # Built-ins are used
        assert client_schema.get_type('Int') is GraphQLInt
        assert client_schema.get_type('Float') is GraphQLFloat
        assert client_schema.get_type('String') is GraphQLString
        assert client_schema.get_type('Boolean') is GraphQLBoolean
        assert client_schema.get_type('ID') is GraphQLID

        # Custom are built
        assert client_schema.get_type('CustomScalar') is not custom_scalar
    def fails_on_very_deep_lists_more_than_7_levels():
        schema = GraphQLSchema(
            GraphQLObjectType(
                'Query', {
                    'foo':
                    GraphQLField(
                        GraphQLList(
                            GraphQLList(
                                GraphQLList(
                                    GraphQLList(
                                        GraphQLList(
                                            GraphQLList(
                                                GraphQLList(
                                                    GraphQLList(
                                                        GraphQLString)))))))))
                }))

        introspection = introspection_from_schema(schema)

        with raises(TypeError) as exc_info:
            build_client_schema(introspection)

        assert str(exc_info.value) == (
            'Query fields cannot be resolved:'
            ' Decorated type deeper than introspection query.')
示例#5
0
    def can_use_client_schema_for_limited_execution():
        custom_scalar = GraphQLScalarType("CustomScalar",
                                          serialize=lambda: None)

        schema = GraphQLSchema(
            GraphQLObjectType(
                "Query",
                {
                    "foo":
                    GraphQLField(
                        GraphQLString,
                        args={
                            "custom1": GraphQLArgument(custom_scalar),
                            "custom2": GraphQLArgument(custom_scalar),
                        },
                    )
                },
            ))

        introspection = introspection_from_schema(schema)
        client_schema = build_client_schema(introspection)

        class Data:
            foo = "bar"
            unused = "value"

        result = graphql_sync(
            client_schema,
            "query Limited($v: CustomScalar) { foo(custom1: 123, custom2: $v) }",
            Data(),
            variable_values={"v": "baz"},
        )

        assert result.data == {"foo": "bar"}
示例#6
0
    def uses_built_in_scalars_when_possible():
        sdl = dedent("""
            scalar CustomScalar

            type Query {
              int: Int
              float: Float
              string: String
              boolean: Boolean
              id: ID
              custom: CustomScalar
            }
            """)

        assert cycle_introspection(sdl) == sdl

        schema = build_schema(sdl)
        introspection = introspection_from_schema(schema)
        client_schema = build_client_schema(introspection)

        # Built-ins are used
        assert client_schema.get_type("Int") is GraphQLInt
        assert client_schema.get_type("Float") is GraphQLFloat
        assert client_schema.get_type("String") is GraphQLString
        assert client_schema.get_type("Boolean") is GraphQLBoolean
        assert client_schema.get_type("ID") is GraphQLID

        # Custom are built
        custom_scalar = schema.get_type("CustomScalar")
        assert client_schema.get_type("CustomScalar") is not custom_scalar
示例#7
0
    def can_use_client_schema_for_limited_execution():
        schema = build_schema(
            """
            scalar CustomScalar

            type Query {
              foo(custom1: CustomScalar, custom2: CustomScalar): String
            }
            """
        )

        introspection = introspection_from_schema(schema)
        client_schema = build_client_schema(introspection)

        class Data:
            foo = "bar"
            unused = "value"

        result = graphql_sync(
            client_schema,
            "query Limited($v: CustomScalar) { foo(custom1: 123, custom2: $v) }",
            root_value=Data(),
            variable_values={"v": "baz"},
        )

        assert result.data == {"foo": "bar"}
示例#8
0
    def can_build_invalid_schema():
        schema = build_schema("type Query", assume_valid=True)

        introspection = introspection_from_schema(schema)
        client_schema = build_client_schema(introspection, assume_valid=True)

        assert client_schema.to_kwargs()["assume_valid"] is True
示例#9
0
    def uses_built_in_scalars_when_possible():
        custom_scalar = GraphQLScalarType("CustomScalar",
                                          serialize=lambda: None)

        schema = GraphQLSchema(
            GraphQLObjectType(
                "Scalars",
                {
                    "int": GraphQLField(GraphQLInt),
                    "float": GraphQLField(GraphQLFloat),
                    "string": GraphQLField(GraphQLString),
                    "boolean": GraphQLField(GraphQLBoolean),
                    "id": GraphQLField(GraphQLID),
                    "custom": GraphQLField(custom_scalar),
                },
            ))

        check_schema(schema)

        introspection = introspection_from_schema(schema)
        client_schema = build_client_schema(introspection)

        # Built-ins are used
        assert client_schema.get_type("Int") is GraphQLInt
        assert client_schema.get_type("Float") is GraphQLFloat
        assert client_schema.get_type("String") is GraphQLString
        assert client_schema.get_type("Boolean") is GraphQLBoolean
        assert client_schema.get_type("ID") is GraphQLID

        # Custom are built
        assert client_schema.get_type("CustomScalar") is not custom_scalar
示例#10
0
        def recursive_interfaces():
            sdl = """
                type Query {
                  foo: Foo
                }

                type Foo {
                  foo: String
                }
                """
            schema = build_schema(sdl, assume_valid=True)
            introspection = introspection_from_schema(schema)

            foo_type_introspection = introspection["__schema"]["types"][1]
            assert foo_type_introspection["name"] == "Foo"
            assert foo_type_introspection["interfaces"] == []
            # we need to patch here since invalid interfaces cannot be built with Python
            foo_type_introspection["interfaces"] = [
                {"kind": "OBJECT", "name": "Foo", "ofType": None}
            ]

            with raises(TypeError) as exc_info:
                build_client_schema(introspection)
            assert str(exc_info.value) == (
                "Foo interfaces cannot be resolved: "
                "Expected Foo to be a GraphQL Interface type."
            )
    def can_use_client_schema_for_limited_execution():
        custom_scalar = GraphQLScalarType('CustomScalar',
                                          serialize=lambda: None)

        schema = GraphQLSchema(
            GraphQLObjectType(
                'Query', {
                    'foo':
                    GraphQLField(GraphQLString,
                                 args={
                                     'custom1': GraphQLArgument(custom_scalar),
                                     'custom2': GraphQLArgument(custom_scalar)
                                 })
                }))

        introspection = introspection_from_schema(schema)
        client_schema = build_client_schema(introspection)

        class Data:
            foo = 'bar'
            unused = 'value'

        result = graphql_sync(client_schema,
                              'query Limited($v: CustomScalar) {'
                              ' foo(custom1: 123, custom2: $v) }',
                              Data(),
                              variable_values={'v': 'baz'})

        assert result.data == {'foo': 'bar'}
示例#12
0
    def fails_on_a_very_deep_non_null_more_than_7_levels():
        schema = GraphQLSchema(
            GraphQLObjectType(
                "Query",
                {
                    "foo":
                    GraphQLField(
                        GraphQLList(
                            GraphQLNonNull(
                                GraphQLList(
                                    GraphQLNonNull(
                                        GraphQLList(
                                            GraphQLNonNull(
                                                GraphQLList(
                                                    GraphQLNonNull(
                                                        GraphQLString)))))))))
                },
            ))

        introspection = introspection_from_schema(schema)

        with raises(TypeError) as exc_info:
            build_client_schema(introspection)

        assert str(exc_info.value) == (
            "Query fields cannot be resolved:"
            " Decorated type deeper than introspection query.")
示例#13
0
        def recursive_union():
            sdl = """
                type Query {
                  foo: Foo
                }

                union Foo
                """
            schema = build_schema(sdl, assume_valid=True)
            introspection = introspection_from_schema(schema)

            foo_type_introspection = introspection["__schema"]["types"][1]
            assert foo_type_introspection["name"] == "Foo"
            assert foo_type_introspection["kind"] == "UNION"
            assert foo_type_introspection["possibleTypes"] == []
            # we need to patch here since invalid unions cannot be built with Python
            foo_type_introspection["possibleTypes"] = [
                {"kind": "UNION", "name": "Foo", "ofType": None}
            ]

            with raises(TypeError) as exc_info:
                build_client_schema(introspection)
            assert str(exc_info.value) == (
                "Foo types cannot be resolved:"
                " Expected Foo to be a GraphQL Object type."
            )
示例#14
0
def cycle_introspection(sdl_string):
    """Test that the client side introspection gives the same result.

    This function does a full cycle of going from a string with the contents of the SDL,
    build in-memory GraphQLSchema from it, produce a client-side representation of the
    schema by using "build_client_schema" and then finally printing that that schema
    into the SDL.
    """
    server_schema = build_schema(sdl_string)
    initial_introspection = introspection_from_schema(server_schema)
    client_schema = build_client_schema(initial_introspection)
    # If the client then runs the introspection query against the client-side schema,
    # it should get a result identical to what was returned by the server
    second_introspection = introspection_from_schema(client_schema)
    assert initial_introspection == second_introspection
    return print_schema(client_schema)
示例#15
0
        def throws_when_type_reference_is_missing_name():
            introspection = introspection_from_schema(dummy_schema)

            assert introspection["__schema"]["queryType"]["name"] == "Query"
            del introspection["__schema"]["queryType"]["name"]

            with raises(TypeError) as exc_info:
                build_client_schema(introspection)

            assert str(exc_info.value) == "Unknown type reference: {}"
    def builds_a_schema_with_an_enum():
        food_enum = GraphQLEnumType('Food', {
            'VEGETABLES':
            GraphQLEnumValue(1, description='Foods that are vegetables.'),
            'FRUITS':
            GraphQLEnumValue(2, description='Foods that are fruits.'),
            'OILS':
            GraphQLEnumValue(3, description='Foods that are oils.'),
            'DAIRY':
            GraphQLEnumValue(4, description='Foods that are dairy.'),
            'MEAT':
            GraphQLEnumValue(5, description='Foods that are meat.')
        },
                                    description='Varieties of food stuffs')

        schema = GraphQLSchema(
            GraphQLObjectType(
                'EnumFields', {
                    'food':
                    GraphQLField(food_enum,
                                 args={
                                     'kind':
                                     GraphQLArgument(
                                         food_enum,
                                         description='what kind of food?')
                                 },
                                 description='Repeats the arg you give it')
                }))

        check_schema(schema)

        introspection = introspection_from_schema(schema)
        client_schema = build_client_schema(introspection)
        client_food_enum = client_schema.get_type('Food')

        # It's also an Enum type on the client.
        assert isinstance(client_food_enum, GraphQLEnumType)

        values = client_food_enum.values
        descriptions = {
            name: value.description
            for name, value in values.items()
        }
        assert descriptions == {
            'VEGETABLES': 'Foods that are vegetables.',
            'FRUITS': 'Foods that are fruits.',
            'OILS': 'Foods that are oils.',
            'DAIRY': 'Foods that are dairy.',
            'MEAT': 'Foods that are meat.'
        }
        values = values.values()
        assert all(value.value is None for value in values)
        assert all(value.is_deprecated is False for value in values)
        assert all(value.deprecation_reason is None for value in values)
        assert all(value.ast_node is None for value in values)
示例#17
0
def cycle_introspection(sdl_string):
    """Test that the client side introspection gives the same result.

    This function does a full cycle of going from a string with the contents of the SDL,
    build in-memory GraphQLSchema from it, produce a client-side representation of the
    schema by using "build_client_schema" and then return that schema printed as SDL.
    """
    options = dict(specified_by_url=True, directive_is_repeatable=True)

    server_schema = build_schema(sdl_string)
    initial_introspection = introspection_from_schema(server_schema, **options)
    client_schema = build_client_schema(initial_introspection)
    # If the client then runs the introspection query against the client-side schema,
    # it should get a result identical to what was returned by the server
    second_introspection = introspection_from_schema(client_schema, **options)

    # If the client then runs the introspection query against the client-side
    # schema, it should get a result identical to what was returned by the server.
    assert initial_introspection == second_introspection
    return print_schema(client_schema)
示例#18
0
        def legacy_support_for_interfaces_with_null_as_interfaces_field():
            introspection = introspection_from_schema(dummy_schema)
            some_interface_introspection = next(
                type_ for type_ in introspection["__schema"]["types"]
                if type_["name"] == "SomeInterface")

            assert some_interface_introspection["interfaces"] == []
            some_interface_introspection["interfaces"] = None

            client_schema = build_client_schema(introspection)
            assert print_schema(client_schema) == print_schema(dummy_schema)
示例#19
0
    def include_standard_type_only_if_it_is_used():
        schema = build_schema("""
            type Query {
              foo: String
            }
            """)
        introspection = introspection_from_schema(schema)
        client_schema = build_client_schema(introspection)

        assert client_schema.get_type("Int") is None
        assert client_schema.get_type("Float") is None
        assert client_schema.get_type("ID") is None
    def converts_a_simple_schema_without_description():
        introspection = introspection_from_schema(schema, descriptions=False)

        assert introspection_to_sdl(introspection) == dedent("""
            schema {
              query: Simple
            }

            type Simple {
              string: String
            }
            """)
示例#21
0
        def throws_when_missing_directive_args():
            introspection = introspection_from_schema(dummy_schema)

            some_directive_introspection = introspection["__schema"]["directives"][0]
            assert some_directive_introspection["name"] == "SomeDirective"
            assert some_directive_introspection["args"] == []
            del some_directive_introspection["args"]

            with raises(
                TypeError,
                match="^Introspection result missing directive args:"
                r" {'name': 'SomeDirective', .*}\.$",
            ):
                build_client_schema(introspection)
示例#22
0
    def builds_a_schema_without_the_query_type():
        sdl = dedent("""
            type Query {
              foo: String
            }
            """)

        schema = build_schema(sdl)
        introspection = introspection_from_schema(schema)
        del introspection["__schema"]["queryType"]

        client_schema = build_client_schema(introspection)
        assert client_schema.query_type is None
        assert print_schema(client_schema) == sdl
    def converts_a_simple_schema():
        introspection = introspection_from_schema(schema)

        assert introspection_to_sdl(introspection) == dedent('''
            schema {
              query: Simple
            }

            """This is a simple type"""
            type Simple {
              """This is a string field"""
              string: String
            }
            ''')
示例#24
0
    def fails_on_a_very_deep_non_null_more_than_7_levels():
        schema = build_schema("""
            type Query {
              foo: [[[[String!]!]!]!]
            }
            """)

        introspection = introspection_from_schema(schema)

        with raises(TypeError) as exc_info:
            build_client_schema(introspection)

        assert str(exc_info.value) == (
            "Query fields cannot be resolved:"
            " Decorated type deeper than introspection query.")
示例#25
0
        def throws_when_missing_enum_values():
            introspection = introspection_from_schema(dummy_schema)

            some_enum_introspection = next(
                type_ for type_ in introspection["__schema"]["types"]
                if type_["name"] == "SomeEnum")
            assert some_enum_introspection["enumValues"]
            del some_enum_introspection["enumValues"]

            with raises(
                    TypeError,
                    match="^Introspection result missing enumValues:"
                    r" {'kind': 'ENUM', 'name': 'SomeEnum', .*}\.$",
            ):
                build_client_schema(introspection)
        def throws_when_missing_kind():
            introspection = introspection_from_schema(dummy_schema)
            query_type_introspection = next(
                type_ for type_ in introspection["__schema"]["types"]
                if type_["name"] == "Query")
            assert query_type_introspection["kind"] == "OBJECT"
            del query_type_introspection["kind"]

            with raises(
                    TypeError,
                    match=r"^Invalid or incomplete introspection result\."
                    " Ensure that a full introspection query is used"
                    r" in order to build a client schema: {'name': 'Query', .*}\.$",
            ):
                build_client_schema(introspection)
        def throws_when_missing_directive_locations():
            introspection = introspection_from_schema(dummy_schema)
            some_directive_introspection = introspection["__schema"][
                "directives"][0]

            assert some_directive_introspection["name"] == "SomeDirective"
            assert some_directive_introspection["locations"] == ["QUERY"]
            del some_directive_introspection["locations"]  # type: ignore

            with raises(
                    TypeError,
                    match="^Introspection result missing directive locations:"
                    r" {'name': 'SomeDirective', .*}\.$",
            ):
                build_client_schema(introspection)
示例#28
0
        def throws_when_referenced_unknown_type():
            introspection = introspection_from_schema(dummy_schema)

            introspection["__schema"]["types"] = [
                type_ for type_ in introspection["__schema"]["types"]
                if type_["name"] != "Query"
            ]

            with raises(TypeError) as exc_info:
                build_client_schema(introspection)

            assert str(exc_info.value) == (
                "Invalid or incomplete schema, unknown type: Query."
                " Ensure that a full introspection query is used"
                " in order to build a client schema.")
示例#29
0
        def throws_when_missing_input_fields():
            introspection = introspection_from_schema(dummy_schema)

            some_input_object_introspection = next(
                type_ for type_ in introspection["__schema"]["types"]
                if type_["name"] == "SomeInputObject")
            assert some_input_object_introspection["inputFields"]
            del some_input_object_introspection["inputFields"]

            with raises(
                    TypeError,
                    match="^Introspection result missing inputFields:"
                    r" {'kind': 'INPUT_OBJECT', 'name': 'SomeInputObject', .*}\.$",
            ):
                build_client_schema(introspection)
示例#30
0
        def throws_when_missing_directive_args():
            introspection = introspection_from_schema(dummy_schema)

            some_directive_introspection = introspection["__schema"]["directives"][0]
            assert some_directive_introspection["name"] == "SomeDirective"
            assert some_directive_introspection["args"] == []
            del some_directive_introspection["args"]

            with raises(TypeError) as exc_info:
                build_client_schema(introspection)

            assert str(exc_info.value).startswith(
                "Introspection result missing directive args:"
                " {'name': 'SomeDirective',"
            )