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_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_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_subscribe_ramp_wave(engine: Engine): query = """ subscription { subscribeChannel(id: "ssim://rampwave(3, 0.2)") { value { stringArray } } } """ context = make_context() results = [] start = time.time() async for result in engine.subscribe(query, context=context): results.append(result) if len(results) == 4: break # First result immediate, then takes 3x 0.2s assert time.time() - start - 0.6 < 0.2 expected = [ ["0.00000", "1.00000", "2.00000"], ["1.00000", "2.00000", "3.00000"], ["2.00000", "3.00000", "4.00000"], ["3.00000", "4.00000", "5.00000"], ] for i, x in enumerate(expected): assert results[i] == dict(data=dict(subscribeChannel=dict(value=dict( stringArray=x))))
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_advanced( input_sdl, resolver_response, expected, clean_registry): schema_sdl = """ type Test {{ field1: String }} 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 { field1 } } """, operation_name="Test", ) assert expected == 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
def make_engine() -> Engine: engine = Engine( sdl=Path(__file__).resolve().parent / "schema.gql", error_coercer=error_coercer, modules=["coniql.resolvers"], ) return engine
def __init__( self, *, engine: Engine = None, sdl: str = None, graphiql: typing.Union[None, bool, GraphiQL] = True, path: str = "/", subscriptions: typing.Union[bool, Subscriptions] = None, context: dict = None, schema_name: str = "default", ) -> None: if engine is None: assert sdl, "`sdl` expected if `engine` not given" engine = Engine(sdl=sdl, schema_name=schema_name) assert engine, "`engine` expected if `sdl` not given" self.engine = engine if context is None: context = {} if graphiql is True: graphiql = GraphiQL() elif not graphiql: graphiql = None assert graphiql is None or isinstance(graphiql, GraphiQL) if subscriptions is True: subscriptions = Subscriptions(path="/subscriptions") elif not subscriptions: subscriptions = None assert subscriptions is None or isinstance(subscriptions, Subscriptions) self.router = Router(on_startup=[self.startup]) if graphiql and graphiql.path is not None: self.router.add_route(path=graphiql.path, endpoint=GraphiQLEndpoint) self.router.add_route(path=path, endpoint=GraphQLEndpoint) if subscriptions is not None: self.router.add_websocket_route(path=subscriptions.path, endpoint=SubscriptionEndpoint) config = GraphQLConfig( engine=self.engine, context=context, graphiql=graphiql, path=path, subscriptions=subscriptions, ) self.app = GraphQLMiddleware(self.router, config=config) self._started_up = False
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_subscribe_ticking(engine: Engine, ioc: Popen): query = (""" subscription { subscribeChannel(id: "ca://%sticking") { value { string(units: true) } display { precision units } } } """ % PV_PREFIX) results = [] wait_for_ioc(ioc) start = time.time() async for result in engine.subscribe(query, context=make_context()): results.append(result) if time.time() - start > 0.9: break for i, x in enumerate(range(3)): display = None if i == 0: display = dict(precision=5, units="mm") assert results[i] == dict(data=dict(subscribeChannel=dict( value=dict(string="%.5f mm" % x), display=display))) assert len(results) == 3
def test_issue201(): assert ( Engine( [f"{os.path.dirname(__file__)}/sdl/issue201.sdl"], schema_name="test_issue201", ) 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_engine_cook_is_idempotent(): from tartiflette import Engine sdl = "type Query { lol: Int }" engine = Engine(sdl) await engine.cook() await engine.cook()
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_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
def __init__( self, *, engine: Engine = None, sdl: str = None, graphiql: typing.Union[bool, GraphiQL] = True, path: str = "/", subscriptions: typing.Union[bool, Subscriptions] = None, context: dict = None, schema_name: str = "default", ): if engine is None: assert sdl, "`sdl` expected if `engine` not given" engine = Engine(sdl=sdl, schema_name=schema_name) assert engine, "`engine` expected if `sdl` not given" self.engine = engine if context is None: context = {} if graphiql is True: graphiql = GraphiQL() if subscriptions is True: subscriptions = Subscriptions(path="/subscriptions") routes = [] if graphiql and graphiql.path is not None: routes.append(Route(path=graphiql.path, endpoint=GraphiQLEndpoint)) graphql_route = Route(path=path, endpoint=GraphQLEndpoint) routes.append(graphql_route) if subscriptions is not None: subscription_route = WebSocketRoute(path=subscriptions.path, endpoint=SubscriptionEndpoint) routes.append(subscription_route) config = GraphQLConfig( engine=self.engine, context=context, graphiql=graphiql, path=graphql_route.path, subscriptions=subscriptions, ) router = Router(routes=routes) self.app = GraphQLMiddleware(router, config=config) self.lifespan = Lifespan(on_startup=self.startup) self._started_up = False
async def test_engine_init_no_loader(): import json from tartiflette import Engine e = Engine( sdl="""type A{ B:String } type Query { a:A }""", schema_name="test_issue362_test_engine_init_no_loader", ) await e.cook() assert e._schema.json_loader == json.loads
async def test_engine_api_sdl(sdl, expected, pass_to, clean_registry): from tartiflette import Engine if pass_to == "engine": e = Engine(sdl) else: e = Engine() if isinstance(expected, Exception): with pytest.raises(Exception): if pass_to == "cook": await e.cook(sdl) else: await e.cook() else: if pass_to == "cook": await e.cook(sdl) else: await e.cook() assert e._schema 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_engine_api_cdr(cdr, expected, pass_to, clean_registry): from tartiflette import Engine sdl = "type Query { lol: Int }" if pass_to == "engine": e = Engine(sdl, custom_default_resolver=cdr) else: e = Engine() if isinstance(expected, Exception): with pytest.raises(Exception): if pass_to == "cook": await e.cook(sdl, custom_default_resolver=cdr) else: await e.cook() else: if pass_to == "cook": await e.cook(sdl, custom_default_resolver=cdr) else: await e.cook() assert e._schema is not None
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_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)
async def test_engine_cook_loader(): def my_loader(*_args, **__kwargs): pass from tartiflette import Engine e = Engine( sdl="""type A{ B:String } type Query { a:A }""", schema_name="test_issue362_test_engine_cook_loader", ) await e.cook(json_loader=my_loader) assert e._schema.json_loader == my_loader
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 init(app): log.critical("Loading GraphQL SDL and install resolvers...") engine = app["engine"] = Engine( os.path.join(os.path.dirname(os.path.abspath(__file__)), "sdl"), modules=["gen3.peregrine.resolvers"], ) register_graphql_handlers( app=app, engine=engine, subscription_ws_endpoint=f"{config.PEREGRINE_PREFIX}ws", executor_http_endpoint=f"{config.PEREGRINE_PREFIX}graphql", executor_http_methods=["POST"], graphiql_enabled=config.PEREGRINE_GRAPHIQL, graphiql_options=dict(endpoint=f"{config.PEREGRINE_PREFIX}graphiql"), ) return engine
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_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"}}} }