Skip to content

Commit

Permalink
100% tests coverage! (graphql-python#107)
Browse files Browse the repository at this point in the history
dsl: Fix select used multiple times on same field
local_schema: Fix correct return of errors in subscriptions
  • Loading branch information
leszekhanusz committed Jul 5, 2020
1 parent 81b3036 commit bd83d33
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 21 deletions.
2 changes: 1 addition & 1 deletion gql/dsl.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def select(self, *fields):
added_selections = selections(*fields)
if selection_set:
selection_set.selections = FrozenList(
selection_set.selections + added_selections
selection_set.selections + list(added_selections)
)
else:
self.ast_field.selection_set = SelectionSetNode(
Expand Down
21 changes: 5 additions & 16 deletions gql/transport/local_schema.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from inspect import isawaitable
from typing import Any, AsyncGenerator, AsyncIterator, Awaitable, Coroutine, cast
from typing import AsyncGenerator, Awaitable, cast

from graphql import DocumentNode, ExecutionResult, GraphQLSchema, execute, subscribe

Expand Down Expand Up @@ -50,27 +50,16 @@ async def execute(
async def subscribe(
self, document: DocumentNode, *args, **kwargs,
) -> AsyncGenerator[ExecutionResult, None]:
"""Send a query and receive the results using an async generator
The query can be a graphql query, mutation or subscription
"""Send a subscription and receive the results using an async generator
The results are sent as an ExecutionResult object
"""

subscribe_result = subscribe(self.schema, document, *args, **kwargs)
subscribe_result = await subscribe(self.schema, document, *args, **kwargs)

if isinstance(subscribe_result, ExecutionResult):
yield ExecutionResult
yield subscribe_result

else:
# if we don't get an ExecutionResult, then we should receive
# a Coroutine returning an AsyncIterator[ExecutionResult]

subscribe_coro = cast(
Coroutine[Any, Any, AsyncIterator[ExecutionResult]], subscribe_result
)

subscribe_generator = await subscribe_coro

async for result in subscribe_generator:
async for result in subscribe_result:
yield result
2 changes: 1 addition & 1 deletion gql/transport/transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def execute(self, document: DocumentNode, *args, **kwargs) -> ExecutionResult:
def connect(self):
"""Establish a session with the transport.
"""
pass
pass # pragma: no cover

def close(self):
"""Close the transport
Expand Down
6 changes: 6 additions & 0 deletions tests/starwars/fixtures.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import asyncio
from collections import namedtuple

Human = namedtuple("Human", "id name friends appearsIn homePlanet")
Expand Down Expand Up @@ -94,6 +95,11 @@ def getHero(episode):
return artoo


async def getHeroAsync(episode):
await asyncio.sleep(0.001)
return getHero(episode)


def getHuman(id):
return humanData.get(id)

Expand Down
4 changes: 2 additions & 2 deletions tests/starwars/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
getCharacters,
getDroid,
getFriends,
getHero,
getHeroAsync,
getHuman,
reviews,
)
Expand Down Expand Up @@ -146,7 +146,7 @@
type_=episodeEnum, # type: ignore
)
},
resolve=lambda root, info, **args: getHero(args.get("episode")),
resolve=lambda root, info, **args: getHeroAsync(args.get("episode")),
),
"human": GraphQLField(
humanType,
Expand Down
12 changes: 12 additions & 0 deletions tests/starwars/test_dsl.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@ def test_hero_name_and_friends_query(ds):
assert query == str(query_dsl)


def test_hero_id_and_name(ds):
query = """
hero {
id
name
}
""".strip()
query_dsl = ds.Query.hero.select(ds.Character.id)
query_dsl = query_dsl.select(ds.Character.name)
assert query == str(query_dsl)


def test_nested_query(ds):
query = """
hero {
Expand Down
37 changes: 36 additions & 1 deletion tests/starwars/test_subscription.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import pytest
from graphql import subscribe
from graphql import ExecutionResult, GraphQLError, subscribe

from gql import Client, gql

Expand Down Expand Up @@ -57,3 +57,38 @@ async def test_subscription_support_using_client():
]

assert results == expected


subscription_invalid_str = """
subscription ListenEpisodeReviews($ep: Episode!) {
qsdfqsdfqsdf
}
"""


@pytest.mark.asyncio
async def test_subscription_support_using_client_invalid_field():

subs = gql(subscription_invalid_str)

params = {"ep": "JEDI"}

async with Client(schema=StarWarsSchema) as session:

# We subscribe directly from the transport to avoid local validation
results = [
result
async for result in session.transport.subscribe(
subs, variable_values=params
)
]

assert len(results) == 1
result = results[0]
assert isinstance(result, ExecutionResult)
assert result.data is None
assert isinstance(result.errors, list)
assert len(result.errors) == 1
error = result.errors[0]
assert isinstance(error, GraphQLError)
assert error.message == "The subscription field 'qsdfqsdfqsdf' is not defined."

0 comments on commit bd83d33

Please sign in to comment.