Repository: mirumee/ariadne

Issue:
Argument 'code' has invalid value "ABC"
I think there is a bug when using both literal and variable values with a custom scalar.

```python
from ariadne import ScalarType

testscalar = ScalarType('TestScalar')

@testscalar.serializer
def serializer(value):
    return value.upper()


@testscalar.value_parser
def value_parser(value):
    if value:
        return serializer(value)


@testscalar.literal_parser
def literal_parser(ast):
    value = str(ast.value)
    return value_parser(value)
```

If you then make the following query:
```graphql
query($code: TestScalar) {
  test1: testType(code: $code) {
    id
  }
  test2: testType(code: "ABC") {
    id
  }
}
```
 This error is returned: Argument 'code' has invalid value "ABC"

If you don't pass variables and only use "literal" values it works. Same for if you only pass variables it works fine.

If you don't set up a resolver for "testType" then no error is returned.

Not sure what is happening but I think this is a bug. If not, does anyone know why this is happening?


Discussion:
Can you post the SDL for testType?
@thebenwaters Sure thing! Here is the entire SDL

```graphql
type Query {
  testType(code: TestScalar): TestType
}

scalar TestScalar

type TestType {
  id: ID!
  code: TestScalar
}
```
Seems that there's already an PR with fix for it: https://github.com/mirumee/ariadne/pull/280

But this seems like an issue with custom scalar handling in `graphql-core`. I'll confirm this with the library author first.

Resolving patch:
diff --git a/ariadne/scalars.py b/ariadne/scalars.py
--- a/ariadne/scalars.py
+++ b/ariadne/scalars.py
@@ -1,11 +1,5 @@
 from typing import Optional, cast
 
-from graphql.language.ast import (
-    BooleanValueNode,
-    FloatValueNode,
-    IntValueNode,
-    StringValueNode,
-)
 from graphql.type import (
     GraphQLNamedType,
     GraphQLScalarLiteralParser,
@@ -14,7 +8,6 @@
     GraphQLScalarValueParser,
     GraphQLSchema,
 )
-from graphql.utilities import value_from_ast_untyped
 
 from .types import SchemaBindable
 
@@ -43,8 +36,6 @@ def set_serializer(self, f: GraphQLScalarSerializer) -> GraphQLScalarSerializer:
 
     def set_value_parser(self, f: GraphQLScalarValueParser) -> GraphQLScalarValueParser:
         self._parse_value = f
-        if not self._parse_literal:
-            self._parse_literal = create_default_literal_parser(f)
         return f
 
     def set_literal_parser(
@@ -79,15 +70,3 @@ def validate_graphql_type(self, graphql_type: Optional[GraphQLNamedType]) -> Non
                 "%s is defined in the schema, but it is instance of %s (expected %s)"
                 % (self.name, type(graphql_type).__name__, GraphQLScalarType.__name__)
             )
-
-
-SCALAR_AST_NODES = (BooleanValueNode, FloatValueNode, IntValueNode, StringValueNode)
-
-
-def create_default_literal_parser(
-    value_parser: GraphQLScalarValueParser,
-) -> GraphQLScalarLiteralParser:
-    def default_literal_parser(ast):
-        return value_parser(value_from_ast_untyped(ast))
-
-    return default_literal_parser


Test patch:
diff --git a/tests/django/test_scalars.py b/tests/django/test_scalars.py
--- a/tests/django/test_scalars.py
+++ b/tests/django/test_scalars.py
@@ -82,17 +82,9 @@ def test_date_scalar_has_value_parser_set():
     assert date_scalar._parse_value == parse_date_value
 
 
-def test_date_scalar_has_lister_parser():
-    assert date_scalar._parse_literal
-
-
 def test_datetime_scalar_has_serializer_set():
     assert datetime_scalar._serialize == serialize_datetime
 
 
 def test_datetime_scalar_has_value_parser_set():
     assert datetime_scalar._parse_value == parse_datetime_value
-
-
-def test_datetime_scalar_has_lister_parser():
-    assert datetime_scalar._parse_literal
diff --git a/tests/test_custom_scalars.py b/tests/test_custom_scalars.py
--- a/tests/test_custom_scalars.py
+++ b/tests/test_custom_scalars.py
@@ -52,13 +52,13 @@ def serialize_date(date):
 
 
 @dateinput.value_parser
-def parse_date_str(formatted_date):
+def parse_date_value(formatted_date):
     parsed_datetime = datetime.strptime(formatted_date, "%Y-%m-%d")
     return parsed_datetime.date()
 
 
 @dateinput.literal_parser
-def parse_date_literal(ast):
+def parse_date_literal(ast, variable_values=None):  # pylint: disable=unused-argument
     if not isinstance(ast, StringValueNode):
         raise ValueError()
 
@@ -126,6 +126,18 @@ def test_attempt_deserialize_wrong_type_literal_raises_error():
     ]
 
 
+def test_default_literal_parser_is_used_to_extract_value_str_from_ast_node():
+    dateinput = ScalarType("DateInput")
+    dateinput.set_value_parser(parse_date_value)
+    schema = make_executable_schema(type_defs, query, dateinput)
+
+    result = graphql_sync(
+        schema, """{ testInput(value: "%s") }""" % TEST_DATE_SERIALIZED
+    )
+    assert result.errors is None
+    assert result.data == {"testInput": True}
+
+
 parametrized_query = """
     query parseValueTest($value: DateInput!) {
         testInput(value: $value)
@@ -182,21 +194,21 @@ def test_scalar_serializer_can_be_set_with_setter():
 
 def test_scalar_value_parser_can_be_set_on_initialization():
     schema = build_schema(type_defs)
-    scalar = ScalarType("DateInput", value_parser=parse_date_str)
+    scalar = ScalarType("DateInput", value_parser=parse_date_value)
     scalar.bind_to_schema(schema)
 
     schema_scalar = schema.type_map.get("DateInput")
-    assert schema_scalar.parse_value is parse_date_str
+    assert schema_scalar.parse_value is parse_date_value
 
 
 def test_scalar_value_parser_can_be_set_with_setter():
     schema = build_schema(type_defs)
     scalar = ScalarType("DateInput")
-    scalar.set_value_parser(parse_date_str)
+    scalar.set_value_parser(parse_date_value)
     scalar.bind_to_schema(schema)
 
     schema_scalar = schema.type_map.get("DateInput")
-    assert schema_scalar.parse_value is parse_date_str
+    assert schema_scalar.parse_value is parse_date_value
 
 
 def test_scalar_literal_parser_can_be_set_on_initialization():
@@ -221,26 +233,14 @@ def test_scalar_literal_parser_can_be_set_with_setter():
 def test_setting_scalar_value_parser_sets_default_literal_parsers_if_none_is_set():
     schema = build_schema(type_defs)
     scalar = ScalarType("DateInput")
-    scalar.set_value_parser(parse_date_str)
+    scalar.set_value_parser(parse_date_value)
     scalar.bind_to_schema(schema)
 
     schema_scalar = schema.type_map.get("DateInput")
-    assert schema_scalar.parse_value is parse_date_str
+    assert schema_scalar.parse_value is parse_date_value
     assert schema_scalar.parse_literal
 
 
-def test_setting_scalar_value_parser_doesnt_override_already_set_literal_parser():
-    schema = build_schema(type_defs)
-    scalar = ScalarType("DateInput")
-    scalar.set_literal_parser(parse_date_literal)
-    scalar.set_value_parser(parse_date_str)
-    scalar.bind_to_schema(schema)
-
-    schema_scalar = schema.type_map.get("DateInput")
-    assert schema_scalar.parse_value is parse_date_str
-    assert schema_scalar.parse_literal is parse_date_literal
-
-
 def test_literal_string_is_deserialized_by_default_parser():
     result = graphql_sync(schema, '{ testInputValueType(value: "test") }')
     assert result.errors is None