async def test_issue154_input_type(sdl, should_exp): if should_exp: with pytest.raises(GraphQLSchemaError): Engine(sdl=sdl, schema_name=f"issue154_{sdl}") else: e = Engine(sdl=sdl, schema_name=f"issue154_{sdl}") assert e._schema is not None
async def test_engine_subscribe_with_default_resolver_alias(clean_registry): from tartiflette import Engine, Subscription, Resolver @Subscription("Subscription.counter", schema_name="subscribe_counter") async def _subscription_counter_subscription(parent_result, args, *_args, **_kwargs): start_at = args["startAt"] while start_at > 0: await asyncio.sleep(0.01) start_at -= 1 yield start_at e = Engine( """ type Query { a: String } type Subscription { counter(startAt: Int!): Int! } """, schema_name="subscribe_counter", ) expected_values = list(range(4)) async for result in e.subscribe( "subscription { aliasCounter: counter(startAt: 4) }"): assert result == {"data": {"aliasCounter": expected_values.pop()}}
async def test_issue154(sdl, should_exp, adddir): class aDirective(CommonDirective): pass if adddir: Directive("adirective", schema_name=f"issue154_{sdl}")(aDirective) if should_exp: with pytest.raises(GraphQLSchemaError): Engine(sdl=sdl, schema_name=f"issue154_{sdl}") else: e = Engine(sdl=sdl, schema_name=f"issue154_{sdl}") assert e._schema is not None
async def test_engine_execute_custom_error_coercer(clean_registry): from tartiflette.engine import Engine def custom_error_coercer(exception): error = default_error_coercer(exception) error["message"] = error["message"] + "Custom" return error e = Engine("type Query { a: String }", error_coercer=custom_error_coercer) assert await e.execute("query { unknownNode1 unknownNode2 }") == { "data": None, "errors": [ { "message": "field `Query.unknownNode1` was not found in GraphQL schema.Custom", "path": ["unknownNode1"], "locations": [{ "column": 9, "line": 1 }], }, { "message": "field `Query.unknownNode2` was not found in GraphQL schema.Custom", "path": ["unknownNode2"], "locations": [{ "column": 22, "line": 1 }], }, ], }
async def test_issue21_okayquery( query, expected, typee, varis, clean_registry ): from tartiflette.engine import Engine @Resolver("Query.a") async def a_resolver(_, arguments, __, info: Info): return {"iam": info.query_field.name, "args": arguments} ttftt = Engine( """ type Args{ xid: %s } type Obj { iam: String args: Args } type Query { a(xid: %s): Obj } """ % (typee, typee) ) results = await ttftt.execute( query, context={}, variables=varis, operation_name="LOL" ) assert results == expected
async def test_tartiflette_execute_enum_type_output(clean_registry): schema_sdl = """ enum Test { Value1 Value2 Value3 } type Query { enumTest: Test } """ @Resolver("Query.enumTest") async def func_field_resolver(*args, **kwargs): return "Value1" ttftt = Engine(schema_sdl) result = await ttftt.execute( """ query Test{ enumTest } """, operation_name="Test", ) assert {"data": {"enumTest": "Value1"}} == result
async def test_tartiflette_execute_object_type_output(clean_registry): schema_sdl = """ type Test { field1: String } type Query { objectTest: Test } """ @Resolver("Query.objectTest") async def func_field_resolver(*args, **kwargs): return {"field1": "Test"} ttftt = Engine(schema_sdl) result = await ttftt.execute( """ query Test{ objectTest { field1 } } """, operation_name="Test", ) assert {"data": {"objectTest": {"field1": "Test"}}} == result
async def test_tartiflette_execute_hello_world(clean_registry): schema_sdl = """ type Query { hello: String! } """ @Resolver("Query.hello") async def func_field_resolver(parent, arguments, request_ctx, info): return "world" ttftt = Engine(schema_sdl) result = await ttftt.execute( """ query Test{ hello } """, operation_name="Test", ) assert {"data": {"hello": "world"}} == result # Try twice to be sure everything works mutliple times result = await ttftt.execute( """ query Test{ hello } """, operation_name="Test", ) assert {"data": {"hello": "world"}} == result
async def test_engine_execute_parse_error(clean_registry): from tartiflette.engine import Engine e = Engine("type Query { a: String }") assert await e.execute("query { unknownNode1 unknownNode2 }") == { "data": None, "errors": [ { "message": "field `Query.unknownNode1` was not found in GraphQL schema.", "path": ["unknownNode1"], "locations": [{ "column": 9, "line": 1 }], }, { "message": "field `Query.unknownNode2` was not found in GraphQL schema.", "path": ["unknownNode2"], "locations": [{ "column": 22, "line": 1 }], }, ], }
async def test_tartiflette_execute_scalar_type_output(clean_registry): schema_sdl = """ type Query { lastUpdate: DateTime } """ @Resolver("Query.lastUpdate") async def func_field_resolver(*args, **kwargs): return datetime(year=2018, month=4, day=19, hour=14, minute=57, second=38) ttftt = Engine(schema_sdl) result = await ttftt.execute( """ query Test{ lastUpdate } """, operation_name="Test", ) assert {"data": {"lastUpdate": "2018-04-19T14:57:38"}} == result
async def test_issue21_exceptquery(query, expected, varis, clean_registry): from tartiflette.engine import Engine @Resolver("Query.a") async def a_resolver(_, arguments, __, info: Info): return {"iam": info.query_field.name, "args": arguments} ttftt = Engine( """ type Args{ xid: Int } type Obj { iam: String args: Args } type Query { a(xid: Int): Obj } """ ) assert await ttftt.execute(query, context={}, variables=varis) == expected
async def test_tartiflette_execute_enum_type_advanced(input_sdl, resolver_response, expected, clean_registry): schema_sdl = """ enum Test {{ Value1 Value2 Value3 }} type Query {{ testField: {} }} """.format(input_sdl) @Resolver("Query.testField") async def func_field_resolver(*args, **kwargs): return resolver_response ttftt = Engine(schema_sdl) result = await ttftt.execute( """ query Test{ testField } """, operation_name="Test", ) assert expected == result
async def test_engine_execute(clean_registry): from tartiflette.engine import Engine e = Engine("type Query { a:String }") result = await e.execute("query aquery { a }", operation_name="aquery") assert result == {"data": {"a": None}}
async def create_engine( sdl: Union[str, List[str]], schema_name: str = "default", error_coercer: Callable[[Exception, Dict[str, Any]], Dict[str, Any]] = None, custom_default_resolver: Optional[Callable] = None, custom_default_type_resolver: Optional[Callable] = None, modules: Optional[Union[str, List[str], List[Dict[str, Any]]]] = None, ) -> "Engine": """ Create an engine by analyzing the SDL and connecting it with the imported Resolver, Mutation, Subscription, Directive and Scalar linking them through the `schema_name`. :param sdl: the SDL to work with :param schema_name: the name of the SDL :param error_coercer: callable in charge of transforming a couple Exception/error into an error dictionary :param custom_default_resolver: callable that will replace the tartiflette `default_resolver` (Will be called like a resolver for each UNDECORATED field) :param custom_default_type_resolver: callable that will replace the tartiflette `default_type_resolver` (will be called on abstract types to deduct the type of a result) :param modules: list of string containing the name of the modules you want the engine to import, usually this modules contains your Resolvers, Directives, Scalar or Subscription code :type sdl: Union[str, List[str]] :type schema_name: str :type error_coercer: Callable[[Exception, Dict[str, Any]], Dict[str, Any]] :type custom_default_resolver: Optional[Callable] :type custom_default_type_resolver: Optional[Callable] :type modules: Optional[Union[str, List[str], List[Dict[str, Any]]]] :return: a Cooked Engine instance :rtype: Engine :Example: >>> from tartiflette import create_engine >>> >>> >>> engine = await create_engine('''type Query { >>> hello(name: String!): String! >>> }''') """ e = Engine() await e.cook( sdl=sdl, error_coercer=error_coercer, custom_default_resolver=custom_default_resolver, custom_default_type_resolver=custom_default_type_resolver, modules=modules, schema_name=schema_name, ) return e
def test_engine(clean_registry): from tartiflette.engine import Engine from tartiflette.schema.registry import SchemaRegistry e = Engine("type Query { a:String }") s = SchemaRegistry.find_schema() assert e._parser is not None assert s is not None assert s.name == "default" ee = Engine("type Query { a:String }", "Bob") ss = SchemaRegistry.find_schema("Bob") assert ee._parser is not None assert ss is not None assert ss.name == "Bob" assert ss != s
async def test_tartiflette_execute_union_type_output(query, expected, clean_registry): schema_sdl = """ type One { aField: String bField: Int } type Two { cField: Int dField: String } type Three { eField: Float fField: String } union Mixed = One | Two | Three type Query { test(choose: Int!): Mixed } """ @Resolver("Query.test") async def func_field_resolver(parent, arguments, request_ctx, info: Info): chosen = arguments.get("choose", 0) if chosen == 1: return {"aField": "aValue", "bField": 1, "_typename": "One"} elif chosen == 2: class Lol: def __init__(self, *args, **kwargs): self._typename = "Two" self.cField = 2 self.dField = "dValue" return Lol() elif chosen == 3: class Three: def __init__(self, *args, **kwargs): self.eField = 3.6 self.fField = "fValue" return Three() return None ttftt = Engine(schema_sdl) result = await ttftt.execute(query, operation_name="aquery") assert expected == result
async def test_tartiflette_engine_initialization_with_single_sdl_file( clean_registry ): engine = Engine(_curr_path + "/data/simple_full_sdl/simple_full.sdl") assert clean_registry.find_schema().find_type("Author") is not None assert clean_registry.find_schema().find_type("Blog") is not None assert clean_registry.find_schema().find_type("Post") is not None assert ( clean_registry.find_schema().find_type("Query").find_field("blogs") is not None )
async def test_tartiflette_engine_initialization_with_sdl_folder( path, clean_registry ): engine = Engine(path) assert clean_registry.find_schema().find_type("Author") is not None assert clean_registry.find_schema().find_type("Blog") is not None assert clean_registry.find_schema().find_type("Post") is not None assert ( clean_registry.find_schema().find_type("Query").find_field("blogs") is not None )
async def test_tartiflette_execute_object_type_unknown_field(clean_registry): schema_sdl = """ type Post { content: Content meta_creator: String } type Content { title: String } type Query { posts: [Post!] } """ mock_call = Mock() @Resolver("Content.title") async def func_field_resolver(*args, **kwargs): mock_call() return "Test" @Resolver("Post.content") async def func_field_resolver(*args, **kwargs): return {"title": "Stuff"} Post = namedtuple("Post", ["content", "meta_creator"]) Content = namedtuple("Content", ["title"]) @Resolver("Query.posts") async def func_field_resolver(*args, **kwargs): return [ Post(content=Content(title="Test"), meta_creator="Dailymotion") ] ttftt = Engine(schema_sdl) result = await ttftt.execute( """ query Test{ posts { content { title } } } """, operation_name="Test", ) assert result == {"data": {"posts": [{"content": {"title": "Test"}}]}} assert mock_call.called is True
async def test_arguments_in_sdl(sdl, query, expected, varis, clean_registry): @Resolver("Query.bob") async def func_bob_resolver(_pr, arguments, _ctx, _info): return arguments["id"] + 2 ttftt = Engine(sdl) result = await ttftt.execute( query, variables=varis, operation_name="aQuery" ) assert expected == result
async def test_tartiflette_nested_resolvers(clean_registry): schema_sdl = """ type Query { rootField: RootType } type RootType { nestedField: NestedType } type NestedType { endField: String } """ @Resolver("Query.rootField") async def func_resolver(parent, arguments, request_ctx, info): return {"nestedField": "Nested ?"} @Resolver("RootType.nestedField") async def func_resolver(parent, arguments, request_ctx, info): return {"endField": "Another"} @Resolver("NestedType.endField") async def func_resolver(parent, arguments, request_ctx, info): return "Test" ttftt = Engine(schema_sdl) result = await ttftt.execute( """ query Test{ rootField { nestedField { endField } } } """, operation_name="Test", ) assert result == { "data": { "rootField": { "nestedField": { "endField": "Test" } } } }
async def test_engine_execute_syntax_error(clean_registry): from tartiflette.engine import Engine e = Engine("type Query { a: String }") assert await e.execute("query { a { }") == { "data": None, "errors": [{ "message": "1.12: unrecognized character \\xc2", "path": None, "locations": [], }], }
async def test_engine_execute_empty_req_except(clean_registry): from tartiflette.engine import Engine e = Engine("type Query { a: String }") assert await e.execute("") == { "data": None, "errors": [{ "message": "1.1: syntax error, unexpected EOF", "path": None, "locations": [], }], }
async def test_tartiflette_non_introspectable_execution_directive( clean_registry): schema = """ type Query { fieldNormal: Int fieldHiddendToIntrospactable: Int @non_introspectable } """ @Resolver("Query.fieldNormal") async def func_field_resolver4(parent, arguments, request_ctx, info): return 42 @Resolver("Query.fieldHiddendToIntrospactable") async def func_field_resolver5(parent, arguments, request_ctx, info): return 42 ttftt = Engine(schema) assert (clean_registry.find_schema().find_directive("non_introspectable") is not None) assert (clean_registry.find_schema().find_directive( "non_introspectable").implementation is not None) result = await ttftt.execute( """ query Test{ __type(name: "Query") { fields { name isDeprecated deprecationReason } } } """, operation_name="Test", ) assert { "data": { "__type": { "fields": [{ "name": "fieldNormal", "isDeprecated": False, "deprecationReason": None, }] } } } == result
async def test_tartiflette_execute_basic(clean_registry): schema_sdl = """ schema { query: RootQuery } type RootQuery { defaultField: Int testField: Test } type Test { field: String } """ mock_one = Mock() mock_two = Mock() @Resolver("Test.field") async def func_field_resolver(*_args, **_kwargs): mock_one() return None @Resolver("RootQuery.testField") async def func_testfield_resolver(*_args, **_kwargs): return {} @Resolver("RootQuery.defaultField") async def func_default_query_resolver(*_args, **_kwargs): mock_two() return 1 ttftt = Engine(schema_sdl) result = await ttftt.execute( """ query Test{ testField { field } } """, operation_name="Test", ) assert result == {"data": {"testField": {"field": None}}} assert mock_one.called is True assert mock_two.called is False
async def test_tartiflette_execute_nested_coercion(clean_registry): schema_sdl = """ type Book { title: String! authors: [Author] } type Author { name: String! } type Query { library: [Book!] } """ Book = namedtuple("Book", "title,authors") Author = namedtuple("Author", "name") @Resolver("Query.library") async def func_field_library_resolver(*args, **kwargs): return [Book("A new beginning", [Author("Lemony Snicket")])] ttftt = Engine(sdl=schema_sdl) result = await ttftt.execute( """ query TestExecutionCoercion{ library { title authors { name } } } """, operation_name="TestExecutionCoercion", ) assert { "data": { "library": [ { "title": "A new beginning", "authors": [{"name": "Lemony Snicket"}], } ] } } == result
async def test_tartiflette_deprecated_execution_directive(clean_registry): schema = """ type Query { fieldNormal: Int fieldDeprecatedDefault: Int @deprecated fieldDeprecatedCustom: Int @deprecated(reason: "Unused anymore") } """ @Resolver("Query.fieldNormal") async def func_field_resolver4(parent, arguments, request_ctx, info): return 42 @Resolver("Query.fieldDeprecatedDefault") async def func_field_resolver5(parent, arguments, request_ctx, info): return 42 @Resolver("Query.fieldDeprecatedCustom") async def func_field_resolver6(parent, arguments, request_ctx, info): return 42 ttftt = Engine(schema) assert (clean_registry.find_schema().find_directive("deprecated") is not None) assert (clean_registry.find_schema().find_directive( "deprecated").implementation is not None) result = await ttftt.execute( """ query Test{ fieldNormal fieldDeprecatedDefault fieldDeprecatedCustom } """, operation_name="Test", ) assert { "data": { "fieldNormal": 42, "fieldDeprecatedDefault": 42, "fieldDeprecatedCustom": 42, } } == result
async def test_tartiflette_declare_custom_scalar(clean_registry): from tartiflette import Scalar sdl = """ scalar Ntm type Lol { joey: Ntm } type Query { alol: Lol } """ @Resolver("Query.alol") async def alol_resolver(*_, **__): class customobject: def __init__(self, p1): self.p1 = p1 return {"joey": customobject("OL")} @Scalar(name="Ntm") class Ntm: @staticmethod def coerce_output(val): return "I'am a val %s " % val.p1 @staticmethod def coerce_input(val): return val ttftt = Engine(sdl) result = await ttftt.execute( query=""" query { alol { joey } } """ ) assert {"data": {"alol": {"joey": "I'am a val OL "}}} == result
async def test_engine_execute_unhandled_exception(clean_registry): from tartiflette.engine import Engine e = Engine("type Query { a: Ninja } type Ninja { a: String }") assert (await e.execute(""" fragment AFragment on Ninja { a } fragment AFragment on Ninja { a } query { a { } } """) == { "data": None, "errors": [{ "message": "4.20: unrecognized character \\xc2", "path": None, "locations": [], }], })
async def test_tartiflette_engine_initialization_with_sdl_file_list( clean_registry ): engine = Engine( [ _curr_path + "/data/splitted_sdl/author.sdl", _curr_path + "/data/splitted_sdl/blog.sdl", _curr_path + "/data/splitted_sdl/post.sdl", _curr_path + "/data/splitted_sdl/query.sdl", ] ) assert clean_registry.find_schema().find_type("Author") is not None assert clean_registry.find_schema().find_type("Blog") is not None assert clean_registry.find_schema().find_type("Post") is not None assert ( clean_registry.find_schema().find_type("Query").find_field("blogs") is not None )