Beispiel #1
0
def test_graphql_options():
    class Book(GraphQLModel):
        class GraphQL:
            gql_type = "Book"

    class User_2(GraphQLModel):
        class GraphQL:
            gql_type = "User"
            include = ["username"]
            exclude = ["profile"]

    class User_3(GraphQLModel):
        class GraphQL:
            gql_type = "User"
            include = ["unknow"]

    bindable = PydanticBindable({"User_2": User_2, "Book": Book})

    with pytest.raises(PydanticBindError):
        make_executable_schema(
            schema,
            base_scalars_resolvers,
            snake_case_fallback_resolvers,
            bindable,
        )

    bindable = PydanticBindable({"User_3": User_3, "Book": Book})

    with pytest.raises(PydanticBindError):
        make_executable_schema(
            schema,
            base_scalars_resolvers,
            snake_case_fallback_resolvers,
            bindable,
        )
def test_executable_schema_creation_errors_if_type_defs_is_graphql_query():
    type_defs = """
        query { test }
    """

    with pytest.raises(TypeError):
        make_executable_schema(type_defs)
Beispiel #3
0
def test_non_null():
    schema = gql(
        """
    scalar Date
    scalar DateTime
    scalar JSON
    directive @policy on FIELD_DEFINITION

    type Query {
    _: Boolean
    }

    type Mutation {
    _: Boolean
    }

    type GraphQLTypes {
        nonNull: Int! @policy
    }
    """
    )

    from turbulette.apps.auth.directives import PolicyDirective

    with pytest.raises(SchemaError):
        make_executable_schema(
            schema,
            base_scalars_resolvers,
            snake_case_fallback_resolvers,
            directives={"policy": PolicyDirective},
        )
Beispiel #4
0
def test_validator():
    class Book(GraphQLModel):
        class GraphQL:
            gql_type = "Book"

    class User(GraphQLModel):
        class GraphQL:
            gql_type = "User"

        @validator("username")
        def check_username(value):
            if len(value) <= 3:
                raise ValueError("Username length must be greater than 3")
            return value

    bindable = PydanticBindable({"User": User, "Book": Book})

    make_executable_schema(
        schema,
        base_scalars_resolvers,
        snake_case_fallback_resolvers,
        bindable,
    )

    User(username="******")

    with pytest.raises(ValidationError):
        User(username="******")
Beispiel #5
0
def test_register_type():
    class Foo(GraphQLModel):
        class GraphQL:
            gql_type = "Foo"

    bindable = PydanticBindable({"Foo": Foo})

    # Remove JSON type
    bindable._type_map.pop("JSON")
    with pytest.raises(PydanticBindError):
        make_executable_schema(
            schema,
            base_scalars_resolvers,
            snake_case_fallback_resolvers,
            bindable,
        )

    # Bring it back through `register` method
    bindable.register_scalar("JSON", dict)
    make_executable_schema(
        schema,
        base_scalars_resolvers,
        snake_case_fallback_resolvers,
        bindable,
    )
def test_executable_schema_creation_errors_if_type_defs_is_invalid_schema():
    type_defs = """
        type Mutation {
            test: Boolean!
        }
    """

    with pytest.raises(TypeError):
        make_executable_schema(type_defs)
Beispiel #7
0
def test_directive_raises_type_error_if_required_argument_is_not_given():
    type_defs = """
        directive @test(arg: String!) on FIELD_DEFINITION

        type Query {
            hello: String @test
        }
    """

    with pytest.raises(TypeError):
        make_executable_schema(type_defs, directives={"test": ReturnValueDirective})
Beispiel #8
0
def test_graphql_types():
    """Test pydantic bindings."""
    class GraphQLTypes(GraphQLModel):
        class GraphQL:
            gql_type = "GraphQLTypes"

    bindable = PydanticBindable({"GraphQLTypes": GraphQLTypes})
    make_executable_schema(
        schema,
        base_scalars_resolvers,
        snake_case_fallback_resolvers,
        bindable,
    )
    book_schema = GraphQLTypes.schema()
    book_schema.pop("description")
    assert book_schema == {
        "properties": {
            "id": {
                "title": "Id",
                "anyOf": [{
                    "type": "integer"
                }, {
                    "type": "string"
                }],
            },
            "string": {
                "title": "String",
                "type": "string"
            },
            "int": {
                "title": "Int",
                "type": "integer"
            },
            "float": {
                "title": "Float",
                "type": "number"
            },
            "bool": {
                "title": "Bool",
                "type": "boolean"
            },
        },
        "required": ["int"],
        "title": "GraphQLTypes",
        "type": "object",
    }
    GraphQLTypes(int=1)

    with pytest.raises(ValueError):
        GraphQLTypes()
Beispiel #9
0
def test_visitor_missing_method_raises_error():
    type_defs = """
        directive @objectFieldDirective on FIELD_DEFINITION

        type Query {
            people: [String] @objectFieldDirective
        }
    """

    class Visitor(SchemaDirectiveVisitor):
        def visit_object(self, object_: GraphQLObjectType):
            return object_

    with pytest.raises(ValueError):
        make_executable_schema(type_defs, directives={"objectFieldDirective": Visitor})
Beispiel #10
0
def schema():
    type_defs = """
        interface Other {
            name: String!
        }

        type Query {
            constant: Int!
            simple(value: Int!): Int!
            complex(valueA: Int, valueB: Int): Int!
            nested(value: NestedInput!): Int!
            child(value: Int!): [Child!]!
        }

        input NestedInput{
            num: Int!
        }

        type Child {
            name: String!
            online: Boolean!
        }
    """

    return make_executable_schema(type_defs)
Beispiel #11
0
def test_int_enum_input_nested_default_python_value_is_set():
    input_schema = """
        type Query {
            complex(i: BetterTest = { test: { role: EMPIRE }}): Boolean 
        }
        input Test {
            ignore: String 
            role: Episode = EMPIRE  
        }
        input BetterTest {
            newIgnore: String
            test: Test = { role: NEWHOPE }
        }
    """
    query = QueryType()

    def resolve_test_enum(*_, i):
        return i["test"]["role"] == PyIntEnum.EMPIRE

    query.set_field("complex", resolve_test_enum)
    schema = make_executable_schema([enum_definition, input_schema],
                                    [query, int_enum])
    result = graphql_sync(schema, "{ complex(i: {test: {} }) }")

    assert result.errors is None
    assert result.data["complex"]
Beispiel #12
0
def test_query_custom_type_custom_resolver():
    type_defs = """
        schema {
            query: Query
        }

        type Query {
            test: Custom
        }

        type Custom {
            node: String
        }
    """

    resolvers = {
        "Query": {
            "test": lambda *_: {
                "node": "custom"
            }
        },
        "Custom": {
            "node": lambda *_: "deep"
        },
    }

    schema = make_executable_schema(type_defs, resolvers)

    result = graphql(schema, "{ test { node } }")
    assert result.errors is None
    assert result.data == {"test": {"node": "deep"}}
Beispiel #13
0
def test_query_custom_scalar():
    type_defs = """
        schema {
            query: Query
        }

        scalar Date

        type Query {
            test: Date
        }
    """

    resolvers = {
        "Query": {
            "test": lambda *_: date.today()
        },
        "Date": lambda date: date.strftime("%Y-%m-%d"),
    }

    schema = make_executable_schema(type_defs, resolvers)

    result = graphql(schema, "{ test }")
    assert result.errors is None
    assert result.data == {"test": date.today().strftime("%Y-%m-%d")}
Beispiel #14
0
def test_mapping_resolver_to_object_attribute():
    type_defs = """
        type Query {
            user: User
        }

        type User {
            firstName: String
        }
    """

    resolvers = {
        "Query": {
            "user": lambda *_: Mock(first_name="Joe")
        },
        "User": {
            "firstName": resolve_to("first_name")
        },
    }

    schema = make_executable_schema(type_defs, resolvers)

    result = graphql(schema, "{ user { firstName } }")
    assert result.errors is None
    assert result.data == {"user": {"firstName": "Joe"}}
Beispiel #15
0
def test_query_custom_type_merged_custom_default_resolvers():
    type_defs = """
        type Query {
            test: Custom
        }

        type Custom {
            node: String
            default: String
        }
    """

    resolvers = {
        "Query": {
            "test": lambda *_: {
                "node": "custom",
                "default": "ok"
            }
        },
        "Custom": {
            "node": lambda *_: "deep"
        },
    }

    schema = make_executable_schema(type_defs, resolvers)

    result = graphql(schema, "{ test { node default } }")
    assert result.errors is None
    assert result.data == {"test": {"node": "deep", "default": "ok"}}
Beispiel #16
0
def test_mutation_input():
    type_defs = """
        type Query {
            _: String
        }

        input StaffInput {
            name: String
        }

        type Staff {
            name: String
        }

        type Mutation {
            addStaff(data: StaffInput): Staff
        }
    """

    def resolve_add_staff(*_, data):
        assert data == {"name": "Bob"}
        return data

    resolvers = {"Mutation": {"addStaff": resolve_add_staff}}

    schema = make_executable_schema(type_defs, resolvers)

    result = graphql(schema,
                     'mutation { addStaff(data: { name: "Bob" }) { name } }')
    assert result.errors is None
    assert result.data == {"addStaff": {"name": "Bob"}}
def test_enum_input_value_resolution(mocker):
    class ClownTypes(Enum):
        SAD = "Sad Clown"
        HAPPY = "Happy Clown"

    class ClownEmotionResolver(InputMixin, Resolver):
        def retrieve(self, *args, **kwargs):
            """Get sad, return happy"""
            assert self.get_input_data().get("type") == "Sad Clown"
            return ClownTypes.HAPPY

    class ClownEmotionResolverOff(InputMixin, Resolver):
        convert_enums = False

        def retrieve(self, *args, **kwargs):
            """Get sad enum, return happy enum"""
            assert self.get_input_data().get("type") == ClownTypes.SAD
            return ClownTypes.HAPPY

    type_defs = """
        enum ClownTypes {
            "Sad Clown"
            SAD
            "Happy Clown"
            HAPPY
        }

        input ClownInput {
            type: ClownTypes
        }

        type Query {
            clownEmotion(input: ClownInput!): ClownTypes
            clownEmotionOff(input: ClownInput!): ClownTypes
        }
    """

    query = QueryType()

    clown_types = EnumType("ClownTypes", ClownTypes)

    query.set_field("clownEmotion", ClownEmotionResolver.as_resolver())
    query.set_field("clownEmotionOff", ClownEmotionResolverOff.as_resolver())

    resolvers = [query, clown_types]

    schema = make_executable_schema(type_defs, resolvers)

    result = graphql_sync(
        schema,
        """
            query {
                on: clownEmotion(input: {type: SAD})
                off: clownEmotionOff(input: {type: SAD})
            }
        """,
    )
    assert result.errors is None
    assert glom(result.data, "on") == "HAPPY"
    assert glom(result.data, "off") == "HAPPY"
Beispiel #18
0
def test_field_definition_directive_replaces_field_resolver_with_custom_one():
    type_defs = """
        directive @upper on FIELD_DEFINITION
        directive @reverse on FIELD_DEFINITION

        type Query {
            test: Custom
        }

        type Custom {
            node: String @upper
            name: String @reverse
        }
    """

    query = QueryType()
    query.set_field("test", lambda *_: {"node": "custom", "name": "uppercase"})

    schema = make_executable_schema(
        type_defs,
        [query],
        directives={"upper": UpperDirective, "reverse": ReverseDirective},
    )

    result = graphql_sync(schema, "{ test { node name }}")
    assert result.errors is None
    assert result.data == {"test": {"node": "CUSTOM", "name": "esacreppu"}}
Beispiel #19
0
def test_succesfull_enum_typed_field():
    query = QueryType()
    query.set_field("testEnum", lambda *_: TEST_VALUE)

    schema = make_executable_schema([enum_definition, enum_field], query)
    result = graphql_sync(schema, "{ testEnum }")
    assert result.errors is None
Beispiel #20
0
def create_server(
    type_defs, resolvers, directives=None, extensions=None, error_formatter=None
):
    schema = make_executable_schema(
        type_defs, *resolvers, snake_case_fallback_resolvers, directives=directives,
    )
    app = Flask(__name__)

    @app.route("/graphql", methods=["GET"])
    def graphql_playgroud():
        return PLAYGROUND_HTML, 200

    @app.route("/graphql", methods=["POST"])
    def graphql_server():
        data = request.get_json()

        success, result = graphql_sync(
            schema,
            data,
            debug=app.debug,
            context_value=None,
            error_formatter=error_formatter,
            extensions=extensions,
        )

        status_code = 200 if success else 400
        return jsonify(result), status_code

    return app
Beispiel #21
0
def test_can_implement_remove_enum_values_directive():
    type_defs = """
        directive @remove(if: Boolean) on ENUM_VALUE

        type Query {
            age(unit: AgeUnit): Int
        }

        enum AgeUnit {
            DOG_YEARS
            TURTLE_YEARS @remove(if: true)
            PERSON_YEARS @remove(if: false)
        }
    """

    class RemoveEnumDirective(SchemaDirectiveVisitor):
        def visit_enum_value(self, value: GraphQLEnumValue, enum_type: GraphQLEnumType):
            if self.args["if"]:
                return False
            return None

    schema = make_executable_schema(
        type_defs, directives={"remove": RemoveEnumDirective}
    )

    enum_type: GraphQLEnumType = schema.get_type("AgeUnit")
    assert list(enum_type.values.keys()) == ["DOG_YEARS", "PERSON_YEARS"]
Beispiel #22
0
def test_directive_can_add_new_type_to_schema():
    type_defs = """
        directive @key on OBJECT

        type Query {
            people: [String]
        }
        type User @key {
            id: Int
        }

        type Admin @key {
            id: Int
        }
    """

    class Visitor(SchemaDirectiveVisitor):
        def visit_object(self, object_: GraphQLObjectType):
            try:
                types = self.schema.type_map["_Entity"].types
            except KeyError:
                u = self.schema.type_map["_Entity"] = GraphQLUnionType("_Entity", [])
                types = u.types
            types.append(object_)

    schema = make_executable_schema(type_defs, directives={"key": Visitor})
    assert {t.name for t in schema.get_type("_Entity").types} == {"User", "Admin"}
Beispiel #23
0
def test_executing_mutation_takes_scalar_arg_and_returns_type():
    type_defs = """
        type Query {
            _: String
        }

        type Staff {
            name: String
        }

        type Mutation {
            addStaff(name: String): Staff
        }
    """

    mutation = MutationType()

    @mutation.field("addStaff")
    def resolve_add_staff(*_, name):  # pylint: disable=unused-variable
        assert name == "Bob"
        return {"name": name}

    schema = make_executable_schema(type_defs, mutation)

    result = graphql_sync(schema,
                          'mutation { addStaff(name: "Bob") { name } }')
    assert result.errors is None
    assert result.data == {"addStaff": {"name": "Bob"}}
Beispiel #24
0
def test_result_is_thread_title_if_union_resolves_type_to_thread(
    query_with_thread_item,
):
    union = UnionType("FeedItem", type_resolver=resolve_result_type)
    schema = make_executable_schema(type_defs, [query_with_thread_item, union])
    result = graphql_sync(schema, test_query)
    assert result.data == {"item": {"__typename": "Thread", "title": Thread.title}}
Beispiel #25
0
def test_executing_mutation_using_input_type():
    type_defs = """
        type Query {
            _: String
        }

        input StaffInput {
            name: String
        }

        type Staff {
            name: String
        }

        type Mutation {
            addStaff(data: StaffInput): Staff
        }
    """

    mutation = MutationType()

    @mutation.field("addStaff")
    def resolve_add_staff(*_, data):  # pylint: disable=unused-variable
        assert data == {"name": "Bob"}
        return data

    schema = make_executable_schema(type_defs, mutation)

    result = graphql_sync(
        schema, 'mutation { addStaff(data: { name: "Bob" }) { name } }')
    assert result.errors is None
    assert result.data == {"addStaff": {"name": "Bob"}}
Beispiel #26
0
def test_result_is_none_if_union_didnt_resolve_the_type(
        query_with_invalid_item):
    union = UnionType("FeedItem", type_resolver=resolve_result_type)
    schema = make_executable_schema(type_defs,
                                    [query_with_invalid_item, union])
    result = graphql_sync(schema, test_query)
    assert result.data == {"item": None}
Beispiel #27
0
def test_graphql():
    type_defs = load_schema_from_path('schema.graphql')

    query = QueryType()
    building = ObjectType('Building')
    resident = ObjectType('Resident')

    # test dataset
    rec = building_with_id(None, None, "1")
    assert rec == {'id': '1', 'buildYear': 2009}
    residents = resolve_residents_in_building(rec, None)
    assert len(residents) > 0

    # field holders
    query.set_field('building_with_id', building_with_id)
    building.set_field('residents', resolve_residents_in_building)

    schema = make_executable_schema(type_defs, [building, resident, query])

    q = """{
        building_with_id(_id:"1"){
            id
            residents {
                id
                name
            }
        }
    }
    """
    result = graphql_sync(schema, q)
    pprint(result.data)
    assert result.data['building_with_id']['id'] == '1'
Beispiel #28
0
def test_mutation_return_type():
    type_defs = """
        type Query {
            _: String
        }

        type Staff {
            name: String
        }

        type Mutation {
            addStaff(name: String): Staff
        }
    """

    def resolve_add_staff(*_, name):
        assert name == "Bob"
        return {"name": name}

    resolvers = {"Mutation": {"addStaff": resolve_add_staff}}

    schema = make_executable_schema(type_defs, resolvers)

    result = graphql(schema, 'mutation { addStaff(name: "Bob") { name } }')
    assert result.errors is None
    assert result.data == {"addStaff": {"name": "Bob"}}
Beispiel #29
0
def test_unsuccesfull_invalid_enum_value_evaluation():
    query = QueryType()
    query.set_field("testEnum", lambda *_: INVALID_VALUE)

    schema = make_executable_schema([enum_definition, enum_field], query)
    result = graphql_sync(schema, "{ testEnum }")
    assert result.errors is not None
Beispiel #30
0
def test_unsuccessful_invalid_enum_value_passed_as_argument():
    query = QueryType()
    query.set_field("testEnum", lambda *_, value: True)

    schema = make_executable_schema([enum_definition, enum_param], query)
    result = graphql_sync(schema, "{ testEnum(value: %s) }" % INVALID_VALUE)
    assert result.errors is not None
Beispiel #31
0
import os

from ariadne import QueryType, load_schema_from_path, make_executable_schema

from .analytics import analytics
from .status import status
from .versioncheck import version_check

FILE_PATH = os.path.dirname(os.path.abspath(__file__))
SCHEMA_PATH = os.path.join(FILE_PATH, "schema.graphql")

type_defs = load_schema_from_path(SCHEMA_PATH)
schema = make_executable_schema(type_defs, [analytics, status, version_check])