Repository: strawberry-graphql/strawberry

Issue:
Using an `Enum` as default value in resolver method raises `GraphQLError`
I tried to use an `Enum` as default argument for a resolver method:

```python
@strawberry.enum
class VersionSequence(Enum):
    FULL = "full"
    SHORT = "short"
    PATCH = "patch"

@strawberry.type
class Info:
    @strawberry.field
    def version(
        self, sequence: VersionSequence = VersionSequence.FULL
    ) -> str:
        return getVersion(sequence.value)
```
When accessing the GraphQL endpoint the following error is raised:
```python
Enum 'VersionSequence' cannot represent value: <VersionSequence instance>
Traceback (most recent call last):
  File "/home/mawiegand/.cache/pypoetry/virtualenvs/api-LQwpF9HC-py3.9/lib/python3.9/site-packages/graphql/execution/execute.py", line 617, in resolve_field
    result = resolve_fn(source, info, **args)
  File "/home/mawiegand/.cache/pypoetry/virtualenvs/api-LQwpF9HC-py3.9/lib/python3.9/site-packages/strawberry/middleware.py", line 29, in resolve
    result = next_(root, info, **kwargs)
  File "/home/mawiegand/.cache/pypoetry/virtualenvs/api-LQwpF9HC-py3.9/lib/python3.9/site-packages/graphql/type/introspection.py", line 454, in default_value
    value_ast = ast_from_value(item[1].default_value, item[1].type)
  File "/home/mawiegand/.cache/pypoetry/virtualenvs/api-LQwpF9HC-py3.9/lib/python3.9/site-packages/graphql/utilities/ast_from_value.py", line 63, in ast_from_value
    ast_value = ast_from_value(value, type_.of_type)
  File "/home/mawiegand/.cache/pypoetry/virtualenvs/api-LQwpF9HC-py3.9/lib/python3.9/site-packages/graphql/utilities/ast_from_value.py", line 108, in ast_from_value
    serialized = type_.serialize(value)  # type: ignore
  File "/home/mawiegand/.cache/pypoetry/virtualenvs/api-LQwpF9HC-py3.9/lib/python3.9/site-packages/graphql/type/definition.py", line 1155, in serialize
    raise GraphQLError(
graphql.error.graphql_error.GraphQLError: Enum 'VersionSequence' cannot represent value: <VersionSequence instance>
```
Querying without arguments seems to be working. Probably only the schema representation is affected.

Environment information:
Strawberry: `0.65.3`
Python: `[3.7, 3.9]`

<!-- POLAR PLEDGE BADGE START -->
## Upvote & Fund

- We're using [Polar.sh](https://polar.sh/strawberry-graphql) so you can upvote and help fund this issue.
- We receive the funding once the issue is completed & confirmed by you.
- Thank you in advance for helping prioritize & fund our backlog.

<a href="https://polar.sh/strawberry-graphql/strawberry/issues/1007">
<picture>
  <source media="(prefers-color-scheme: dark)" srcset="https://polar.sh/api/github/strawberry-graphql/strawberry/issues/1007/pledge.svg?darkmode=1">
  <img alt="Fund with Polar" src="https://polar.sh/api/github/strawberry-graphql/strawberry/issues/1007/pledge.svg">
</picture>
</a>
<!-- POLAR PLEDGE BADGE END -->

Using an `Enum` as default value in resolver method raises `GraphQLError`
I tried to use an `Enum` as default argument for a resolver method:

```python
@strawberry.enum
class VersionSequence(Enum):
    FULL = "full"
    SHORT = "short"
    PATCH = "patch"

@strawberry.type
class Info:
    @strawberry.field
    def version(
        self, sequence: VersionSequence = VersionSequence.FULL
    ) -> str:
        return getVersion(sequence.value)
```
When accessing the GraphQL endpoint the following error is raised:
```python
Enum 'VersionSequence' cannot represent value: <VersionSequence instance>
Traceback (most recent call last):
  File "/home/mawiegand/.cache/pypoetry/virtualenvs/api-LQwpF9HC-py3.9/lib/python3.9/site-packages/graphql/execution/execute.py", line 617, in resolve_field
    result = resolve_fn(source, info, **args)
  File "/home/mawiegand/.cache/pypoetry/virtualenvs/api-LQwpF9HC-py3.9/lib/python3.9/site-packages/strawberry/middleware.py", line 29, in resolve
    result = next_(root, info, **kwargs)
  File "/home/mawiegand/.cache/pypoetry/virtualenvs/api-LQwpF9HC-py3.9/lib/python3.9/site-packages/graphql/type/introspection.py", line 454, in default_value
    value_ast = ast_from_value(item[1].default_value, item[1].type)
  File "/home/mawiegand/.cache/pypoetry/virtualenvs/api-LQwpF9HC-py3.9/lib/python3.9/site-packages/graphql/utilities/ast_from_value.py", line 63, in ast_from_value
    ast_value = ast_from_value(value, type_.of_type)
  File "/home/mawiegand/.cache/pypoetry/virtualenvs/api-LQwpF9HC-py3.9/lib/python3.9/site-packages/graphql/utilities/ast_from_value.py", line 108, in ast_from_value
    serialized = type_.serialize(value)  # type: ignore
  File "/home/mawiegand/.cache/pypoetry/virtualenvs/api-LQwpF9HC-py3.9/lib/python3.9/site-packages/graphql/type/definition.py", line 1155, in serialize
    raise GraphQLError(
graphql.error.graphql_error.GraphQLError: Enum 'VersionSequence' cannot represent value: <VersionSequence instance>
```
Querying without arguments seems to be working. Probably only the schema representation is affected.

Environment information:
Strawberry: `0.65.3`
Python: `[3.7, 3.9]`

<!-- POLAR PLEDGE BADGE START -->
## Upvote & Fund

- We're using [Polar.sh](https://polar.sh/strawberry-graphql) so you can upvote and help fund this issue.
- We receive the funding once the issue is completed & confirmed by you.
- Thank you in advance for helping prioritize & fund our backlog.

<a href="https://polar.sh/strawberry-graphql/strawberry/issues/1007">
<picture>
  <source media="(prefers-color-scheme: dark)" srcset="https://polar.sh/api/github/strawberry-graphql/strawberry/issues/1007/pledge.svg?darkmode=1">
  <img alt="Fund with Polar" src="https://polar.sh/api/github/strawberry-graphql/strawberry/issues/1007/pledge.svg">
</picture>
</a>
<!-- POLAR PLEDGE BADGE END -->



Discussion:

Resolving patch:
diff --git a/strawberry/field.py b/strawberry/field.py
--- a/strawberry/field.py
+++ b/strawberry/field.py
@@ -1,5 +1,4 @@
 import dataclasses
-import enum
 import typing
 from inspect import isasyncgen, iscoroutine
 from typing import Any, Awaitable, Callable, Dict, List, Optional, Tuple, Type, Union
@@ -233,23 +232,6 @@ def _check_permissions(source: Any, info: Info, kwargs: Dict[str, Any]):
                     message = getattr(permission, "message", None)
                     raise PermissionError(message)
 
-        def _convert_enums_to_values(field_: StrawberryField, result: Any) -> Any:
-            # graphql-core expects a resolver for an Enum type to return
-            # the enum's *value* (not its name or an instance of the enum).
-
-            # short circuit to skip checks when result is falsy
-            if not result:
-                return result
-
-            if isinstance(result, enum.Enum):
-                return result.value
-
-            if field_.is_list:
-                assert field_.child is not None
-                return [_convert_enums_to_values(field_.child, item) for item in result]
-
-            return result
-
         def _strawberry_info_from_graphql(info: GraphQLResolveInfo) -> Info:
             return Info(
                 field_name=info.field_name,
@@ -272,18 +254,17 @@ def _resolver(_source: Any, info: GraphQLResolveInfo, **kwargs):
 
                 async def yield_results(results):
                     async for value in results:
-                        yield _convert_enums_to_values(self, value)
+                        yield value
 
                 return yield_results(result)
 
             if iscoroutine(result):  # pragma: no cover
 
                 async def await_result(result):
-                    return _convert_enums_to_values(self, await result)
+                    return await result
 
                 return await_result(result)
 
-            result = _convert_enums_to_values(self, result)
             return result
 
         _resolver._is_default = not self.base_resolver  # type: ignore
diff --git a/strawberry/schema/schema_converter.py b/strawberry/schema/schema_converter.py
--- a/strawberry/schema/schema_converter.py
+++ b/strawberry/schema/schema_converter.py
@@ -1,3 +1,4 @@
+from enum import Enum
 from typing import Any, Callable, Dict, Type, cast
 
 from graphql import (
@@ -33,6 +34,17 @@
 from .types.scalar import get_scalar_type
 
 
+# graphql-core expects a resolver for an Enum type to return
+# the enum's *value* (not its name or an instance of the enum). We have to
+# subclass the GraphQLEnumType class to enable returning Enum members from
+# resolvers.
+class CustomGraphQLEnumType(GraphQLEnumType):
+    def serialize(self, output_value: Any) -> str:
+        if isinstance(output_value, Enum):
+            return output_value.name
+        return super().serialize(output_value)
+
+
 class GraphQLCoreConverter:
     # TODO: Make abstract
 
@@ -108,17 +120,17 @@ def from_argument(self, argument: StrawberryArgument) -> GraphQLArgument:
             description=argument.description,
         )
 
-    def from_enum(self, enum: EnumDefinition) -> GraphQLEnumType:
+    def from_enum(self, enum: EnumDefinition) -> CustomGraphQLEnumType:
 
         assert enum.name is not None
 
         # Don't reevaluate known types
         if enum.name in self.type_map:
             graphql_enum = self.type_map[enum.name].implementation
-            assert isinstance(graphql_enum, GraphQLEnumType)  # For mypy
+            assert isinstance(graphql_enum, CustomGraphQLEnumType)  # For mypy
             return graphql_enum
 
-        graphql_enum = GraphQLEnumType(
+        graphql_enum = CustomGraphQLEnumType(
             name=enum.name,
             values={item.name: self.from_enum_value(item) for item in enum.values},
             description=enum.description,


Test patch:
diff --git a/tests/schema/test_enum.py b/tests/schema/test_enum.py
--- a/tests/schema/test_enum.py
+++ b/tests/schema/test_enum.py
@@ -1,5 +1,6 @@
 import typing
 from enum import Enum
+from textwrap import dedent
 from typing import List, Optional
 
 import pytest
@@ -226,3 +227,110 @@ async def best_flavours(self) -> List[IceCreamFlavour]:
 
     assert not result.errors
     assert result.data["bestFlavours"] == ["STRAWBERRY", "PISTACHIO"]
+
+
+def test_enum_as_argument():
+    @strawberry.enum
+    class IceCreamFlavour(Enum):
+        VANILLA = "vanilla"
+        STRAWBERRY = "strawberry"
+        CHOCOLATE = "chocolate"
+        PISTACHIO = "pistachio"
+
+    @strawberry.type
+    class Query:
+        @strawberry.field
+        def create_flavour(self, flavour: IceCreamFlavour) -> str:
+            return f"{flavour.name}"
+
+    schema = strawberry.Schema(query=Query)
+
+    expected = dedent(
+        """
+        enum IceCreamFlavour {
+          VANILLA
+          STRAWBERRY
+          CHOCOLATE
+          PISTACHIO
+        }
+
+        type Query {
+          createFlavour(flavour: IceCreamFlavour!): String!
+        }
+        """
+    ).strip()
+
+    assert str(schema) == expected
+
+    query = "{ createFlavour(flavour: CHOCOLATE) }"
+
+    result = schema.execute_sync(query)
+
+    assert not result.errors
+    assert result.data["createFlavour"] == "CHOCOLATE"
+
+
+def test_enum_as_default_argument():
+    @strawberry.enum
+    class IceCreamFlavour(Enum):
+        VANILLA = "vanilla"
+        STRAWBERRY = "strawberry"
+        CHOCOLATE = "chocolate"
+        PISTACHIO = "pistachio"
+
+    @strawberry.type
+    class Query:
+        @strawberry.field
+        def create_flavour(
+            self, flavour: IceCreamFlavour = IceCreamFlavour.STRAWBERRY
+        ) -> str:
+            return f"{flavour.name}"
+
+    schema = strawberry.Schema(query=Query)
+
+    expected = dedent(
+        """
+        enum IceCreamFlavour {
+          VANILLA
+          STRAWBERRY
+          CHOCOLATE
+          PISTACHIO
+        }
+
+        type Query {
+          createFlavour(flavour: IceCreamFlavour! = STRAWBERRY): String!
+        }
+        """
+    ).strip()
+
+    assert str(schema) == expected
+
+    query = "{ createFlavour }"
+
+    result = schema.execute_sync(query)
+
+    assert not result.errors
+    assert result.data["createFlavour"] == "STRAWBERRY"
+
+
+def test_enum_resolver_plain_value():
+    @strawberry.enum
+    class IceCreamFlavour(Enum):
+        VANILLA = "vanilla"
+        STRAWBERRY = "strawberry"
+        CHOCOLATE = "chocolate"
+
+    @strawberry.type
+    class Query:
+        @strawberry.field
+        def best_flavour(self) -> IceCreamFlavour:
+            return "strawberry"  # type: ignore
+
+    schema = strawberry.Schema(query=Query)
+
+    query = "{ bestFlavour }"
+
+    result = schema.execute_sync(query)
+
+    assert not result.errors
+    assert result.data["bestFlavour"] == "STRAWBERRY"