fix: run the tests in python 3.12 and 3.13 and remove snapshottest dependency (#1572)

* actually run the tests in python 3.12 and 3.13

* remove snapshottest from the example tests

so that the tests pass in 3.12 and 3.13 again

* remove the section about snapshot testing from the testing docs

because the snapshottest package doesn't work on Python 3.12 and above

* fix assertion for badly formed JSON input on Python 3.13

* fix deprecation warning about datetime.utcfromtimestamp()
This commit is contained in:
Florian Zimmermann 2024-08-08 11:49:26 +02:00 committed by GitHub
parent dc3b2e49c1
commit 48678afba4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 344 additions and 445 deletions

View File

@ -69,43 +69,3 @@ You can also add extra keyword arguments to the ``execute`` method, such as
'hey': 'hello Peter!' 'hey': 'hello Peter!'
} }
} }
Snapshot testing
~~~~~~~~~~~~~~~~
As our APIs evolve, we need to know when our changes introduce any breaking changes that might break
some of the clients of our GraphQL app.
However, writing tests and replicating the same response we expect from our GraphQL application can be a
tedious and repetitive task, and sometimes it's easier to skip this process.
Because of that, we recommend the usage of `SnapshotTest <https://github.com/syrusakbary/snapshottest/>`_.
SnapshotTest lets us write all these tests in a breeze, as it automatically creates the ``snapshots`` for us
the first time the test are executed.
Here is a simple example on how our tests will look if we use ``pytest``:
.. code:: python
def test_hey(snapshot):
client = Client(my_schema)
# This will create a snapshot dir and a snapshot file
# the first time the test is executed, with the response
# of the execution.
snapshot.assert_match(client.execute('''{ hey }'''))
If we are using ``unittest``:
.. code:: python
from snapshottest import TestCase
class APITestCase(TestCase):
def test_api_me(self):
"""Testing the API for /me"""
client = Client(my_schema)
self.assertMatchSnapshot(client.execute('''{ hey }'''))

View File

@ -1,98 +0,0 @@
# -*- coding: utf-8 -*-
# snapshottest: v1 - https://goo.gl/zC4yUc
from snapshottest import Snapshot
snapshots = Snapshot()
snapshots["test_hero_name_query 1"] = {"data": {"hero": {"name": "R2-D2"}}}
snapshots["test_hero_name_and_friends_query 1"] = {
"data": {
"hero": {
"id": "2001",
"name": "R2-D2",
"friends": [
{"name": "Luke Skywalker"},
{"name": "Han Solo"},
{"name": "Leia Organa"},
],
}
}
}
snapshots["test_nested_query 1"] = {
"data": {
"hero": {
"name": "R2-D2",
"friends": [
{
"name": "Luke Skywalker",
"appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"],
"friends": [
{"name": "Han Solo"},
{"name": "Leia Organa"},
{"name": "C-3PO"},
{"name": "R2-D2"},
],
},
{
"name": "Han Solo",
"appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"],
"friends": [
{"name": "Luke Skywalker"},
{"name": "Leia Organa"},
{"name": "R2-D2"},
],
},
{
"name": "Leia Organa",
"appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"],
"friends": [
{"name": "Luke Skywalker"},
{"name": "Han Solo"},
{"name": "C-3PO"},
{"name": "R2-D2"},
],
},
],
}
}
}
snapshots["test_fetch_luke_query 1"] = {"data": {"human": {"name": "Luke Skywalker"}}}
snapshots["test_fetch_some_id_query 1"] = {
"data": {"human": {"name": "Luke Skywalker"}}
}
snapshots["test_fetch_some_id_query2 1"] = {"data": {"human": {"name": "Han Solo"}}}
snapshots["test_invalid_id_query 1"] = {"data": {"human": None}}
snapshots["test_fetch_luke_aliased 1"] = {"data": {"luke": {"name": "Luke Skywalker"}}}
snapshots["test_fetch_luke_and_leia_aliased 1"] = {
"data": {"luke": {"name": "Luke Skywalker"}, "leia": {"name": "Leia Organa"}}
}
snapshots["test_duplicate_fields 1"] = {
"data": {
"luke": {"name": "Luke Skywalker", "homePlanet": "Tatooine"},
"leia": {"name": "Leia Organa", "homePlanet": "Alderaan"},
}
}
snapshots["test_use_fragment 1"] = {
"data": {
"luke": {"name": "Luke Skywalker", "homePlanet": "Tatooine"},
"leia": {"name": "Leia Organa", "homePlanet": "Alderaan"},
}
}
snapshots["test_check_type_of_r2 1"] = {
"data": {"hero": {"__typename": "Droid", "name": "R2-D2"}}
}
snapshots["test_check_type_of_luke 1"] = {
"data": {"hero": {"__typename": "Human", "name": "Luke Skywalker"}}
}

View File

@ -8,19 +8,19 @@ setup()
client = Client(schema) client = Client(schema)
def test_hero_name_query(snapshot): def test_hero_name_query():
query = """ result = client.execute("""
query HeroNameQuery { query HeroNameQuery {
hero { hero {
name name
} }
} }
""" """)
snapshot.assert_match(client.execute(query)) assert result == {"data": {"hero": {"name": "R2-D2"}}}
def test_hero_name_and_friends_query(snapshot): def test_hero_name_and_friends_query():
query = """ result = client.execute("""
query HeroNameAndFriendsQuery { query HeroNameAndFriendsQuery {
hero { hero {
id id
@ -30,12 +30,24 @@ def test_hero_name_and_friends_query(snapshot):
} }
} }
} }
""" """)
snapshot.assert_match(client.execute(query)) assert result == {
"data": {
"hero": {
"id": "2001",
"name": "R2-D2",
"friends": [
{"name": "Luke Skywalker"},
{"name": "Han Solo"},
{"name": "Leia Organa"},
],
}
}
}
def test_nested_query(snapshot): def test_nested_query():
query = """ result = client.execute("""
query NestedQuery { query NestedQuery {
hero { hero {
name name
@ -48,70 +60,113 @@ def test_nested_query(snapshot):
} }
} }
} }
""" """)
snapshot.assert_match(client.execute(query)) assert result == {
"data": {
"hero": {
"name": "R2-D2",
"friends": [
{
"name": "Luke Skywalker",
"appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"],
"friends": [
{"name": "Han Solo"},
{"name": "Leia Organa"},
{"name": "C-3PO"},
{"name": "R2-D2"},
],
},
{
"name": "Han Solo",
"appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"],
"friends": [
{"name": "Luke Skywalker"},
{"name": "Leia Organa"},
{"name": "R2-D2"},
],
},
{
"name": "Leia Organa",
"appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"],
"friends": [
{"name": "Luke Skywalker"},
{"name": "Han Solo"},
{"name": "C-3PO"},
{"name": "R2-D2"},
],
},
],
}
}
}
def test_fetch_luke_query(snapshot): def test_fetch_luke_query():
query = """ result = client.execute("""
query FetchLukeQuery { query FetchLukeQuery {
human(id: "1000") { human(id: "1000") {
name name
} }
} }
""" """)
snapshot.assert_match(client.execute(query)) assert result == {"data": {"human": {"name": "Luke Skywalker"}}}
def test_fetch_some_id_query(snapshot): def test_fetch_some_id_query():
query = """ result = client.execute(
"""
query FetchSomeIDQuery($someId: String!) { query FetchSomeIDQuery($someId: String!) {
human(id: $someId) { human(id: $someId) {
name name
} }
} }
""" """,
params = {"someId": "1000"} variables={"someId": "1000"},
snapshot.assert_match(client.execute(query, variables=params)) )
assert result == {"data": {"human": {"name": "Luke Skywalker"}}}
def test_fetch_some_id_query2(snapshot): def test_fetch_some_id_query2():
query = """ result = client.execute(
"""
query FetchSomeIDQuery($someId: String!) { query FetchSomeIDQuery($someId: String!) {
human(id: $someId) { human(id: $someId) {
name name
} }
} }
""" """,
params = {"someId": "1002"} variables={"someId": "1002"},
snapshot.assert_match(client.execute(query, variables=params)) )
assert result == {"data": {"human": {"name": "Han Solo"}}}
def test_invalid_id_query(snapshot): def test_invalid_id_query():
query = """ result = client.execute(
"""
query humanQuery($id: String!) { query humanQuery($id: String!) {
human(id: $id) { human(id: $id) {
name name
} }
} }
""" """,
params = {"id": "not a valid id"} variables={"id": "not a valid id"},
snapshot.assert_match(client.execute(query, variables=params)) )
assert result == {"data": {"human": None}}
def test_fetch_luke_aliased(snapshot): def test_fetch_luke_aliased():
query = """ result = client.execute("""
query FetchLukeAliased { query FetchLukeAliased {
luke: human(id: "1000") { luke: human(id: "1000") {
name name
} }
} }
""" """)
snapshot.assert_match(client.execute(query)) assert result == {"data": {"luke": {"name": "Luke Skywalker"}}}
def test_fetch_luke_and_leia_aliased(snapshot): def test_fetch_luke_and_leia_aliased():
query = """ result = client.execute("""
query FetchLukeAndLeiaAliased { query FetchLukeAndLeiaAliased {
luke: human(id: "1000") { luke: human(id: "1000") {
name name
@ -120,12 +175,14 @@ def test_fetch_luke_and_leia_aliased(snapshot):
name name
} }
} }
""" """)
snapshot.assert_match(client.execute(query)) assert result == {
"data": {"luke": {"name": "Luke Skywalker"}, "leia": {"name": "Leia Organa"}}
}
def test_duplicate_fields(snapshot): def test_duplicate_fields():
query = """ result = client.execute("""
query DuplicateFields { query DuplicateFields {
luke: human(id: "1000") { luke: human(id: "1000") {
name name
@ -136,12 +193,17 @@ def test_duplicate_fields(snapshot):
homePlanet homePlanet
} }
} }
""" """)
snapshot.assert_match(client.execute(query)) assert result == {
"data": {
"luke": {"name": "Luke Skywalker", "homePlanet": "Tatooine"},
"leia": {"name": "Leia Organa", "homePlanet": "Alderaan"},
}
}
def test_use_fragment(snapshot): def test_use_fragment():
query = """ result = client.execute("""
query UseFragment { query UseFragment {
luke: human(id: "1000") { luke: human(id: "1000") {
...HumanFragment ...HumanFragment
@ -154,29 +216,36 @@ def test_use_fragment(snapshot):
name name
homePlanet homePlanet
} }
""" """)
snapshot.assert_match(client.execute(query)) assert result == {
"data": {
"luke": {"name": "Luke Skywalker", "homePlanet": "Tatooine"},
"leia": {"name": "Leia Organa", "homePlanet": "Alderaan"},
}
}
def test_check_type_of_r2(snapshot): def test_check_type_of_r2():
query = """ result = client.execute("""
query CheckTypeOfR2 { query CheckTypeOfR2 {
hero { hero {
__typename __typename
name name
} }
} }
""" """)
snapshot.assert_match(client.execute(query)) assert result == {"data": {"hero": {"__typename": "Droid", "name": "R2-D2"}}}
def test_check_type_of_luke(snapshot): def test_check_type_of_luke():
query = """ result = client.execute("""
query CheckTypeOfLuke { query CheckTypeOfLuke {
hero(episode: EMPIRE) { hero(episode: EMPIRE) {
__typename __typename
name name
} }
} }
""" """)
snapshot.assert_match(client.execute(query)) assert result == {
"data": {"hero": {"__typename": "Human", "name": "Luke Skywalker"}}
}

View File

@ -1,24 +0,0 @@
# -*- coding: utf-8 -*-
# snapshottest: v1 - https://goo.gl/zC4yUc
from snapshottest import Snapshot
snapshots = Snapshot()
snapshots["test_correct_fetch_first_ship_rebels 1"] = {
"data": {
"rebels": {
"name": "Alliance to Restore the Republic",
"ships": {
"pageInfo": {
"startCursor": "YXJyYXljb25uZWN0aW9uOjA=",
"endCursor": "YXJyYXljb25uZWN0aW9uOjA=",
"hasNextPage": True,
"hasPreviousPage": False,
},
"edges": [
{"cursor": "YXJyYXljb25uZWN0aW9uOjA=", "node": {"name": "X-Wing"}}
],
},
}
}
}

View File

@ -1,26 +0,0 @@
# -*- coding: utf-8 -*-
# snapshottest: v1 - https://goo.gl/zC4yUc
from snapshottest import Snapshot
snapshots = Snapshot()
snapshots["test_mutations 1"] = {
"data": {
"introduceShip": {
"ship": {"id": "U2hpcDo5", "name": "Peter"},
"faction": {
"name": "Alliance to Restore the Republic",
"ships": {
"edges": [
{"node": {"id": "U2hpcDox", "name": "X-Wing"}},
{"node": {"id": "U2hpcDoy", "name": "Y-Wing"}},
{"node": {"id": "U2hpcDoz", "name": "A-Wing"}},
{"node": {"id": "U2hpcDo0", "name": "Millennium Falcon"}},
{"node": {"id": "U2hpcDo1", "name": "Home One"}},
{"node": {"id": "U2hpcDo5", "name": "Peter"}},
]
},
},
}
}
}

View File

@ -1,114 +0,0 @@
# -*- coding: utf-8 -*-
# snapshottest: v1 - https://goo.gl/zC4yUc
from snapshottest import Snapshot
snapshots = Snapshot()
snapshots["test_correctly_fetches_id_name_rebels 1"] = {
"data": {
"rebels": {"id": "RmFjdGlvbjox", "name": "Alliance to Restore the Republic"}
}
}
snapshots["test_correctly_refetches_rebels 1"] = {
"data": {"node": {"id": "RmFjdGlvbjox", "name": "Alliance to Restore the Republic"}}
}
snapshots["test_correctly_fetches_id_name_empire 1"] = {
"data": {"empire": {"id": "RmFjdGlvbjoy", "name": "Galactic Empire"}}
}
snapshots["test_correctly_refetches_empire 1"] = {
"data": {"node": {"id": "RmFjdGlvbjoy", "name": "Galactic Empire"}}
}
snapshots["test_correctly_refetches_xwing 1"] = {
"data": {"node": {"id": "U2hpcDox", "name": "X-Wing"}}
}
snapshots["test_str_schema 1"] = '''type Query {
rebels: Faction
empire: Faction
node(
"""The ID of the object"""
id: ID!
): Node
}
"""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
"""The ships used by the faction."""
ships(before: String, after: String, first: Int, last: Int): ShipConnection
}
"""An object with an ID"""
interface Node {
"""The ID of the object"""
id: ID!
}
type ShipConnection {
"""Pagination data for this connection."""
pageInfo: PageInfo!
"""Contains the nodes in this connection."""
edges: [ShipEdge]!
}
"""
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 `Ship` and its cursor."""
type ShipEdge {
"""The item at the end of the edge"""
node: Ship
"""A cursor for use in pagination"""
cursor: String!
}
"""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 Mutation {
introduceShip(input: IntroduceShipInput!): IntroduceShipPayload
}
type IntroduceShipPayload {
ship: Ship
faction: Faction
clientMutationId: String
}
input IntroduceShipInput {
shipName: String!
factionId: String!
clientMutationId: String
}'''

View File

@ -8,26 +8,46 @@ setup()
client = Client(schema) client = Client(schema)
def test_correct_fetch_first_ship_rebels(snapshot): def test_correct_fetch_first_ship_rebels():
query = """ result = client.execute("""
query RebelsShipsQuery { query RebelsShipsQuery {
rebels { rebels {
name, name,
ships(first: 1) { ships(first: 1) {
pageInfo { pageInfo {
startCursor startCursor
endCursor endCursor
hasNextPage hasNextPage
hasPreviousPage hasPreviousPage
} }
edges { edges {
cursor cursor
node { node {
name name
}
}
} }
} }
} }
} """)
assert result == {
"data": {
"rebels": {
"name": "Alliance to Restore the Republic",
"ships": {
"pageInfo": {
"startCursor": "YXJyYXljb25uZWN0aW9uOjA=",
"endCursor": "YXJyYXljb25uZWN0aW9uOjA=",
"hasNextPage": True,
"hasPreviousPage": False,
},
"edges": [
{
"cursor": "YXJyYXljb25uZWN0aW9uOjA=",
"node": {"name": "X-Wing"},
}
],
},
}
}
} }
"""
snapshot.assert_match(client.execute(query))

View File

@ -8,26 +8,45 @@ setup()
client = Client(schema) client = Client(schema)
def test_mutations(snapshot): def test_mutations():
query = """ result = client.execute("""
mutation MyMutation { mutation MyMutation {
introduceShip(input:{clientMutationId:"abc", shipName: "Peter", factionId: "1"}) { introduceShip(input:{clientMutationId:"abc", shipName: "Peter", factionId: "1"}) {
ship { ship {
id id
name name
} }
faction { faction {
name name
ships { ships {
edges { edges {
node { node {
id id
name name
}
}
} }
} }
} }
} }
} """)
assert result == {
"data": {
"introduceShip": {
"ship": {"id": "U2hpcDo5", "name": "Peter"},
"faction": {
"name": "Alliance to Restore the Republic",
"ships": {
"edges": [
{"node": {"id": "U2hpcDox", "name": "X-Wing"}},
{"node": {"id": "U2hpcDoy", "name": "Y-Wing"}},
{"node": {"id": "U2hpcDoz", "name": "A-Wing"}},
{"node": {"id": "U2hpcDo0", "name": "Millennium Falcon"}},
{"node": {"id": "U2hpcDo1", "name": "Home One"}},
{"node": {"id": "U2hpcDo5", "name": "Peter"}},
]
},
},
}
}
} }
"""
snapshot.assert_match(client.execute(query))

View File

@ -1,3 +1,5 @@
import textwrap
from graphene.test import Client from graphene.test import Client
from ..data import setup from ..data import setup
@ -8,24 +10,115 @@ setup()
client = Client(schema) client = Client(schema)
def test_str_schema(snapshot): def test_str_schema():
snapshot.assert_match(str(schema).strip()) assert str(schema).strip() == textwrap.dedent(
'''\
type Query {
rebels: Faction
empire: Faction
node(
"""The ID of the object"""
id: ID!
): Node
}
"""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
"""The ships used by the faction."""
ships(before: String, after: String, first: Int, last: Int): ShipConnection
}
"""An object with an ID"""
interface Node {
"""The ID of the object"""
id: ID!
}
type ShipConnection {
"""Pagination data for this connection."""
pageInfo: PageInfo!
"""Contains the nodes in this connection."""
edges: [ShipEdge]!
}
"""
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 `Ship` and its cursor."""
type ShipEdge {
"""The item at the end of the edge"""
node: Ship
"""A cursor for use in pagination"""
cursor: String!
}
"""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 Mutation {
introduceShip(input: IntroduceShipInput!): IntroduceShipPayload
}
type IntroduceShipPayload {
ship: Ship
faction: Faction
clientMutationId: String
}
input IntroduceShipInput {
shipName: String!
factionId: String!
clientMutationId: String
}'''
)
def test_correctly_fetches_id_name_rebels(snapshot): def test_correctly_fetches_id_name_rebels():
query = """ result = client.execute("""
query RebelsQuery { query RebelsQuery {
rebels { rebels {
id id
name name
} }
} }
""" """)
snapshot.assert_match(client.execute(query)) assert result == {
"data": {
"rebels": {"id": "RmFjdGlvbjox", "name": "Alliance to Restore the Republic"}
}
}
def test_correctly_refetches_rebels(snapshot): def test_correctly_refetches_rebels():
query = """ result = client.execute("""
query RebelsRefetchQuery { query RebelsRefetchQuery {
node(id: "RmFjdGlvbjox") { node(id: "RmFjdGlvbjox") {
id id
@ -34,24 +127,30 @@ def test_correctly_refetches_rebels(snapshot):
} }
} }
} }
""" """)
snapshot.assert_match(client.execute(query)) assert result == {
"data": {
"node": {"id": "RmFjdGlvbjox", "name": "Alliance to Restore the Republic"}
}
}
def test_correctly_fetches_id_name_empire(snapshot): def test_correctly_fetches_id_name_empire():
query = """ result = client.execute("""
query EmpireQuery { query EmpireQuery {
empire { empire {
id id
name name
} }
} }
""" """)
snapshot.assert_match(client.execute(query)) assert result == {
"data": {"empire": {"id": "RmFjdGlvbjoy", "name": "Galactic Empire"}}
}
def test_correctly_refetches_empire(snapshot): def test_correctly_refetches_empire():
query = """ result = client.execute("""
query EmpireRefetchQuery { query EmpireRefetchQuery {
node(id: "RmFjdGlvbjoy") { node(id: "RmFjdGlvbjoy") {
id id
@ -60,12 +159,14 @@ def test_correctly_refetches_empire(snapshot):
} }
} }
} }
""" """)
snapshot.assert_match(client.execute(query)) assert result == {
"data": {"node": {"id": "RmFjdGlvbjoy", "name": "Galactic Empire"}}
}
def test_correctly_refetches_xwing(snapshot): def test_correctly_refetches_xwing():
query = """ result = client.execute("""
query XWingRefetchQuery { query XWingRefetchQuery {
node(id: "U2hpcDox") { node(id: "U2hpcDox") {
id id
@ -74,5 +175,5 @@ def test_correctly_refetches_xwing(snapshot):
} }
} }
} }
""" """)
snapshot.assert_match(client.execute(query)) assert result == {"data": {"node": {"id": "U2hpcDox", "name": "X-Wing"}}}

View File

@ -1,6 +1,6 @@
# https://github.com/graphql-python/graphene/issues/1293 # https://github.com/graphql-python/graphene/issues/1293
import datetime from datetime import datetime, timezone
import graphene import graphene
from graphql.utilities import print_schema from graphql.utilities import print_schema
@ -9,11 +9,11 @@ from graphql.utilities import print_schema
class Filters(graphene.InputObjectType): class Filters(graphene.InputObjectType):
datetime_after = graphene.DateTime( datetime_after = graphene.DateTime(
required=False, required=False,
default_value=datetime.datetime.utcfromtimestamp(1434549820776 / 1000), default_value=datetime.fromtimestamp(1434549820.776, timezone.utc),
) )
datetime_before = graphene.DateTime( datetime_before = graphene.DateTime(
required=False, required=False,
default_value=datetime.datetime.utcfromtimestamp(1444549820776 / 1000), default_value=datetime.fromtimestamp(1444549820.776, timezone.utc),
) )

View File

@ -51,35 +51,30 @@ def test_jsonstring_invalid_query():
Test that if an invalid type is provided we get an error Test that if an invalid type is provided we get an error
""" """
result = schema.execute("{ json(input: 1) }") result = schema.execute("{ json(input: 1) }")
assert result.errors assert result.errors == [
assert len(result.errors) == 1 {"message": "Expected value of type 'JSONString', found 1."},
assert result.errors[0].message == "Expected value of type 'JSONString', found 1." ]
result = schema.execute("{ json(input: {}) }") result = schema.execute("{ json(input: {}) }")
assert result.errors assert result.errors == [
assert len(result.errors) == 1 {"message": "Expected value of type 'JSONString', found {}."},
assert result.errors[0].message == "Expected value of type 'JSONString', found {}." ]
result = schema.execute('{ json(input: "a") }') result = schema.execute('{ json(input: "a") }')
assert result.errors assert result.errors == [
assert len(result.errors) == 1 {
assert result.errors[0].message == ( "message": "Expected value of type 'JSONString', found \"a\"; "
"Expected value of type 'JSONString', found \"a\"; " "Badly formed JSONString: Expecting value: line 1 column 1 (char 0)",
"Badly formed JSONString: Expecting value: line 1 column 1 (char 0)" },
) ]
result = schema.execute("""{ json(input: "{\\'key\\': 0}") }""") result = schema.execute("""{ json(input: "{\\'key\\': 0}") }""")
assert result.errors assert result.errors == [
assert len(result.errors) == 1 {"message": "Syntax Error: Invalid character escape sequence: '\\''."},
assert ( ]
result.errors[0].message
== "Syntax Error: Invalid character escape sequence: '\\''."
)
result = schema.execute("""{ json(input: "{\\"key\\": 0,}") }""") result = schema.execute("""{ json(input: "{\\"key\\": 0,}") }""")
assert result.errors
assert len(result.errors) == 1 assert len(result.errors) == 1
assert result.errors[0].message == ( assert result.errors[0].message.startswith(
'Expected value of type \'JSONString\', found "{\\"key\\": 0,}"; ' 'Expected value of type \'JSONString\', found "{\\"key\\": 0,}"; Badly formed JSONString:'
"Badly formed JSONString: Expecting property name enclosed in double quotes: line 1 column 11 (char 10)"
) )

View File

@ -50,7 +50,6 @@ tests_require = [
"pytest-cov>=5,<6", "pytest-cov>=5,<6",
"pytest-mock>=3,<4", "pytest-mock>=3,<4",
"pytest-asyncio>=0.16,<2", "pytest-asyncio>=0.16,<2",
"snapshottest>=0.6,<1",
"coveralls>=3.3,<5", "coveralls>=3.3,<5",
] ]

View File

@ -5,10 +5,8 @@ skipsdist = true
[testenv] [testenv]
deps = deps =
.[test] .[test]
setenv =
PYTHONPATH = .:{envdir}
commands = commands =
py{38,39,310,311,12,13}: pytest --cov=graphene graphene --cov-report=term --cov-report=xml examples {posargs} pytest --cov=graphene graphene --cov-report=term --cov-report=xml examples {posargs}
[testenv:pre-commit] [testenv:pre-commit]
basepython = python3.10 basepython = python3.10