diff --git a/examples/starwars_relay/tests/snapshots/snap_test_objectidentification.py b/examples/starwars_relay/tests/snapshots/snap_test_objectidentification.py index 7bce5ba3..d7694e90 100644 --- a/examples/starwars_relay/tests/snapshots/snap_test_objectidentification.py +++ b/examples/starwars_relay/tests/snapshots/snap_test_objectidentification.py @@ -49,7 +49,7 @@ type Faction implements Node { name: String """The ships used by the faction.""" - ships(before: String = null, after: String = null, first: Int = null, last: Int = null): ShipConnection + ships(before: String, after: String, first: Int, last: Int): ShipConnection } """An object with an ID""" diff --git a/graphene/relay/node.py b/graphene/relay/node.py index c1316d22..dabcff6c 100644 --- a/graphene/relay/node.py +++ b/graphene/relay/node.py @@ -86,6 +86,8 @@ class Node(AbstractNode): def get_node_from_global_id(cls, info, global_id, only_type=None): try: _type, _id = cls.from_global_id(global_id) + if not _type: + raise ValueError("Invalid Global ID") except Exception as e: raise Exception( f'Unable to parse global ID "{global_id}". ' diff --git a/graphene/tests/issues/test_1394.py b/graphene/tests/issues/test_1394.py new file mode 100644 index 00000000..39374381 --- /dev/null +++ b/graphene/tests/issues/test_1394.py @@ -0,0 +1,36 @@ +from ...types import ObjectType, Schema, String, NonNull + + +class Query(ObjectType): + hello = String(input=NonNull(String)) + + def resolve_hello(self, info, input): + if input == "nothing": + return None + return f"Hello {input}!" + + +schema = Schema(query=Query) + + +def test_required_input_provided(): + """ + Test that a required argument works when provided. + """ + input_value = "Potato" + result = schema.execute('{ hello(input: "%s") }' % input_value) + assert not result.errors + assert result.data == {"hello": "Hello Potato!"} + + +def test_required_input_missing(): + """ + Test that a required argument raised an error if not provided. + """ + result = schema.execute("{ hello }") + assert result.errors + assert len(result.errors) == 1 + assert ( + result.errors[0].message + == "Field 'hello' argument 'input' of type 'String!' is required, but it was not provided." + ) diff --git a/graphene/types/argument.py b/graphene/types/argument.py index 71026d45..f9dc843b 100644 --- a/graphene/types/argument.py +++ b/graphene/types/argument.py @@ -1,4 +1,5 @@ from itertools import chain +from graphql import Undefined from .dynamic import Dynamic from .mountedtype import MountedType @@ -41,7 +42,7 @@ class Argument(MountedType): def __init__( self, type_, - default_value=None, + default_value=Undefined, description=None, name=None, required=False, diff --git a/graphene/types/tests/test_query.py b/graphene/types/tests/test_query.py index 2d3e4c73..e117754f 100644 --- a/graphene/types/tests/test_query.py +++ b/graphene/types/tests/test_query.py @@ -229,11 +229,11 @@ def test_query_arguments(): result = test_schema.execute("{ test }", None) assert not result.errors - assert result.data == {"test": '[null,{"a_str":null,"a_int":null}]'} + assert result.data == {"test": "[null,{}]"} result = test_schema.execute('{ test(aStr: "String!") }', "Source!") assert not result.errors - assert result.data == {"test": '["Source!",{"a_str":"String!","a_int":null}]'} + assert result.data == {"test": '["Source!",{"a_str":"String!"}]'} result = test_schema.execute('{ test(aInt: -123, aStr: "String!") }', "Source!") assert not result.errors @@ -258,7 +258,7 @@ def test_query_input_field(): result = test_schema.execute("{ test }", None) assert not result.errors - assert result.data == {"test": '[null,{"a_input":null}]'} + assert result.data == {"test": "[null,{}]"} result = test_schema.execute('{ test(aInput: {aField: "String!"} ) }', "Source!") assert not result.errors diff --git a/graphene/types/tests/test_type_map.py b/graphene/types/tests/test_type_map.py index 12e7a1f4..f0c78e08 100644 --- a/graphene/types/tests/test_type_map.py +++ b/graphene/types/tests/test_type_map.py @@ -1,3 +1,4 @@ +from graphql import Undefined from graphql.type import ( GraphQLArgument, GraphQLEnumType, @@ -244,7 +245,9 @@ def test_objecttype_camelcase(): foo_field = fields["fooBar"] assert isinstance(foo_field, GraphQLField) assert foo_field.args == { - "barFoo": GraphQLArgument(GraphQLString, default_value=None, out_name="bar_foo") + "barFoo": GraphQLArgument( + GraphQLString, default_value=Undefined, out_name="bar_foo" + ) } @@ -267,7 +270,7 @@ def test_objecttype_camelcase_disabled(): assert isinstance(foo_field, GraphQLField) assert foo_field.args == { "bar_foo": GraphQLArgument( - GraphQLString, default_value=None, out_name="bar_foo" + GraphQLString, default_value=Undefined, out_name="bar_foo" ) } diff --git a/graphene/utils/tests/test_deduplicator.py b/graphene/utils/tests/test_deduplicator.py index b845caf1..95a70e74 100644 --- a/graphene/utils/tests/test_deduplicator.py +++ b/graphene/utils/tests/test_deduplicator.py @@ -94,6 +94,7 @@ TEST_DATA = { ], "movies": { "1198359": { + "id": "1198359", "name": "King Arthur: Legend of the Sword", "synopsis": ( "When the child Arthur's father is murdered, Vortigern, " @@ -159,7 +160,7 @@ def test_example_end_to_end(): "date": "2017-05-19", "movie": { "__typename": "Movie", - "id": "TW92aWU6Tm9uZQ==", + "id": "TW92aWU6MTE5ODM1OQ==", "name": "King Arthur: Legend of the Sword", "synopsis": ( "When the child Arthur's father is murdered, Vortigern, " @@ -172,7 +173,7 @@ def test_example_end_to_end(): "__typename": "Event", "id": "RXZlbnQ6MjM0", "date": "2017-05-20", - "movie": {"__typename": "Movie", "id": "TW92aWU6Tm9uZQ=="}, + "movie": {"__typename": "Movie", "id": "TW92aWU6MTE5ODM1OQ=="}, }, ] }