def schema(session_maker): from tests.query import Query schema = Schema(query=Query) schema.set_session_factory(session_factory=session_maker) return schema
def test_should_query_filter_node_limit(): class ReporterFilter(FilterSet): limit = NumberFilter(method="filter_limit") def filter_limit(self, queryset, name, value): return queryset[:value] class Meta: model = Reporter fields = ["first_name"] class ReporterType(DjangoObjectType): class Meta: model = Reporter interfaces = (Node,) class ArticleType(DjangoObjectType): class Meta: model = Article interfaces = (Node,) filter_fields = ("lang",) class Query(ObjectType): all_reporters = DjangoFilterConnectionField( ReporterType, filterset_class=ReporterFilter ) def resolve_all_reporters(self, info, **args): return Reporter.objects.order_by("a_choice") Reporter.objects.create( first_name="Bob", last_name="Doe", email="*****@*****.**", a_choice=2 ) r = Reporter.objects.create( first_name="John", last_name="Doe", email="*****@*****.**", a_choice=1 ) Article.objects.create( headline="Article Node 1", pub_date=datetime.now(), pub_date_time=datetime.now(), reporter=r, editor=r, lang="es", ) Article.objects.create( headline="Article Node 2", pub_date=datetime.now(), pub_date_time=datetime.now(), reporter=r, editor=r, lang="en", ) schema = Schema(query=Query) query = """ query NodeFilteringQuery { allReporters(limit: 1) { edges { node { id firstName articles(lang: "es") { edges { node { id lang } } } } } } } """ expected = { "allReporters": { "edges": [ { "node": { "id": "UmVwb3J0ZXJUeXBlOjI=", "firstName": "John", "articles": { "edges": [ {"node": {"id": "QXJ0aWNsZVR5cGU6MQ==", "lang": "ES"}} ] }, } } ] } } result = schema.execute(query) assert not result.errors assert result.data == expected
from starlette.routing import Route from starlette.graphql import GraphQLApp from graphene import ObjectType, String, Schema class Query(ObjectType): hello = String(name=String(default_value='stranger')) goodbye = String() def resolve_hello(self, info, name): return f'Hello {name}' def resolve_goodbye(self, info): return 'bye felicia' graphql_route = Route('/', endpoint=GraphQLApp(schema=Schema(query=Query)))
faction = get_faction(faction_id) return IntroduceShip(ship=ship, faction=faction) class Query(graphene.ObjectType): rebels = graphene.Field(Faction) empire = graphene.Field(Faction) node = relay.Node.Field() ships = DjangoConnectionField(Ship, description='All the ships.') @resolve_only_args def resolve_ships(self): return get_ships() @resolve_only_args def resolve_rebels(self): return get_rebels() @resolve_only_args def resolve_empire(self): return get_empire() class Mutation(graphene.ObjectType): introduce_ship = IntroduceShip.Field() # We register the Character Model because if not would be # inaccessible for the schema schema = Schema(query=Query, mutation=Mutation, types=[Ship, Character])
def test_filter_filterset_based_on_mixin(): class ArticleFilterMixin(FilterSet): @classmethod def get_filters(cls): filters = super(FilterSet, cls).get_filters() filters.update( { "viewer__email__in": django_filters.CharFilter( method="filter_email_in", field_name="reporter__email__in" ) } ) return filters def filter_email_in(cls, queryset, name, value): return queryset.filter(**{name: [value]}) class NewArticleFilter(ArticleFilterMixin, ArticleFilter): pass class NewReporterNode(DjangoObjectType): class Meta: model = Reporter interfaces = (Node,) class NewArticleFilterNode(DjangoObjectType): viewer = Field(NewReporterNode) class Meta: model = Article interfaces = (Node,) filterset_class = NewArticleFilter def resolve_viewer(self, info): return self.reporter class Query(ObjectType): all_articles = DjangoFilterConnectionField(NewArticleFilterNode) reporter_1 = Reporter.objects.create( first_name="John", last_name="Doe", email="*****@*****.**" ) article_1 = Article.objects.create( headline="Hello", reporter=reporter_1, editor=reporter_1, pub_date=datetime.now(), pub_date_time=datetime.now(), ) reporter_2 = Reporter.objects.create( first_name="Adam", last_name="Doe", email="*****@*****.**" ) article_2 = Article.objects.create( headline="Good Bye", reporter=reporter_2, editor=reporter_2, pub_date=datetime.now(), pub_date_time=datetime.now(), ) schema = Schema(query=Query) query = ( """ query NodeFilteringQuery { allArticles(viewer_Email_In: "%s") { edges { node { headline viewer { email } } } } } """ % reporter_1.email ) expected = { "allArticles": { "edges": [ { "node": { "headline": article_1.headline, "viewer": {"email": reporter_1.email}, } } ] } } result = schema.execute(query) assert not result.errors assert result.data == expected
return films class AddFilm(Mutation): film = Field(Film) class Arguments: film = Argument(AddFilmInput) async def mutate(self, info, film): new_film = db.add_film(film) return AddFilm(film=new_film) class DemoMutation(ObjectType): add_film = AddFilm.Field() # swapi.create_films_db() # swapi.create_characters_db() app = FastAPI() app.add_route( "/graphql", GraphQLApp( schema=Schema(query=DemoQuery, mutation=DemoMutation), executor_class=AsyncioExecutor, ), )
from graphene import Schema, ObjectType from department import Department, Mutation as DepartmentMutation, Query as DepartmentQuery from session import Session, Mutation as SessionMutation, Query as SessionQuery from teacher import Teacher, Mutation as TeacherMutation, Query as TeacherQuery from subject import Subject, Mutation as SubjectMutation, Query as SubjectQuery class Query(DepartmentQuery, TeacherQuery, SessionQuery, SubjectQuery, ObjectType): pass class Mutation(DepartmentMutation, TeacherMutation, SessionMutation, SubjectMutation, ObjectType): pass schema = Schema(query=Query, mutation=Mutation, types=[Teacher, Department, Session, Subject])
from graphene import ObjectType, String, Schema class Query(ObjectType): name = String() def resolve_name(root, info): print('root', root) print('info', info) print('info', dir(info)) print('info', info.context) print('info', dir(info.context)) return info.context.get('name') schema = Schema(Query) result = schema.execute('{ name }', context={'name': 'Syrus'}) print(result.data['name']) assert result.data['name'] == 'Syrus'
from graphene import Schema from brave_cane.api.partner.app_graphql.schemas_graphql import QueryPdv from brave_cane.api.partner.app_graphql.mutations import MutationPDV GQLPdv = Schema(query=QueryPdv, mutation=MutationPDV)
def test_resolvers(session): """Test that the correct resolver functions are called""" class ReporterMixin(object): def resolve_id(root, _info): return 'ID' class ReporterType(ReporterMixin, SQLAlchemyObjectType): class Meta: model = Reporter email = ORMField() email_v2 = ORMField(model_attr='email') favorite_pet_kind = Field(String) favorite_pet_kind_v2 = Field(String) def resolve_last_name(root, _info): return root.last_name.upper() def resolve_email_v2(root, _info): return root.email + '_V2' def resolve_favorite_pet_kind_v2(root, _info): return str(root.favorite_pet_kind) + '_V2' class Query(ObjectType): reporter = Field(ReporterType) def resolve_reporter(self, _info): return session.query(Reporter).first() reporter = Reporter(first_name='first_name', last_name='last_name', email='email', favorite_pet_kind='cat') session.add(reporter) session.commit() schema = Schema(query=Query) result = schema.execute(""" query { reporter { id firstName lastName email emailV2 favoritePetKind favoritePetKindV2 } } """) assert not result.errors # Custom resolver on a base class assert result.data['reporter']['id'] == 'ID' # Default field + default resolver assert result.data['reporter']['firstName'] == 'first_name' # Default field + custom resolver assert result.data['reporter']['lastName'] == 'LAST_NAME' # ORMField + default resolver assert result.data['reporter']['email'] == 'email' # ORMField + custom resolver assert result.data['reporter']['emailV2'] == 'email_V2' # Field + default resolver assert result.data['reporter']['favoritePetKind'] == 'cat' # Field + custom resolver assert result.data['reporter']['favoritePetKindV2'] == 'cat_V2'
def graphql_client(): class SchemaQuery(Query, ObjectType): pass client = Client(schema=Schema(query=SchemaQuery)) return client
class Mutations(ObjectType): clear_broadcast = ClearBroadcast.Field( description=ClearBroadcast._meta.description) expire_broadcast = ExpireBroadcast.Field( description=ExpireBroadcast._meta.description) put_broadcast = PutBroadcast.Field( description=PutBroadcast._meta.description) ext_trigger = ExternalTrigger.Field( description=ExternalTrigger._meta.description) hold_workflow = HoldWorkflow.Field( description=HoldWorkflow._meta.description) nudge_workflow = NudgeWorkflow.Field( description=NudgeWorkflow._meta.description) put_messages = PutMessages.Field( description=PutMessages._meta.description) release_workflow = ReleaseWorkflow.Field( description=ReleaseWorkflow._meta.description) reload_workflow = ReloadWorkflow.Field( description=ReloadWorkflow._meta.description) set_verbosity = SetVerbosity.Field( description=SetVerbosity._meta.description) stop_workflow = StopWorkflow.Field( description=StopWorkflow._meta.description) take_checkpoint = TakeCheckpoint.Field( description=TakeCheckpoint._meta.description) task_actions = TaskActions.Field( description=TaskActions._meta.description) schema = Schema(query=Queries, mutation=Mutations)
"""Configuration Schema module, this is where all project queries will be register.""" from graphene import ObjectType, Schema from graphene.relay import Node from src.token.mutation import Mutations as TokenMutation from src.token.query import Query as TokenQuery from src.user.mutation import Mutations as UserMutation from src.user.query import Query as UserQuery class Query(UserQuery, TokenQuery, ObjectType): """All GraphQL Queries in project.""" node = Node.Field() class Mutation(UserMutation, TokenMutation, ObjectType): """All GraphQL Mutations in project.""" SCHEMA = Schema(query=Query, mutation=Mutation)
class ServerRootQuery(ObjectType): node = relay.Node.Field() class Subscription(ObjectType): kernel = Field(stitch(KernelRootQuery)) def resolve_kernel(self, info): assert len(info.field_asts) == 1 assert info.field_asts[0].name.value == 'kernel' return rx.Observable.merge( rx.Observable.just(True), # Send data at least once info.context.reloadable ).flat_map( lambda _: rx.Observable.from_future( asyncio.get_running_loop().create_task( info.context.reloadable.call( info.context.kernel.query, construct_stitched_query(info), variables=info.variable_values))) ).map(lambda result: stitch(KernelRootQuery)(json.loads(result))) schema = Schema(query=ServerRootQuery, subscription=Subscription) if __name__ == '__main__': print(json.dumps({'data': schema.introspect()}))
def test_integer_field_filter_type(): class PetType(DjangoObjectType): class Meta: model = Pet interfaces = (Node,) filter_fields = {"age": ["exact"]} fields = ("age",) class Query(ObjectType): pets = DjangoFilterConnectionField(PetType) schema = Schema(query=Query) assert str(schema) == dedent( """\ type Query { pets(offset: Int = null, before: String = null, after: String = null, first: Int = null, last: Int = null, age: Int = null): PetTypeConnection } type PetTypeConnection { \"""Pagination data for this connection.\""" pageInfo: PageInfo! \"""Contains the nodes in this connection.\""" edges: [PetTypeEdge]! } \""" The Relay compliant `PageInfo` type, containing data necessary to paginate this connection. \""" type PageInfo { \"""When paginating forwards, are there more items?\""" hasNextPage: Boolean! \"""When paginating backwards, are there more items?\""" hasPreviousPage: Boolean! \"""When paginating backwards, the cursor to continue.\""" startCursor: String \"""When paginating forwards, the cursor to continue.\""" endCursor: String } \"""A Relay edge containing a `PetType` and its cursor.\""" type PetTypeEdge { \"""The item at the end of the edge\""" node: PetType \"""A cursor for use in pagination\""" cursor: String! } type PetType implements Node { age: Int! \"""The ID of the object\""" id: ID! } \"""An object with an ID\""" interface Node { \"""The ID of the object\""" id: ID! } """ )
import graphene from graphene import ObjectType, Schema from tornado.escape import to_unicode class QueryRoot(ObjectType): thrower = graphene.String(required=True) request = graphene.String(required=True) test = graphene.String(who=graphene.String()) def resolve_thrower(self, info): raise Exception("Throws!") def resolve_request(self, info): return to_unicode(info.context.arguments['q'][0]) def resolve_test(self, info, who=None): return 'Hello %s' % (who or 'World') class MutationRoot(ObjectType): write_test = graphene.Field(QueryRoot) def resolve_write_test(self, info): return QueryRoot() schema = Schema(query=QueryRoot, mutation=MutationRoot)
@staticmethod def resolve_viewer(root, _): """ Return the current viewer, if existed :param root: the root object :return: object represents current viewer, or None """ return root.get("viewer") @staticmethod def resolve_posts(_, info, **kwargs): """ Return the search based on query (or show them all) :param info: the info (context, etc.) on query :param kwargs: rest of the query :return: a list of post """ keyword = "%{}%".format(kwargs.get("query", "")) query = Post.get_query(info) return query.filter( or_(models.Post.title.like(keyword), models.Post.content.like(keyword), models.Post.excerpt.like(keyword))).all() schema = Schema(query=Query, mutation=Mutations, types=[User, Post, Tag, Comment, Category])
from graphene import ObjectType, Schema from graphql_jwt import ObtainJSONWebToken, Refresh, Verify from app.schema import AppMutation class Mutation(ObjectType, AppMutation): token_auth = ObtainJSONWebToken.Field() verify_token = Verify.Field() refresh_token = Refresh.Field() ROOT_SCHEMA = Schema(mutation=Mutation)
link = Links.query.filter_by(full_url=url).first() if link: return link.short_url else: link = Links(full_url=url, short_url=short_url) if link.full_url.find("http://") != 0: link.full_url = "http://" + link.full_url db.session.add(link) db.session.commit() return link.short_url class ExampleQuery(ObjectType, Url): hello = String(name=String(default_value="World")) link = String(url=String()) def resolve_hello(self, info, name): return f"Hello {name}" # def resolve_link(self, info, url): # link = short_code(url) # return link class RootQuery(ExampleQuery, ObjectType): pass schema = Schema(query=RootQuery)
from graphene import ObjectType, Schema, String from app.modules.murmurations.mutations import UpdateMutation, UpdateRecords from graphene import ObjectType from app.modules.murmurations.queries.MurmurationRecord import MurmurationRecord class RecordQuery(MurmurationRecord, ObjectType): pass class RootQuery(RecordQuery, ObjectType): pass class RootMutation(ObjectType): update_cache = UpdateRecords.Field() schema = Schema(query=RootQuery, mutation=RootMutation)
def test_sort_query(session): add_pets(session) class PetNode(SQLAlchemyObjectType): class Meta: model = Pet interfaces = (Node, ) class Query(ObjectType): defaultSort = SQLAlchemyConnectionField(PetNode.connection) nameSort = SQLAlchemyConnectionField(PetNode.connection) multipleSort = SQLAlchemyConnectionField(PetNode.connection) descSort = SQLAlchemyConnectionField(PetNode.connection) singleColumnSort = SQLAlchemyConnectionField(PetNode.connection, sort=Argument( PetNode.sort_enum())) noDefaultSort = SQLAlchemyConnectionField( PetNode.connection, sort=PetNode.sort_argument(has_default=False)) noSort = SQLAlchemyConnectionField(PetNode.connection, sort=None) query = """ query sortTest { defaultSort { edges { node { name } } } nameSort(sort: NAME_ASC) { edges { node { name } } } multipleSort(sort: [PET_KIND_ASC, NAME_DESC]) { edges { node { name petKind } } } descSort(sort: [NAME_DESC]) { edges { node { name } } } singleColumnSort(sort: NAME_DESC) { edges { node { name } } } noDefaultSort(sort: NAME_ASC) { edges { node { name } } } } """ def makeNodes(nodeList): nodes = [{"node": item} for item in nodeList] return {"edges": nodes} expected = { "defaultSort": makeNodes( [{"name": "Lassie"}, {"name": "Barf"}, {"name": "Alf"}] ), "nameSort": makeNodes([{"name": "Alf"}, {"name": "Barf"}, {"name": "Lassie"}]), "noDefaultSort": makeNodes( [{"name": "Alf"}, {"name": "Barf"}, {"name": "Lassie"}] ), "multipleSort": makeNodes( [ {"name": "Alf", "petKind": "CAT"}, {"name": "Lassie", "petKind": "DOG"}, {"name": "Barf", "petKind": "DOG"}, ] ), "descSort": makeNodes([{"name": "Lassie"}, {"name": "Barf"}, {"name": "Alf"}]), "singleColumnSort": makeNodes( [{"name": "Lassie"}, {"name": "Barf"}, {"name": "Alf"}] ), } # yapf: disable schema = Schema(query=Query) result = schema.execute(query, context_value={"session": session}) assert not result.errors result = to_std_dicts(result.data) assert result == expected queryError = """ query sortTest { singleColumnSort(sort: [PET_KIND_ASC, NAME_DESC]) { edges { node { name } } } } """ result = schema.execute(queryError, context_value={"session": session}) assert result.errors is not None assert 'cannot represent non-enum value' in result.errors[0].message queryNoSort = """ query sortTest { noDefaultSort { edges { node { name } } } noSort { edges { node { name } } } } """ result = schema.execute(queryNoSort, context_value={"session": session}) assert not result.errors # TODO: SQLite usually returns the results ordered by primary key, # so we cannot test this way whether sorting actually happens or not. # Also, no sort order is guaranteed by SQLite if "no order" by is used. assert [node["node"]["name"] for node in result.data["noSort"]["edges"]] == [ node["node"]["name"] for node in result.data["noDefaultSort"]["edges"] ]
from graphene import Schema from flask import Flask from flask_graphql import GraphQLView from functools import lru_cache import schema as s schema = Schema(query=s.Query) app = Flask(__name__) app.add_url_rule('/graphql', view_func=GraphQLView.as_view( 'graphql', schema=schema, graphiql=True, )) if __name__ == '__main__': app.run(host='0.0.0.0')
break logger.debug( 'resolve_search_current_snapshot_items %r found %s items in %.3f s', path_query, len(found_items), monotime() - t) return found_items async def resolve_active_alerts(root, info): return await get_model(info).alerts.list_active() async def resolve_active_unacknowledged_alerts(root, info): return await get_model(info).alerts.list_active_unacknowledged() async def resolve_active_acknowledged_alerts(root, info): return await get_model(info).alerts.list_active_acknowledged() async def resolve_inactive_alerts(root, info): return await get_model(info).alerts.list_inactive(limit=1000) async def resolve_alert(root, info, alert_id): return await get_model(info).alerts.get_by_id(alert_id) def get_model(info): if 'request' in info.context: return info.context['request'].app['model'] return info.context['model'] graphql_schema = Schema(query=Query)
abstract = True class Article(DjangoObjectType): '''Article description''' class Meta: model = ArticleModel interfaces = (Node, ) connection_class = ArticleConnection class RootQuery(ObjectType): node = Node.Field() schema = Schema(query=RootQuery, types=[Article, Reporter]) def test_django_interface(): assert issubclass(Node, Interface) assert issubclass(Node, Node) @patch('graphene_django.tests.models.Article.objects.get', return_value=Article(id=1)) def test_django_get_node(get): article = Article.get_node(None, 1) get.assert_called_with(pk=1) assert article.id == 1
def test_filter_filterset_related_results(): class ReporterFilterNode(DjangoObjectType): class Meta: model = Reporter interfaces = (Node,) filter_fields = ["first_name", "articles"] class ArticleFilterNode(DjangoObjectType): class Meta: interfaces = (Node,) model = Article filter_fields = ["headline", "reporter"] class Query(ObjectType): all_reporters = DjangoFilterConnectionField(ReporterFilterNode) all_articles = DjangoFilterConnectionField(ArticleFilterNode) reporter = Field(ReporterFilterNode) article = Field(ArticleFilterNode) r1 = Reporter.objects.create(first_name="r1", last_name="r1", email="*****@*****.**") r2 = Reporter.objects.create(first_name="r2", last_name="r2", email="*****@*****.**") Article.objects.create( headline="a1", pub_date=datetime.now(), pub_date_time=datetime.now(), reporter=r1, editor=r1, ) Article.objects.create( headline="a2", pub_date=datetime.now(), pub_date_time=datetime.now(), reporter=r2, editor=r2, ) query = """ query { allReporters { edges { node { articles { edges { node { headline } } } } } } } """ schema = Schema(query=Query) result = schema.execute(query) assert not result.errors # We should only get back a single article for each reporter assert ( len(result.data["allReporters"]["edges"][0]["node"]["articles"]["edges"]) == 1 ) assert ( len(result.data["allReporters"]["edges"][1]["node"]["articles"]["edges"]) == 1 )
return agency_metrics.get_route_metrics(route_id) def resolve_interval(agency_metrics, info, date_strs, start_time=None, end_time=None): dates = [util.parse_date(date_str) for date_str in date_strs] rng = metrics.Range(dates, start_time, end_time, None) return metrics.AgencyIntervalMetrics(agency_metrics, rng) class Query(ObjectType): agencies = List(AgencyMetrics, agency_ids=List(String)) agency = Field(AgencyMetrics, agency_id=String(required=True)) def resolve_agencies(parent, info, agency_ids): return [metrics.AgencyMetrics(agency_id) for agency_id in agency_ids] def resolve_agency(parent, info, agency_id): return metrics.AgencyMetrics(agency_id) def round_or_none(number, num_digits=ROUND_DIGITS): if number is None: return None return round(number, num_digits) metrics_api = Schema(query=Query)
class CompanyNode(DjangoObjectType): class Meta: model = CompanyModel filter_fields = { 'name': ['exact', 'icontains'], 'ticker': ['exact', 'icontains'], 'sector__id': ['exact'], 'sector__name': ['exact', 'icontains'], 'industry__id': ['exact'], 'industry__name': ['exact', 'icontains'], } interfaces = (relay.Node, ) class Query(AbstractType, ObjectType): exchange = relay.Node.Field(ExchangeNode) all_exchanges = DjangoFilterConnectionField(ExchangeNode) company = relay.Node.Field(CompanyNode) all_companies = DjangoFilterConnectionField(CompanyNode) industry = relay.Node.Field(IndustryNode) all_industries = DjangoFilterConnectionField(IndustryNode) sector = relay.Node.Field(SectorNode) all_sectors = DjangoFilterConnectionField(SectorNode) schema = Schema(query=Query)
def test_order_by(): class ReporterType(DjangoObjectType): class Meta: model = Reporter interfaces = (Node,) class Query(ObjectType): all_reporters = DjangoFilterConnectionField( ReporterType, filterset_class=ReporterFilter ) Reporter.objects.create(first_name="b") Reporter.objects.create(first_name="a") schema = Schema(query=Query) query = """ query NodeFilteringQuery { allReporters(orderBy: "-firstName") { edges { node { firstName } } } } """ expected = { "allReporters": { "edges": [{"node": {"firstName": "b"}}, {"node": {"firstName": "a"}}] } } result = schema.execute(query) assert not result.errors assert result.data == expected query = """ query NodeFilteringQuery { allReporters(orderBy: "-first_name") { edges { node { firstName } } } } """ result = schema.execute(query) assert not result.errors assert result.data == expected query = """ query NodeFilteringQuery { allReporters(orderBy: "-firtsnaMe") { edges { node { firstName } } } } """ result = schema.execute(query) assert result.errors
from graphene import ObjectType, Schema, Field from cookbook.ingredients.schema import IngredientQuery, IngredientMutation from cookbook.spacex.schema import SpacexQuery class Query(IngredientQuery, SpacexQuery, ObjectType): # This class will inherit from multiple Queries # as we begin to add more apps to our project pass class Mutation(IngredientMutation, ObjectType): # This class will inherit from multiple Queries # as we begin to add more apps to our project pass schema = Schema(query=Query, mutation=Mutation)
def test_order_by_is_perserved(): class ReporterType(DjangoObjectType): class Meta: model = Reporter interfaces = (Node, ) filter_fields = () class Query(ObjectType): all_reporters = DjangoFilterConnectionField(ReporterType, reverse_order=Boolean()) def resolve_all_reporters(self, info, reverse_order=False, **args): reporters = Reporter.objects.order_by("first_name") if reverse_order: return reporters.reverse() return reporters Reporter.objects.create(first_name="b") Reporter.objects.create(first_name="a") schema = Schema(query=Query) query = """ query NodeFilteringQuery { allReporters(first: 1) { edges { node { firstName } } } } """ expected = {"allReporters": {"edges": [{"node": {"firstName": "a"}}]}} result = schema.execute(query) assert not result.errors assert result.data == expected reverse_query = """ query NodeFilteringQuery { allReporters(first: 1, reverseOrder: true) { edges { node { firstName } } } } """ reverse_expected = { "allReporters": { "edges": [{ "node": { "firstName": "b" } }] } } reverse_result = schema.execute(reverse_query) assert not reverse_result.errors assert reverse_result.data == reverse_expected