mirror of
https://github.com/graphql-python/graphene.git
synced 2025-09-21 11:22:33 +03:00
Make all 345 tests pass with graphql-core-next
This commit is contained in:
parent
f1ae6e4cd7
commit
c4a850f2ea
|
@ -30,21 +30,22 @@ snapshots["test_correctly_refetches_xwing 1"] = {
|
|||
|
||||
snapshots[
|
||||
"test_str_schema 1"
|
||||
] = """schema {
|
||||
query: Query
|
||||
mutation: Mutation
|
||||
}
|
||||
|
||||
] = '''"""A faction in the Star Wars saga"""
|
||||
type Faction implements Node {
|
||||
"""The ID of the object"""
|
||||
id: ID!
|
||||
|
||||
"""The name of the faction."""
|
||||
name: String
|
||||
ships(before: String, after: String, first: Int, last: Int): ShipConnection
|
||||
|
||||
"""The ships used by the faction."""
|
||||
ships(before: String = null, after: String = null, first: Int = null, last: Int = null): ShipConnection
|
||||
}
|
||||
|
||||
input IntroduceShipInput {
|
||||
shipName: String!
|
||||
factionId: String!
|
||||
clientMutationId: String
|
||||
clientMutationId: String = null
|
||||
}
|
||||
|
||||
type IntroduceShipPayload {
|
||||
|
@ -57,35 +58,60 @@ type Mutation {
|
|||
introduceShip(input: IntroduceShipInput!): IntroduceShipPayload
|
||||
}
|
||||
|
||||
"""An object with an ID"""
|
||||
interface Node {
|
||||
"""The ID of the object"""
|
||||
id: ID!
|
||||
}
|
||||
|
||||
"""
|
||||
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
|
||||
}
|
||||
|
||||
type Query {
|
||||
rebels: Faction
|
||||
empire: Faction
|
||||
|
||||
"""The ID of the object"""
|
||||
node(id: ID!): Node
|
||||
}
|
||||
|
||||
"""A ship in the Star Wars saga"""
|
||||
type Ship implements Node {
|
||||
"""The ID of the object"""
|
||||
id: ID!
|
||||
|
||||
"""The name of the ship."""
|
||||
name: String
|
||||
}
|
||||
|
||||
type ShipConnection {
|
||||
"""Pagination data for this connection."""
|
||||
pageInfo: PageInfo!
|
||||
|
||||
"""Contains the nodes in this connection."""
|
||||
edges: [ShipEdge]!
|
||||
}
|
||||
|
||||
"""A Relay edge containing a `Ship` and its cursor."""
|
||||
type ShipEdge {
|
||||
"""The item at the end of the edge"""
|
||||
node: Ship
|
||||
|
||||
"""A cursor for use in pagination"""
|
||||
cursor: String!
|
||||
}
|
||||
"""
|
||||
'''
|
||||
|
|
|
@ -133,7 +133,7 @@ class IterableConnectionField(Field):
|
|||
)
|
||||
|
||||
assert issubclass(connection_type, Connection), (
|
||||
'{} type have to be a subclass of Connection. Received "{}".'
|
||||
'{} type has to be a subclass of Connection. Received "{}".'
|
||||
).format(self.__class__.__name__, connection_type)
|
||||
return type
|
||||
|
||||
|
@ -143,7 +143,7 @@ class IterableConnectionField(Field):
|
|||
return resolved
|
||||
|
||||
assert isinstance(resolved, Iterable), (
|
||||
"Resolved value from the connection field have to be iterable or instance of {}. "
|
||||
"Resolved value from the connection field has to be iterable or instance of {}. "
|
||||
'Received "{}"'
|
||||
).format(connection_type, resolved)
|
||||
connection = connection_from_list(
|
||||
|
|
|
@ -73,7 +73,7 @@ class AbstractNode(Interface):
|
|||
def __init_subclass_with_meta__(cls, **options):
|
||||
_meta = InterfaceOptions(cls)
|
||||
_meta.fields = OrderedDict(
|
||||
id=GlobalID(cls, description="The ID of the object.")
|
||||
id=GlobalID(cls, description="The ID of the object")
|
||||
)
|
||||
super(AbstractNode, cls).__init_subclass_with_meta__(_meta=_meta, **options)
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
from collections import OrderedDict
|
||||
from pytest import mark
|
||||
|
||||
from graphql_relay.utils import base64
|
||||
from promise import Promise
|
||||
|
||||
from ...types import ObjectType, Schema, String
|
||||
from ..connection import Connection, ConnectionField, PageInfo
|
||||
|
@ -25,15 +24,15 @@ class LetterConnection(Connection):
|
|||
class Query(ObjectType):
|
||||
letters = ConnectionField(LetterConnection)
|
||||
connection_letters = ConnectionField(LetterConnection)
|
||||
promise_letters = ConnectionField(LetterConnection)
|
||||
async_letters = ConnectionField(LetterConnection)
|
||||
|
||||
node = Node.Field()
|
||||
|
||||
def resolve_letters(self, info, **args):
|
||||
return list(letters.values())
|
||||
|
||||
def resolve_promise_letters(self, info, **args):
|
||||
return Promise.resolve(list(letters.values()))
|
||||
async def resolve_async_letters(self, info, **args):
|
||||
return list(letters.values())
|
||||
|
||||
def resolve_connection_letters(self, info, **args):
|
||||
return LetterConnection(
|
||||
|
@ -46,9 +45,7 @@ class Query(ObjectType):
|
|||
|
||||
schema = Schema(Query)
|
||||
|
||||
letters = OrderedDict()
|
||||
for i, letter in enumerate(letter_chars):
|
||||
letters[letter] = Letter(id=i, letter=letter)
|
||||
letters = {letter: Letter(id=i, letter=letter) for i, letter in enumerate(letter_chars)}
|
||||
|
||||
|
||||
def edges(selected_letters):
|
||||
|
@ -66,11 +63,11 @@ def cursor_for(ltr):
|
|||
return base64("arrayconnection:%s" % letter.id)
|
||||
|
||||
|
||||
def execute(args=""):
|
||||
async def execute(args=""):
|
||||
if args:
|
||||
args = "(" + args + ")"
|
||||
|
||||
return schema.execute(
|
||||
return await schema.execute_async(
|
||||
"""
|
||||
{
|
||||
letters%s {
|
||||
|
@ -94,8 +91,8 @@ def execute(args=""):
|
|||
)
|
||||
|
||||
|
||||
def check(args, letters, has_previous_page=False, has_next_page=False):
|
||||
result = execute(args)
|
||||
async def check(args, letters, has_previous_page=False, has_next_page=False):
|
||||
result = await execute(args)
|
||||
expected_edges = edges(letters)
|
||||
expected_page_info = {
|
||||
"hasPreviousPage": has_previous_page,
|
||||
|
@ -110,96 +107,114 @@ def check(args, letters, has_previous_page=False, has_next_page=False):
|
|||
}
|
||||
|
||||
|
||||
def test_returns_all_elements_without_filters():
|
||||
check("", "ABCDE")
|
||||
@mark.asyncio
|
||||
async def test_returns_all_elements_without_filters():
|
||||
await check("", "ABCDE")
|
||||
|
||||
|
||||
def test_respects_a_smaller_first():
|
||||
check("first: 2", "AB", has_next_page=True)
|
||||
@mark.asyncio
|
||||
async def test_respects_a_smaller_first():
|
||||
await check("first: 2", "AB", has_next_page=True)
|
||||
|
||||
|
||||
def test_respects_an_overly_large_first():
|
||||
check("first: 10", "ABCDE")
|
||||
@mark.asyncio
|
||||
async def test_respects_an_overly_large_first():
|
||||
await check("first: 10", "ABCDE")
|
||||
|
||||
|
||||
def test_respects_a_smaller_last():
|
||||
check("last: 2", "DE", has_previous_page=True)
|
||||
@mark.asyncio
|
||||
async def test_respects_a_smaller_last():
|
||||
await check("last: 2", "DE", has_previous_page=True)
|
||||
|
||||
|
||||
def test_respects_an_overly_large_last():
|
||||
check("last: 10", "ABCDE")
|
||||
@mark.asyncio
|
||||
async def test_respects_an_overly_large_last():
|
||||
await check("last: 10", "ABCDE")
|
||||
|
||||
|
||||
def test_respects_first_and_after():
|
||||
check('first: 2, after: "{}"'.format(cursor_for("B")), "CD", has_next_page=True)
|
||||
@mark.asyncio
|
||||
async def test_respects_first_and_after():
|
||||
await check('first: 2, after: "{}"'.format(cursor_for("B")), "CD", has_next_page=True)
|
||||
|
||||
|
||||
def test_respects_first_and_after_with_long_first():
|
||||
check('first: 10, after: "{}"'.format(cursor_for("B")), "CDE")
|
||||
@mark.asyncio
|
||||
async def test_respects_first_and_after_with_long_first():
|
||||
await check('first: 10, after: "{}"'.format(cursor_for("B")), "CDE")
|
||||
|
||||
|
||||
def test_respects_last_and_before():
|
||||
check('last: 2, before: "{}"'.format(cursor_for("D")), "BC", has_previous_page=True)
|
||||
@mark.asyncio
|
||||
async def test_respects_last_and_before():
|
||||
await check('last: 2, before: "{}"'.format(cursor_for("D")), "BC", has_previous_page=True)
|
||||
|
||||
|
||||
def test_respects_last_and_before_with_long_last():
|
||||
check('last: 10, before: "{}"'.format(cursor_for("D")), "ABC")
|
||||
@mark.asyncio
|
||||
async def test_respects_last_and_before_with_long_last():
|
||||
await check('last: 10, before: "{}"'.format(cursor_for("D")), "ABC")
|
||||
|
||||
|
||||
def test_respects_first_and_after_and_before_too_few():
|
||||
check(
|
||||
@mark.asyncio
|
||||
async def test_respects_first_and_after_and_before_too_few():
|
||||
await check(
|
||||
'first: 2, after: "{}", before: "{}"'.format(cursor_for("A"), cursor_for("E")),
|
||||
"BC",
|
||||
has_next_page=True,
|
||||
)
|
||||
|
||||
|
||||
def test_respects_first_and_after_and_before_too_many():
|
||||
check(
|
||||
@mark.asyncio
|
||||
async def test_respects_first_and_after_and_before_too_many():
|
||||
await check(
|
||||
'first: 4, after: "{}", before: "{}"'.format(cursor_for("A"), cursor_for("E")),
|
||||
"BCD",
|
||||
)
|
||||
|
||||
|
||||
def test_respects_first_and_after_and_before_exactly_right():
|
||||
check(
|
||||
@mark.asyncio
|
||||
async def test_respects_first_and_after_and_before_exactly_right():
|
||||
await check(
|
||||
'first: 3, after: "{}", before: "{}"'.format(cursor_for("A"), cursor_for("E")),
|
||||
"BCD",
|
||||
)
|
||||
|
||||
|
||||
def test_respects_last_and_after_and_before_too_few():
|
||||
check(
|
||||
@mark.asyncio
|
||||
async def test_respects_last_and_after_and_before_too_few():
|
||||
await check(
|
||||
'last: 2, after: "{}", before: "{}"'.format(cursor_for("A"), cursor_for("E")),
|
||||
"CD",
|
||||
has_previous_page=True,
|
||||
)
|
||||
|
||||
|
||||
def test_respects_last_and_after_and_before_too_many():
|
||||
check(
|
||||
@mark.asyncio
|
||||
async def test_respects_last_and_after_and_before_too_many():
|
||||
await check(
|
||||
'last: 4, after: "{}", before: "{}"'.format(cursor_for("A"), cursor_for("E")),
|
||||
"BCD",
|
||||
)
|
||||
|
||||
|
||||
def test_respects_last_and_after_and_before_exactly_right():
|
||||
check(
|
||||
@mark.asyncio
|
||||
async def test_respects_last_and_after_and_before_exactly_right():
|
||||
await check(
|
||||
'last: 3, after: "{}", before: "{}"'.format(cursor_for("A"), cursor_for("E")),
|
||||
"BCD",
|
||||
)
|
||||
|
||||
|
||||
def test_returns_no_elements_if_first_is_0():
|
||||
check("first: 0", "", has_next_page=True)
|
||||
@mark.asyncio
|
||||
async def test_returns_no_elements_if_first_is_0():
|
||||
await check("first: 0", "", has_next_page=True)
|
||||
|
||||
|
||||
def test_returns_all_elements_if_cursors_are_invalid():
|
||||
check('before: "invalid" after: "invalid"', "ABCDE")
|
||||
@mark.asyncio
|
||||
async def test_returns_all_elements_if_cursors_are_invalid():
|
||||
await check('before: "invalid" after: "invalid"', "ABCDE")
|
||||
|
||||
|
||||
def test_returns_all_elements_if_cursors_are_on_the_outside():
|
||||
check(
|
||||
@mark.asyncio
|
||||
async def test_returns_all_elements_if_cursors_are_on_the_outside():
|
||||
await check(
|
||||
'before: "{}" after: "{}"'.format(
|
||||
base64("arrayconnection:%s" % 6), base64("arrayconnection:%s" % -1)
|
||||
),
|
||||
|
@ -207,8 +222,9 @@ def test_returns_all_elements_if_cursors_are_on_the_outside():
|
|||
)
|
||||
|
||||
|
||||
def test_returns_no_elements_if_cursors_cross():
|
||||
check(
|
||||
@mark.asyncio
|
||||
async def test_returns_no_elements_if_cursors_cross():
|
||||
await check(
|
||||
'before: "{}" after: "{}"'.format(
|
||||
base64("arrayconnection:%s" % 2), base64("arrayconnection:%s" % 4)
|
||||
),
|
||||
|
@ -216,8 +232,9 @@ def test_returns_no_elements_if_cursors_cross():
|
|||
)
|
||||
|
||||
|
||||
def test_connection_type_nodes():
|
||||
result = schema.execute(
|
||||
@mark.asyncio
|
||||
async def test_connection_type_nodes():
|
||||
result = await schema.execute_async(
|
||||
"""
|
||||
{
|
||||
connectionLetters {
|
||||
|
@ -248,11 +265,12 @@ def test_connection_type_nodes():
|
|||
}
|
||||
|
||||
|
||||
def test_connection_promise():
|
||||
result = schema.execute(
|
||||
@mark.asyncio
|
||||
async def test_connection_async():
|
||||
result = await schema.execute_async(
|
||||
"""
|
||||
{
|
||||
promiseLetters(first:1) {
|
||||
asyncLetters(first:1) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
|
@ -270,7 +288,7 @@ def test_connection_promise():
|
|||
|
||||
assert not result.errors
|
||||
assert result.data == {
|
||||
"promiseLetters": {
|
||||
"asyncLetters": {
|
||||
"edges": [{"node": {"id": "TGV0dGVyOjA=", "letter": "A"}}],
|
||||
"pageInfo": {"hasPreviousPage": False, "hasNextPage": True},
|
||||
}
|
||||
|
|
|
@ -80,11 +80,11 @@ class OtherMutation(ClientIDMutation):
|
|||
|
||||
@staticmethod
|
||||
def mutate_and_get_payload(
|
||||
self, info, shared="", additional_field="", client_mutation_id=None
|
||||
self, info, shared, additional_field, client_mutation_id=None
|
||||
):
|
||||
edge_type = MyEdge
|
||||
return OtherMutation(
|
||||
name=shared + additional_field,
|
||||
name=(shared or "") + (additional_field or ""),
|
||||
my_node_edge=edge_type(cursor="1", node=MyNode(name="name")),
|
||||
)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from collections import OrderedDict
|
||||
|
||||
from graphql_relay import to_global_id
|
||||
|
||||
from graphql.pyutils import dedent
|
||||
|
||||
from ...types import ObjectType, Schema, String
|
||||
from ..node import Node, is_node
|
||||
|
||||
|
@ -70,17 +70,13 @@ def test_subclassed_node_query():
|
|||
% to_global_id("MyOtherNode", 1)
|
||||
)
|
||||
assert not executed.errors
|
||||
assert executed.data == OrderedDict(
|
||||
{
|
||||
"node": OrderedDict(
|
||||
[
|
||||
("shared", "1"),
|
||||
("extraField", "extra field info."),
|
||||
("somethingElse", "----"),
|
||||
]
|
||||
)
|
||||
assert executed.data == {
|
||||
"node": {
|
||||
"shared": "1",
|
||||
"extraField": "extra field info.",
|
||||
"somethingElse": "----"
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def test_node_requesting_non_node():
|
||||
|
@ -124,7 +120,7 @@ def test_node_field_only_type_wrong():
|
|||
% Node.to_global_id("MyOtherNode", 1)
|
||||
)
|
||||
assert len(executed.errors) == 1
|
||||
assert str(executed.errors[0]) == "Must receive a MyNode id."
|
||||
assert str(executed.errors[0]).startswith("Must receive a MyNode id.")
|
||||
assert executed.data == {"onlyNode": None}
|
||||
|
||||
|
||||
|
@ -143,39 +139,48 @@ def test_node_field_only_lazy_type_wrong():
|
|||
% Node.to_global_id("MyOtherNode", 1)
|
||||
)
|
||||
assert len(executed.errors) == 1
|
||||
assert str(executed.errors[0]) == "Must receive a MyNode id."
|
||||
assert str(executed.errors[0]).startswith("Must receive a MyNode id.")
|
||||
assert executed.data == {"onlyNodeLazy": None}
|
||||
|
||||
|
||||
def test_str_schema():
|
||||
assert (
|
||||
str(schema)
|
||||
== """
|
||||
schema {
|
||||
assert (str(schema) == dedent(
|
||||
'''
|
||||
schema {
|
||||
query: RootQuery
|
||||
}
|
||||
}
|
||||
|
||||
type MyNode implements Node {
|
||||
type MyNode implements Node {
|
||||
"""The ID of the object"""
|
||||
id: ID!
|
||||
name: String
|
||||
}
|
||||
}
|
||||
|
||||
type MyOtherNode implements Node {
|
||||
type MyOtherNode implements Node {
|
||||
"""The ID of the object"""
|
||||
id: ID!
|
||||
shared: String
|
||||
somethingElse: String
|
||||
extraField: String
|
||||
}
|
||||
}
|
||||
|
||||
interface Node {
|
||||
"""An object with an ID"""
|
||||
interface Node {
|
||||
"""The ID of the object"""
|
||||
id: ID!
|
||||
}
|
||||
}
|
||||
|
||||
type RootQuery {
|
||||
type RootQuery {
|
||||
first: String
|
||||
|
||||
"""The ID of the object"""
|
||||
node(id: ID!): Node
|
||||
|
||||
"""The ID of the object"""
|
||||
onlyNode(id: ID!): MyNode
|
||||
|
||||
"""The ID of the object"""
|
||||
onlyNodeLazy(id: ID!): MyNode
|
||||
}
|
||||
""".lstrip()
|
||||
}
|
||||
''')
|
||||
)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from graphql import graphql
|
||||
from graphql import graphql_sync
|
||||
from graphql.pyutils import dedent
|
||||
|
||||
from ...types import Interface, ObjectType, Schema
|
||||
from ...types.scalars import Int, String
|
||||
|
@ -15,7 +16,7 @@ class CustomNode(Node):
|
|||
|
||||
@staticmethod
|
||||
def get_node_from_global_id(info, id, only_type=None):
|
||||
assert info.schema == schema
|
||||
assert info.schema is graphql_schema
|
||||
if id in user_data:
|
||||
return user_data.get(id)
|
||||
else:
|
||||
|
@ -23,14 +24,14 @@ class CustomNode(Node):
|
|||
|
||||
|
||||
class BasePhoto(Interface):
|
||||
width = Int()
|
||||
width = Int(description="The width of the photo in pixels")
|
||||
|
||||
|
||||
class User(ObjectType):
|
||||
class Meta:
|
||||
interfaces = [CustomNode]
|
||||
|
||||
name = String()
|
||||
name = String(description="The full name of the user")
|
||||
|
||||
|
||||
class Photo(ObjectType):
|
||||
|
@ -48,37 +49,47 @@ class RootQuery(ObjectType):
|
|||
|
||||
|
||||
schema = Schema(query=RootQuery, types=[User, Photo])
|
||||
graphql_schema = schema.graphql_schema
|
||||
|
||||
|
||||
def test_str_schema_correct():
|
||||
assert (
|
||||
str(schema)
|
||||
== """schema {
|
||||
assert (str(schema) == dedent(
|
||||
'''
|
||||
schema {
|
||||
query: RootQuery
|
||||
}
|
||||
}
|
||||
|
||||
interface BasePhoto {
|
||||
interface BasePhoto {
|
||||
"""The width of the photo in pixels"""
|
||||
width: Int
|
||||
}
|
||||
}
|
||||
|
||||
interface Node {
|
||||
interface Node {
|
||||
"""The ID of the object"""
|
||||
id: ID!
|
||||
}
|
||||
}
|
||||
|
||||
type Photo implements Node, BasePhoto {
|
||||
type Photo implements Node & BasePhoto {
|
||||
"""The ID of the object"""
|
||||
id: ID!
|
||||
|
||||
"""The width of the photo in pixels"""
|
||||
width: Int
|
||||
}
|
||||
}
|
||||
|
||||
type RootQuery {
|
||||
type RootQuery {
|
||||
"""The ID of the object"""
|
||||
node(id: ID!): Node
|
||||
}
|
||||
}
|
||||
|
||||
type User implements Node {
|
||||
type User implements Node {
|
||||
"""The ID of the object"""
|
||||
id: ID!
|
||||
|
||||
"""The full name of the user"""
|
||||
name: String
|
||||
}
|
||||
"""
|
||||
}
|
||||
''')
|
||||
)
|
||||
|
||||
|
||||
|
@ -91,7 +102,7 @@ def test_gets_the_correct_id_for_users():
|
|||
}
|
||||
"""
|
||||
expected = {"node": {"id": "1"}}
|
||||
result = graphql(schema, query)
|
||||
result = graphql_sync(graphql_schema, query)
|
||||
assert not result.errors
|
||||
assert result.data == expected
|
||||
|
||||
|
@ -105,7 +116,7 @@ def test_gets_the_correct_id_for_photos():
|
|||
}
|
||||
"""
|
||||
expected = {"node": {"id": "4"}}
|
||||
result = graphql(schema, query)
|
||||
result = graphql_sync(graphql_schema, query)
|
||||
assert not result.errors
|
||||
assert result.data == expected
|
||||
|
||||
|
@ -122,7 +133,7 @@ def test_gets_the_correct_name_for_users():
|
|||
}
|
||||
"""
|
||||
expected = {"node": {"id": "1", "name": "John Doe"}}
|
||||
result = graphql(schema, query)
|
||||
result = graphql_sync(graphql_schema, query)
|
||||
assert not result.errors
|
||||
assert result.data == expected
|
||||
|
||||
|
@ -139,7 +150,7 @@ def test_gets_the_correct_width_for_photos():
|
|||
}
|
||||
"""
|
||||
expected = {"node": {"id": "4", "width": 400}}
|
||||
result = graphql(schema, query)
|
||||
result = graphql_sync(graphql_schema, query)
|
||||
assert not result.errors
|
||||
assert result.data == expected
|
||||
|
||||
|
@ -154,7 +165,7 @@ def test_gets_the_correct_typename_for_users():
|
|||
}
|
||||
"""
|
||||
expected = {"node": {"id": "1", "__typename": "User"}}
|
||||
result = graphql(schema, query)
|
||||
result = graphql_sync(graphql_schema, query)
|
||||
assert not result.errors
|
||||
assert result.data == expected
|
||||
|
||||
|
@ -169,7 +180,7 @@ def test_gets_the_correct_typename_for_photos():
|
|||
}
|
||||
"""
|
||||
expected = {"node": {"id": "4", "__typename": "Photo"}}
|
||||
result = graphql(schema, query)
|
||||
result = graphql_sync(graphql_schema, query)
|
||||
assert not result.errors
|
||||
assert result.data == expected
|
||||
|
||||
|
@ -186,7 +197,7 @@ def test_ignores_photo_fragments_on_user():
|
|||
}
|
||||
"""
|
||||
expected = {"node": {"id": "1"}}
|
||||
result = graphql(schema, query)
|
||||
result = graphql_sync(graphql_schema, query)
|
||||
assert not result.errors
|
||||
assert result.data == expected
|
||||
|
||||
|
@ -200,7 +211,7 @@ def test_returns_null_for_bad_ids():
|
|||
}
|
||||
"""
|
||||
expected = {"node": None}
|
||||
result = graphql(schema, query)
|
||||
result = graphql_sync(graphql_schema, query)
|
||||
assert not result.errors
|
||||
assert result.data == expected
|
||||
|
||||
|
@ -239,7 +250,7 @@ def test_have_correct_node_interface():
|
|||
],
|
||||
}
|
||||
}
|
||||
result = graphql(schema, query)
|
||||
result = graphql_sync(graphql_schema, query)
|
||||
assert not result.errors
|
||||
assert result.data == expected
|
||||
|
||||
|
@ -291,6 +302,6 @@ def test_has_correct_node_root_field():
|
|||
}
|
||||
}
|
||||
}
|
||||
result = graphql(schema, query)
|
||||
result = graphql_sync(graphql_schema, query)
|
||||
assert not result.errors
|
||||
assert result.data == expected
|
||||
|
|
|
@ -27,6 +27,7 @@ def test_issue():
|
|||
graphene.Schema(query=Query)
|
||||
|
||||
assert str(exc_info.value) == (
|
||||
"IterableConnectionField type have to be a subclass of Connection. "
|
||||
'Received "MyUnion".'
|
||||
"Query fields cannot be resolved:"
|
||||
" IterableConnectionField type has to be a subclass of Connection."
|
||||
' Received "MyUnion".'
|
||||
)
|
||||
|
|
|
@ -185,7 +185,6 @@ def test_bad_variables(sample_date, sample_datetime, sample_time):
|
|||
# when `input` is not JSON serializable formatting the error message in
|
||||
# `graphql.utils.is_valid_value` line 79 fails with a TypeError
|
||||
assert isinstance(result.errors[0], GraphQLError)
|
||||
print(result.errors[0])
|
||||
assert result.data is None
|
||||
|
||||
not_a_date = dict()
|
||||
|
|
|
@ -229,11 +229,11 @@ def test_query_arguments():
|
|||
|
||||
result = test_schema.execute("{ test }", None)
|
||||
assert not result.errors
|
||||
assert result.data == {"test": "[null,{}]"}
|
||||
assert result.data == {"test": '[null,{"a_str":null,"a_int":null}]'}
|
||||
|
||||
result = test_schema.execute('{ test(aStr: "String!") }', "Source!")
|
||||
assert not result.errors
|
||||
assert result.data == {"test": '["Source!",{"a_str":"String!"}]'}
|
||||
assert result.data == {"test": '["Source!",{"a_str":"String!","a_int":null}]'}
|
||||
|
||||
result = test_schema.execute('{ test(aInt: -123, aStr: "String!") }', "Source!")
|
||||
assert not result.errors
|
||||
|
@ -258,18 +258,20 @@ def test_query_input_field():
|
|||
|
||||
result = test_schema.execute("{ test }", None)
|
||||
assert not result.errors
|
||||
assert result.data == {"test": "[null,{}]"}
|
||||
assert result.data == {"test": '[null,{"a_input":null}]'}
|
||||
|
||||
result = test_schema.execute('{ test(aInput: {aField: "String!"} ) }', "Source!")
|
||||
assert not result.errors
|
||||
assert result.data == {"test": '["Source!",{"a_input":{"a_field":"String!"}}]'}
|
||||
assert result.data == {
|
||||
"test": '["Source!",{"a_input":{"a_field":"String!","recursive_field":null}}]'}
|
||||
|
||||
result = test_schema.execute(
|
||||
'{ test(aInput: {recursiveField: {aField: "String!"}}) }', "Source!"
|
||||
)
|
||||
assert not result.errors
|
||||
assert result.data == {
|
||||
"test": '["Source!",{"a_input":{"recursive_field":{"a_field":"String!"}}}]'
|
||||
"test": '["Source!",{"a_input":{"a_field":null,"recursive_field":'
|
||||
'{"a_field":"String!","recursive_field":null}}}]'
|
||||
}
|
||||
|
||||
|
||||
|
@ -285,8 +287,7 @@ def test_query_middlewares():
|
|||
return "other"
|
||||
|
||||
def reversed_middleware(next, *args, **kwargs):
|
||||
p = next(*args, **kwargs)
|
||||
return p.then(lambda x: x[::-1])
|
||||
return next(*args, **kwargs)[::-1]
|
||||
|
||||
hello_schema = Schema(Query)
|
||||
|
||||
|
@ -348,10 +349,11 @@ def test_big_list_query_compiled_query_benchmark(benchmark):
|
|||
return big_list
|
||||
|
||||
hello_schema = Schema(Query)
|
||||
graphql_schema = hello_schema.graphql_schema
|
||||
source = Source("{ allInts }")
|
||||
query_ast = parse(source)
|
||||
|
||||
big_list_query = partial(execute, hello_schema, query_ast)
|
||||
big_list_query = partial(execute, graphql_schema, query_ast)
|
||||
result = benchmark(big_list_query)
|
||||
assert not result.errors
|
||||
assert result.data == {"allInts": list(big_list)}
|
||||
|
|
|
@ -1,28 +1,15 @@
|
|||
"""
|
||||
This file is used mainly as a bridge for thenable abstractions.
|
||||
This includes:
|
||||
- Promises
|
||||
- Asyncio Coroutines
|
||||
"""
|
||||
|
||||
try:
|
||||
from promise import Promise, is_thenable # type: ignore
|
||||
except ImportError:
|
||||
|
||||
class Promise(object): # type: ignore
|
||||
pass
|
||||
|
||||
def is_thenable(obj): # type: ignore
|
||||
return False
|
||||
from inspect import isawaitable
|
||||
|
||||
|
||||
try:
|
||||
from inspect import isawaitable
|
||||
from .thenables_asyncio import await_and_execute
|
||||
except ImportError:
|
||||
def await_and_execute(obj, on_resolve):
|
||||
async def build_resolve_async():
|
||||
return on_resolve(await obj)
|
||||
|
||||
def isawaitable(obj): # type: ignore
|
||||
return False
|
||||
return build_resolve_async()
|
||||
|
||||
|
||||
def maybe_thenable(obj, on_resolve):
|
||||
|
@ -31,12 +18,8 @@ def maybe_thenable(obj, on_resolve):
|
|||
returning the same type of object inputed.
|
||||
If the object is not thenable, it should return on_resolve(obj)
|
||||
"""
|
||||
if isawaitable(obj) and not isinstance(obj, Promise):
|
||||
if isawaitable(obj):
|
||||
return await_and_execute(obj, on_resolve)
|
||||
|
||||
if is_thenable(obj):
|
||||
return Promise.resolve(obj).then(on_resolve)
|
||||
|
||||
# If it's not awaitable not a Promise, return
|
||||
# the function executed over the object
|
||||
# If it's not awaitable, return the function executed over the object
|
||||
return on_resolve(obj)
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
def await_and_execute(obj, on_resolve):
|
||||
async def build_resolve_async():
|
||||
return on_resolve(await obj)
|
||||
|
||||
return build_resolve_async()
|
|
@ -1,7 +1,4 @@
|
|||
import pytest
|
||||
|
||||
from collections import OrderedDict
|
||||
from graphql.execution.executors.asyncio import AsyncioExecutor
|
||||
from pytest import mark
|
||||
|
||||
from graphql_relay.utils import base64
|
||||
|
||||
|
@ -27,14 +24,14 @@ class LetterConnection(Connection):
|
|||
class Query(ObjectType):
|
||||
letters = ConnectionField(LetterConnection)
|
||||
connection_letters = ConnectionField(LetterConnection)
|
||||
promise_letters = ConnectionField(LetterConnection)
|
||||
async_letters = ConnectionField(LetterConnection)
|
||||
|
||||
node = Node.Field()
|
||||
|
||||
def resolve_letters(self, info, **args):
|
||||
return list(letters.values())
|
||||
|
||||
async def resolve_promise_letters(self, info, **args):
|
||||
async def resolve_async_letters(self, info, **args):
|
||||
return list(letters.values())
|
||||
|
||||
def resolve_connection_letters(self, info, **args):
|
||||
|
@ -48,9 +45,7 @@ class Query(ObjectType):
|
|||
|
||||
schema = Schema(Query)
|
||||
|
||||
letters = OrderedDict()
|
||||
for i, letter in enumerate(letter_chars):
|
||||
letters[letter] = Letter(id=i, letter=letter)
|
||||
letters = {letter: Letter(id=i, letter=letter) for i, letter in enumerate(letter_chars)}
|
||||
|
||||
|
||||
def edges(selected_letters):
|
||||
|
@ -96,12 +91,12 @@ def execute(args=""):
|
|||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_connection_promise():
|
||||
result = await schema.execute(
|
||||
@mark.asyncio
|
||||
async def test_connection_async():
|
||||
result = await schema.execute_async(
|
||||
"""
|
||||
{
|
||||
promiseLetters(first:1) {
|
||||
asyncLetters(first:1) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
|
@ -115,13 +110,11 @@ async def test_connection_promise():
|
|||
}
|
||||
}
|
||||
""",
|
||||
executor=AsyncioExecutor(),
|
||||
return_promise=True,
|
||||
)
|
||||
|
||||
assert not result.errors
|
||||
assert result.data == {
|
||||
"promiseLetters": {
|
||||
"asyncLetters": {
|
||||
"edges": [{"node": {"id": "TGV0dGVyOjA=", "letter": "A"}}],
|
||||
"pageInfo": {"hasPreviousPage": False, "hasNextPage": True},
|
||||
}
|
||||
|
|
|
@ -42,11 +42,11 @@ class OtherMutation(ClientIDMutation):
|
|||
|
||||
@staticmethod
|
||||
def mutate_and_get_payload(
|
||||
self, info, shared="", additional_field="", client_mutation_id=None
|
||||
self, info, shared, additional_field, client_mutation_id=None
|
||||
):
|
||||
edge_type = MyEdge
|
||||
return OtherMutation(
|
||||
name=shared + additional_field,
|
||||
name=(shared or "") + (additional_field or ""),
|
||||
my_node_edge=edge_type(cursor="1", node=MyNode(name="name")),
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user