def make_app(db: AsyncIOMotorClient = None): try: if not db: db = AsyncIOMotorClient(DB_URL).get_database() graphiql = GraphiQL( # path=MONGOKE_BASE_PATH, default_headers={ "Authorization": "Bearer " + GRAPHIQL_DEFAULT_JWT } if GRAPHIQL_DEFAULT_JWT else {}, default_query=GRAPHIQL_QUERY, ) context = {"db": db, "loop": None} app = TartifletteApp( context=context, engine=engine, path=MONGOKE_BASE_PATH, graphiql=graphiql if not DISABLE_GRAPHIQL else False, ) app = CORSMiddleware( app, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"], ) app = JwtMiddleware(app, ) # app = CatchAll(app,) app = ServerErrorMiddleware(app, ) return app except Exception as e: print('got an error starting the Mongoke server:') print(e) return
async def test_post_invalid_json(engine: Engine) -> None: app = TartifletteApp(engine=engine) async with get_client(app) as client: response = await client.post( "/", data="{test", headers={"content-type": "application/json"}) assert response.status_code == 400 assert response.json() == {"error": "Invalid JSON."}
def fixture_client(engine: Engine, subscriptions, pubsub: PubSub) -> TestClient: ttftt = TartifletteApp(engine=engine, subscriptions=subscriptions, context={"pubsub": pubsub}) with TestClient(ttftt) as client: yield client
async def test_post_invalid_media_type(engine: Engine) -> None: app = TartifletteApp(engine=engine) async with get_client(app) as client: response = await client.post("/", data="{ hello }", headers={"content-type": "dummy"}) assert response.status_code == 415 assert response.text == "Unsupported Media Type"
async def test_post_querystring_variables(engine: Engine) -> None: app = TartifletteApp(engine=engine) async with get_client(app) as client: response = await client.post( ("/?query=query($name: String) { hello(name: $name) }" '&variables={ "name": "world" }')) assert response.status_code == 200 assert response.json() == {"data": {"hello": "Hello world"}}
async def test_get_invalid_json(engine: Engine) -> None: app = TartifletteApp(engine=engine) async with get_client(app) as client: response = await client.get("/?query={ hello }&variables={test") assert response.status_code == 400 assert response.json() == { "error": "Unable to decode variables: Invalid JSON." }
def fixture_client( engine: Engine, subscriptions: typing.Any, pubsub: PubSub ) -> typing.Iterator[TestClient]: ttftt = TartifletteApp( engine=engine, subscriptions=subscriptions, context={"pubsub": pubsub} ) with TestClient(ttftt) as client: # type: TestClient # type: ignore yield client
def test_path(engine: Engine) -> None: ttftt = TartifletteApp(engine=engine, path="/graphql") with TestClient(ttftt) as client: assert client.get("/").status_code == 404 response = client.get("/graphql?query={ hello }") assert response.status_code == 200 assert response.json() == {"data": {"hello": "Hello stranger"}}
async def test_post_graphql(engine: Engine) -> None: app = TartifletteApp(engine=engine) async with get_client(app) as client: response = await client.post( "/", data="{ hello }", headers={"content-type": "application/graphql"}) assert response.status_code == 200 assert response.json() == {"data": {"hello": "Hello stranger"}}
async def test_path(engine: Engine) -> None: app = TartifletteApp(engine=engine, path="/graphql") async with get_client(app) as client: response = await client.get("/") assert response.status_code == 404 response = await client.get("/graphql?query={ hello }") assert response.status_code == 200 assert response.json() == {"data": {"hello": "Hello stranger"}}
def test_extra_context(engine: Engine, context: typing.Optional[dict]): ttftt = TartifletteApp(engine=engine, context=context) with TestClient(ttftt) as client: response = client.post("/", json={"query": "{ foo }"}) assert response.status_code == 200 expected_foo = "bar" if context else "default" assert response.json() == {"data": {"foo": expected_foo}}
async def test_post_graphql_variables(engine: Engine) -> None: app = TartifletteApp(engine=engine) async with get_client(app) as client: response = await client.post( '/?variables={ "name": "world" }', data="query($name: String) { hello(name: $name) }", headers={"content-type": "application/graphql"}, ) assert response.status_code == 200 assert response.json() == {"data": {"hello": "Hello world"}}
async def test_post_querystring_invalid_json(engine: Engine) -> None: app = TartifletteApp(engine=engine) async with get_client(app) as client: response = await client.post( "/?query=query($name: String) { hello(name: $name) }&variables={test" ) assert response.status_code == 400 assert response.json() == { "error": "Unable to decode variables: Invalid JSON." }
def test_if_subscriptions_disabled_then_cannot_connect( engine: Engine, subscriptions: typing.Any) -> None: kwargs = {} if subscriptions is not MISSING: kwargs["subscriptions"] = subscriptions app = TartifletteApp(engine=engine, **kwargs) with TestClient(app) as client: # type: TestClient # type: ignore with pytest.raises(WebSocketDisconnect): client.websocket_connect("/subscriptions")
def test_if_subscriptions_disabled_then_cannot_connect(engine: Engine, subscriptions): kwargs = {} if subscriptions is not MISSING: kwargs["subscriptions"] = subscriptions ttftt = TartifletteApp(engine=engine, **kwargs) with TestClient(ttftt) as client: with pytest.raises(WebSocketDisconnect): client.websocket_connect("/subscriptions")
async def test_error_handling(engine: Engine) -> None: app = TartifletteApp(engine=engine) async with get_client(app) as client: response = await client.post("/", json={"query": "{ dummy }"}) assert response.status_code == 400 json = response.json() assert json["data"] is None assert len(json["errors"]) == 1 error = json["errors"][0] assert error["locations"] == [{"column": 3, "line": 1}] assert "dummy" in error["message"] assert error["path"] == ["dummy"]
def test_defaults(engine: Engine, variables: dict, query: str, headers: dict): graphiql = GraphiQL(default_variables=variables, default_query=query, default_headers=headers) ttftt = TartifletteApp(engine=engine, graphiql=graphiql) with build_graphiql_client(ttftt) as client: response = client.get("/") assert response.status_code == 200 assert json.dumps(variables) in response.text assert inspect.cleandoc(query) in response.text assert json.dumps(headers) in response.text
async def test_post_json_variables(engine: Engine) -> None: app = TartifletteApp(engine=engine) async with get_client(app) as client: response = await client.post( "/", json={ "query": "query($name: String) { hello(name: $name) }", "variables": { "name": "world" }, }, ) assert response.status_code == 200 assert response.json() == {"data": {"hello": "Hello world"}}
async def test_must_register_startup_handler(engine: Engine) -> None: graphql = TartifletteApp(engine=engine) app = Starlette(routes=[Mount("/graphql", graphql)], on_startup=[]) async with get_client(app) as client: with pytest.raises(RuntimeError) as ctx: await client.get("/graphql") error = str(ctx.value).lower() assert "hint" in error assert "starlette example" in error assert ".add_event_handler" in error assert "'startup'" in error assert ".startup" in error
async def test_defaults(engine: Engine, variables: dict, query: str, headers: dict) -> None: graphiql = GraphiQL(default_variables=variables, default_query=query, default_headers=headers) app = TartifletteApp(engine=engine, graphiql=graphiql) async with get_client(app) as client: response = await client.get("/", headers={"accept": "text/html"}) assert response.status_code == 200 assert json.dumps(variables) in response.text assert inspect.cleandoc(query) in response.text assert json.dumps(headers) in response.text
def test_endpoint_paths_when_mounted(starlette: Starlette, engine: Engine, mount_path: str) -> None: ttftt = TartifletteApp(engine=engine, graphiql=True, subscriptions=True) mount.starlette(starlette, mount_path, ttftt) with TestClient(starlette) as client: response = client.get(mount_path, headers={"accept": "text/html"}) assert response.status_code == 200 graphql_endpoint = mount_path + "/" assert fr"var graphQLEndpoint = `{graphql_endpoint}`;" in response.text subscriptions_endpoint = mount_path + "/subscriptions" assert fr"var subscriptionsEndpoint = `{subscriptions_endpoint}`;" in response.text
def test_protocol_connect_disconnect(engine: Engine, subscriptions: typing.Any, pubsub: PubSub, path: str) -> None: app = TartifletteApp(engine=engine, subscriptions=subscriptions, context={"pubsub": pubsub}) with TestClient(app) as client: # type: typing.Any with client.websocket_connect(path) as ws: _init(ws) _terminate(ws) with pytest.raises(WebSocketDisconnect) as ctx: ws.receive_json() exc: WebSocketDisconnect = ctx.value assert exc.code == 1011
async def test_graphiql_endpoint_paths_when_mounted(engine: Engine, mount_path: str) -> None: graphql = TartifletteApp(engine=engine, graphiql=True, subscriptions=True) app = Starlette(routes=[Mount(mount_path, graphql)], on_startup=[graphql.startup]) async with get_client(app) as client: response = await client.get(mount_path, headers={"accept": "text/html"}) assert response.status_code == 200 graphql_endpoint = mount_path + "/" assert f"var graphQLEndpoint = `{graphql_endpoint}`;" in response.text subscriptions_endpoint = mount_path + "/subscriptions" assert f"var subscriptionsEndpoint = `{subscriptions_endpoint}`;" in response.text
async def test_graphiql(engine: Engine, graphiql: typing.Any, path: str) -> None: app = TartifletteApp(engine=engine, graphiql=graphiql) async with get_client(app) as client: response = await client.get(path, headers={"accept": "text/html"}) assert response.status_code == 200 if graphiql else 404 if response.status_code == 200: assert "<!DOCTYPE html>" in response.text m = re.search(r"var (\w+) = `/`;", response.text) assert m is not None, response.text endpoint_variable_name = m.group(1) assert f"fetch({endpoint_variable_name}," in response.text assert "None" not in response.text else: assert response.text == "Not Found"
def test_tartiflette_app_as_sub_starlette_app(engine: Engine) -> None: async def home(_request: Request) -> PlainTextResponse: return PlainTextResponse("Hello, world!") graphql = TartifletteApp(engine=engine) routes = [ Route("/", endpoint=home), Mount("/graphql", app=graphql, name="tartiflette-asgi"), ] app = Starlette(routes=routes, on_startup=[graphql.startup]) with TestClient(app) as client: response = client.get("/") assert response.status_code == 200 assert response.text == "Hello, world!" response = client.get("/graphql?query={ hello }") assert response.status_code == 200 assert response.json() == {"data": {"hello": "Hello stranger"}}
def test_starlette_mount(starlette: Starlette, engine: Engine, mount_path: str, path: str): kwargs = omit_none({"engine": engine, "path": path}) app = TartifletteApp(**kwargs) mount.starlette(starlette, mount_path, app) query = "{ hello }" full_path = mount_path.rstrip("/") + ("/" if path is None else path) assert "//" not in full_path url = f"{full_path}?query={query}" with TestClient(starlette) as client: response = client.get(url) graphiql_response = client.get(url, headers={"accept": "text/html"}) assert response.status_code == 200 assert response.json() == {"data": {"hello": "Hello stranger"}} assert graphiql_response.status_code == 200 assert full_path in graphiql_response.text
async def test_starlette_mount(engine: Engine, mount_path: str, path: str) -> None: kwargs = omit_none({"engine": engine, "path": path}) graphql = TartifletteApp(**kwargs) routes = [Mount(mount_path, graphql)] app = Starlette(routes=routes, on_startup=[graphql.startup]) query = "{ hello }" full_path = mount_path.rstrip("/") + ("/" if path is None else path) assert "//" not in full_path url = f"{full_path}?query={query}" async with get_client(app) as client: response = await client.get(url) graphiql_response = await client.get(url, headers={"accept": "text/html"}) assert response.status_code == 200 assert response.json() == {"data": {"hello": "Hello stranger"}} assert graphiql_response.status_code == 200 assert full_path in graphiql_response.text
def fixture_client(graphiql: typing.Any, engine: Engine) -> typing.Iterator[TestClient]: ttftt = TartifletteApp(engine=engine, graphiql=graphiql) with build_graphiql_client( ttftt) as client: # type: TestClient # type: ignore yield client
def fixture_ttftt(engine: Engine) -> TartifletteApp: return TartifletteApp(engine=engine)
async def test_get_querystring(engine: Engine) -> None: app = TartifletteApp(engine=engine) async with get_client(app) as client: response = await client.get("/?query={ hello }") assert response.status_code == 200 assert response.json() == {"data": {"hello": "Hello stranger"}}