diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index c421c2b..a555ccd 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -8,7 +8,6 @@ on:
jobs:
build:
-
runs-on: ubuntu-latest
strategy:
fail-fast: false
@@ -16,20 +15,20 @@ jobs:
python-version: ["3.9", "3.10", "3.11", "3.12"]
steps:
- - uses: actions/checkout@v2
- - name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v2
- with:
- python-version: ${{ matrix.python-version }}
- - name: Install dependencies
- run: |
- python -m pip install --upgrade pip
- pip install -e .[test]
- - name: Pytest
- run: |
- pytest
- - name: Linters
- run: |
- pylint ariadne_graphql_modules tests
- mypy ariadne_graphql_modules --ignore-missing-imports
- black --check .
+ - uses: actions/checkout@v2
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v2
+ with:
+ python-version: ${{ matrix.python-version }}
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install -e .[test]
+ - name: Pytest
+ run: |
+ pytest
+ - name: Linters
+ run: |
+ pylint ariadne_graphql_modules
+ mypy ariadne_graphql_modules --ignore-missing-imports
+ black --check .
diff --git a/ariadne_graphql_modules/__init__.py b/ariadne_graphql_modules/__init__.py
index 789effe..c80762d 100644
--- a/ariadne_graphql_modules/__init__.py
+++ b/ariadne_graphql_modules/__init__.py
@@ -1,38 +1,58 @@
-from ariadne import gql
-
-from .bases import BaseType, BindableType, DeferredType, DefinitionType
-from .collection_type import CollectionType
-from .convert_case import convert_case
-from .directive_type import DirectiveType
-from .enum_type import EnumType
+from .base import GraphQLMetadata, GraphQLModel, GraphQLType
+from .convert_name import (
+ convert_graphql_name_to_python,
+ convert_python_name_to_graphql,
+)
+from .deferredtype import deferred
+from .description import get_description_node
+from .enum_type import (
+ GraphQLEnum,
+ GraphQLEnumModel,
+ create_graphql_enum_model,
+ graphql_enum,
+)
from .executable_schema import make_executable_schema
-from .input_type import InputType
-from .interface_type import InterfaceType
-from .mutation_type import MutationType
-from .object_type import ObjectType
-from .scalar_type import ScalarType
-from .subscription_type import SubscriptionType
-from .union_type import UnionType
-from .utils import create_alias_resolver, parse_definition
+from .idtype import GraphQLID
+from .input_type import GraphQLInput, GraphQLInputModel
+from .object_type import GraphQLObject, GraphQLObjectModel, object_field
+from .roots import ROOTS_NAMES, merge_root_nodes
+from .scalar_type import GraphQLScalar, GraphQLScalarModel
+from .sort import sort_schema_document
+from .union_type import GraphQLUnion, GraphQLUnionModel
+from .value import get_value_from_node, get_value_node
+from .interface_type import GraphQLInterface, GraphQLInterfaceModel
+from .subscription_type import GraphQLSubscription, GraphQLSubscriptionModel
__all__ = [
- "BaseType",
- "BindableType",
- "CollectionType",
- "DeferredType",
- "DefinitionType",
- "DirectiveType",
- "EnumType",
- "InputType",
- "InterfaceType",
- "MutationType",
- "ObjectType",
- "ScalarType",
- "SubscriptionType",
- "UnionType",
- "convert_case",
- "create_alias_resolver",
- "gql",
+ "GraphQLEnum",
+ "GraphQLEnumModel",
+ "GraphQLID",
+ "GraphQLInput",
+ "GraphQLInputModel",
+ "GraphQLInterface",
+ "GraphQLInterfaceModel",
+ "GraphQLSubscription",
+ "GraphQLSubscriptionModel",
+ "GraphQLMetadata",
+ "GraphQLModel",
+ "GraphQLObject",
+ "GraphQLObjectModel",
+ "GraphQLScalar",
+ "GraphQLScalarModel",
+ "GraphQLType",
+ "GraphQLUnion",
+ "GraphQLUnionModel",
+ "ROOTS_NAMES",
+ "convert_graphql_name_to_python",
+ "convert_python_name_to_graphql",
+ "create_graphql_enum_model",
+ "deferred",
+ "get_description_node",
+ "get_value_from_node",
+ "get_value_node",
+ "graphql_enum",
"make_executable_schema",
- "parse_definition",
+ "merge_root_nodes",
+ "object_field",
+ "sort_schema_document",
]
diff --git a/ariadne_graphql_modules/next/base.py b/ariadne_graphql_modules/base.py
similarity index 97%
rename from ariadne_graphql_modules/next/base.py
rename to ariadne_graphql_modules/base.py
index fcf7991..aa57f2a 100644
--- a/ariadne_graphql_modules/next/base.py
+++ b/ariadne_graphql_modules/base.py
@@ -84,7 +84,7 @@ def get_graphql_model(
if hasattr(graphql_type, "__get_graphql_model__"):
self.models[graphql_type] = graphql_type.__get_graphql_model__(self)
elif issubclass(graphql_type, Enum):
- from .graphql_enum_type import ( # pylint: disable=R0401,C0415
+ from .enum_type import ( # pylint: disable=R0401,C0415
create_graphql_enum_model,
)
diff --git a/ariadne_graphql_modules/base_object_type/__init__.py b/ariadne_graphql_modules/base_object_type/__init__.py
new file mode 100644
index 0000000..6884aa9
--- /dev/null
+++ b/ariadne_graphql_modules/base_object_type/__init__.py
@@ -0,0 +1,15 @@
+from .graphql_type import GraphQLBaseObject
+from .graphql_field import GraphQLFieldData, GraphQLObjectData
+from .validators import (
+ validate_object_type_with_schema,
+ validate_object_type_without_schema,
+)
+
+
+__all__ = [
+ "GraphQLBaseObject",
+ "GraphQLObjectData",
+ "GraphQLFieldData",
+ "validate_object_type_with_schema",
+ "validate_object_type_without_schema",
+]
diff --git a/ariadne_graphql_modules/next/graphql_object/object_field.py b/ariadne_graphql_modules/base_object_type/graphql_field.py
similarity index 78%
rename from ariadne_graphql_modules/next/graphql_object/object_field.py
rename to ariadne_graphql_modules/base_object_type/graphql_field.py
index 15b5491..a7ced74 100644
--- a/ariadne_graphql_modules/next/graphql_object/object_field.py
+++ b/ariadne_graphql_modules/base_object_type/graphql_field.py
@@ -1,5 +1,5 @@
-from dataclasses import dataclass
-from typing import Any, Dict, Optional
+from dataclasses import dataclass, field
+from typing import Any, Dict, List, Optional
from ariadne.types import Resolver, Subscriber
@@ -12,6 +12,47 @@ class GraphQLObjectFieldArg:
default_value: Optional[Any] = None
+@dataclass(frozen=True)
+class GraphQLObjectData:
+ fields: Dict[str, "GraphQLObjectField"]
+ interfaces: List[str]
+
+
+@dataclass(frozen=True)
+class GraphQLObjectResolver:
+ resolver: Resolver
+ field: str
+ description: Optional[str] = None
+ args: Optional[Dict[str, GraphQLObjectFieldArg]] = None
+ field_type: Optional[Any] = None
+
+
+@dataclass(frozen=True)
+class GraphQLObjectSource:
+ subscriber: Subscriber
+ field: str
+ description: Optional[str] = None
+ args: Optional[Dict[str, GraphQLObjectFieldArg]] = None
+ field_type: Optional[Any] = None
+
+
+@dataclass
+class GraphQLFieldData:
+ fields_types: Dict[str, str] = field(default_factory=dict)
+ fields_names: Dict[str, str] = field(default_factory=dict)
+ fields_descriptions: Dict[str, str] = field(default_factory=dict)
+ fields_args: Dict[str, Dict[str, GraphQLObjectFieldArg]] = field(
+ default_factory=dict
+ )
+ fields_resolvers: Dict[str, Resolver] = field(default_factory=dict)
+ fields_subscribers: Dict[str, Subscriber] = field(default_factory=dict)
+ fields_defaults: Dict[str, Any] = field(default_factory=dict)
+ fields_order: List[str] = field(default_factory=list)
+ type_hints: Dict[str, Any] = field(default_factory=dict)
+ aliases: Dict[str, str] = field(default_factory=dict)
+ aliases_targets: List[str] = field(default_factory=list)
+
+
class GraphQLObjectField:
def __init__(
self,
@@ -40,24 +81,6 @@ def __call__(self, resolver: Resolver):
return self
-@dataclass(frozen=True)
-class GraphQLObjectResolver:
- resolver: Resolver
- field: str
- description: Optional[str] = None
- args: Optional[Dict[str, GraphQLObjectFieldArg]] = None
- field_type: Optional[Any] = None
-
-
-@dataclass(frozen=True)
-class GraphQLObjectSource:
- subscriber: Subscriber
- field: str
- description: Optional[str] = None
- args: Optional[Dict[str, GraphQLObjectFieldArg]] = None
- field_type: Optional[Any] = None
-
-
def object_field(
resolver: Optional[Resolver] = None,
*,
diff --git a/ariadne_graphql_modules/next/graphql_object/object_type.py b/ariadne_graphql_modules/base_object_type/graphql_type.py
similarity index 57%
rename from ariadne_graphql_modules/next/graphql_object/object_type.py
rename to ariadne_graphql_modules/base_object_type/graphql_type.py
index 80f8e67..6dc9b9d 100644
--- a/ariadne_graphql_modules/next/graphql_object/object_type.py
+++ b/ariadne_graphql_modules/base_object_type/graphql_type.py
@@ -7,22 +7,24 @@
Iterable,
List,
Optional,
+ Tuple,
Type,
Union,
- cast,
)
-from ariadne.types import Resolver, Subscriber
+from ariadne.types import Resolver
from graphql import (
FieldDefinitionNode,
InputValueDefinitionNode,
- NameNode,
- NamedTypeNode,
ObjectTypeDefinitionNode,
StringValueNode,
)
-from .object_field import (
+from ..types import GraphQLClassType
+
+from .graphql_field import (
+ GraphQLFieldData,
+ GraphQLObjectData,
GraphQLObjectField,
GraphQLObjectFieldArg,
GraphQLObjectResolver,
@@ -30,7 +32,6 @@
object_field,
object_resolver,
)
-from .object_model import GraphQLObjectModel
from .utils import (
get_field_args_from_resolver,
get_field_args_from_subscriber,
@@ -39,7 +40,6 @@
update_field_args_options,
)
-from ...utils import parse_definition
from ..base import GraphQLMetadata, GraphQLModel, GraphQLType
from ..convert_name import convert_python_name_to_graphql
from ..description import get_description_node
@@ -51,26 +51,21 @@
from ..value import get_value_node
-@dataclass(frozen=True)
-class GraphQLObjectData:
- fields: Dict[str, "GraphQLObjectField"]
- interfaces: List[str]
-
-
-class GraphQLObject(GraphQLType):
+class GraphQLBaseObject(GraphQLType):
__kwargs__: Dict[str, Any]
__abstract__: bool = True
__schema__: Optional[str]
__description__: Optional[str]
__aliases__: Optional[Dict[str, str]]
__requires__: Optional[Iterable[Union[Type[GraphQLType], Type[Enum]]]]
- __implements__: Optional[Iterable[Type[GraphQLType]]]
+ __graphql_type__ = GraphQLClassType.BASE
def __init__(self, **kwargs: Any):
default_values: Dict[str, Any] = {}
- for interface in getattr(self, "__implements__", []):
- if hasattr(interface, "__kwargs__"):
- default_values.update(interface.__kwargs__)
+
+ for inherited_obj in self._collect_inherited_objects():
+ if hasattr(inherited_obj, "__kwargs__"):
+ default_values.update(inherited_obj.__kwargs__)
default_values.update(self.__kwargs__)
@@ -112,16 +107,22 @@ def __get_graphql_model__(cls, metadata: GraphQLMetadata) -> "GraphQLModel":
@classmethod
def __get_graphql_model_with_schema__(cls) -> "GraphQLModel":
- definition = cast(
- ObjectTypeDefinitionNode,
- parse_definition(ObjectTypeDefinitionNode, cls.__schema__),
- )
+ raise NotImplementedError()
+
+ @classmethod
+ def __get_graphql_model_without_schema__(
+ cls, metadata: GraphQLMetadata, name: str
+ ) -> "GraphQLModel":
+ raise NotImplementedError()
+ @classmethod
+ def _create_fields_and_resolvers_with_schema(
+ cls, definition_fields: Tuple["FieldDefinitionNode", ...]
+ ) -> Tuple[tuple[FieldDefinitionNode, ...], Dict[str, Resolver]]:
descriptions: Dict[str, StringValueNode] = {}
args_descriptions: Dict[str, Dict[str, StringValueNode]] = {}
args_defaults: Dict[str, Dict[str, Any]] = {}
resolvers: Dict[str, Resolver] = {}
- out_names: Dict[str, Dict[str, str]] = {}
for attr_name in dir(cls):
cls_attr = getattr(cls, attr_name)
@@ -133,26 +134,24 @@ def __get_graphql_model_with_schema__(cls) -> "GraphQLModel":
field_args = get_field_args_from_resolver(cls_attr.resolver)
if field_args:
- args_descriptions[cls_attr.field] = {}
- args_defaults[cls_attr.field] = {}
+ args_descriptions[cls_attr.field], args_defaults[cls_attr.field] = (
+ {},
+ {},
+ )
final_args = update_field_args_options(field_args, cls_attr.args)
-
for arg_name, arg_options in final_args.items():
- arg_description = get_description_node(arg_options.description)
- if arg_description:
- args_descriptions[cls_attr.field][
- arg_name
- ] = arg_description
-
- arg_default = arg_options.default_value
- if arg_default is not None:
+ description_node = get_description_node(cls_attr.description)
+ if description_node:
+ descriptions[cls_attr.field] = description_node
+
+ if arg_options.default_value is not None:
args_defaults[cls_attr.field][arg_name] = get_value_node(
- arg_default
+ arg_options.default_value
)
fields: List[FieldDefinitionNode] = []
- for field in definition.fields:
+ for field in definition_fields:
field_args_descriptions = args_descriptions.get(field.name.value, {})
field_args_defaults = args_defaults.get(field.name.value, {})
@@ -185,30 +184,21 @@ def __get_graphql_model_with_schema__(cls) -> "GraphQLModel":
)
)
- return GraphQLObjectModel(
- name=definition.name.value,
- ast_type=ObjectTypeDefinitionNode,
- ast=ObjectTypeDefinitionNode(
- name=NameNode(value=definition.name.value),
- fields=tuple(fields),
- interfaces=definition.interfaces,
- ),
- resolvers=resolvers,
- aliases=getattr(cls, "__aliases__", {}),
- out_names=out_names,
- )
+ return tuple(fields), resolvers
@classmethod
- def __get_graphql_model_without_schema__(
- cls, metadata: GraphQLMetadata, name: str
- ) -> "GraphQLModel":
- type_data = get_graphql_object_data(metadata, cls)
- type_aliases = getattr(cls, "__aliases__", {})
-
- fields_ast: List[FieldDefinitionNode] = []
- resolvers: Dict[str, Resolver] = {}
- aliases: Dict[str, str] = {}
- out_names: Dict[str, Dict[str, str]] = {}
+ def _process_graphql_fields(
+ cls, metadata: GraphQLMetadata, type_data, type_aliases
+ ) -> Tuple[
+ List[FieldDefinitionNode],
+ Dict[str, Resolver],
+ Dict[str, str],
+ Dict[str, Dict[str, str]],
+ ]:
+ fields_ast = []
+ resolvers = {}
+ aliases = {}
+ out_names = {}
for attr_name, field in type_data.fields.items():
fields_ast.append(get_field_node_from_obj_field(cls, metadata, field))
@@ -224,25 +214,7 @@ def __get_graphql_model_without_schema__(
if field.args and field.name:
out_names[field.name] = get_field_args_out_names(field.args)
- interfaces_ast: List[NamedTypeNode] = []
- for interface_name in type_data.interfaces:
- interfaces_ast.append(NamedTypeNode(name=NameNode(value=interface_name)))
-
- return GraphQLObjectModel(
- name=name,
- ast_type=ObjectTypeDefinitionNode,
- ast=ObjectTypeDefinitionNode(
- name=NameNode(value=name),
- description=get_description_node(
- getattr(cls, "__description__", None),
- ),
- fields=tuple(fields_ast),
- interfaces=tuple(interfaces_ast),
- ),
- resolvers=resolvers,
- aliases=aliases,
- out_names=out_names,
- )
+ return fields_ast, resolvers, aliases, out_names
@classmethod
def __get_graphql_types__(
@@ -268,7 +240,7 @@ def __get_graphql_types_without_schema__(
cls, metadata: "GraphQLMetadata"
) -> Iterable[Union[Type["GraphQLType"], Type[Enum]]]:
types: List[Union[Type["GraphQLType"], Type[Enum]]] = [cls]
- type_data = get_graphql_object_data(metadata, cls)
+ type_data = cls.get_graphql_object_data(metadata)
for field in type_data.fields.values():
field_type = get_graphql_type(field.field_type)
@@ -333,130 +305,135 @@ def argument(
default_value=default_value,
)
+ @classmethod
+ def get_graphql_object_data(
+ cls,
+ metadata: GraphQLMetadata,
+ ) -> GraphQLObjectData:
+ try:
+ return metadata.get_data(cls)
+ except KeyError as exc:
+ if getattr(cls, "__schema__", None):
+ raise NotImplementedError(
+ "'get_graphql_object_data' is not supported for "
+ "objects with '__schema__'."
+ ) from exc
+ object_data = cls.create_graphql_object_data_without_schema()
+
+ metadata.set_data(cls, object_data)
+ return object_data
-def get_graphql_object_data(
- metadata: GraphQLMetadata, cls: Type[GraphQLObject]
-) -> GraphQLObjectData:
- try:
- return metadata.get_data(cls)
- except KeyError as exc:
- if getattr(cls, "__schema__", None):
- raise NotImplementedError(
- "'get_graphql_object_data' is not supported for "
- "objects with '__schema__'."
- ) from exc
- object_data = create_graphql_object_data_without_schema(cls)
-
- metadata.set_data(cls, object_data)
- return object_data
-
-
-def create_graphql_object_data_without_schema(
- cls: Type["GraphQLObject"],
-) -> GraphQLObjectData:
- fields_types: Dict[str, str] = {}
- fields_names: Dict[str, str] = {}
- fields_descriptions: Dict[str, str] = {}
- fields_args: Dict[str, Dict[str, GraphQLObjectFieldArg]] = {}
- fields_resolvers: Dict[str, Resolver] = {}
- fields_subscribers: Dict[str, Subscriber] = {}
- fields_defaults: Dict[str, Any] = {}
- fields_order: List[str] = []
-
- interfaces = getattr(cls, "__implements__", [])
- interfaces_names: List[str] = [interface.__name__ for interface in interfaces]
- type_hints: dict[str, Any] = {}
- aliases: Dict[str, str] = {}
-
- for interface in reversed(interfaces):
- type_hints.update(interface.__annotations__)
- aliases.update(getattr(interface, "__aliases__", {}))
-
- type_hints.update(cls.__annotations__)
- aliases.update(getattr(cls, "__aliases__", None) or {})
- aliases_targets: List[str] = list(aliases.values())
-
- for attr_name, attr_type in type_hints.items():
- if attr_name.startswith("__"):
- continue
-
- if attr_name in aliases_targets:
- # Alias target is not included in schema
- # unless its explicit field
- cls_attr = getattr(cls, attr_name, None)
- if not isinstance(cls_attr, GraphQLObjectField):
+ @classmethod
+ def create_graphql_object_data_without_schema(cls) -> GraphQLObjectData:
+ raise NotImplementedError()
+
+ @staticmethod
+ def _build_fields(fields_data: GraphQLFieldData) -> Dict[str, "GraphQLObjectField"]:
+ fields = {}
+ for field_name in fields_data.fields_order:
+ fields[field_name] = GraphQLObjectField(
+ name=fields_data.fields_names[field_name],
+ description=fields_data.fields_descriptions.get(field_name),
+ field_type=fields_data.fields_types[field_name],
+ args=fields_data.fields_args.get(field_name),
+ resolver=fields_data.fields_resolvers.get(field_name),
+ subscriber=fields_data.fields_subscribers.get(field_name),
+ default_value=fields_data.fields_defaults.get(field_name),
+ )
+ return fields
+
+ @classmethod
+ def _process_type_hints_and_aliases(cls, fields_data: GraphQLFieldData):
+ fields_data.type_hints.update(cls.__annotations__) # pylint: disable=no-member
+ fields_data.aliases.update(getattr(cls, "__aliases__", None) or {})
+ fields_data.aliases_targets = list(fields_data.aliases.values())
+
+ for attr_name, attr_type in fields_data.type_hints.items():
+ if attr_name.startswith("__"):
continue
- fields_order.append(attr_name)
+ if attr_name in fields_data.aliases_targets:
+ cls_attr = getattr(cls, attr_name, None)
+ if not isinstance(cls_attr, GraphQLObjectField):
+ continue
- fields_names[attr_name] = convert_python_name_to_graphql(attr_name)
- fields_types[attr_name] = attr_type
+ fields_data.fields_order.append(attr_name)
+ fields_data.fields_names[attr_name] = convert_python_name_to_graphql(
+ attr_name
+ )
+ fields_data.fields_types[attr_name] = attr_type
- def process_class_attributes(target_cls):
+ @staticmethod
+ def _process_class_attributes(target_cls, fields_data: GraphQLFieldData):
for attr_name in dir(target_cls):
if attr_name.startswith("__"):
continue
cls_attr = getattr(target_cls, attr_name)
if isinstance(cls_attr, GraphQLObjectField):
- if attr_name not in fields_order:
- fields_order.append(attr_name)
+ if attr_name not in fields_data.fields_order:
+ fields_data.fields_order.append(attr_name)
- fields_names[attr_name] = (
+ fields_data.fields_names[attr_name] = (
cls_attr.name or convert_python_name_to_graphql(attr_name)
)
if cls_attr.field_type:
- fields_types[attr_name] = cls_attr.field_type
+ fields_data.fields_types[attr_name] = cls_attr.field_type
if cls_attr.description:
- fields_descriptions[attr_name] = cls_attr.description
+ fields_data.fields_descriptions[attr_name] = cls_attr.description
if cls_attr.resolver:
- fields_resolvers[attr_name] = cls_attr.resolver
+ fields_data.fields_resolvers[attr_name] = cls_attr.resolver
field_args = get_field_args_from_resolver(cls_attr.resolver)
if field_args:
- fields_args[attr_name] = update_field_args_options(
+ fields_data.fields_args[attr_name] = update_field_args_options(
field_args, cls_attr.args
)
if cls_attr.default_value:
- fields_defaults[attr_name] = cls_attr.default_value
+ fields_data.fields_defaults[attr_name] = cls_attr.default_value
elif isinstance(cls_attr, GraphQLObjectResolver):
- if cls_attr.field_type and cls_attr.field not in fields_types:
- fields_types[cls_attr.field] = cls_attr.field_type
- if cls_attr.description and cls_attr.field not in fields_descriptions:
- fields_descriptions[cls_attr.field] = cls_attr.description
- fields_resolvers[cls_attr.field] = cls_attr.resolver
+ if (
+ cls_attr.field_type
+ and cls_attr.field not in fields_data.fields_types
+ ):
+ fields_data.fields_types[cls_attr.field] = cls_attr.field_type
+ if (
+ cls_attr.description
+ and cls_attr.field not in fields_data.fields_descriptions
+ ):
+ fields_data.fields_descriptions[cls_attr.field] = (
+ cls_attr.description
+ )
+ fields_data.fields_resolvers[cls_attr.field] = cls_attr.resolver
field_args = get_field_args_from_resolver(cls_attr.resolver)
- if field_args and not fields_args.get(cls_attr.field):
- fields_args[cls_attr.field] = update_field_args_options(
+ if field_args and not fields_data.fields_args.get(cls_attr.field):
+ fields_data.fields_args[cls_attr.field] = update_field_args_options(
field_args, cls_attr.args
)
elif isinstance(cls_attr, GraphQLObjectSource):
- if cls_attr.field_type and cls_attr.field not in fields_types:
- fields_types[cls_attr.field] = cls_attr.field_type
- if cls_attr.description and cls_attr.field not in fields_descriptions:
- fields_descriptions[cls_attr.field] = cls_attr.description
- fields_subscribers[cls_attr.field] = cls_attr.subscriber
+ if (
+ cls_attr.field_type
+ and cls_attr.field not in fields_data.fields_types
+ ):
+ fields_data.fields_types[cls_attr.field] = cls_attr.field_type
+ if (
+ cls_attr.description
+ and cls_attr.field not in fields_data.fields_descriptions
+ ):
+ fields_data.fields_descriptions[cls_attr.field] = (
+ cls_attr.description
+ )
+ fields_data.fields_subscribers[cls_attr.field] = cls_attr.subscriber
field_args = get_field_args_from_subscriber(cls_attr.subscriber)
if field_args:
- fields_args[cls_attr.field] = update_field_args_options(
+ fields_data.fields_args[cls_attr.field] = update_field_args_options(
field_args, cls_attr.args
)
- elif attr_name not in aliases_targets and not callable(cls_attr):
- fields_defaults[attr_name] = cls_attr
-
- for interface in getattr(cls, "__implements__", []):
- process_class_attributes(interface)
-
- process_class_attributes(cls)
- fields: Dict[str, "GraphQLObjectField"] = {}
- for field_name in fields_order:
- fields[field_name] = GraphQLObjectField(
- name=fields_names[field_name],
- description=fields_descriptions.get(field_name),
- field_type=fields_types[field_name],
- args=fields_args.get(field_name),
- resolver=fields_resolvers.get(field_name),
- subscriber=fields_subscribers.get(field_name),
- default_value=fields_defaults.get(field_name),
- )
- return GraphQLObjectData(fields=fields, interfaces=interfaces_names)
+ elif attr_name not in fields_data.aliases_targets and not callable(
+ cls_attr
+ ):
+ fields_data.fields_defaults[attr_name] = cls_attr
+
+ @classmethod
+ def _collect_inherited_objects(cls):
+ raise NotImplementedError
diff --git a/ariadne_graphql_modules/next/graphql_object/utils.py b/ariadne_graphql_modules/base_object_type/utils.py
similarity index 97%
rename from ariadne_graphql_modules/next/graphql_object/utils.py
rename to ariadne_graphql_modules/base_object_type/utils.py
index e562287..a3d9025 100644
--- a/ariadne_graphql_modules/next/graphql_object/utils.py
+++ b/ariadne_graphql_modules/base_object_type/utils.py
@@ -10,14 +10,14 @@
from ..description import get_description_node
from ..typing import get_type_node
from ..value import get_value_node
-from .object_field import GraphQLObjectField, GraphQLObjectFieldArg
+from .graphql_field import GraphQLObjectField, GraphQLObjectFieldArg
if TYPE_CHECKING:
- from .object_type import GraphQLObject
+ from .graphql_type import GraphQLBaseObject
def get_field_node_from_obj_field(
- parent_type: Type["GraphQLObject"],
+ parent_type: Type["GraphQLBaseObject"],
metadata: GraphQLMetadata,
field: GraphQLObjectField,
) -> FieldDefinitionNode:
diff --git a/ariadne_graphql_modules/next/graphql_object/validators.py b/ariadne_graphql_modules/base_object_type/validators.py
similarity index 95%
rename from ariadne_graphql_modules/next/graphql_object/validators.py
rename to ariadne_graphql_modules/base_object_type/validators.py
index 672ad98..f104655 100644
--- a/ariadne_graphql_modules/next/graphql_object/validators.py
+++ b/ariadne_graphql_modules/base_object_type/validators.py
@@ -4,7 +4,7 @@
from graphql import FieldDefinitionNode, ObjectTypeDefinitionNode, TypeDefinitionNode
from ..convert_name import convert_python_name_to_graphql
-from .object_field import (
+from .graphql_field import (
GraphQLObjectField,
GraphQLObjectFieldArg,
GraphQLObjectResolver,
@@ -16,10 +16,10 @@
)
from ..validators import validate_description, validate_name
from ..value import get_value_node
-from ...utils import parse_definition
+from ..utils import parse_definition
if TYPE_CHECKING:
- from .object_type import GraphQLObject
+ from .graphql_type import GraphQLBaseObject
@dataclass
@@ -31,8 +31,15 @@ class GraphQLObjectValidationData:
sources_instances: Dict[str, GraphQLObjectSource]
+def get_all_annotations(cls):
+ annotations = {}
+ for base_cls in reversed(cls.__mro__):
+ annotations.update(getattr(base_cls, "__annotations__", {}))
+ return annotations
+
+
def validate_object_type_with_schema(
- cls: Type["GraphQLObject"],
+ cls: Type["GraphQLBaseObject"],
valid_type: Type[TypeDefinitionNode] = ObjectTypeDefinitionNode,
) -> Dict[str, Any]:
definition = cast(
@@ -212,7 +219,9 @@ def validate_object_type_with_schema(
return get_object_type_with_schema_kwargs(cls, aliases, field_names)
-def validate_object_type_without_schema(cls: Type["GraphQLObject"]) -> Dict[str, Any]:
+def validate_object_type_without_schema(
+ cls: Type["GraphQLBaseObject"],
+) -> Dict[str, Any]:
data = get_object_type_validation_data(cls)
# Alias target is not present in schema as a field if its not an
@@ -246,7 +255,7 @@ def validate_object_type_without_schema(cls: Type["GraphQLObject"]) -> Dict[str,
def validate_object_unique_graphql_names(
- cls: Type["GraphQLObject"],
+ cls: Type["GraphQLBaseObject"],
fields_attrs: List[str],
fields_instances: Dict[str, GraphQLObjectField],
):
@@ -272,7 +281,7 @@ def validate_object_unique_graphql_names(
def validate_object_resolvers(
- cls: Type["GraphQLObject"],
+ cls: Type["GraphQLBaseObject"],
fields_names: List[str],
fields_instances: Dict[str, GraphQLObjectField],
resolvers_instances: Dict[str, GraphQLObjectResolver],
@@ -317,7 +326,7 @@ def validate_object_resolvers(
def validate_object_subscribers(
- cls: Type["GraphQLObject"],
+ cls: Type["GraphQLBaseObject"],
fields_names: List[str],
sources_instances: Dict[str, GraphQLObjectSource],
):
@@ -356,7 +365,7 @@ def validate_object_subscribers(
)
-def validate_object_fields_args(cls: Type["GraphQLObject"]):
+def validate_object_fields_args(cls: Type["GraphQLBaseObject"]):
for field_name in dir(cls):
field_instance = getattr(cls, field_name)
if (
@@ -367,7 +376,7 @@ def validate_object_fields_args(cls: Type["GraphQLObject"]):
def validate_object_field_args(
- cls: Type["GraphQLObject"],
+ cls: Type["GraphQLBaseObject"],
field_name: str,
field_instance: Union["GraphQLObjectField", "GraphQLObjectResolver"],
):
@@ -411,7 +420,7 @@ def validate_object_field_args(
def validate_object_aliases(
- cls: Type["GraphQLObject"],
+ cls: Type["GraphQLBaseObject"],
aliases: Dict[str, str],
fields_names: List[str],
fields_resolvers: List[str],
@@ -432,7 +441,7 @@ def validate_object_aliases(
def validate_field_arg_default_value(
- cls: Type["GraphQLObject"], field_name: str, arg_name: str, default_value: Any
+ cls: Type["GraphQLBaseObject"], field_name: str, arg_name: str, default_value: Any
):
if default_value is None:
return
@@ -449,10 +458,12 @@ def validate_field_arg_default_value(
def get_object_type_validation_data(
- cls: Type["GraphQLObject"],
+ cls: Type["GraphQLBaseObject"],
) -> GraphQLObjectValidationData:
fields_attrs: List[str] = [
- attr_name for attr_name in cls.__annotations__ if not attr_name.startswith("__")
+ attr_name
+ for attr_name in get_all_annotations(cls)
+ if not attr_name.startswith("__")
]
fields_instances: Dict[str, GraphQLObjectField] = {}
@@ -494,12 +505,12 @@ def get_object_type_validation_data(
def get_object_type_kwargs(
- cls: Type["GraphQLObject"],
+ cls: Type["GraphQLBaseObject"],
aliases: Dict[str, str],
) -> Dict[str, Any]:
kwargs: Dict[str, Any] = {}
- for attr_name in cls.__annotations__:
+ for attr_name in get_all_annotations(cls):
if attr_name.startswith("__"):
continue
@@ -527,7 +538,7 @@ def get_object_type_kwargs(
def get_object_type_with_schema_kwargs(
- cls: Type["GraphQLObject"],
+ cls: Type["GraphQLBaseObject"],
aliases: Dict[str, str],
field_names: List[str],
) -> Dict[str, Any]:
diff --git a/ariadne_graphql_modules/next/compatibility_layer.py b/ariadne_graphql_modules/compatibility_layer.py
similarity index 92%
rename from ariadne_graphql_modules/next/compatibility_layer.py
rename to ariadne_graphql_modules/compatibility_layer.py
index 8106dc5..182e2a0 100644
--- a/ariadne_graphql_modules/next/compatibility_layer.py
+++ b/ariadne_graphql_modules/compatibility_layer.py
@@ -12,20 +12,19 @@
UnionTypeDefinitionNode,
)
-from ..executable_schema import get_all_types
+from .v1.executable_schema import get_all_types
+
+from .v1.directive_type import DirectiveType
+from .v1.enum_type import EnumType
+from .v1.input_type import InputType
+from .v1.interface_type import InterfaceType
+from .v1.mutation_type import MutationType
+from .v1.scalar_type import ScalarType
+from .v1.subscription_type import SubscriptionType
+from .v1.union_type import UnionType
+from .v1.object_type import ObjectType
+from .v1.bases import BindableType
-from ..directive_type import DirectiveType
-from ..enum_type import EnumType
-from ..input_type import InputType
-from ..interface_type import InterfaceType
-from ..mutation_type import MutationType
-from ..scalar_type import ScalarType
-from ..subscription_type import SubscriptionType
-from ..union_type import UnionType
-
-from ..object_type import ObjectType
-
-from ..bases import BindableType
from .base import GraphQLModel, GraphQLType
from . import (
GraphQLObjectModel,
diff --git a/ariadne_graphql_modules/next/convert_name.py b/ariadne_graphql_modules/convert_name.py
similarity index 100%
rename from ariadne_graphql_modules/next/convert_name.py
rename to ariadne_graphql_modules/convert_name.py
diff --git a/ariadne_graphql_modules/next/deferredtype.py b/ariadne_graphql_modules/deferredtype.py
similarity index 100%
rename from ariadne_graphql_modules/next/deferredtype.py
rename to ariadne_graphql_modules/deferredtype.py
diff --git a/ariadne_graphql_modules/next/description.py b/ariadne_graphql_modules/description.py
similarity index 100%
rename from ariadne_graphql_modules/next/description.py
rename to ariadne_graphql_modules/description.py
diff --git a/ariadne_graphql_modules/enum_type/__init__.py b/ariadne_graphql_modules/enum_type/__init__.py
new file mode 100644
index 0000000..2782ef5
--- /dev/null
+++ b/ariadne_graphql_modules/enum_type/__init__.py
@@ -0,0 +1,9 @@
+from .graphql_type import GraphQLEnum, graphql_enum, create_graphql_enum_model
+from .models import GraphQLEnumModel
+
+__all__ = [
+ "GraphQLEnum",
+ "GraphQLEnumModel",
+ "create_graphql_enum_model",
+ "graphql_enum",
+]
diff --git a/ariadne_graphql_modules/next/graphql_enum_type/enum_type.py b/ariadne_graphql_modules/enum_type/graphql_type.py
similarity index 99%
rename from ariadne_graphql_modules/next/graphql_enum_type/enum_type.py
rename to ariadne_graphql_modules/enum_type/graphql_type.py
index 84a12e8..fc33745 100644
--- a/ariadne_graphql_modules/next/graphql_enum_type/enum_type.py
+++ b/ariadne_graphql_modules/enum_type/graphql_type.py
@@ -5,9 +5,9 @@
from graphql import EnumTypeDefinitionNode, EnumValueDefinitionNode, NameNode
from ..base import GraphQLMetadata, GraphQLModel, GraphQLType
from ..description import get_description_node
-from ..graphql_enum_type.enum_model import GraphQLEnumModel
+from .models import GraphQLEnumModel
from ..validators import validate_description, validate_name
-from ...utils import parse_definition
+from ..utils import parse_definition
class GraphQLEnum(GraphQLType):
diff --git a/ariadne_graphql_modules/next/graphql_enum_type/enum_model.py b/ariadne_graphql_modules/enum_type/models.py
similarity index 100%
rename from ariadne_graphql_modules/next/graphql_enum_type/enum_model.py
rename to ariadne_graphql_modules/enum_type/models.py
diff --git a/ariadne_graphql_modules/enum_type/type.py b/ariadne_graphql_modules/enum_type/type.py
new file mode 100644
index 0000000..fc33745
--- /dev/null
+++ b/ariadne_graphql_modules/enum_type/type.py
@@ -0,0 +1,343 @@
+from enum import Enum
+from inspect import isclass
+from typing import Any, Dict, Iterable, List, Optional, Set, Type, Union, cast
+
+from graphql import EnumTypeDefinitionNode, EnumValueDefinitionNode, NameNode
+from ..base import GraphQLMetadata, GraphQLModel, GraphQLType
+from ..description import get_description_node
+from .models import GraphQLEnumModel
+from ..validators import validate_description, validate_name
+from ..utils import parse_definition
+
+
+class GraphQLEnum(GraphQLType):
+ __abstract__: bool = True
+ __schema__: Optional[str]
+ __description__: Optional[str]
+ __members__: Optional[Union[Type[Enum], Dict[str, Any], List[str]]]
+ __members_descriptions__: Optional[Dict[str, str]]
+
+ def __init_subclass__(cls) -> None:
+ super().__init_subclass__()
+
+ if cls.__dict__.get("__abstract__"):
+ return
+
+ cls.__abstract__ = False
+ cls._validate()
+
+ @classmethod
+ def __get_graphql_model__(cls, metadata: GraphQLMetadata) -> "GraphQLModel":
+ name = cls.__get_graphql_name__()
+
+ if getattr(cls, "__schema__", None):
+ return cls.__get_graphql_model_with_schema__(name)
+
+ return cls.__get_graphql_model_without_schema__(name)
+
+ @classmethod
+ def __get_graphql_model_with_schema__(cls, name: str) -> "GraphQLEnumModel":
+ definition: EnumTypeDefinitionNode = cast(
+ EnumTypeDefinitionNode,
+ parse_definition(EnumTypeDefinitionNode, cls.__schema__),
+ )
+
+ members = getattr(cls, "__members__", [])
+ members_values: Dict[str, Any] = {}
+
+ if isinstance(members, dict):
+ members_values = dict(members.items())
+ elif isclass(members) and issubclass(members, Enum):
+ members_values = {member.name: member for member in members}
+ else:
+ members_values = {
+ value.name.value: value.name.value
+ for value in definition.values # pylint: disable=no-member
+ }
+
+ members_descriptions = getattr(cls, "__members_descriptions__", {})
+
+ return GraphQLEnumModel(
+ name=name,
+ members=members_values,
+ ast_type=EnumTypeDefinitionNode,
+ ast=EnumTypeDefinitionNode(
+ name=NameNode(value=name),
+ directives=definition.directives,
+ description=definition.description
+ or (get_description_node(getattr(cls, "__description__", None))),
+ values=tuple(
+ EnumValueDefinitionNode(
+ name=value.name,
+ directives=value.directives,
+ description=value.description
+ or (
+ get_description_node(
+ members_descriptions.get(value.name.value),
+ )
+ ),
+ )
+ for value in definition.values # pylint: disable=no-member
+ ),
+ ),
+ )
+
+ @classmethod
+ def __get_graphql_model_without_schema__(cls, name: str) -> "GraphQLEnumModel":
+ members = getattr(cls, "__members__", [])
+ members_values = {}
+ if isinstance(members, dict):
+ members_values = dict(members.items())
+ elif isclass(members) and issubclass(members, Enum):
+ members_values = {i.name: i for i in members}
+ elif isinstance(members, list):
+ members_values = {kv: kv for kv in members}
+
+ members_descriptions = getattr(cls, "__members_descriptions__", {})
+
+ return GraphQLEnumModel(
+ name=name,
+ members=members_values,
+ ast_type=EnumTypeDefinitionNode,
+ ast=EnumTypeDefinitionNode(
+ name=NameNode(value=name),
+ description=get_description_node(
+ getattr(cls, "__description__", None),
+ ),
+ values=tuple(
+ EnumValueDefinitionNode(
+ name=NameNode(value=value_name),
+ description=get_description_node(
+ members_descriptions.get(value_name)
+ ),
+ )
+ for value_name in members_values
+ ),
+ ),
+ )
+
+ @classmethod
+ def _validate(cls):
+ if getattr(cls, "__schema__", None):
+ cls._validate_enum_type_with_schema()
+ else:
+ cls._validate_enum_type()
+
+ @classmethod
+ def _validate_enum_type_with_schema(cls):
+ definition = parse_definition(EnumTypeDefinitionNode, cls.__schema__)
+
+ if not isinstance(definition, EnumTypeDefinitionNode):
+ raise ValueError(
+ f"Class '{cls.__name__}' defines '__schema__' attribute "
+ f"with declaration for an invalid GraphQL type. "
+ f"('{definition.__class__.__name__}' != '{EnumTypeDefinitionNode.__name__}')"
+ )
+
+ validate_name(cls, definition)
+ validate_description(cls, definition)
+
+ members_names = {
+ value.name.value for value in definition.values # pylint: disable=no-member
+ }
+ if not members_names:
+ raise ValueError(
+ f"Class '{cls.__name__}' defines '__schema__' attribute "
+ "that doesn't declare any enum members."
+ )
+
+ members_values = getattr(cls, "__members__", None)
+ if members_values:
+ cls.validate_members_values(members_values, members_names)
+
+ members_descriptions = getattr(cls, "__members_descriptions__", {})
+ cls.validate_enum_members_descriptions(members_names, members_descriptions)
+
+ duplicate_descriptions = [
+ ast_member.name.value
+ for ast_member in definition.values # pylint: disable=no-member
+ if ast_member.description
+ and ast_member.description.value
+ and members_descriptions.get(ast_member.name.value)
+ ]
+
+ if duplicate_descriptions:
+ raise ValueError(
+ f"Class '{cls.__name__}' '__members_descriptions__' attribute defines "
+ f"descriptions for enum members that also have description in '__schema__' "
+ f"attribute. (members: '{', '.join(duplicate_descriptions)}')"
+ )
+
+ @classmethod
+ def validate_members_values(cls, members_values, members_names):
+ if isinstance(members_values, list):
+ raise ValueError(
+ f"Class '{cls.__name__}' '__members__' attribute "
+ "can't be a list when used together with '__schema__'."
+ )
+
+ missing_members = None
+ if isinstance(members_values, dict):
+ missing_members = members_names - set(members_values)
+ elif isclass(members_values) and issubclass(members_values, Enum):
+ missing_members = members_names - {value.name for value in members_values}
+
+ if missing_members:
+ raise ValueError(
+ f"Class '{cls.__name__}' '__members__' is missing values "
+ f"for enum members defined in '__schema__'. "
+ f"(missing items: '{', '.join(missing_members)}')"
+ )
+
+ @classmethod
+ def _validate_enum_type(cls):
+ members_values = getattr(cls, "__members__", None)
+ if not members_values:
+ raise ValueError(
+ f"Class '{cls.__name__}' '__members__' attribute is either missing or "
+ "empty. Either define it or provide full SDL for this enum using "
+ "the '__schema__' attribute."
+ )
+
+ if not any(
+ [
+ isinstance(members_values, (dict, list)),
+ isclass(members_values) and issubclass(members_values, Enum),
+ ]
+ ):
+ raise ValueError(
+ f"Class '{cls.__name__}' '__members__' attribute is of unsupported type. "
+ f"Expected 'Dict[str, Any]', 'Type[Enum]' or List[str]. "
+ f"(found: '{type(members_values)}')"
+ )
+
+ members_names = cls.get_members_set(members_values)
+ members_descriptions = getattr(cls, "__members_descriptions__", {})
+ cls.validate_enum_members_descriptions(members_names, members_descriptions)
+
+ @classmethod
+ def validate_enum_members_descriptions(
+ cls, members: Set[str], members_descriptions: dict
+ ):
+ invalid_descriptions = set(members_descriptions) - members
+ if invalid_descriptions:
+ invalid_descriptions_str = "', '".join(invalid_descriptions)
+ raise ValueError(
+ f"Class '{cls.__name__}' '__members_descriptions__' attribute defines "
+ f"descriptions for undefined enum members. "
+ f"(undefined members: '{invalid_descriptions_str}')"
+ )
+
+ @staticmethod
+ def get_members_set(
+ members: Optional[Union[Type[Enum], Dict[str, Any], List[str]]]
+ ) -> Set[str]:
+ if isinstance(members, dict):
+ return set(members.keys())
+
+ if isclass(members) and issubclass(members, Enum):
+ return set(member.name for member in members)
+
+ if isinstance(members, list):
+ return set(members)
+
+ raise TypeError(
+ f"Expected members to be of type Dict[str, Any], List[str], or Enum."
+ f"Got {type(members).__name__} instead."
+ )
+
+
+def create_graphql_enum_model(
+ enum: Type[Enum],
+ *,
+ name: Optional[str] = None,
+ description: Optional[str] = None,
+ members_descriptions: Optional[Dict[str, str]] = None,
+ members_include: Optional[Iterable[str]] = None,
+ members_exclude: Optional[Iterable[str]] = None,
+) -> "GraphQLEnumModel":
+ if members_include and members_exclude:
+ raise ValueError(
+ "'members_include' and 'members_exclude' options are mutually exclusive."
+ )
+
+ if hasattr(enum, "__get_graphql_model__"):
+ return cast(GraphQLEnumModel, enum.__get_graphql_model__())
+
+ if not name:
+ if hasattr(enum, "__get_graphql_name__"):
+ name = cast("str", enum.__get_graphql_name__())
+ else:
+ name = enum.__name__
+
+ members: Dict[str, Any] = {i.name: i for i in enum}
+ final_members: Dict[str, Any] = {}
+
+ if members_include:
+ for key, value in members.items():
+ if key in members_include:
+ final_members[key] = value
+ elif members_exclude:
+ for key, value in members.items():
+ if key not in members_exclude:
+ final_members[key] = value
+ else:
+ final_members = members
+
+ members_descriptions = members_descriptions or {}
+ for member in members_descriptions:
+ if member not in final_members:
+ raise ValueError(
+ f"Member description was specified for a member '{member}' "
+ "not present in final GraphQL enum."
+ )
+
+ return GraphQLEnumModel(
+ name=name,
+ members=final_members,
+ ast_type=EnumTypeDefinitionNode,
+ ast=EnumTypeDefinitionNode(
+ name=NameNode(value=name),
+ description=get_description_node(description),
+ values=tuple(
+ EnumValueDefinitionNode(
+ name=NameNode(value=value_name),
+ description=get_description_node(
+ members_descriptions.get(value_name)
+ ),
+ )
+ for value_name in final_members
+ ),
+ ),
+ )
+
+
+def graphql_enum(
+ cls: Optional[Type[Enum]] = None,
+ *,
+ name: Optional[str] = None,
+ description: Optional[str] = None,
+ members_descriptions: Optional[Dict[str, str]] = None,
+ members_include: Optional[Iterable[str]] = None,
+ members_exclude: Optional[Iterable[str]] = None,
+):
+ def graphql_enum_decorator(cls: Type[Enum]):
+ graphql_model = create_graphql_enum_model(
+ cls,
+ name=name,
+ description=description,
+ members_descriptions=members_descriptions,
+ members_include=members_include,
+ members_exclude=members_exclude,
+ )
+
+ def __get_graphql_model__(*_) -> GraphQLEnumModel:
+ return graphql_model
+
+ setattr(cls, "__get_graphql_model__", classmethod(__get_graphql_model__))
+ return cls
+
+ if cls:
+ return graphql_enum_decorator(cls)
+
+ return graphql_enum_decorator
diff --git a/ariadne_graphql_modules/executable_schema.py b/ariadne_graphql_modules/executable_schema.py
index 1914742..79da59f 100644
--- a/ariadne_graphql_modules/executable_schema.py
+++ b/ariadne_graphql_modules/executable_schema.py
@@ -1,236 +1,243 @@
-from typing import (
- Dict,
- List,
- Optional,
- Sequence,
- Tuple,
- Type,
- Union,
- cast,
-)
+from enum import Enum
+from typing import Any, Dict, List, Optional, Sequence, Type, Union
from ariadne import (
SchemaBindable,
SchemaDirectiveVisitor,
+ SchemaNameConverter,
+ convert_schema_names,
repair_schema_default_enum_values,
validate_schema_default_enum_values,
)
from graphql import (
- ConstDirectiveNode,
DocumentNode,
- FieldDefinitionNode,
GraphQLSchema,
- NamedTypeNode,
- ObjectTypeDefinitionNode,
- TypeDefinitionNode,
assert_valid_schema,
build_ast_schema,
- concat_ast,
parse,
+ concat_ast,
)
-from graphql.language import ast
-from .bases import BaseType, BindableType, DeferredType, DefinitionType
-from .enum_type import EnumType
+from .base import GraphQLMetadata, GraphQLModel, GraphQLType
+from .roots import ROOTS_NAMES, merge_root_nodes
+from .sort import sort_schema_document
-ROOT_TYPES = ["Query", "Mutation", "Subscription"]
+SchemaType = Union[str, Enum, SchemaBindable, Type[GraphQLType], Type[Enum]]
def make_executable_schema(
- *args: Union[Type[BaseType], SchemaBindable, str],
+ *types: SchemaType,
+ directives: Optional[Dict[str, Type[SchemaDirectiveVisitor]]] = None,
+ convert_names_case: Union[bool, SchemaNameConverter] = False,
merge_roots: bool = True,
- extra_directives: Optional[Dict[str, Type[SchemaDirectiveVisitor]]] = None,
-):
- all_types = get_all_types(args)
- extra_defs = parse_extra_sdl(args)
- extra_bindables: List[SchemaBindable] = [
- arg for arg in args if isinstance(arg, SchemaBindable)
+) -> GraphQLSchema:
+ metadata = GraphQLMetadata()
+ type_defs: List[str] = find_type_defs(types)
+ types_list: List[SchemaType] = flatten_types(types, metadata)
+
+ assert_types_unique(types_list, merge_roots)
+ assert_types_not_abstract(types_list)
+
+ schema_bindables: List[Union[SchemaBindable, GraphQLModel]] = []
+ for type_def in types_list:
+ if isinstance(type_def, SchemaBindable):
+ schema_bindables.append(type_def)
+ elif isinstance(type_def, type) and issubclass(type_def, (GraphQLType, Enum)):
+ schema_bindables.append(metadata.get_graphql_model(type_def))
+
+ schema_models: List[GraphQLModel] = [
+ type_def for type_def in schema_bindables if isinstance(type_def, GraphQLModel)
]
- type_defs: List[Type[DefinitionType]] = []
- for type_ in all_types:
- if issubclass(type_, DefinitionType):
- type_defs.append(type_)
+ models_document: Optional[DocumentNode] = None
+ type_defs_document: Optional[DocumentNode] = None
- validate_no_missing_definitions(all_types, type_defs, extra_defs)
+ if schema_models:
+ models_document = DocumentNode(
+ definitions=tuple(schema_model.ast for schema_model in schema_models),
+ )
+
+ if type_defs:
+ type_defs_document = parse("\n".join(type_defs))
+
+ if models_document and type_defs_document:
+ document_node = concat_ast((models_document, type_defs_document))
+ elif models_document:
+ document_node = models_document
+ elif type_defs_document:
+ document_node = type_defs_document
+ else:
+ raise ValueError(
+ "'make_executable_schema' was called without any GraphQL types."
+ )
- schema = build_schema(type_defs, extra_defs, merge_roots)
+ if merge_roots:
+ document_node = merge_root_nodes(document_node)
- if extra_bindables:
- for bindable in extra_bindables:
- bindable.bind_to_schema(schema)
+ document_node = sort_schema_document(document_node)
+ schema = build_ast_schema(document_node)
- if extra_directives:
- SchemaDirectiveVisitor.visit_schema_directives(schema, extra_directives)
+ if directives:
+ SchemaDirectiveVisitor.visit_schema_directives(schema, directives)
assert_valid_schema(schema)
validate_schema_default_enum_values(schema)
repair_schema_default_enum_values(schema)
- add_directives_to_schema(schema, type_defs)
+ for schema_bindable in schema_bindables:
+ schema_bindable.bind_to_schema(schema)
+
+ if convert_names_case:
+ convert_schema_names(
+ schema,
+ convert_names_case if callable(convert_names_case) else None,
+ )
return schema
-def get_all_types(
- args: Sequence[Union[Type[BaseType], SchemaBindable, str]]
-) -> List[Type[BaseType]]:
- all_types: List[Type[BaseType]] = []
- for arg in args:
- if isinstance(arg, (str, SchemaBindable)):
- continue # Skip args of unsupported types
+def find_type_defs(types: Sequence[SchemaType]) -> List[str]:
+ type_defs: List[str] = []
- for child_type in arg.__get_types__():
- if child_type not in all_types:
- all_types.append(child_type)
- return all_types
+ for type_def in types:
+ if isinstance(type_def, str):
+ type_defs.append(type_def)
+ elif isinstance(type_def, list):
+ type_defs += find_type_defs(type_def)
+ return type_defs
-def parse_extra_sdl(
- args: Sequence[Union[Type[BaseType], SchemaBindable, str]]
-) -> List[TypeDefinitionNode]:
- sdl_strings: List[str] = [cast(str, arg) for arg in args if isinstance(arg, str)]
- if not sdl_strings:
- return []
- extra_sdl = "\n\n".join(sdl_strings)
- return cast(
- List[TypeDefinitionNode],
- list(parse(extra_sdl).definitions),
+def flatten_types(
+ types: Sequence[SchemaType],
+ metadata: GraphQLMetadata,
+) -> List[SchemaType]:
+ flat_schema_types_list: List[SchemaType] = flatten_schema_types(
+ types, metadata, dedupe=True
)
+ types_list: List[SchemaType] = []
+ for type_def in flat_schema_types_list:
+ if isinstance(type_def, SchemaBindable):
+ types_list.append(type_def)
-def validate_no_missing_definitions(
- all_types: List[Type[BaseType]],
- type_defs: List[Type[DefinitionType]],
- extra_defs: List[TypeDefinitionNode],
-):
- deferred_names: List[str] = []
- for type_ in all_types:
- if isinstance(type_, DeferredType):
- deferred_names.append(type_.graphql_name)
-
- real_names = [type_.graphql_name for type_ in type_defs]
- real_names += [definition.name.value for definition in extra_defs]
-
- missing_names = set(deferred_names) - set(real_names)
- if missing_names:
- raise ValueError(
- "Following types are defined as deferred and are missing "
- f"from schema: {', '.join(missing_names)}"
- )
+ elif isinstance(type_def, type) and issubclass(type_def, GraphQLType):
+ type_name = type_def.__name__
+ if getattr(type_def, "__abstract__", None):
+ raise ValueError(
+ f"Type '{type_name}' is an abstract type and can't be used "
+ "for schema creation."
+ )
-def build_schema(
- type_defs: List[Type[DefinitionType]],
- extra_defs: List[TypeDefinitionNode],
- merge_roots: bool = True,
-) -> GraphQLSchema:
- schema_definitions: List[ast.DocumentNode] = []
- if merge_roots:
- schema_definitions.append(build_root_schema(type_defs, extra_defs))
- for type_ in type_defs:
- if type_.graphql_name not in ROOT_TYPES or not merge_roots:
- schema_definitions.append(parse(type_.__schema__))
- for extra_type_def in extra_defs:
- if extra_type_def.name.value not in ROOT_TYPES or not merge_roots:
- schema_definitions.append(DocumentNode(definitions=(extra_type_def,)))
+ types_list.append(type_def)
- ast_document = concat_ast(schema_definitions)
- schema = build_ast_schema(ast_document)
+ elif isinstance(type_def, type) and issubclass(type_def, Enum):
+ types_list.append(type_def)
- for type_ in type_defs:
- if issubclass(type_, BindableType):
- type_.__bind_to_schema__(schema)
+ elif isinstance(type_def, list):
+ types_list += find_type_defs(type_def)
- return schema
+ return types_list
-RootTypeDef = Tuple[str, DocumentNode]
+def flatten_schema_types(
+ types: Sequence[Union[SchemaType, List[SchemaType]]],
+ metadata: GraphQLMetadata,
+ dedupe: bool,
+) -> List[SchemaType]:
+ flat_list: List[SchemaType] = []
+ checked_types: List[Type[GraphQLType]] = []
+ for type_def in types:
+ if isinstance(type_def, str):
+ continue
+ if isinstance(type_def, list):
+ flat_list += flatten_schema_types(type_def, metadata, dedupe=False)
+ elif isinstance(type_def, SchemaBindable):
+ flat_list.append(type_def)
+ elif isinstance(type_def, type) and issubclass(type_def, Enum):
+ flat_list.append(type_def)
+ elif isinstance(type_def, type) and issubclass(type_def, GraphQLType):
+ add_graphql_type_to_flat_list(flat_list, checked_types, type_def, metadata)
+ elif get_graphql_type_name(type_def):
+ flat_list.append(type_def)
-def build_root_schema(
- type_defs: List[Type[DefinitionType]],
- extra_defs: List[TypeDefinitionNode],
-) -> DocumentNode:
- root_types: Dict[str, List[RootTypeDef]] = {
- "Query": [],
- "Mutation": [],
- "Subscription": [],
- }
+ if not dedupe:
+ return flat_list
- for type_def in type_defs:
- if type_def.graphql_name in root_types:
- root_types[type_def.graphql_name].append(
- (type_def.__name__, parse(type_def.__schema__))
- )
+ unique_list: List[SchemaType] = []
+ for type_def in flat_list:
+ if type_def not in unique_list:
+ unique_list.append(type_def)
- for extra_type_def in extra_defs:
- if extra_type_def.name.value in root_types:
- root_types[extra_type_def.name.value].append(
- ("extra_sdl", DocumentNode(definitions=(extra_type_def,)))
- )
+ return unique_list
- schema: List[DocumentNode] = []
- for root_name, root_type_defs in root_types.items():
- if len(root_type_defs) == 1:
- schema.append(root_type_defs[0][1])
- elif root_type_defs:
- schema.append(merge_root_types(root_name, root_type_defs))
- return concat_ast(schema)
+def add_graphql_type_to_flat_list(
+ flat_list: List[SchemaType],
+ checked_types: List[Type[GraphQLType]],
+ type_def: Type[GraphQLType],
+ metadata: GraphQLMetadata,
+) -> None:
+ if type_def in checked_types:
+ return
+ checked_types.append(type_def)
-def merge_root_types(root_name: str, type_defs: List[RootTypeDef]) -> DocumentNode:
- interfaces: List[NamedTypeNode] = []
- directives: List[ConstDirectiveNode] = []
- fields: Dict[str, Tuple[str, FieldDefinitionNode]] = {}
+ for child_type in type_def.__get_graphql_types__(metadata):
+ flat_list.append(child_type)
- for type_source, type_def in type_defs:
- type_definition = cast(ObjectTypeDefinitionNode, type_def.definitions[0])
- interfaces.extend(type_definition.interfaces)
- directives.extend(type_definition.directives)
+ if issubclass(child_type, GraphQLType):
+ add_graphql_type_to_flat_list(
+ flat_list, checked_types, child_type, metadata
+ )
- for field_def in type_definition.fields:
- field_name = field_def.name.value
- if field_name in fields:
- other_type_source = fields[field_name][0]
- raise ValueError(
- f"Multiple {root_name} types are defining same field "
- f"'{field_name}': {other_type_source}, {type_source}"
- )
- fields[field_name] = (type_source, field_def)
+def get_graphql_type_name(type_def: SchemaType) -> Optional[str]:
+ if isinstance(type_def, SchemaBindable):
+ return None
- merged_definition = ast.ObjectTypeDefinitionNode()
- merged_definition.name = ast.NameNode()
- merged_definition.name.value = root_name
- merged_definition.interfaces = tuple(interfaces)
- merged_definition.directives = tuple(directives)
- merged_definition.fields = tuple(
- fields[field_name][1] for field_name in sorted(fields)
- )
+ if isinstance(type_def, type) and issubclass(type_def, Enum):
+ return type_def.__name__
- merged_document = DocumentNode()
- merged_document.definitions = (merged_definition,)
+ if isinstance(type_def, type) and issubclass(type_def, GraphQLType):
+ return type_def.__get_graphql_name__()
- return merged_document
+ return None
-def add_directives_to_schema(
- schema: GraphQLSchema, type_defs: List[Type[DefinitionType]]
-):
- directives: Dict[str, Type[SchemaDirectiveVisitor]] = {}
+def assert_types_unique(type_defs: List[SchemaType], merge_roots: bool):
+ types_names: Dict[str, Any] = {}
for type_def in type_defs:
- visitor = getattr(type_def, "__visitor__", None)
- if visitor and issubclass(visitor, SchemaDirectiveVisitor):
- directives[type_def.graphql_name] = visitor
+ type_name = get_graphql_type_name(type_def)
+ if not type_name:
+ continue
+
+ if merge_roots and type_name in ROOTS_NAMES:
+ continue
+
+ if type_name in types_names:
+ type_def_name = getattr(type_def, "__name__") or type_def
+ raise ValueError(
+ f"Types '{type_def_name}' and '{types_names[type_name]}' both define "
+ f"GraphQL type with name '{type_name}'."
+ )
- if directives:
- SchemaDirectiveVisitor.visit_schema_directives(schema, directives)
+ types_names[type_name] = type_def
-def repair_default_enum_values(schema, types_list: List[Type[DefinitionType]]) -> None:
- for type_ in types_list:
- if issubclass(type_, EnumType):
- type_.__bind_to_default_values__(schema)
+def assert_types_not_abstract(type_defs: List[SchemaType]):
+ for type_def in type_defs:
+ if isinstance(type_def, SchemaBindable):
+ continue
+
+ if (
+ isinstance(type_def, type)
+ and issubclass(type_def, GraphQLType)
+ and getattr(type_def, "__abstract__", None)
+ ):
+ raise ValueError(
+ f"Type '{type_def.__name__}' is an abstract type and can't be used "
+ "for schema creation."
+ )
diff --git a/ariadne_graphql_modules/next/idtype.py b/ariadne_graphql_modules/idtype.py
similarity index 100%
rename from ariadne_graphql_modules/next/idtype.py
rename to ariadne_graphql_modules/idtype.py
diff --git a/ariadne_graphql_modules/input_type/__init__.py b/ariadne_graphql_modules/input_type/__init__.py
new file mode 100644
index 0000000..23a8e12
--- /dev/null
+++ b/ariadne_graphql_modules/input_type/__init__.py
@@ -0,0 +1,8 @@
+from .graphql_type import GraphQLInput
+from .models import GraphQLInputModel
+
+
+__all__ = [
+ "GraphQLInput",
+ "GraphQLInputModel",
+]
diff --git a/ariadne_graphql_modules/next/graphql_input/input_field.py b/ariadne_graphql_modules/input_type/graphql_field.py
similarity index 100%
rename from ariadne_graphql_modules/next/graphql_input/input_field.py
rename to ariadne_graphql_modules/input_type/graphql_field.py
diff --git a/ariadne_graphql_modules/next/graphql_input/input_type.py b/ariadne_graphql_modules/input_type/graphql_type.py
similarity index 97%
rename from ariadne_graphql_modules/next/graphql_input/input_type.py
rename to ariadne_graphql_modules/input_type/graphql_type.py
index 6d03a05..9670ea4 100644
--- a/ariadne_graphql_modules/next/graphql_input/input_type.py
+++ b/ariadne_graphql_modules/input_type/graphql_type.py
@@ -4,21 +4,21 @@
from graphql import InputObjectTypeDefinitionNode, InputValueDefinitionNode, NameNode
-from .input_field import GraphQLInputField
+from .graphql_field import GraphQLInputField
from ..base import GraphQLMetadata, GraphQLModel, GraphQLType
from ..convert_name import (
convert_graphql_name_to_python,
convert_python_name_to_graphql,
)
from ..description import get_description_node
-from ..graphql_input.input_model import GraphQLInputModel
-from ..graphql_input.validators import (
+from .models import GraphQLInputModel
+from .validators import (
validate_input_type,
validate_input_type_with_schema,
)
from ..typing import get_graphql_type, get_type_node
from ..value import get_value_node
-from ...utils import parse_definition
+from ..utils import parse_definition
class GraphQLInput(GraphQLType):
diff --git a/ariadne_graphql_modules/next/graphql_input/input_model.py b/ariadne_graphql_modules/input_type/models.py
similarity index 100%
rename from ariadne_graphql_modules/next/graphql_input/input_model.py
rename to ariadne_graphql_modules/input_type/models.py
diff --git a/ariadne_graphql_modules/next/graphql_input/validators.py b/ariadne_graphql_modules/input_type/validators.py
similarity index 97%
rename from ariadne_graphql_modules/next/graphql_input/validators.py
rename to ariadne_graphql_modules/input_type/validators.py
index 852a778..68432b8 100644
--- a/ariadne_graphql_modules/next/graphql_input/validators.py
+++ b/ariadne_graphql_modules/input_type/validators.py
@@ -4,11 +4,11 @@
from ..convert_name import convert_graphql_name_to_python
from ..validators import validate_description, validate_name
from ..value import get_value_from_node, get_value_node
-from ...utils import parse_definition
-from .input_field import GraphQLInputField
+from ..utils import parse_definition
+from .graphql_field import GraphQLInputField
if TYPE_CHECKING:
- from .input_type import GraphQLInput
+ from .graphql_type import GraphQLInput
def validate_input_type_with_schema(cls: Type["GraphQLInput"]) -> Dict[str, Any]:
diff --git a/ariadne_graphql_modules/interface_type/__init__.py b/ariadne_graphql_modules/interface_type/__init__.py
new file mode 100644
index 0000000..0ec79d8
--- /dev/null
+++ b/ariadne_graphql_modules/interface_type/__init__.py
@@ -0,0 +1,8 @@
+from .graphql_type import GraphQLInterface
+from .models import GraphQLInterfaceModel
+
+
+__all__ = [
+ "GraphQLInterface",
+ "GraphQLInterfaceModel",
+]
diff --git a/ariadne_graphql_modules/interface_type/graphql_type.py b/ariadne_graphql_modules/interface_type/graphql_type.py
new file mode 100644
index 0000000..9a33c14
--- /dev/null
+++ b/ariadne_graphql_modules/interface_type/graphql_type.py
@@ -0,0 +1,147 @@
+from typing import Any, Dict, List, Optional, Tuple, cast
+
+from ariadne.types import Resolver
+from graphql import (
+ FieldDefinitionNode,
+ InterfaceTypeDefinitionNode,
+ NameNode,
+ NamedTypeNode,
+)
+
+from ..base_object_type import (
+ GraphQLFieldData,
+ GraphQLBaseObject,
+ GraphQLObjectData,
+ validate_object_type_with_schema,
+ validate_object_type_without_schema,
+)
+from ..types import GraphQLClassType
+
+from ..utils import parse_definition
+from ..base import GraphQLMetadata
+from ..description import get_description_node
+from ..object_type import GraphQLObject
+from .models import GraphQLInterfaceModel
+
+
+class GraphQLInterface(GraphQLBaseObject):
+ __valid_type__ = InterfaceTypeDefinitionNode
+ __graphql_type__ = GraphQLClassType.INTERFACE
+ __abstract__ = True
+ __description__: Optional[str] = None
+
+ def __init_subclass__(cls) -> None:
+ super().__init_subclass__()
+
+ if cls.__dict__.get("__abstract__"):
+ return
+
+ cls.__abstract__ = False
+
+ if cls.__dict__.get("__schema__"):
+ valid_type = getattr(cls, "__valid_type__", InterfaceTypeDefinitionNode)
+ cls.__kwargs__ = validate_object_type_with_schema(cls, valid_type)
+ else:
+ cls.__kwargs__ = validate_object_type_without_schema(cls)
+
+ @classmethod
+ def __get_graphql_model_with_schema__(cls) -> "GraphQLInterfaceModel":
+ definition = cast(
+ InterfaceTypeDefinitionNode,
+ parse_definition(InterfaceTypeDefinitionNode, cls.__schema__),
+ )
+
+ resolvers: Dict[str, Resolver] = {}
+ fields: Tuple[FieldDefinitionNode, ...] = tuple()
+ fields, resolvers = cls._create_fields_and_resolvers_with_schema(
+ definition.fields
+ )
+
+ return GraphQLInterfaceModel(
+ name=definition.name.value,
+ ast_type=InterfaceTypeDefinitionNode,
+ ast=InterfaceTypeDefinitionNode(
+ name=NameNode(value=definition.name.value),
+ fields=tuple(fields),
+ interfaces=definition.interfaces,
+ ),
+ resolve_type=cls.resolve_type,
+ resolvers=resolvers,
+ aliases=getattr(cls, "__aliases__", {}),
+ out_names={},
+ )
+
+ @classmethod
+ def __get_graphql_model_without_schema__(
+ cls, metadata: GraphQLMetadata, name: str
+ ) -> "GraphQLInterfaceModel":
+ type_data = cls.get_graphql_object_data(metadata)
+ type_aliases = getattr(cls, "__aliases__", None) or {}
+
+ fields_ast: List[FieldDefinitionNode] = []
+ resolvers: Dict[str, Resolver] = {}
+ aliases: Dict[str, str] = {}
+ out_names: Dict[str, Dict[str, str]] = {}
+
+ fields_ast, resolvers, aliases, out_names = cls._process_graphql_fields(
+ metadata, type_data, type_aliases
+ )
+
+ interfaces_ast: List[NamedTypeNode] = []
+ for interface_name in type_data.interfaces:
+ interfaces_ast.append(NamedTypeNode(name=NameNode(value=interface_name)))
+
+ return GraphQLInterfaceModel(
+ name=name,
+ ast_type=InterfaceTypeDefinitionNode,
+ ast=InterfaceTypeDefinitionNode(
+ name=NameNode(value=name),
+ description=get_description_node(
+ getattr(cls, "__description__", None),
+ ),
+ fields=tuple(fields_ast),
+ interfaces=tuple(interfaces_ast),
+ ),
+ resolve_type=cls.resolve_type,
+ resolvers=resolvers,
+ aliases=aliases,
+ out_names=out_names,
+ )
+
+ @staticmethod
+ def resolve_type(obj: Any, *_) -> str:
+ if isinstance(obj, GraphQLObject):
+ return obj.__get_graphql_name__()
+
+ raise ValueError(
+ f"Cannot resolve GraphQL type {obj} for object of type '{type(obj).__name__}'."
+ )
+
+ @classmethod
+ def _collect_inherited_objects(cls):
+ return [
+ inherited_obj
+ for inherited_obj in cls.__mro__[1:]
+ if getattr(inherited_obj, "__graphql_type__", None)
+ == GraphQLClassType.INTERFACE
+ and not getattr(inherited_obj, "__abstract__", True)
+ ]
+
+ @classmethod
+ def create_graphql_object_data_without_schema(cls) -> GraphQLObjectData:
+ fields_data = GraphQLFieldData()
+ inherited_objects = list(reversed(cls._collect_inherited_objects()))
+
+ for inherited_obj in inherited_objects:
+ fields_data.type_hints.update(inherited_obj.__annotations__)
+ fields_data.aliases.update(getattr(inherited_obj, "__aliases__", {}))
+
+ cls._process_type_hints_and_aliases(fields_data)
+ for inherited_obj in inherited_objects:
+ cls._process_class_attributes(inherited_obj, fields_data)
+ cls._process_class_attributes(cls, fields_data)
+
+ return GraphQLObjectData(
+ fields=cls._build_fields(fields_data=fields_data),
+ interfaces=[],
+ )
diff --git a/ariadne_graphql_modules/next/graphql_interface/interface_model.py b/ariadne_graphql_modules/interface_type/models.py
similarity index 100%
rename from ariadne_graphql_modules/next/graphql_interface/interface_model.py
rename to ariadne_graphql_modules/interface_type/models.py
diff --git a/ariadne_graphql_modules/next/__init__.py b/ariadne_graphql_modules/next/__init__.py
deleted file mode 100644
index 6aea1ab..0000000
--- a/ariadne_graphql_modules/next/__init__.py
+++ /dev/null
@@ -1,58 +0,0 @@
-from .base import GraphQLMetadata, GraphQLModel, GraphQLType
-from .convert_name import (
- convert_graphql_name_to_python,
- convert_python_name_to_graphql,
-)
-from .deferredtype import deferred
-from .description import get_description_node
-from .graphql_enum_type import (
- GraphQLEnum,
- GraphQLEnumModel,
- create_graphql_enum_model,
- graphql_enum,
-)
-from .executable_schema import make_executable_schema
-from .idtype import GraphQLID
-from .graphql_input import GraphQLInput, GraphQLInputModel
-from .graphql_object import GraphQLObject, GraphQLObjectModel, object_field
-from .roots import ROOTS_NAMES, merge_root_nodes
-from .graphql_scalar import GraphQLScalar, GraphQLScalarModel
-from .sort import sort_schema_document
-from .graphql_union import GraphQLUnion, GraphQLUnionModel
-from .value import get_value_from_node, get_value_node
-from .graphql_interface import GraphQLInterface, GraphQLInterfaceModel
-from .graphql_subscription import GraphQLSubscription, GraphQLSubscriptionModel
-
-__all__ = [
- "GraphQLEnum",
- "GraphQLEnumModel",
- "GraphQLID",
- "GraphQLInput",
- "GraphQLInputModel",
- "GraphQLInterface",
- "GraphQLInterfaceModel",
- "GraphQLSubscription",
- "GraphQLSubscriptionModel",
- "GraphQLMetadata",
- "GraphQLModel",
- "GraphQLObject",
- "GraphQLObjectModel",
- "GraphQLScalar",
- "GraphQLScalarModel",
- "GraphQLType",
- "GraphQLUnion",
- "GraphQLUnionModel",
- "ROOTS_NAMES",
- "convert_graphql_name_to_python",
- "convert_python_name_to_graphql",
- "create_graphql_enum_model",
- "deferred",
- "get_description_node",
- "get_value_from_node",
- "get_value_node",
- "graphql_enum",
- "make_executable_schema",
- "merge_root_nodes",
- "object_field",
- "sort_schema_document",
-]
diff --git a/ariadne_graphql_modules/next/executable_schema.py b/ariadne_graphql_modules/next/executable_schema.py
deleted file mode 100644
index 79da59f..0000000
--- a/ariadne_graphql_modules/next/executable_schema.py
+++ /dev/null
@@ -1,243 +0,0 @@
-from enum import Enum
-from typing import Any, Dict, List, Optional, Sequence, Type, Union
-
-from ariadne import (
- SchemaBindable,
- SchemaDirectiveVisitor,
- SchemaNameConverter,
- convert_schema_names,
- repair_schema_default_enum_values,
- validate_schema_default_enum_values,
-)
-from graphql import (
- DocumentNode,
- GraphQLSchema,
- assert_valid_schema,
- build_ast_schema,
- parse,
- concat_ast,
-)
-
-from .base import GraphQLMetadata, GraphQLModel, GraphQLType
-from .roots import ROOTS_NAMES, merge_root_nodes
-from .sort import sort_schema_document
-
-SchemaType = Union[str, Enum, SchemaBindable, Type[GraphQLType], Type[Enum]]
-
-
-def make_executable_schema(
- *types: SchemaType,
- directives: Optional[Dict[str, Type[SchemaDirectiveVisitor]]] = None,
- convert_names_case: Union[bool, SchemaNameConverter] = False,
- merge_roots: bool = True,
-) -> GraphQLSchema:
- metadata = GraphQLMetadata()
- type_defs: List[str] = find_type_defs(types)
- types_list: List[SchemaType] = flatten_types(types, metadata)
-
- assert_types_unique(types_list, merge_roots)
- assert_types_not_abstract(types_list)
-
- schema_bindables: List[Union[SchemaBindable, GraphQLModel]] = []
- for type_def in types_list:
- if isinstance(type_def, SchemaBindable):
- schema_bindables.append(type_def)
- elif isinstance(type_def, type) and issubclass(type_def, (GraphQLType, Enum)):
- schema_bindables.append(metadata.get_graphql_model(type_def))
-
- schema_models: List[GraphQLModel] = [
- type_def for type_def in schema_bindables if isinstance(type_def, GraphQLModel)
- ]
-
- models_document: Optional[DocumentNode] = None
- type_defs_document: Optional[DocumentNode] = None
-
- if schema_models:
- models_document = DocumentNode(
- definitions=tuple(schema_model.ast for schema_model in schema_models),
- )
-
- if type_defs:
- type_defs_document = parse("\n".join(type_defs))
-
- if models_document and type_defs_document:
- document_node = concat_ast((models_document, type_defs_document))
- elif models_document:
- document_node = models_document
- elif type_defs_document:
- document_node = type_defs_document
- else:
- raise ValueError(
- "'make_executable_schema' was called without any GraphQL types."
- )
-
- if merge_roots:
- document_node = merge_root_nodes(document_node)
-
- document_node = sort_schema_document(document_node)
- schema = build_ast_schema(document_node)
-
- if directives:
- SchemaDirectiveVisitor.visit_schema_directives(schema, directives)
-
- assert_valid_schema(schema)
- validate_schema_default_enum_values(schema)
- repair_schema_default_enum_values(schema)
-
- for schema_bindable in schema_bindables:
- schema_bindable.bind_to_schema(schema)
-
- if convert_names_case:
- convert_schema_names(
- schema,
- convert_names_case if callable(convert_names_case) else None,
- )
-
- return schema
-
-
-def find_type_defs(types: Sequence[SchemaType]) -> List[str]:
- type_defs: List[str] = []
-
- for type_def in types:
- if isinstance(type_def, str):
- type_defs.append(type_def)
- elif isinstance(type_def, list):
- type_defs += find_type_defs(type_def)
-
- return type_defs
-
-
-def flatten_types(
- types: Sequence[SchemaType],
- metadata: GraphQLMetadata,
-) -> List[SchemaType]:
- flat_schema_types_list: List[SchemaType] = flatten_schema_types(
- types, metadata, dedupe=True
- )
-
- types_list: List[SchemaType] = []
- for type_def in flat_schema_types_list:
- if isinstance(type_def, SchemaBindable):
- types_list.append(type_def)
-
- elif isinstance(type_def, type) and issubclass(type_def, GraphQLType):
- type_name = type_def.__name__
-
- if getattr(type_def, "__abstract__", None):
- raise ValueError(
- f"Type '{type_name}' is an abstract type and can't be used "
- "for schema creation."
- )
-
- types_list.append(type_def)
-
- elif isinstance(type_def, type) and issubclass(type_def, Enum):
- types_list.append(type_def)
-
- elif isinstance(type_def, list):
- types_list += find_type_defs(type_def)
-
- return types_list
-
-
-def flatten_schema_types(
- types: Sequence[Union[SchemaType, List[SchemaType]]],
- metadata: GraphQLMetadata,
- dedupe: bool,
-) -> List[SchemaType]:
- flat_list: List[SchemaType] = []
- checked_types: List[Type[GraphQLType]] = []
-
- for type_def in types:
- if isinstance(type_def, str):
- continue
- if isinstance(type_def, list):
- flat_list += flatten_schema_types(type_def, metadata, dedupe=False)
- elif isinstance(type_def, SchemaBindable):
- flat_list.append(type_def)
- elif isinstance(type_def, type) and issubclass(type_def, Enum):
- flat_list.append(type_def)
- elif isinstance(type_def, type) and issubclass(type_def, GraphQLType):
- add_graphql_type_to_flat_list(flat_list, checked_types, type_def, metadata)
- elif get_graphql_type_name(type_def):
- flat_list.append(type_def)
-
- if not dedupe:
- return flat_list
-
- unique_list: List[SchemaType] = []
- for type_def in flat_list:
- if type_def not in unique_list:
- unique_list.append(type_def)
-
- return unique_list
-
-
-def add_graphql_type_to_flat_list(
- flat_list: List[SchemaType],
- checked_types: List[Type[GraphQLType]],
- type_def: Type[GraphQLType],
- metadata: GraphQLMetadata,
-) -> None:
- if type_def in checked_types:
- return
-
- checked_types.append(type_def)
-
- for child_type in type_def.__get_graphql_types__(metadata):
- flat_list.append(child_type)
-
- if issubclass(child_type, GraphQLType):
- add_graphql_type_to_flat_list(
- flat_list, checked_types, child_type, metadata
- )
-
-
-def get_graphql_type_name(type_def: SchemaType) -> Optional[str]:
- if isinstance(type_def, SchemaBindable):
- return None
-
- if isinstance(type_def, type) and issubclass(type_def, Enum):
- return type_def.__name__
-
- if isinstance(type_def, type) and issubclass(type_def, GraphQLType):
- return type_def.__get_graphql_name__()
-
- return None
-
-
-def assert_types_unique(type_defs: List[SchemaType], merge_roots: bool):
- types_names: Dict[str, Any] = {}
- for type_def in type_defs:
- type_name = get_graphql_type_name(type_def)
- if not type_name:
- continue
-
- if merge_roots and type_name in ROOTS_NAMES:
- continue
-
- if type_name in types_names:
- type_def_name = getattr(type_def, "__name__") or type_def
- raise ValueError(
- f"Types '{type_def_name}' and '{types_names[type_name]}' both define "
- f"GraphQL type with name '{type_name}'."
- )
-
- types_names[type_name] = type_def
-
-
-def assert_types_not_abstract(type_defs: List[SchemaType]):
- for type_def in type_defs:
- if isinstance(type_def, SchemaBindable):
- continue
-
- if (
- isinstance(type_def, type)
- and issubclass(type_def, GraphQLType)
- and getattr(type_def, "__abstract__", None)
- ):
- raise ValueError(
- f"Type '{type_def.__name__}' is an abstract type and can't be used "
- "for schema creation."
- )
diff --git a/ariadne_graphql_modules/next/graphql_enum_type/__init__.py b/ariadne_graphql_modules/next/graphql_enum_type/__init__.py
deleted file mode 100644
index a4c8666..0000000
--- a/ariadne_graphql_modules/next/graphql_enum_type/__init__.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from .enum_type import GraphQLEnum, graphql_enum, create_graphql_enum_model
-from .enum_model import GraphQLEnumModel
-
-__all__ = [
- "GraphQLEnum",
- "GraphQLEnumModel",
- "create_graphql_enum_model",
- "graphql_enum",
-]
diff --git a/ariadne_graphql_modules/next/graphql_input/__init__.py b/ariadne_graphql_modules/next/graphql_input/__init__.py
deleted file mode 100644
index 5d1e0b5..0000000
--- a/ariadne_graphql_modules/next/graphql_input/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from .input_type import GraphQLInput
-from .input_model import GraphQLInputModel
-
-
-__all__ = [
- "GraphQLInput",
- "GraphQLInputModel",
-]
diff --git a/ariadne_graphql_modules/next/graphql_interface/__init__.py b/ariadne_graphql_modules/next/graphql_interface/__init__.py
deleted file mode 100644
index 7ccd6d6..0000000
--- a/ariadne_graphql_modules/next/graphql_interface/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from .interface_type import GraphQLInterface
-from .interface_model import GraphQLInterfaceModel
-
-
-__all__ = [
- "GraphQLInterface",
- "GraphQLInterfaceModel",
-]
diff --git a/ariadne_graphql_modules/next/graphql_interface/interface_type.py b/ariadne_graphql_modules/next/graphql_interface/interface_type.py
deleted file mode 100644
index 1a7832b..0000000
--- a/ariadne_graphql_modules/next/graphql_interface/interface_type.py
+++ /dev/null
@@ -1,175 +0,0 @@
-from typing import Any, Dict, List, cast
-
-from ariadne.types import Resolver
-from graphql import (
- FieldDefinitionNode,
- InputValueDefinitionNode,
- InterfaceTypeDefinitionNode,
- NameNode,
- NamedTypeNode,
- StringValueNode,
-)
-
-from ...utils import parse_definition
-from ..base import GraphQLMetadata
-from ..description import get_description_node
-from ..graphql_object import GraphQLObject, GraphQLObjectResolver
-from ..graphql_object.object_type import get_graphql_object_data
-from ..graphql_object.utils import (
- get_field_args_from_resolver,
- get_field_args_out_names,
- get_field_node_from_obj_field,
- update_field_args_options,
-)
-from ..value import get_value_node
-from .interface_model import GraphQLInterfaceModel
-
-
-class GraphQLInterface(GraphQLObject):
- __abstract__: bool = True
- __valid_type__ = InterfaceTypeDefinitionNode
-
- @classmethod
- def __get_graphql_model_with_schema__(cls) -> "GraphQLInterfaceModel":
- definition = cast(
- InterfaceTypeDefinitionNode,
- parse_definition(InterfaceTypeDefinitionNode, cls.__schema__),
- )
-
- descriptions: Dict[str, StringValueNode] = {}
- args_descriptions: Dict[str, Dict[str, StringValueNode]] = {}
- args_defaults: Dict[str, Dict[str, Any]] = {}
- resolvers: Dict[str, Resolver] = {}
- out_names: Dict[str, Dict[str, str]] = {}
-
- for attr_name in dir(cls):
- cls_attr = getattr(cls, attr_name)
- if isinstance(cls_attr, GraphQLObjectResolver):
- resolvers[cls_attr.field] = cls_attr.resolver
- description_node = get_description_node(cls_attr.description)
- if description_node:
- descriptions[cls_attr.field] = description_node
-
- field_args = get_field_args_from_resolver(cls_attr.resolver)
- if field_args:
- args_descriptions[cls_attr.field] = {}
- args_defaults[cls_attr.field] = {}
-
- final_args = update_field_args_options(field_args, cls_attr.args)
-
- for arg_name, arg_options in final_args.items():
- arg_description = get_description_node(arg_options.description)
- if arg_description:
- args_descriptions[cls_attr.field][
- arg_name
- ] = arg_description
-
- arg_default = arg_options.default_value
- if arg_default is not None:
- args_defaults[cls_attr.field][arg_name] = get_value_node(
- arg_default
- )
-
- fields: List[FieldDefinitionNode] = []
- for field in definition.fields:
- field_args_descriptions = args_descriptions.get(field.name.value, {})
- field_args_defaults = args_defaults.get(field.name.value, {})
-
- args: List[InputValueDefinitionNode] = []
- for arg in field.arguments:
- arg_name = arg.name.value
- args.append(
- InputValueDefinitionNode(
- description=(
- arg.description or field_args_descriptions.get(arg_name)
- ),
- name=arg.name,
- directives=arg.directives,
- type=arg.type,
- default_value=(
- arg.default_value or field_args_defaults.get(arg_name)
- ),
- )
- )
-
- fields.append(
- FieldDefinitionNode(
- name=field.name,
- description=(
- field.description or descriptions.get(field.name.value)
- ),
- directives=field.directives,
- arguments=tuple(args),
- type=field.type,
- )
- )
-
- return GraphQLInterfaceModel(
- name=definition.name.value,
- ast_type=InterfaceTypeDefinitionNode,
- ast=InterfaceTypeDefinitionNode(
- name=NameNode(value=definition.name.value),
- fields=tuple(fields),
- interfaces=definition.interfaces,
- ),
- resolve_type=cls.resolve_type,
- resolvers=resolvers,
- aliases=getattr(cls, "__aliases__", {}),
- out_names=out_names,
- )
-
- @classmethod
- def __get_graphql_model_without_schema__(
- cls, metadata: GraphQLMetadata, name: str
- ) -> "GraphQLInterfaceModel":
- type_data = get_graphql_object_data(metadata, cls)
- type_aliases = getattr(cls, "__aliases__", None) or {}
-
- fields_ast: List[FieldDefinitionNode] = []
- resolvers: Dict[str, Resolver] = {}
- aliases: Dict[str, str] = {}
- out_names: Dict[str, Dict[str, str]] = {}
-
- for attr_name, field in type_data.fields.items():
- fields_ast.append(get_field_node_from_obj_field(cls, metadata, field))
-
- if attr_name in type_aliases and field.name:
- aliases[field.name] = type_aliases[attr_name]
- elif field.name and attr_name != field.name and not field.resolver:
- aliases[field.name] = attr_name
-
- if field.resolver and field.name:
- resolvers[field.name] = field.resolver
-
- if field.args and field.name:
- out_names[field.name] = get_field_args_out_names(field.args)
-
- interfaces_ast: List[NamedTypeNode] = []
- for interface_name in type_data.interfaces:
- interfaces_ast.append(NamedTypeNode(name=NameNode(value=interface_name)))
-
- return GraphQLInterfaceModel(
- name=name,
- ast_type=InterfaceTypeDefinitionNode,
- ast=InterfaceTypeDefinitionNode(
- name=NameNode(value=name),
- description=get_description_node(
- getattr(cls, "__description__", None),
- ),
- fields=tuple(fields_ast),
- interfaces=tuple(interfaces_ast),
- ),
- resolve_type=cls.resolve_type,
- resolvers=resolvers,
- aliases=aliases,
- out_names=out_names,
- )
-
- @staticmethod
- def resolve_type(obj: Any, *_) -> str:
- if isinstance(obj, GraphQLObject):
- return obj.__get_graphql_name__()
-
- raise ValueError(
- f"Cannot resolve GraphQL type {obj} for object of type '{type(obj).__name__}'."
- )
diff --git a/ariadne_graphql_modules/next/graphql_scalar/__init__.py b/ariadne_graphql_modules/next/graphql_scalar/__init__.py
deleted file mode 100644
index 1c1d0d2..0000000
--- a/ariadne_graphql_modules/next/graphql_scalar/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from .scalar_type import GraphQLScalar
-from .scalar_model import GraphQLScalarModel
-
-
-__all__ = [
- "GraphQLScalar",
- "GraphQLScalarModel",
-]
diff --git a/ariadne_graphql_modules/next/graphql_subscription/__init__.py b/ariadne_graphql_modules/next/graphql_subscription/__init__.py
deleted file mode 100644
index 962d24e..0000000
--- a/ariadne_graphql_modules/next/graphql_subscription/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from .subscription_type import GraphQLSubscription
-from .subscription_model import GraphQLSubscriptionModel
-
-
-__all__ = [
- "GraphQLSubscription",
- "GraphQLSubscriptionModel",
-]
diff --git a/ariadne_graphql_modules/next/graphql_union/__init__.py b/ariadne_graphql_modules/next/graphql_union/__init__.py
deleted file mode 100644
index 7e9462d..0000000
--- a/ariadne_graphql_modules/next/graphql_union/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from .union_type import GraphQLUnion
-from .union_model import GraphQLUnionModel
-
-
-__all__ = [
- "GraphQLUnion",
- "GraphQLUnionModel",
-]
diff --git a/ariadne_graphql_modules/next/graphql_object/__init__.py b/ariadne_graphql_modules/object_type/__init__.py
similarity index 77%
rename from ariadne_graphql_modules/next/graphql_object/__init__.py
rename to ariadne_graphql_modules/object_type/__init__.py
index a2b2c67..03db715 100644
--- a/ariadne_graphql_modules/next/graphql_object/__init__.py
+++ b/ariadne_graphql_modules/object_type/__init__.py
@@ -1,13 +1,13 @@
-from .object_field import (
+from ..base_object_type.graphql_field import (
object_field,
GraphQLObjectResolver,
GraphQLObjectSource,
object_subscriber,
GraphQLObjectFieldArg,
)
-from .object_type import GraphQLObject, get_graphql_object_data
-from .object_model import GraphQLObjectModel
-from .utils import (
+from .graphql_type import GraphQLObject
+from .models import GraphQLObjectModel
+from ..base_object_type.utils import (
get_field_args_from_resolver,
get_field_args_out_names,
get_field_node_from_obj_field,
@@ -24,7 +24,6 @@
"get_field_node_from_obj_field",
"update_field_args_options",
"GraphQLObjectResolver",
- "get_graphql_object_data",
"GraphQLObjectSource",
"object_subscriber",
"get_field_args_from_subscriber",
diff --git a/ariadne_graphql_modules/object_type/graphql_type.py b/ariadne_graphql_modules/object_type/graphql_type.py
new file mode 100644
index 0000000..89e0227
--- /dev/null
+++ b/ariadne_graphql_modules/object_type/graphql_type.py
@@ -0,0 +1,148 @@
+from typing import (
+ Dict,
+ List,
+ Optional,
+ Tuple,
+ cast,
+)
+
+from ariadne.types import Resolver
+from graphql import (
+ FieldDefinitionNode,
+ NameNode,
+ NamedTypeNode,
+ ObjectTypeDefinitionNode,
+)
+
+from ..types import GraphQLClassType
+
+from ..base_object_type import (
+ GraphQLFieldData,
+ GraphQLBaseObject,
+ GraphQLObjectData,
+ validate_object_type_with_schema,
+ validate_object_type_without_schema,
+)
+from .models import GraphQLObjectModel
+
+
+from ..utils import parse_definition
+from ..base import GraphQLMetadata, GraphQLModel
+from ..description import get_description_node
+
+
+class GraphQLObject(GraphQLBaseObject):
+ __valid_type__ = ObjectTypeDefinitionNode
+ __graphql_type__ = GraphQLClassType.OBJECT
+ __abstract__ = True
+ __description__: Optional[str] = None
+
+ def __init_subclass__(cls) -> None:
+ super().__init_subclass__()
+
+ if cls.__dict__.get("__abstract__"):
+ return
+
+ cls.__abstract__ = False
+
+ if cls.__dict__.get("__schema__"):
+ valid_type = getattr(cls, "__valid_type__", ObjectTypeDefinitionNode)
+ cls.__kwargs__ = validate_object_type_with_schema(cls, valid_type)
+ else:
+ cls.__kwargs__ = validate_object_type_without_schema(cls)
+
+ @classmethod
+ def __get_graphql_model_with_schema__(cls) -> "GraphQLModel":
+ definition = cast(
+ ObjectTypeDefinitionNode,
+ parse_definition(ObjectTypeDefinitionNode, cls.__schema__),
+ )
+
+ resolvers: Dict[str, Resolver] = {}
+ fields: Tuple[FieldDefinitionNode, ...] = tuple()
+ fields, resolvers = cls._create_fields_and_resolvers_with_schema(
+ definition.fields
+ )
+
+ return GraphQLObjectModel(
+ name=definition.name.value,
+ ast_type=ObjectTypeDefinitionNode,
+ ast=ObjectTypeDefinitionNode(
+ name=NameNode(value=definition.name.value),
+ fields=tuple(fields),
+ interfaces=definition.interfaces,
+ ),
+ resolvers=resolvers,
+ aliases=getattr(cls, "__aliases__", {}),
+ out_names={},
+ )
+
+ @classmethod
+ def __get_graphql_model_without_schema__(
+ cls, metadata: GraphQLMetadata, name: str
+ ) -> "GraphQLModel":
+ type_data = cls.get_graphql_object_data(metadata)
+ type_aliases = getattr(cls, "__aliases__", {})
+
+ fields_ast: List[FieldDefinitionNode] = []
+ resolvers: Dict[str, Resolver] = {}
+ aliases: Dict[str, str] = {}
+ out_names: Dict[str, Dict[str, str]] = {}
+
+ fields_ast, resolvers, aliases, out_names = cls._process_graphql_fields(
+ metadata, type_data, type_aliases
+ )
+
+ interfaces_ast: List[NamedTypeNode] = []
+ for interface_name in type_data.interfaces:
+ interfaces_ast.append(NamedTypeNode(name=NameNode(value=interface_name)))
+
+ return GraphQLObjectModel(
+ name=name,
+ ast_type=ObjectTypeDefinitionNode,
+ ast=ObjectTypeDefinitionNode(
+ name=NameNode(value=name),
+ description=get_description_node(
+ getattr(cls, "__description__", None),
+ ),
+ fields=tuple(fields_ast),
+ interfaces=tuple(interfaces_ast),
+ ),
+ resolvers=resolvers,
+ aliases=aliases,
+ out_names=out_names,
+ )
+
+ @classmethod
+ def _collect_inherited_objects(cls):
+ return [
+ inherited_obj
+ for inherited_obj in cls.__mro__[1:]
+ if getattr(inherited_obj, "__graphql_type__", None)
+ in (GraphQLClassType.INTERFACE, GraphQLClassType.OBJECT)
+ and not getattr(inherited_obj, "__abstract__", True)
+ ]
+
+ @classmethod
+ def create_graphql_object_data_without_schema(cls) -> GraphQLObjectData:
+ fields_data = GraphQLFieldData()
+ inherited_objects = list(reversed(cls._collect_inherited_objects()))
+
+ for inherited_obj in inherited_objects:
+ fields_data.type_hints.update(inherited_obj.__annotations__)
+ fields_data.aliases.update(getattr(inherited_obj, "__aliases__", {}))
+
+ cls._process_type_hints_and_aliases(fields_data)
+
+ for inherited_obj in inherited_objects:
+ cls._process_class_attributes(inherited_obj, fields_data)
+ cls._process_class_attributes(cls, fields_data)
+ return GraphQLObjectData(
+ fields=cls._build_fields(fields_data=fields_data),
+ interfaces=[
+ interface.__name__
+ for interface in inherited_objects
+ if getattr(interface, "__graphql_type__", None)
+ == GraphQLClassType.INTERFACE
+ ],
+ )
diff --git a/ariadne_graphql_modules/next/graphql_object/object_model.py b/ariadne_graphql_modules/object_type/models.py
similarity index 94%
rename from ariadne_graphql_modules/next/graphql_object/object_model.py
rename to ariadne_graphql_modules/object_type/models.py
index 7a75065..1241188 100644
--- a/ariadne_graphql_modules/next/graphql_object/object_model.py
+++ b/ariadne_graphql_modules/object_type/models.py
@@ -5,7 +5,7 @@
from ariadne.types import Resolver
from graphql import GraphQLField, GraphQLObjectType, GraphQLSchema
-from ariadne_graphql_modules.next.base import GraphQLModel
+from ..base import GraphQLModel
@dataclass(frozen=True)
diff --git a/ariadne_graphql_modules/next/roots.py b/ariadne_graphql_modules/roots.py
similarity index 100%
rename from ariadne_graphql_modules/next/roots.py
rename to ariadne_graphql_modules/roots.py
diff --git a/ariadne_graphql_modules/scalar_type/__init__.py b/ariadne_graphql_modules/scalar_type/__init__.py
new file mode 100644
index 0000000..82909c7
--- /dev/null
+++ b/ariadne_graphql_modules/scalar_type/__init__.py
@@ -0,0 +1,8 @@
+from .graphql_type import GraphQLScalar
+from .models import GraphQLScalarModel
+
+
+__all__ = [
+ "GraphQLScalar",
+ "GraphQLScalarModel",
+]
diff --git a/ariadne_graphql_modules/next/graphql_scalar/scalar_type.py b/ariadne_graphql_modules/scalar_type/graphql_type.py
similarity index 97%
rename from ariadne_graphql_modules/next/graphql_scalar/scalar_type.py
rename to ariadne_graphql_modules/scalar_type/graphql_type.py
index 75436c8..60f27f3 100644
--- a/ariadne_graphql_modules/next/graphql_scalar/scalar_type.py
+++ b/ariadne_graphql_modules/scalar_type/graphql_type.py
@@ -8,9 +8,9 @@
)
from ..description import get_description_node
-from .scalar_model import GraphQLScalarModel
+from .models import GraphQLScalarModel
-from ...utils import parse_definition
+from ..utils import parse_definition
from .validators import validate_scalar_type_with_schema
diff --git a/ariadne_graphql_modules/next/graphql_scalar/scalar_model.py b/ariadne_graphql_modules/scalar_type/models.py
similarity index 100%
rename from ariadne_graphql_modules/next/graphql_scalar/scalar_model.py
rename to ariadne_graphql_modules/scalar_type/models.py
diff --git a/ariadne_graphql_modules/next/graphql_scalar/validators.py b/ariadne_graphql_modules/scalar_type/validators.py
similarity index 89%
rename from ariadne_graphql_modules/next/graphql_scalar/validators.py
rename to ariadne_graphql_modules/scalar_type/validators.py
index 374c482..ddf6512 100644
--- a/ariadne_graphql_modules/next/graphql_scalar/validators.py
+++ b/ariadne_graphql_modules/scalar_type/validators.py
@@ -4,10 +4,10 @@
from ..validators import validate_description, validate_name
-from ...utils import parse_definition
+from ..utils import parse_definition
if TYPE_CHECKING:
- from .scalar_type import GraphQLScalar
+ from .graphql_type import GraphQLScalar
def validate_scalar_type_with_schema(cls: Type["GraphQLScalar"]):
diff --git a/ariadne_graphql_modules/next/sort.py b/ariadne_graphql_modules/sort.py
similarity index 100%
rename from ariadne_graphql_modules/next/sort.py
rename to ariadne_graphql_modules/sort.py
diff --git a/ariadne_graphql_modules/subscription_type/__init__.py b/ariadne_graphql_modules/subscription_type/__init__.py
new file mode 100644
index 0000000..c271e40
--- /dev/null
+++ b/ariadne_graphql_modules/subscription_type/__init__.py
@@ -0,0 +1,8 @@
+from .graphql_type import GraphQLSubscription
+from .models import GraphQLSubscriptionModel
+
+
+__all__ = [
+ "GraphQLSubscription",
+ "GraphQLSubscriptionModel",
+]
diff --git a/ariadne_graphql_modules/next/graphql_subscription/subscription_type.py b/ariadne_graphql_modules/subscription_type/graphql_type.py
similarity index 78%
rename from ariadne_graphql_modules/next/graphql_subscription/subscription_type.py
rename to ariadne_graphql_modules/subscription_type/graphql_type.py
index 41aef33..90fd7e7 100644
--- a/ariadne_graphql_modules/next/graphql_subscription/subscription_type.py
+++ b/ariadne_graphql_modules/subscription_type/graphql_type.py
@@ -11,12 +11,22 @@
from ariadne.types import Resolver, Subscriber
+from ..base_object_type import (
+ GraphQLFieldData,
+ GraphQLObjectData,
+ validate_object_type_with_schema,
+ validate_object_type_without_schema,
+)
+
+from ..types import GraphQLClassType
+
+from ..base_object_type import GraphQLBaseObject
-from ...utils import parse_definition
+
+from ..utils import parse_definition
from ..base import GraphQLMetadata, GraphQLModel
from ..description import get_description_node
-from ..graphql_object import (
- GraphQLObject,
+from ..object_type import (
GraphQLObjectResolver,
GraphQLObjectSource,
GraphQLObjectFieldArg,
@@ -24,17 +34,32 @@
get_field_args_from_subscriber,
get_field_args_out_names,
get_field_node_from_obj_field,
- get_graphql_object_data,
object_subscriber,
update_field_args_options,
)
from ..value import get_value_node
-from .subscription_model import GraphQLSubscriptionModel
+from .models import GraphQLSubscriptionModel
-class GraphQLSubscription(GraphQLObject):
- __abstract__: bool = True
+class GraphQLSubscription(GraphQLBaseObject):
__valid_type__ = ObjectTypeDefinitionNode
+ __graphql_type__ = GraphQLClassType.SUBSCRIPTION
+ __abstract__: bool = True
+ __description__: Optional[str] = None
+
+ def __init_subclass__(cls) -> None:
+ super().__init_subclass__()
+
+ if cls.__dict__.get("__abstract__"):
+ return
+
+ cls.__abstract__ = False
+
+ if cls.__dict__.get("__schema__"):
+ valid_type = getattr(cls, "__valid_type__", ObjectTypeDefinitionNode)
+ cls.__kwargs__ = validate_object_type_with_schema(cls, valid_type)
+ else:
+ cls.__kwargs__ = validate_object_type_without_schema(cls)
@classmethod
def __get_graphql_model_with_schema__(cls) -> "GraphQLModel":
@@ -48,7 +73,6 @@ def __get_graphql_model_with_schema__(cls) -> "GraphQLModel":
args_defaults: Dict[str, Dict[str, Any]] = {}
resolvers: Dict[str, Resolver] = {}
subscribers: Dict[str, Subscriber] = {}
- out_names: Dict[str, Dict[str, str]] = {}
for attr_name in dir(cls):
cls_attr = getattr(cls, attr_name)
@@ -148,14 +172,14 @@ def __get_graphql_model_with_schema__(cls) -> "GraphQLModel":
resolvers=resolvers,
subscribers=subscribers,
aliases=getattr(cls, "__aliases__", {}),
- out_names=out_names,
+ out_names={},
)
@classmethod
def __get_graphql_model_without_schema__(
cls, metadata: GraphQLMetadata, name: str
) -> "GraphQLModel":
- type_data = get_graphql_object_data(metadata, cls)
+ type_data = cls.get_graphql_object_data(metadata)
type_aliases = getattr(cls, "__aliases__", None) or {}
fields_ast: List[FieldDefinitionNode] = []
@@ -215,3 +239,33 @@ def source(
graphql_type=graphql_type,
description=description,
)
+
+ @classmethod
+ def _collect_inherited_objects(cls):
+ return [
+ inherited_obj
+ for inherited_obj in cls.__mro__[1:]
+ if getattr(inherited_obj, "__graphql_type__", None)
+ == GraphQLClassType.SUBSCRIPTION
+ and not getattr(inherited_obj, "__abstract__", True)
+ ]
+
+ @classmethod
+ def create_graphql_object_data_without_schema(cls) -> GraphQLObjectData:
+ fields_data = GraphQLFieldData()
+ inherited_objects = list(reversed(cls._collect_inherited_objects()))
+
+ for inherited_obj in inherited_objects:
+ fields_data.type_hints.update(inherited_obj.__annotations__)
+ fields_data.aliases.update(getattr(inherited_obj, "__aliases__", {}))
+
+ cls._process_type_hints_and_aliases(fields_data)
+
+ for inherited_obj in inherited_objects:
+ cls._process_class_attributes(inherited_obj, fields_data)
+ cls._process_class_attributes(cls, fields_data)
+
+ return GraphQLObjectData(
+ fields=cls._build_fields(fields_data=fields_data),
+ interfaces=[],
+ )
diff --git a/ariadne_graphql_modules/next/graphql_subscription/subscription_model.py b/ariadne_graphql_modules/subscription_type/models.py
similarity index 95%
rename from ariadne_graphql_modules/next/graphql_subscription/subscription_model.py
rename to ariadne_graphql_modules/subscription_type/models.py
index 95bff2d..d32aa1b 100644
--- a/ariadne_graphql_modules/next/graphql_subscription/subscription_model.py
+++ b/ariadne_graphql_modules/subscription_type/models.py
@@ -5,7 +5,7 @@
from ariadne.types import Resolver, Subscriber
from graphql import GraphQLField, GraphQLObjectType, GraphQLSchema
-from ariadne_graphql_modules.next.base import GraphQLModel
+from ..base import GraphQLModel
@dataclass(frozen=True)
diff --git a/ariadne_graphql_modules/types.py b/ariadne_graphql_modules/types.py
index 9c2173b..13f8880 100644
--- a/ariadne_graphql_modules/types.py
+++ b/ariadne_graphql_modules/types.py
@@ -1,5 +1,6 @@
from typing import Dict, Type
+from enum import Enum
from graphql import (
DefinitionNode,
FieldDefinitionNode,
@@ -9,3 +10,10 @@
FieldsDict = Dict[str, FieldDefinitionNode]
InputFieldsDict = Dict[str, InputValueDefinitionNode]
RequirementsDict = Dict[str, Type[DefinitionNode]]
+
+
+class GraphQLClassType(Enum):
+ BASE = "base"
+ OBJECT = "object"
+ INTERFACE = "interface"
+ SUBSCRIPTION = "subscription"
diff --git a/ariadne_graphql_modules/next/typing.py b/ariadne_graphql_modules/typing.py
similarity index 100%
rename from ariadne_graphql_modules/next/typing.py
rename to ariadne_graphql_modules/typing.py
diff --git a/ariadne_graphql_modules/union_type/__init__.py b/ariadne_graphql_modules/union_type/__init__.py
new file mode 100644
index 0000000..d6ebe06
--- /dev/null
+++ b/ariadne_graphql_modules/union_type/__init__.py
@@ -0,0 +1,8 @@
+from .graphql_type import GraphQLUnion
+from .models import GraphQLUnionModel
+
+
+__all__ = [
+ "GraphQLUnion",
+ "GraphQLUnionModel",
+]
diff --git a/ariadne_graphql_modules/next/graphql_union/union_type.py b/ariadne_graphql_modules/union_type/graphql_type.py
similarity index 95%
rename from ariadne_graphql_modules/next/graphql_union/union_type.py
rename to ariadne_graphql_modules/union_type/graphql_type.py
index d74c796..154c8c8 100644
--- a/ariadne_graphql_modules/next/graphql_union/union_type.py
+++ b/ariadne_graphql_modules/union_type/graphql_type.py
@@ -3,13 +3,13 @@
from graphql import NameNode, NamedTypeNode, UnionTypeDefinitionNode
from ..base import GraphQLMetadata, GraphQLModel, GraphQLType
from ..description import get_description_node
-from ..graphql_object.object_type import GraphQLObject
-from .union_model import GraphQLUnionModel
+from ..object_type.graphql_type import GraphQLObject
+from .models import GraphQLUnionModel
from .validators import (
validate_union_type,
validate_union_type_with_schema,
)
-from ...utils import parse_definition
+from ..utils import parse_definition
class GraphQLUnion(GraphQLType):
diff --git a/ariadne_graphql_modules/next/graphql_union/union_model.py b/ariadne_graphql_modules/union_type/models.py
similarity index 100%
rename from ariadne_graphql_modules/next/graphql_union/union_model.py
rename to ariadne_graphql_modules/union_type/models.py
diff --git a/ariadne_graphql_modules/next/graphql_union/validators.py b/ariadne_graphql_modules/union_type/validators.py
similarity index 96%
rename from ariadne_graphql_modules/next/graphql_union/validators.py
rename to ariadne_graphql_modules/union_type/validators.py
index 3d7f280..d22aece 100644
--- a/ariadne_graphql_modules/next/graphql_union/validators.py
+++ b/ariadne_graphql_modules/union_type/validators.py
@@ -4,10 +4,10 @@
from ..validators import validate_description, validate_name
-from ...utils import parse_definition
+from ..utils import parse_definition
if TYPE_CHECKING:
- from .union_type import GraphQLUnion
+ from .graphql_type import GraphQLUnion
def validate_union_type(cls: Type["GraphQLUnion"]) -> None:
diff --git a/ariadne_graphql_modules/v1/__init__.py b/ariadne_graphql_modules/v1/__init__.py
new file mode 100644
index 0000000..d6406a3
--- /dev/null
+++ b/ariadne_graphql_modules/v1/__init__.py
@@ -0,0 +1,38 @@
+from ariadne import gql
+
+from .bases import BaseType, BindableType, DeferredType, DefinitionType
+from .collection_type import CollectionType
+from .convert_case import convert_case
+from .directive_type import DirectiveType
+from .enum_type import EnumType
+from .executable_schema import make_executable_schema
+from .input_type import InputType
+from .interface_type import InterfaceType
+from .mutation_type import MutationType
+from .object_type import ObjectType
+from .scalar_type import ScalarType
+from .subscription_type import SubscriptionType
+from .union_type import UnionType
+from ..utils import create_alias_resolver, parse_definition
+
+__all__ = [
+ "BaseType",
+ "BindableType",
+ "CollectionType",
+ "DeferredType",
+ "DefinitionType",
+ "DirectiveType",
+ "EnumType",
+ "InputType",
+ "InterfaceType",
+ "MutationType",
+ "ObjectType",
+ "ScalarType",
+ "SubscriptionType",
+ "UnionType",
+ "convert_case",
+ "create_alias_resolver",
+ "gql",
+ "make_executable_schema",
+ "parse_definition",
+]
diff --git a/ariadne_graphql_modules/bases.py b/ariadne_graphql_modules/v1/bases.py
similarity index 98%
rename from ariadne_graphql_modules/bases.py
rename to ariadne_graphql_modules/v1/bases.py
index 2ff42e2..cfc983c 100644
--- a/ariadne_graphql_modules/bases.py
+++ b/ariadne_graphql_modules/v1/bases.py
@@ -8,7 +8,7 @@
)
from .dependencies import Dependencies
-from .types import RequirementsDict
+from ..types import RequirementsDict
__all__ = ["BaseType", "BindableType", "DeferredType", "DefinitionType"]
diff --git a/ariadne_graphql_modules/collection_type.py b/ariadne_graphql_modules/v1/collection_type.py
similarity index 100%
rename from ariadne_graphql_modules/collection_type.py
rename to ariadne_graphql_modules/v1/collection_type.py
diff --git a/ariadne_graphql_modules/convert_case.py b/ariadne_graphql_modules/v1/convert_case.py
similarity index 97%
rename from ariadne_graphql_modules/convert_case.py
rename to ariadne_graphql_modules/v1/convert_case.py
index d0c7b18..f44e878 100644
--- a/ariadne_graphql_modules/convert_case.py
+++ b/ariadne_graphql_modules/v1/convert_case.py
@@ -4,7 +4,7 @@
from ariadne import convert_camel_case_to_snake
from graphql import FieldDefinitionNode
-from .types import FieldsDict, InputFieldsDict
+from ..types import FieldsDict, InputFieldsDict
def convert_case(
diff --git a/ariadne_graphql_modules/dependencies.py b/ariadne_graphql_modules/v1/dependencies.py
similarity index 99%
rename from ariadne_graphql_modules/dependencies.py
rename to ariadne_graphql_modules/v1/dependencies.py
index f3b436d..cd04c06 100644
--- a/ariadne_graphql_modules/dependencies.py
+++ b/ariadne_graphql_modules/v1/dependencies.py
@@ -15,7 +15,7 @@
UnionTypeExtensionNode,
)
-from .utils import unwrap_type_node
+from ..utils import unwrap_type_node
GRAPHQL_TYPES = ("ID", "Int", "String", "Boolean", "Float")
diff --git a/ariadne_graphql_modules/directive_type.py b/ariadne_graphql_modules/v1/directive_type.py
similarity index 97%
rename from ariadne_graphql_modules/directive_type.py
rename to ariadne_graphql_modules/v1/directive_type.py
index d6e2706..14d9817 100644
--- a/ariadne_graphql_modules/directive_type.py
+++ b/ariadne_graphql_modules/v1/directive_type.py
@@ -7,7 +7,7 @@
)
from .bases import DefinitionType
-from .utils import parse_definition
+from ..utils import parse_definition
class DirectiveType(DefinitionType):
diff --git a/ariadne_graphql_modules/enum_type.py b/ariadne_graphql_modules/v1/enum_type.py
similarity index 98%
rename from ariadne_graphql_modules/enum_type.py
rename to ariadne_graphql_modules/v1/enum_type.py
index c555b33..66236d4 100644
--- a/ariadne_graphql_modules/enum_type.py
+++ b/ariadne_graphql_modules/v1/enum_type.py
@@ -10,8 +10,8 @@
)
from .bases import BindableType
-from .types import RequirementsDict
-from .utils import parse_definition
+from ..types import RequirementsDict
+from ..utils import parse_definition
EnumNodeType = Union[EnumTypeDefinitionNode, EnumTypeExtensionNode]
diff --git a/ariadne_graphql_modules/v1/executable_schema.py b/ariadne_graphql_modules/v1/executable_schema.py
new file mode 100644
index 0000000..1914742
--- /dev/null
+++ b/ariadne_graphql_modules/v1/executable_schema.py
@@ -0,0 +1,236 @@
+from typing import (
+ Dict,
+ List,
+ Optional,
+ Sequence,
+ Tuple,
+ Type,
+ Union,
+ cast,
+)
+
+from ariadne import (
+ SchemaBindable,
+ SchemaDirectiveVisitor,
+ repair_schema_default_enum_values,
+ validate_schema_default_enum_values,
+)
+from graphql import (
+ ConstDirectiveNode,
+ DocumentNode,
+ FieldDefinitionNode,
+ GraphQLSchema,
+ NamedTypeNode,
+ ObjectTypeDefinitionNode,
+ TypeDefinitionNode,
+ assert_valid_schema,
+ build_ast_schema,
+ concat_ast,
+ parse,
+)
+from graphql.language import ast
+
+from .bases import BaseType, BindableType, DeferredType, DefinitionType
+from .enum_type import EnumType
+
+ROOT_TYPES = ["Query", "Mutation", "Subscription"]
+
+
+def make_executable_schema(
+ *args: Union[Type[BaseType], SchemaBindable, str],
+ merge_roots: bool = True,
+ extra_directives: Optional[Dict[str, Type[SchemaDirectiveVisitor]]] = None,
+):
+ all_types = get_all_types(args)
+ extra_defs = parse_extra_sdl(args)
+ extra_bindables: List[SchemaBindable] = [
+ arg for arg in args if isinstance(arg, SchemaBindable)
+ ]
+
+ type_defs: List[Type[DefinitionType]] = []
+ for type_ in all_types:
+ if issubclass(type_, DefinitionType):
+ type_defs.append(type_)
+
+ validate_no_missing_definitions(all_types, type_defs, extra_defs)
+
+ schema = build_schema(type_defs, extra_defs, merge_roots)
+
+ if extra_bindables:
+ for bindable in extra_bindables:
+ bindable.bind_to_schema(schema)
+
+ if extra_directives:
+ SchemaDirectiveVisitor.visit_schema_directives(schema, extra_directives)
+
+ assert_valid_schema(schema)
+ validate_schema_default_enum_values(schema)
+ repair_schema_default_enum_values(schema)
+
+ add_directives_to_schema(schema, type_defs)
+
+ return schema
+
+
+def get_all_types(
+ args: Sequence[Union[Type[BaseType], SchemaBindable, str]]
+) -> List[Type[BaseType]]:
+ all_types: List[Type[BaseType]] = []
+ for arg in args:
+ if isinstance(arg, (str, SchemaBindable)):
+ continue # Skip args of unsupported types
+
+ for child_type in arg.__get_types__():
+ if child_type not in all_types:
+ all_types.append(child_type)
+ return all_types
+
+
+def parse_extra_sdl(
+ args: Sequence[Union[Type[BaseType], SchemaBindable, str]]
+) -> List[TypeDefinitionNode]:
+ sdl_strings: List[str] = [cast(str, arg) for arg in args if isinstance(arg, str)]
+ if not sdl_strings:
+ return []
+
+ extra_sdl = "\n\n".join(sdl_strings)
+ return cast(
+ List[TypeDefinitionNode],
+ list(parse(extra_sdl).definitions),
+ )
+
+
+def validate_no_missing_definitions(
+ all_types: List[Type[BaseType]],
+ type_defs: List[Type[DefinitionType]],
+ extra_defs: List[TypeDefinitionNode],
+):
+ deferred_names: List[str] = []
+ for type_ in all_types:
+ if isinstance(type_, DeferredType):
+ deferred_names.append(type_.graphql_name)
+
+ real_names = [type_.graphql_name for type_ in type_defs]
+ real_names += [definition.name.value for definition in extra_defs]
+
+ missing_names = set(deferred_names) - set(real_names)
+ if missing_names:
+ raise ValueError(
+ "Following types are defined as deferred and are missing "
+ f"from schema: {', '.join(missing_names)}"
+ )
+
+
+def build_schema(
+ type_defs: List[Type[DefinitionType]],
+ extra_defs: List[TypeDefinitionNode],
+ merge_roots: bool = True,
+) -> GraphQLSchema:
+ schema_definitions: List[ast.DocumentNode] = []
+ if merge_roots:
+ schema_definitions.append(build_root_schema(type_defs, extra_defs))
+ for type_ in type_defs:
+ if type_.graphql_name not in ROOT_TYPES or not merge_roots:
+ schema_definitions.append(parse(type_.__schema__))
+ for extra_type_def in extra_defs:
+ if extra_type_def.name.value not in ROOT_TYPES or not merge_roots:
+ schema_definitions.append(DocumentNode(definitions=(extra_type_def,)))
+
+ ast_document = concat_ast(schema_definitions)
+ schema = build_ast_schema(ast_document)
+
+ for type_ in type_defs:
+ if issubclass(type_, BindableType):
+ type_.__bind_to_schema__(schema)
+
+ return schema
+
+
+RootTypeDef = Tuple[str, DocumentNode]
+
+
+def build_root_schema(
+ type_defs: List[Type[DefinitionType]],
+ extra_defs: List[TypeDefinitionNode],
+) -> DocumentNode:
+ root_types: Dict[str, List[RootTypeDef]] = {
+ "Query": [],
+ "Mutation": [],
+ "Subscription": [],
+ }
+
+ for type_def in type_defs:
+ if type_def.graphql_name in root_types:
+ root_types[type_def.graphql_name].append(
+ (type_def.__name__, parse(type_def.__schema__))
+ )
+
+ for extra_type_def in extra_defs:
+ if extra_type_def.name.value in root_types:
+ root_types[extra_type_def.name.value].append(
+ ("extra_sdl", DocumentNode(definitions=(extra_type_def,)))
+ )
+
+ schema: List[DocumentNode] = []
+ for root_name, root_type_defs in root_types.items():
+ if len(root_type_defs) == 1:
+ schema.append(root_type_defs[0][1])
+ elif root_type_defs:
+ schema.append(merge_root_types(root_name, root_type_defs))
+
+ return concat_ast(schema)
+
+
+def merge_root_types(root_name: str, type_defs: List[RootTypeDef]) -> DocumentNode:
+ interfaces: List[NamedTypeNode] = []
+ directives: List[ConstDirectiveNode] = []
+ fields: Dict[str, Tuple[str, FieldDefinitionNode]] = {}
+
+ for type_source, type_def in type_defs:
+ type_definition = cast(ObjectTypeDefinitionNode, type_def.definitions[0])
+ interfaces.extend(type_definition.interfaces)
+ directives.extend(type_definition.directives)
+
+ for field_def in type_definition.fields:
+ field_name = field_def.name.value
+ if field_name in fields:
+ other_type_source = fields[field_name][0]
+ raise ValueError(
+ f"Multiple {root_name} types are defining same field "
+ f"'{field_name}': {other_type_source}, {type_source}"
+ )
+
+ fields[field_name] = (type_source, field_def)
+
+ merged_definition = ast.ObjectTypeDefinitionNode()
+ merged_definition.name = ast.NameNode()
+ merged_definition.name.value = root_name
+ merged_definition.interfaces = tuple(interfaces)
+ merged_definition.directives = tuple(directives)
+ merged_definition.fields = tuple(
+ fields[field_name][1] for field_name in sorted(fields)
+ )
+
+ merged_document = DocumentNode()
+ merged_document.definitions = (merged_definition,)
+
+ return merged_document
+
+
+def add_directives_to_schema(
+ schema: GraphQLSchema, type_defs: List[Type[DefinitionType]]
+):
+ directives: Dict[str, Type[SchemaDirectiveVisitor]] = {}
+ for type_def in type_defs:
+ visitor = getattr(type_def, "__visitor__", None)
+ if visitor and issubclass(visitor, SchemaDirectiveVisitor):
+ directives[type_def.graphql_name] = visitor
+
+ if directives:
+ SchemaDirectiveVisitor.visit_schema_directives(schema, directives)
+
+
+def repair_default_enum_values(schema, types_list: List[Type[DefinitionType]]) -> None:
+ for type_ in types_list:
+ if issubclass(type_, EnumType):
+ type_.__bind_to_default_values__(schema)
diff --git a/ariadne_graphql_modules/input_type.py b/ariadne_graphql_modules/v1/input_type.py
similarity index 97%
rename from ariadne_graphql_modules/input_type.py
rename to ariadne_graphql_modules/v1/input_type.py
index 32295db..fa2eedb 100644
--- a/ariadne_graphql_modules/input_type.py
+++ b/ariadne_graphql_modules/v1/input_type.py
@@ -8,8 +8,8 @@
from .bases import BindableType
from .dependencies import Dependencies, get_dependencies_from_input_type
-from .types import InputFieldsDict, RequirementsDict
-from .utils import parse_definition
+from ..types import InputFieldsDict, RequirementsDict
+from ..utils import parse_definition
Args = Dict[str, str]
InputNodeType = Union[InputObjectTypeDefinitionNode, InputObjectTypeExtensionNode]
diff --git a/ariadne_graphql_modules/interface_type.py b/ariadne_graphql_modules/v1/interface_type.py
similarity index 98%
rename from ariadne_graphql_modules/interface_type.py
rename to ariadne_graphql_modules/v1/interface_type.py
index ac34188..c51f28f 100644
--- a/ariadne_graphql_modules/interface_type.py
+++ b/ariadne_graphql_modules/v1/interface_type.py
@@ -16,8 +16,8 @@
from .bases import BindableType
from .dependencies import Dependencies, get_dependencies_from_object_type
from .resolvers_mixin import ResolversMixin
-from .types import FieldsDict, RequirementsDict
-from .utils import parse_definition
+from ..types import FieldsDict, RequirementsDict
+from ..utils import parse_definition
InterfaceNodeType = Union[InterfaceTypeDefinitionNode, InterfaceTypeExtensionNode]
diff --git a/ariadne_graphql_modules/mutation_type.py b/ariadne_graphql_modules/v1/mutation_type.py
similarity index 98%
rename from ariadne_graphql_modules/mutation_type.py
rename to ariadne_graphql_modules/v1/mutation_type.py
index d8e020d..f579d3f 100644
--- a/ariadne_graphql_modules/mutation_type.py
+++ b/ariadne_graphql_modules/v1/mutation_type.py
@@ -10,8 +10,8 @@
from .bases import BindableType
from .dependencies import Dependencies, get_dependencies_from_object_type
-from .types import RequirementsDict
-from .utils import parse_definition
+from ..types import RequirementsDict
+from ..utils import parse_definition
MutationArgs = Dict[str, str]
ObjectNodeType = Union[ObjectTypeDefinitionNode, ObjectTypeExtensionNode]
diff --git a/ariadne_graphql_modules/object_type.py b/ariadne_graphql_modules/v1/object_type.py
similarity index 98%
rename from ariadne_graphql_modules/object_type.py
rename to ariadne_graphql_modules/v1/object_type.py
index bb54b4a..e5183a6 100644
--- a/ariadne_graphql_modules/object_type.py
+++ b/ariadne_graphql_modules/v1/object_type.py
@@ -10,8 +10,8 @@
from .bases import BindableType
from .dependencies import Dependencies, get_dependencies_from_object_type
from .resolvers_mixin import ResolversMixin
-from .types import FieldsDict, RequirementsDict
-from .utils import parse_definition
+from ..types import FieldsDict, RequirementsDict
+from ..utils import parse_definition
ObjectNodeType = Union[ObjectTypeDefinitionNode, ObjectTypeExtensionNode]
diff --git a/ariadne_graphql_modules/resolvers_mixin.py b/ariadne_graphql_modules/v1/resolvers_mixin.py
similarity index 97%
rename from ariadne_graphql_modules/resolvers_mixin.py
rename to ariadne_graphql_modules/v1/resolvers_mixin.py
index 9d641dc..ec24112 100644
--- a/ariadne_graphql_modules/resolvers_mixin.py
+++ b/ariadne_graphql_modules/v1/resolvers_mixin.py
@@ -2,8 +2,8 @@
from graphql import GraphQLFieldResolver, NamedTypeNode
-from .types import FieldsDict
-from .utils import create_alias_resolver
+from ..types import FieldsDict
+from ..utils import create_alias_resolver
Aliases = Dict[str, str]
FieldsArgs = Dict[str, Dict[str, str]]
diff --git a/ariadne_graphql_modules/scalar_type.py b/ariadne_graphql_modules/v1/scalar_type.py
similarity index 97%
rename from ariadne_graphql_modules/scalar_type.py
rename to ariadne_graphql_modules/v1/scalar_type.py
index a86388b..3da456d 100644
--- a/ariadne_graphql_modules/scalar_type.py
+++ b/ariadne_graphql_modules/v1/scalar_type.py
@@ -12,8 +12,8 @@
)
from .bases import BindableType
-from .types import RequirementsDict
-from .utils import parse_definition
+from ..types import RequirementsDict
+from ..utils import parse_definition
ScalarNodeType = Union[ScalarTypeDefinitionNode, ScalarTypeExtensionNode]
diff --git a/ariadne_graphql_modules/subscription_type.py b/ariadne_graphql_modules/v1/subscription_type.py
similarity index 100%
rename from ariadne_graphql_modules/subscription_type.py
rename to ariadne_graphql_modules/v1/subscription_type.py
diff --git a/ariadne_graphql_modules/union_type.py b/ariadne_graphql_modules/v1/union_type.py
similarity index 97%
rename from ariadne_graphql_modules/union_type.py
rename to ariadne_graphql_modules/v1/union_type.py
index 932ba4f..94b8575 100644
--- a/ariadne_graphql_modules/union_type.py
+++ b/ariadne_graphql_modules/v1/union_type.py
@@ -11,8 +11,8 @@
from .bases import BindableType
from .dependencies import Dependencies, get_dependencies_from_union_type
-from .types import RequirementsDict
-from .utils import parse_definition
+from ..types import RequirementsDict
+from ..utils import parse_definition
UnionNodeType = Union[UnionTypeDefinitionNode, UnionTypeExtensionNode]
diff --git a/ariadne_graphql_modules/next/validators.py b/ariadne_graphql_modules/validators.py
similarity index 100%
rename from ariadne_graphql_modules/next/validators.py
rename to ariadne_graphql_modules/validators.py
diff --git a/ariadne_graphql_modules/next/value.py b/ariadne_graphql_modules/value.py
similarity index 100%
rename from ariadne_graphql_modules/next/value.py
rename to ariadne_graphql_modules/value.py
diff --git a/pyproject.toml b/pyproject.toml
index bb2236b..efdba0c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -47,7 +47,7 @@ include = [
"ariadne_graphql_modules/**/*.py",
"ariadne_graphql_modules/py.typed",
]
-exclude = ["tests"]
+exclude = ["tests", "tests_v1"]
[tool.hatch.envs.default]
features = ["test"]
@@ -74,5 +74,5 @@ exclude = '''
'''
[tool.pytest.ini_options]
-testpaths = ["tests_next"]
+testpaths = ["tests"]
asyncio_mode = "strict"
diff --git a/tests/conftest.py b/tests/conftest.py
index 0f16709..c66282b 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,5 +1,33 @@
from pathlib import Path
+from textwrap import dedent
+
import pytest
+from graphql import TypeDefinitionNode, GraphQLSchema, print_ast, print_schema
+
+from ariadne_graphql_modules import GraphQLMetadata
+
+
+@pytest.fixture
+def assert_schema_equals():
+ def schema_equals_assertion(schema: GraphQLSchema, target: str):
+ schema_str = print_schema(schema)
+ assert schema_str == dedent(target).strip()
+
+ return schema_equals_assertion
+
+
+@pytest.fixture
+def assert_ast_equals():
+ def ast_equals_assertion(ast: TypeDefinitionNode, target: str):
+ ast_str = print_ast(ast)
+ assert ast_str == dedent(target).strip()
+
+ return ast_equals_assertion
+
+
+@pytest.fixture
+def metadata():
+ return GraphQLMetadata()
@pytest.fixture(scope="session")
diff --git a/tests_next/snapshots/test_arg_with_description_in_source_with_schema.obtained.yml b/tests/snapshots/test_arg_with_description_in_source_with_schema.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_arg_with_description_in_source_with_schema.obtained.yml
rename to tests/snapshots/test_arg_with_description_in_source_with_schema.obtained.yml
diff --git a/tests_next/snapshots/test_arg_with_description_in_source_with_schema.yml b/tests/snapshots/test_arg_with_description_in_source_with_schema.yml
similarity index 100%
rename from tests_next/snapshots/test_arg_with_description_in_source_with_schema.yml
rename to tests/snapshots/test_arg_with_description_in_source_with_schema.yml
diff --git a/tests_next/snapshots/test_arg_with_name_in_source_with_schema.obtained.yml b/tests/snapshots/test_arg_with_name_in_source_with_schema.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_arg_with_name_in_source_with_schema.obtained.yml
rename to tests/snapshots/test_arg_with_name_in_source_with_schema.obtained.yml
diff --git a/tests_next/snapshots/test_arg_with_name_in_source_with_schema.yml b/tests/snapshots/test_arg_with_name_in_source_with_schema.yml
similarity index 100%
rename from tests_next/snapshots/test_arg_with_name_in_source_with_schema.yml
rename to tests/snapshots/test_arg_with_name_in_source_with_schema.yml
diff --git a/tests_next/snapshots/test_arg_with_type_in_source_with_schema.obtained.yml b/tests/snapshots/test_arg_with_type_in_source_with_schema.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_arg_with_type_in_source_with_schema.obtained.yml
rename to tests/snapshots/test_arg_with_type_in_source_with_schema.obtained.yml
diff --git a/tests_next/snapshots/test_arg_with_type_in_source_with_schema.yml b/tests/snapshots/test_arg_with_type_in_source_with_schema.yml
similarity index 100%
rename from tests_next/snapshots/test_arg_with_type_in_source_with_schema.yml
rename to tests/snapshots/test_arg_with_type_in_source_with_schema.yml
diff --git a/tests_next/snapshots/test_deferred_raises_error_for_invalid_relative_path.obtained.yml b/tests/snapshots/test_deferred_raises_error_for_invalid_relative_path.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_deferred_raises_error_for_invalid_relative_path.obtained.yml
rename to tests/snapshots/test_deferred_raises_error_for_invalid_relative_path.obtained.yml
diff --git a/tests_next/snapshots/test_deferred_raises_error_for_invalid_relative_path.yml b/tests/snapshots/test_deferred_raises_error_for_invalid_relative_path.yml
similarity index 100%
rename from tests_next/snapshots/test_deferred_raises_error_for_invalid_relative_path.yml
rename to tests/snapshots/test_deferred_raises_error_for_invalid_relative_path.yml
diff --git a/tests_next/snapshots/test_description_not_str_without_schema.obtained.yml b/tests/snapshots/test_description_not_str_without_schema.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_description_not_str_without_schema.obtained.yml
rename to tests/snapshots/test_description_not_str_without_schema.obtained.yml
diff --git a/tests_next/snapshots/test_description_not_str_without_schema.yml b/tests/snapshots/test_description_not_str_without_schema.yml
similarity index 100%
rename from tests_next/snapshots/test_description_not_str_without_schema.yml
rename to tests/snapshots/test_description_not_str_without_schema.yml
diff --git a/tests_next/snapshots/test_description_validator_raises_error_for_type_with_two_descriptions.obtained.yml b/tests/snapshots/test_description_validator_raises_error_for_type_with_two_descriptions.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_description_validator_raises_error_for_type_with_two_descriptions.obtained.yml
rename to tests/snapshots/test_description_validator_raises_error_for_type_with_two_descriptions.obtained.yml
diff --git a/tests_next/snapshots/test_description_validator_raises_error_for_type_with_two_descriptions.yml b/tests/snapshots/test_description_validator_raises_error_for_type_with_two_descriptions.yml
similarity index 100%
rename from tests_next/snapshots/test_description_validator_raises_error_for_type_with_two_descriptions.yml
rename to tests/snapshots/test_description_validator_raises_error_for_type_with_two_descriptions.yml
diff --git a/tests_next/snapshots/test_enum_type_validation_fails_for_invalid_members.obtained.yml b/tests/snapshots/test_enum_type_validation_fails_for_invalid_members.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_enum_type_validation_fails_for_invalid_members.obtained.yml
rename to tests/snapshots/test_enum_type_validation_fails_for_invalid_members.obtained.yml
diff --git a/tests_next/snapshots/test_enum_type_validation_fails_for_invalid_members.yml b/tests/snapshots/test_enum_type_validation_fails_for_invalid_members.yml
similarity index 100%
rename from tests_next/snapshots/test_enum_type_validation_fails_for_invalid_members.yml
rename to tests/snapshots/test_enum_type_validation_fails_for_invalid_members.yml
diff --git a/tests_next/snapshots/test_enum_type_validation_fails_for_missing_members.obtained.yml b/tests/snapshots/test_enum_type_validation_fails_for_missing_members.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_enum_type_validation_fails_for_missing_members.obtained.yml
rename to tests/snapshots/test_enum_type_validation_fails_for_missing_members.obtained.yml
diff --git a/tests_next/snapshots/test_enum_type_validation_fails_for_missing_members.yml b/tests/snapshots/test_enum_type_validation_fails_for_missing_members.yml
similarity index 100%
rename from tests_next/snapshots/test_enum_type_validation_fails_for_missing_members.yml
rename to tests/snapshots/test_enum_type_validation_fails_for_missing_members.yml
diff --git a/tests_next/snapshots/test_field_name_not_str_without_schema.obtained.yml b/tests/snapshots/test_field_name_not_str_without_schema.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_field_name_not_str_without_schema.obtained.yml
rename to tests/snapshots/test_field_name_not_str_without_schema.obtained.yml
diff --git a/tests_next/snapshots/test_field_name_not_str_without_schema.yml b/tests/snapshots/test_field_name_not_str_without_schema.yml
similarity index 100%
rename from tests_next/snapshots/test_field_name_not_str_without_schema.yml
rename to tests/snapshots/test_field_name_not_str_without_schema.yml
diff --git a/tests_next/snapshots/test_input_type_instance_with_invalid_attrs_raising_error.obtained.yml b/tests/snapshots/test_input_type_instance_with_invalid_attrs_raising_error.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_input_type_instance_with_invalid_attrs_raising_error.obtained.yml
rename to tests/snapshots/test_input_type_instance_with_invalid_attrs_raising_error.obtained.yml
diff --git a/tests_next/snapshots/test_input_type_instance_with_invalid_attrs_raising_error.yml b/tests/snapshots/test_input_type_instance_with_invalid_attrs_raising_error.yml
similarity index 100%
rename from tests_next/snapshots/test_input_type_instance_with_invalid_attrs_raising_error.yml
rename to tests/snapshots/test_input_type_instance_with_invalid_attrs_raising_error.yml
diff --git a/tests_next/snapshots/test_input_type_validation_fails_for_out_names_without_schema.obtained.yml b/tests/snapshots/test_input_type_validation_fails_for_out_names_without_schema.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_input_type_validation_fails_for_out_names_without_schema.obtained.yml
rename to tests/snapshots/test_input_type_validation_fails_for_out_names_without_schema.obtained.yml
diff --git a/tests_next/snapshots/test_input_type_validation_fails_for_out_names_without_schema.yml b/tests/snapshots/test_input_type_validation_fails_for_out_names_without_schema.yml
similarity index 100%
rename from tests_next/snapshots/test_input_type_validation_fails_for_out_names_without_schema.yml
rename to tests/snapshots/test_input_type_validation_fails_for_out_names_without_schema.yml
diff --git a/tests_next/snapshots/test_input_type_validation_fails_for_unsupported_attr_default.obtained.yml b/tests/snapshots/test_input_type_validation_fails_for_unsupported_attr_default.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_input_type_validation_fails_for_unsupported_attr_default.obtained.yml
rename to tests/snapshots/test_input_type_validation_fails_for_unsupported_attr_default.obtained.yml
diff --git a/tests_next/snapshots/test_input_type_validation_fails_for_unsupported_attr_default.yml b/tests/snapshots/test_input_type_validation_fails_for_unsupported_attr_default.yml
similarity index 100%
rename from tests_next/snapshots/test_input_type_validation_fails_for_unsupported_attr_default.yml
rename to tests/snapshots/test_input_type_validation_fails_for_unsupported_attr_default.yml
diff --git a/tests_next/snapshots/test_input_type_validation_fails_for_unsupported_field_default_option.obtained.yml b/tests/snapshots/test_input_type_validation_fails_for_unsupported_field_default_option.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_input_type_validation_fails_for_unsupported_field_default_option.obtained.yml
rename to tests/snapshots/test_input_type_validation_fails_for_unsupported_field_default_option.obtained.yml
diff --git a/tests_next/snapshots/test_input_type_validation_fails_for_unsupported_field_default_option.yml b/tests/snapshots/test_input_type_validation_fails_for_unsupported_field_default_option.yml
similarity index 100%
rename from tests_next/snapshots/test_input_type_validation_fails_for_unsupported_field_default_option.yml
rename to tests/snapshots/test_input_type_validation_fails_for_unsupported_field_default_option.yml
diff --git a/tests/snapshots/test_interface_no_interface_in_schema.obtained.diff.html b/tests/snapshots/test_interface_no_interface_in_schema.obtained.diff.html
new file mode 100644
index 0000000..c6a19d9
--- /dev/null
+++ b/tests/snapshots/test_interface_no_interface_in_schema.obtained.diff.html
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
|
+
+ t | Unknown type 'BaseInterface'. | t | Query root type must be provided. |
+ | ... | | ... |
+
+
+
+ Legends |
+
+ Colors |
+ Added |
+ Changed |
+ Deleted |
+ |
+
+ Links |
+ (f)irst change |
+ (n)ext change |
+ (t)op |
+ |
+
+
+
+
\ No newline at end of file
diff --git a/tests_next/snapshots/test_interface_no_interface_in_schema.obtained.yml b/tests/snapshots/test_interface_no_interface_in_schema.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_interface_no_interface_in_schema.obtained.yml
rename to tests/snapshots/test_interface_no_interface_in_schema.obtained.yml
diff --git a/tests_next/snapshots/test_interface_no_interface_in_schema.yml b/tests/snapshots/test_interface_no_interface_in_schema.yml
similarity index 100%
rename from tests_next/snapshots/test_interface_no_interface_in_schema.yml
rename to tests/snapshots/test_interface_no_interface_in_schema.yml
diff --git a/tests/snapshots/test_interface_with_different_types.obtained.diff.html b/tests/snapshots/test_interface_with_different_types.obtained.diff.html
new file mode 100644
index 0000000..ef57772
--- /dev/null
+++ b/tests/snapshots/test_interface_with_different_types.obtained.diff.html
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
|
+
+ t | 'Query root type must be provided. | t | Query root type must be provided. |
+ | | | ... |
+ | | | |
+ | Interface field UserInterface.score expects type String! but User.score is type | | |
+ | Int!.' | | |
+
+
+
+ Legends |
+
+ Colors |
+ Added |
+ Changed |
+ Deleted |
+ |
+
+ Links |
+ (f)irst change |
+ (n)ext change |
+ (t)op |
+ |
+
+
+
+
\ No newline at end of file
diff --git a/tests/snapshots/test_interface_with_different_types.obtained.yml b/tests/snapshots/test_interface_with_different_types.obtained.yml
new file mode 100644
index 0000000..322fe60
--- /dev/null
+++ b/tests/snapshots/test_interface_with_different_types.obtained.yml
@@ -0,0 +1,2 @@
+Query root type must be provided.
+...
diff --git a/tests_next/snapshots/test_interface_with_different_types.yml b/tests/snapshots/test_interface_with_different_types.yml
similarity index 100%
rename from tests_next/snapshots/test_interface_with_different_types.yml
rename to tests/snapshots/test_interface_with_different_types.yml
diff --git a/tests_next/snapshots/test_invalid_arg_name_in_source_with_schema.obtained.yml b/tests/snapshots/test_invalid_arg_name_in_source_with_schema.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_invalid_arg_name_in_source_with_schema.obtained.yml
rename to tests/snapshots/test_invalid_arg_name_in_source_with_schema.obtained.yml
diff --git a/tests_next/snapshots/test_invalid_arg_name_in_source_with_schema.yml b/tests/snapshots/test_invalid_arg_name_in_source_with_schema.yml
similarity index 100%
rename from tests_next/snapshots/test_invalid_arg_name_in_source_with_schema.yml
rename to tests/snapshots/test_invalid_arg_name_in_source_with_schema.yml
diff --git a/tests_next/snapshots/test_make_executable_schema_raises_error_if_called_without_any_types.obtained.yml b/tests/snapshots/test_make_executable_schema_raises_error_if_called_without_any_types.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_make_executable_schema_raises_error_if_called_without_any_types.obtained.yml
rename to tests/snapshots/test_make_executable_schema_raises_error_if_called_without_any_types.obtained.yml
diff --git a/tests_next/snapshots/test_make_executable_schema_raises_error_if_called_without_any_types.yml b/tests/snapshots/test_make_executable_schema_raises_error_if_called_without_any_types.yml
similarity index 100%
rename from tests_next/snapshots/test_make_executable_schema_raises_error_if_called_without_any_types.yml
rename to tests/snapshots/test_make_executable_schema_raises_error_if_called_without_any_types.yml
diff --git a/tests/snapshots/test_metadata_raises_key_error_for_unset_data.obtained.diff.html b/tests/snapshots/test_metadata_raises_key_error_for_unset_data.obtained.diff.html
new file mode 100644
index 0000000..4929bd2
--- /dev/null
+++ b/tests/snapshots/test_metadata_raises_key_error_for_unset_data.obtained.diff.html
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
|
+
+ t | '"No data is set for ''<class ''tests_next.test_metadata.QueryType''>''."' | t | '"No data is set for ''<class ''tests.test_metadata.QueryType''>''."' |
+
+
+
+ Legends |
+
+ Colors |
+ Added |
+ Changed |
+ Deleted |
+ |
+
+ Links |
+ (f)irst change |
+ (n)ext change |
+ (t)op |
+ |
+
+
+
+
\ No newline at end of file
diff --git a/tests/snapshots/test_metadata_raises_key_error_for_unset_data.obtained.yml b/tests/snapshots/test_metadata_raises_key_error_for_unset_data.obtained.yml
new file mode 100644
index 0000000..ef7ccb8
--- /dev/null
+++ b/tests/snapshots/test_metadata_raises_key_error_for_unset_data.obtained.yml
@@ -0,0 +1 @@
+'"No data is set for ''''."'
diff --git a/tests/snapshots/test_metadata_raises_key_error_for_unset_data.yml b/tests/snapshots/test_metadata_raises_key_error_for_unset_data.yml
new file mode 100644
index 0000000..ef7ccb8
--- /dev/null
+++ b/tests/snapshots/test_metadata_raises_key_error_for_unset_data.yml
@@ -0,0 +1 @@
+'"No data is set for ''''."'
diff --git a/tests_next/snapshots/test_missing_type_in_schema.obtained.yml b/tests/snapshots/test_missing_type_in_schema.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_missing_type_in_schema.obtained.yml
rename to tests/snapshots/test_missing_type_in_schema.obtained.yml
diff --git a/tests_next/snapshots/test_missing_type_in_schema.yml b/tests/snapshots/test_missing_type_in_schema.yml
similarity index 100%
rename from tests_next/snapshots/test_missing_type_in_schema.yml
rename to tests/snapshots/test_missing_type_in_schema.yml
diff --git a/tests_next/snapshots/test_missing_type_in_types.obtained.yml b/tests/snapshots/test_missing_type_in_types.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_missing_type_in_types.obtained.yml
rename to tests/snapshots/test_missing_type_in_types.obtained.yml
diff --git a/tests_next/snapshots/test_missing_type_in_types.yml b/tests/snapshots/test_missing_type_in_types.yml
similarity index 100%
rename from tests_next/snapshots/test_missing_type_in_types.yml
rename to tests/snapshots/test_missing_type_in_types.yml
diff --git a/tests_next/snapshots/test_multiple_descriptions_for_source_with_schema.obtained.yml b/tests/snapshots/test_multiple_descriptions_for_source_with_schema.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_multiple_descriptions_for_source_with_schema.obtained.yml
rename to tests/snapshots/test_multiple_descriptions_for_source_with_schema.obtained.yml
diff --git a/tests_next/snapshots/test_multiple_descriptions_for_source_with_schema.yml b/tests/snapshots/test_multiple_descriptions_for_source_with_schema.yml
similarity index 100%
rename from tests_next/snapshots/test_multiple_descriptions_for_source_with_schema.yml
rename to tests/snapshots/test_multiple_descriptions_for_source_with_schema.yml
diff --git a/tests/snapshots/test_multiple_roots_fail_validation_if_merge_roots_is_disabled.obtained.diff.html b/tests/snapshots/test_multiple_roots_fail_validation_if_merge_roots_is_disabled.obtained.diff.html
new file mode 100644
index 0000000..1ffb12e
--- /dev/null
+++ b/tests/snapshots/test_multiple_roots_fail_validation_if_merge_roots_is_disabled.obtained.diff.html
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
|
+
+ t | Types 'SecondRoot' and '<class 'tests_next.test_make_executable_schema.test_multiple_roots_fail_validation_if_merge_roots_is_disabled.<locals>.FirstRoot'>' | t | Types 'SecondRoot' and '<class 'tests.test_make_executable_schema.test_multiple_roots_fail_validation_if_merge_roots_is_disabled.<locals>.FirstRoot'>' |
+ | both define GraphQL type with name 'Query'. | | both define GraphQL type with name 'Query'. |
+ | ... | | ... |
+
+
+
+ Legends |
+
+ Colors |
+ Added |
+ Changed |
+ Deleted |
+ |
+
+ Links |
+ (f)irst change |
+ (n)ext change |
+ (t)op |
+ |
+
+
+
+
\ No newline at end of file
diff --git a/tests/snapshots/test_multiple_roots_fail_validation_if_merge_roots_is_disabled.obtained.yml b/tests/snapshots/test_multiple_roots_fail_validation_if_merge_roots_is_disabled.obtained.yml
new file mode 100644
index 0000000..c22028c
--- /dev/null
+++ b/tests/snapshots/test_multiple_roots_fail_validation_if_merge_roots_is_disabled.obtained.yml
@@ -0,0 +1,3 @@
+Types 'SecondRoot' and '.FirstRoot'>'
+ both define GraphQL type with name 'Query'.
+...
diff --git a/tests/snapshots/test_multiple_roots_fail_validation_if_merge_roots_is_disabled.yml b/tests/snapshots/test_multiple_roots_fail_validation_if_merge_roots_is_disabled.yml
new file mode 100644
index 0000000..c22028c
--- /dev/null
+++ b/tests/snapshots/test_multiple_roots_fail_validation_if_merge_roots_is_disabled.yml
@@ -0,0 +1,3 @@
+Types 'SecondRoot' and '.FirstRoot'>'
+ both define GraphQL type with name 'Query'.
+...
diff --git a/tests_next/snapshots/test_multiple_sourced_for_field_with_schema.obtained.yml b/tests/snapshots/test_multiple_sourced_for_field_with_schema.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_multiple_sourced_for_field_with_schema.obtained.yml
rename to tests/snapshots/test_multiple_sourced_for_field_with_schema.obtained.yml
diff --git a/tests_next/snapshots/test_multiple_sourced_for_field_with_schema.yml b/tests/snapshots/test_multiple_sourced_for_field_with_schema.yml
similarity index 100%
rename from tests_next/snapshots/test_multiple_sourced_for_field_with_schema.yml
rename to tests/snapshots/test_multiple_sourced_for_field_with_schema.yml
diff --git a/tests_next/snapshots/test_multiple_sources_without_schema.obtained.yml b/tests/snapshots/test_multiple_sources_without_schema.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_multiple_sources_without_schema.obtained.yml
rename to tests/snapshots/test_multiple_sources_without_schema.obtained.yml
diff --git a/tests_next/snapshots/test_multiple_sources_without_schema.yml b/tests/snapshots/test_multiple_sources_without_schema.yml
similarity index 100%
rename from tests_next/snapshots/test_multiple_sources_without_schema.yml
rename to tests/snapshots/test_multiple_sources_without_schema.yml
diff --git a/tests_next/snapshots/test_name_validator_raises_error_for_name_and_definition_mismatch.obtained.yml b/tests/snapshots/test_name_validator_raises_error_for_name_and_definition_mismatch.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_name_validator_raises_error_for_name_and_definition_mismatch.obtained.yml
rename to tests/snapshots/test_name_validator_raises_error_for_name_and_definition_mismatch.obtained.yml
diff --git a/tests_next/snapshots/test_name_validator_raises_error_for_name_and_definition_mismatch.yml b/tests/snapshots/test_name_validator_raises_error_for_name_and_definition_mismatch.yml
similarity index 100%
rename from tests_next/snapshots/test_name_validator_raises_error_for_name_and_definition_mismatch.yml
rename to tests/snapshots/test_name_validator_raises_error_for_name_and_definition_mismatch.yml
diff --git a/tests_next/snapshots/test_object_type_instance_with_invalid_attrs_raising_error.obtained.yml b/tests/snapshots/test_object_type_instance_with_invalid_attrs_raising_error.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_instance_with_invalid_attrs_raising_error.obtained.yml
rename to tests/snapshots/test_object_type_instance_with_invalid_attrs_raising_error.obtained.yml
diff --git a/tests_next/snapshots/test_object_type_instance_with_invalid_attrs_raising_error.yml b/tests/snapshots/test_object_type_instance_with_invalid_attrs_raising_error.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_instance_with_invalid_attrs_raising_error.yml
rename to tests/snapshots/test_object_type_instance_with_invalid_attrs_raising_error.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_alias_resolver.obtained.yml b/tests/snapshots/test_object_type_validation_fails_for_alias_resolver.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_alias_resolver.obtained.yml
rename to tests/snapshots/test_object_type_validation_fails_for_alias_resolver.obtained.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_alias_resolver.yml b/tests/snapshots/test_object_type_validation_fails_for_alias_resolver.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_alias_resolver.yml
rename to tests/snapshots/test_object_type_validation_fails_for_alias_resolver.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_alias_target_resolver.obtained.yml b/tests/snapshots/test_object_type_validation_fails_for_alias_target_resolver.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_alias_target_resolver.obtained.yml
rename to tests/snapshots/test_object_type_validation_fails_for_alias_target_resolver.obtained.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_alias_target_resolver.yml b/tests/snapshots/test_object_type_validation_fails_for_alias_target_resolver.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_alias_target_resolver.yml
rename to tests/snapshots/test_object_type_validation_fails_for_alias_target_resolver.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_attr_and_field_with_same_graphql_name.obtained.yml b/tests/snapshots/test_object_type_validation_fails_for_attr_and_field_with_same_graphql_name.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_attr_and_field_with_same_graphql_name.obtained.yml
rename to tests/snapshots/test_object_type_validation_fails_for_attr_and_field_with_same_graphql_name.obtained.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_attr_and_field_with_same_graphql_name.yml b/tests/snapshots/test_object_type_validation_fails_for_attr_and_field_with_same_graphql_name.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_attr_and_field_with_same_graphql_name.yml
rename to tests/snapshots/test_object_type_validation_fails_for_attr_and_field_with_same_graphql_name.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_field_with_multiple_args.obtained.yml b/tests/snapshots/test_object_type_validation_fails_for_field_with_multiple_args.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_field_with_multiple_args.obtained.yml
rename to tests/snapshots/test_object_type_validation_fails_for_field_with_multiple_args.obtained.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_field_with_multiple_args.yml b/tests/snapshots/test_object_type_validation_fails_for_field_with_multiple_args.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_field_with_multiple_args.yml
rename to tests/snapshots/test_object_type_validation_fails_for_field_with_multiple_args.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_field_with_multiple_descriptions.obtained.yml b/tests/snapshots/test_object_type_validation_fails_for_field_with_multiple_descriptions.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_field_with_multiple_descriptions.obtained.yml
rename to tests/snapshots/test_object_type_validation_fails_for_field_with_multiple_descriptions.obtained.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_field_with_multiple_descriptions.yml b/tests/snapshots/test_object_type_validation_fails_for_field_with_multiple_descriptions.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_field_with_multiple_descriptions.yml
rename to tests/snapshots/test_object_type_validation_fails_for_field_with_multiple_descriptions.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_invalid_alias.obtained.yml b/tests/snapshots/test_object_type_validation_fails_for_invalid_alias.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_invalid_alias.obtained.yml
rename to tests/snapshots/test_object_type_validation_fails_for_invalid_alias.obtained.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_invalid_alias.yml b/tests/snapshots/test_object_type_validation_fails_for_invalid_alias.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_invalid_alias.yml
rename to tests/snapshots/test_object_type_validation_fails_for_invalid_alias.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_missing_field_resolver_arg.obtained.yml b/tests/snapshots/test_object_type_validation_fails_for_missing_field_resolver_arg.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_missing_field_resolver_arg.obtained.yml
rename to tests/snapshots/test_object_type_validation_fails_for_missing_field_resolver_arg.obtained.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_missing_field_resolver_arg.yml b/tests/snapshots/test_object_type_validation_fails_for_missing_field_resolver_arg.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_missing_field_resolver_arg.yml
rename to tests/snapshots/test_object_type_validation_fails_for_missing_field_resolver_arg.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_missing_resolver_arg.obtained.yml b/tests/snapshots/test_object_type_validation_fails_for_missing_resolver_arg.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_missing_resolver_arg.obtained.yml
rename to tests/snapshots/test_object_type_validation_fails_for_missing_resolver_arg.obtained.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_missing_resolver_arg.yml b/tests/snapshots/test_object_type_validation_fails_for_missing_resolver_arg.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_missing_resolver_arg.yml
rename to tests/snapshots/test_object_type_validation_fails_for_missing_resolver_arg.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_multiple_attrs_with_same_graphql_name.obtained.yml b/tests/snapshots/test_object_type_validation_fails_for_multiple_attrs_with_same_graphql_name.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_multiple_attrs_with_same_graphql_name.obtained.yml
rename to tests/snapshots/test_object_type_validation_fails_for_multiple_attrs_with_same_graphql_name.obtained.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_multiple_attrs_with_same_graphql_name.yml b/tests/snapshots/test_object_type_validation_fails_for_multiple_attrs_with_same_graphql_name.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_multiple_attrs_with_same_graphql_name.yml
rename to tests/snapshots/test_object_type_validation_fails_for_multiple_attrs_with_same_graphql_name.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_multiple_field_resolvers.obtained.yml b/tests/snapshots/test_object_type_validation_fails_for_multiple_field_resolvers.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_multiple_field_resolvers.obtained.yml
rename to tests/snapshots/test_object_type_validation_fails_for_multiple_field_resolvers.obtained.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_multiple_field_resolvers.yml b/tests/snapshots/test_object_type_validation_fails_for_multiple_field_resolvers.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_multiple_field_resolvers.yml
rename to tests/snapshots/test_object_type_validation_fails_for_multiple_field_resolvers.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_multiple_fields_with_same_graphql_name.obtained.yml b/tests/snapshots/test_object_type_validation_fails_for_multiple_fields_with_same_graphql_name.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_multiple_fields_with_same_graphql_name.obtained.yml
rename to tests/snapshots/test_object_type_validation_fails_for_multiple_fields_with_same_graphql_name.obtained.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_multiple_fields_with_same_graphql_name.yml b/tests/snapshots/test_object_type_validation_fails_for_multiple_fields_with_same_graphql_name.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_multiple_fields_with_same_graphql_name.yml
rename to tests/snapshots/test_object_type_validation_fails_for_multiple_fields_with_same_graphql_name.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_undefined_attr_resolver.obtained.yml b/tests/snapshots/test_object_type_validation_fails_for_undefined_attr_resolver.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_undefined_attr_resolver.obtained.yml
rename to tests/snapshots/test_object_type_validation_fails_for_undefined_attr_resolver.obtained.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_undefined_attr_resolver.yml b/tests/snapshots/test_object_type_validation_fails_for_undefined_attr_resolver.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_undefined_attr_resolver.yml
rename to tests/snapshots/test_object_type_validation_fails_for_undefined_attr_resolver.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_undefined_field_resolver_arg.obtained.yml b/tests/snapshots/test_object_type_validation_fails_for_undefined_field_resolver_arg.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_undefined_field_resolver_arg.obtained.yml
rename to tests/snapshots/test_object_type_validation_fails_for_undefined_field_resolver_arg.obtained.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_undefined_field_resolver_arg.yml b/tests/snapshots/test_object_type_validation_fails_for_undefined_field_resolver_arg.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_undefined_field_resolver_arg.yml
rename to tests/snapshots/test_object_type_validation_fails_for_undefined_field_resolver_arg.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_undefined_resolver_arg.obtained.yml b/tests/snapshots/test_object_type_validation_fails_for_undefined_resolver_arg.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_undefined_resolver_arg.obtained.yml
rename to tests/snapshots/test_object_type_validation_fails_for_undefined_resolver_arg.obtained.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_undefined_resolver_arg.yml b/tests/snapshots/test_object_type_validation_fails_for_undefined_resolver_arg.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_undefined_resolver_arg.yml
rename to tests/snapshots/test_object_type_validation_fails_for_undefined_resolver_arg.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_unsupported_resolver_arg_default.obtained.yml b/tests/snapshots/test_object_type_validation_fails_for_unsupported_resolver_arg_default.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_unsupported_resolver_arg_default.obtained.yml
rename to tests/snapshots/test_object_type_validation_fails_for_unsupported_resolver_arg_default.obtained.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_unsupported_resolver_arg_default.yml b/tests/snapshots/test_object_type_validation_fails_for_unsupported_resolver_arg_default.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_unsupported_resolver_arg_default.yml
rename to tests/snapshots/test_object_type_validation_fails_for_unsupported_resolver_arg_default.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_unsupported_resolver_arg_default_option.obtained.yml b/tests/snapshots/test_object_type_validation_fails_for_unsupported_resolver_arg_default_option.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_unsupported_resolver_arg_default_option.obtained.yml
rename to tests/snapshots/test_object_type_validation_fails_for_unsupported_resolver_arg_default_option.obtained.yml
diff --git a/tests_next/snapshots/test_object_type_validation_fails_for_unsupported_resolver_arg_default_option.yml b/tests/snapshots/test_object_type_validation_fails_for_unsupported_resolver_arg_default_option.yml
similarity index 100%
rename from tests_next/snapshots/test_object_type_validation_fails_for_unsupported_resolver_arg_default_option.yml
rename to tests/snapshots/test_object_type_validation_fails_for_unsupported_resolver_arg_default_option.yml
diff --git a/tests_next/snapshots/test_schema_enum_type_validation_fails_for_duplicated_members_descriptions.obtained.yml b/tests/snapshots/test_schema_enum_type_validation_fails_for_duplicated_members_descriptions.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_enum_type_validation_fails_for_duplicated_members_descriptions.obtained.yml
rename to tests/snapshots/test_schema_enum_type_validation_fails_for_duplicated_members_descriptions.obtained.yml
diff --git a/tests_next/snapshots/test_schema_enum_type_validation_fails_for_duplicated_members_descriptions.yml b/tests/snapshots/test_schema_enum_type_validation_fails_for_duplicated_members_descriptions.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_enum_type_validation_fails_for_duplicated_members_descriptions.yml
rename to tests/snapshots/test_schema_enum_type_validation_fails_for_duplicated_members_descriptions.yml
diff --git a/tests_next/snapshots/test_schema_enum_type_validation_fails_for_empty_enum.obtained.yml b/tests/snapshots/test_schema_enum_type_validation_fails_for_empty_enum.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_enum_type_validation_fails_for_empty_enum.obtained.yml
rename to tests/snapshots/test_schema_enum_type_validation_fails_for_empty_enum.obtained.yml
diff --git a/tests_next/snapshots/test_schema_enum_type_validation_fails_for_empty_enum.yml b/tests/snapshots/test_schema_enum_type_validation_fails_for_empty_enum.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_enum_type_validation_fails_for_empty_enum.yml
rename to tests/snapshots/test_schema_enum_type_validation_fails_for_empty_enum.yml
diff --git a/tests_next/snapshots/test_schema_enum_type_validation_fails_for_invalid_members_descriptions.obtained.yml b/tests/snapshots/test_schema_enum_type_validation_fails_for_invalid_members_descriptions.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_enum_type_validation_fails_for_invalid_members_descriptions.obtained.yml
rename to tests/snapshots/test_schema_enum_type_validation_fails_for_invalid_members_descriptions.obtained.yml
diff --git a/tests_next/snapshots/test_schema_enum_type_validation_fails_for_invalid_members_descriptions.yml b/tests/snapshots/test_schema_enum_type_validation_fails_for_invalid_members_descriptions.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_enum_type_validation_fails_for_invalid_members_descriptions.yml
rename to tests/snapshots/test_schema_enum_type_validation_fails_for_invalid_members_descriptions.yml
diff --git a/tests_next/snapshots/test_schema_enum_type_validation_fails_for_invalid_type_schema.obtained.yml b/tests/snapshots/test_schema_enum_type_validation_fails_for_invalid_type_schema.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_enum_type_validation_fails_for_invalid_type_schema.obtained.yml
rename to tests/snapshots/test_schema_enum_type_validation_fails_for_invalid_type_schema.obtained.yml
diff --git a/tests_next/snapshots/test_schema_enum_type_validation_fails_for_invalid_type_schema.yml b/tests/snapshots/test_schema_enum_type_validation_fails_for_invalid_type_schema.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_enum_type_validation_fails_for_invalid_type_schema.yml
rename to tests/snapshots/test_schema_enum_type_validation_fails_for_invalid_type_schema.yml
diff --git a/tests_next/snapshots/test_schema_enum_type_validation_fails_for_names_not_matching.obtained.yml b/tests/snapshots/test_schema_enum_type_validation_fails_for_names_not_matching.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_enum_type_validation_fails_for_names_not_matching.obtained.yml
rename to tests/snapshots/test_schema_enum_type_validation_fails_for_names_not_matching.obtained.yml
diff --git a/tests_next/snapshots/test_schema_enum_type_validation_fails_for_names_not_matching.yml b/tests/snapshots/test_schema_enum_type_validation_fails_for_names_not_matching.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_enum_type_validation_fails_for_names_not_matching.yml
rename to tests/snapshots/test_schema_enum_type_validation_fails_for_names_not_matching.yml
diff --git a/tests_next/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_dict_mismatch.obtained.yml b/tests/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_dict_mismatch.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_dict_mismatch.obtained.yml
rename to tests/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_dict_mismatch.obtained.yml
diff --git a/tests_next/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_dict_mismatch.yml b/tests/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_dict_mismatch.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_dict_mismatch.yml
rename to tests/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_dict_mismatch.yml
diff --git a/tests_next/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_enum_mismatch.obtained.yml b/tests/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_enum_mismatch.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_enum_mismatch.obtained.yml
rename to tests/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_enum_mismatch.obtained.yml
diff --git a/tests_next/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_enum_mismatch.yml b/tests/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_enum_mismatch.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_enum_mismatch.yml
rename to tests/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_enum_mismatch.yml
diff --git a/tests_next/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_list.obtained.yml b/tests/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_list.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_list.obtained.yml
rename to tests/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_list.obtained.yml
diff --git a/tests_next/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_list.yml b/tests/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_list.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_list.yml
rename to tests/snapshots/test_schema_enum_type_validation_fails_for_schema_and_members_list.yml
diff --git a/tests_next/snapshots/test_schema_enum_type_validation_fails_for_two_descriptions.obtained.yml b/tests/snapshots/test_schema_enum_type_validation_fails_for_two_descriptions.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_enum_type_validation_fails_for_two_descriptions.obtained.yml
rename to tests/snapshots/test_schema_enum_type_validation_fails_for_two_descriptions.obtained.yml
diff --git a/tests_next/snapshots/test_schema_enum_type_validation_fails_for_two_descriptions.yml b/tests/snapshots/test_schema_enum_type_validation_fails_for_two_descriptions.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_enum_type_validation_fails_for_two_descriptions.yml
rename to tests/snapshots/test_schema_enum_type_validation_fails_for_two_descriptions.yml
diff --git a/tests_next/snapshots/test_schema_input_type_instance_with_invalid_attrs_raising_error.obtained.yml b/tests/snapshots/test_schema_input_type_instance_with_invalid_attrs_raising_error.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_input_type_instance_with_invalid_attrs_raising_error.obtained.yml
rename to tests/snapshots/test_schema_input_type_instance_with_invalid_attrs_raising_error.obtained.yml
diff --git a/tests_next/snapshots/test_schema_input_type_instance_with_invalid_attrs_raising_error.yml b/tests/snapshots/test_schema_input_type_instance_with_invalid_attrs_raising_error.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_input_type_instance_with_invalid_attrs_raising_error.yml
rename to tests/snapshots/test_schema_input_type_instance_with_invalid_attrs_raising_error.yml
diff --git a/tests_next/snapshots/test_schema_input_type_validation_fails_for_duplicate_out_name.obtained.yml b/tests/snapshots/test_schema_input_type_validation_fails_for_duplicate_out_name.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_input_type_validation_fails_for_duplicate_out_name.obtained.yml
rename to tests/snapshots/test_schema_input_type_validation_fails_for_duplicate_out_name.obtained.yml
diff --git a/tests_next/snapshots/test_schema_input_type_validation_fails_for_duplicate_out_name.yml b/tests/snapshots/test_schema_input_type_validation_fails_for_duplicate_out_name.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_input_type_validation_fails_for_duplicate_out_name.yml
rename to tests/snapshots/test_schema_input_type_validation_fails_for_duplicate_out_name.yml
diff --git a/tests_next/snapshots/test_schema_input_type_validation_fails_for_invalid_out_name.obtained.yml b/tests/snapshots/test_schema_input_type_validation_fails_for_invalid_out_name.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_input_type_validation_fails_for_invalid_out_name.obtained.yml
rename to tests/snapshots/test_schema_input_type_validation_fails_for_invalid_out_name.obtained.yml
diff --git a/tests_next/snapshots/test_schema_input_type_validation_fails_for_invalid_out_name.yml b/tests/snapshots/test_schema_input_type_validation_fails_for_invalid_out_name.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_input_type_validation_fails_for_invalid_out_name.yml
rename to tests/snapshots/test_schema_input_type_validation_fails_for_invalid_out_name.yml
diff --git a/tests_next/snapshots/test_schema_input_type_validation_fails_for_invalid_type_schema.obtained.yml b/tests/snapshots/test_schema_input_type_validation_fails_for_invalid_type_schema.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_input_type_validation_fails_for_invalid_type_schema.obtained.yml
rename to tests/snapshots/test_schema_input_type_validation_fails_for_invalid_type_schema.obtained.yml
diff --git a/tests_next/snapshots/test_schema_input_type_validation_fails_for_invalid_type_schema.yml b/tests/snapshots/test_schema_input_type_validation_fails_for_invalid_type_schema.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_input_type_validation_fails_for_invalid_type_schema.yml
rename to tests/snapshots/test_schema_input_type_validation_fails_for_invalid_type_schema.yml
diff --git a/tests_next/snapshots/test_schema_input_type_validation_fails_for_names_not_matching.obtained.yml b/tests/snapshots/test_schema_input_type_validation_fails_for_names_not_matching.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_input_type_validation_fails_for_names_not_matching.obtained.yml
rename to tests/snapshots/test_schema_input_type_validation_fails_for_names_not_matching.obtained.yml
diff --git a/tests_next/snapshots/test_schema_input_type_validation_fails_for_names_not_matching.yml b/tests/snapshots/test_schema_input_type_validation_fails_for_names_not_matching.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_input_type_validation_fails_for_names_not_matching.yml
rename to tests/snapshots/test_schema_input_type_validation_fails_for_names_not_matching.yml
diff --git a/tests_next/snapshots/test_schema_input_type_validation_fails_for_schema_missing_fields.obtained.yml b/tests/snapshots/test_schema_input_type_validation_fails_for_schema_missing_fields.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_input_type_validation_fails_for_schema_missing_fields.obtained.yml
rename to tests/snapshots/test_schema_input_type_validation_fails_for_schema_missing_fields.obtained.yml
diff --git a/tests_next/snapshots/test_schema_input_type_validation_fails_for_schema_missing_fields.yml b/tests/snapshots/test_schema_input_type_validation_fails_for_schema_missing_fields.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_input_type_validation_fails_for_schema_missing_fields.yml
rename to tests/snapshots/test_schema_input_type_validation_fails_for_schema_missing_fields.yml
diff --git a/tests_next/snapshots/test_schema_input_type_validation_fails_for_two_descriptions.obtained.yml b/tests/snapshots/test_schema_input_type_validation_fails_for_two_descriptions.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_input_type_validation_fails_for_two_descriptions.obtained.yml
rename to tests/snapshots/test_schema_input_type_validation_fails_for_two_descriptions.obtained.yml
diff --git a/tests_next/snapshots/test_schema_input_type_validation_fails_for_two_descriptions.yml b/tests/snapshots/test_schema_input_type_validation_fails_for_two_descriptions.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_input_type_validation_fails_for_two_descriptions.yml
rename to tests/snapshots/test_schema_input_type_validation_fails_for_two_descriptions.yml
diff --git a/tests_next/snapshots/test_schema_object_type_instance_with_invalid_attrs_raising_error.obtained.yml b/tests/snapshots/test_schema_object_type_instance_with_invalid_attrs_raising_error.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_instance_with_invalid_attrs_raising_error.obtained.yml
rename to tests/snapshots/test_schema_object_type_instance_with_invalid_attrs_raising_error.obtained.yml
diff --git a/tests_next/snapshots/test_schema_object_type_instance_with_invalid_attrs_raising_error.yml b/tests/snapshots/test_schema_object_type_instance_with_invalid_attrs_raising_error.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_instance_with_invalid_attrs_raising_error.yml
rename to tests/snapshots/test_schema_object_type_instance_with_invalid_attrs_raising_error.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_alias_resolver.obtained.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_alias_resolver.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_alias_resolver.obtained.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_alias_resolver.obtained.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_alias_resolver.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_alias_resolver.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_alias_resolver.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_alias_resolver.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_alias_target_resolver.obtained.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_alias_target_resolver.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_alias_target_resolver.obtained.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_alias_target_resolver.obtained.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_alias_target_resolver.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_alias_target_resolver.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_alias_target_resolver.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_alias_target_resolver.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_arg_with_double_description.obtained.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_arg_with_double_description.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_arg_with_double_description.obtained.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_arg_with_double_description.obtained.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_arg_with_double_description.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_arg_with_double_description.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_arg_with_double_description.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_arg_with_double_description.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_arg_with_name_option.obtained.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_arg_with_name_option.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_arg_with_name_option.obtained.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_arg_with_name_option.obtained.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_arg_with_name_option.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_arg_with_name_option.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_arg_with_name_option.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_arg_with_name_option.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_arg_with_type_option.obtained.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_arg_with_type_option.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_arg_with_type_option.obtained.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_arg_with_type_option.obtained.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_arg_with_type_option.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_arg_with_type_option.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_arg_with_type_option.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_arg_with_type_option.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_field_instance.obtained.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_field_instance.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_field_instance.obtained.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_field_instance.obtained.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_field_instance.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_field_instance.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_field_instance.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_field_instance.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_field_with_invalid_arg_name.obtained.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_field_with_invalid_arg_name.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_field_with_invalid_arg_name.obtained.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_field_with_invalid_arg_name.obtained.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_field_with_invalid_arg_name.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_field_with_invalid_arg_name.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_field_with_invalid_arg_name.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_field_with_invalid_arg_name.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_field_with_multiple_descriptions.obtained.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_field_with_multiple_descriptions.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_field_with_multiple_descriptions.obtained.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_field_with_multiple_descriptions.obtained.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_field_with_multiple_descriptions.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_field_with_multiple_descriptions.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_field_with_multiple_descriptions.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_field_with_multiple_descriptions.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_invalid_alias.obtained.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_invalid_alias.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_invalid_alias.obtained.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_invalid_alias.obtained.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_invalid_alias.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_invalid_alias.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_invalid_alias.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_invalid_alias.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_invalid_type_schema.obtained.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_invalid_type_schema.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_invalid_type_schema.obtained.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_invalid_type_schema.obtained.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_invalid_type_schema.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_invalid_type_schema.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_invalid_type_schema.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_invalid_type_schema.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_missing_fields.obtained.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_missing_fields.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_missing_fields.obtained.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_missing_fields.obtained.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_missing_fields.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_missing_fields.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_missing_fields.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_missing_fields.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_multiple_field_resolvers.obtained.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_multiple_field_resolvers.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_multiple_field_resolvers.obtained.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_multiple_field_resolvers.obtained.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_multiple_field_resolvers.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_multiple_field_resolvers.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_multiple_field_resolvers.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_multiple_field_resolvers.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_names_not_matching.obtained.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_names_not_matching.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_names_not_matching.obtained.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_names_not_matching.obtained.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_names_not_matching.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_names_not_matching.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_names_not_matching.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_names_not_matching.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_two_descriptions.obtained.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_two_descriptions.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_two_descriptions.obtained.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_two_descriptions.obtained.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_two_descriptions.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_two_descriptions.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_two_descriptions.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_two_descriptions.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_undefined_field_resolver.obtained.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_undefined_field_resolver.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_undefined_field_resolver.obtained.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_undefined_field_resolver.obtained.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_undefined_field_resolver.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_undefined_field_resolver.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_undefined_field_resolver.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_undefined_field_resolver.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_unsupported_resolver_arg_default.obtained.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_unsupported_resolver_arg_default.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_unsupported_resolver_arg_default.obtained.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_unsupported_resolver_arg_default.obtained.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_unsupported_resolver_arg_default.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_unsupported_resolver_arg_default.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_unsupported_resolver_arg_default.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_unsupported_resolver_arg_default.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_unsupported_resolver_arg_option_default.obtained.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_unsupported_resolver_arg_option_default.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_unsupported_resolver_arg_option_default.obtained.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_unsupported_resolver_arg_option_default.obtained.yml
diff --git a/tests_next/snapshots/test_schema_object_type_validation_fails_for_unsupported_resolver_arg_option_default.yml b/tests/snapshots/test_schema_object_type_validation_fails_for_unsupported_resolver_arg_option_default.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_object_type_validation_fails_for_unsupported_resolver_arg_option_default.yml
rename to tests/snapshots/test_schema_object_type_validation_fails_for_unsupported_resolver_arg_option_default.yml
diff --git a/tests_next/snapshots/test_schema_scalar_type_validation_fails_for_different_names.obtained.yml b/tests/snapshots/test_schema_scalar_type_validation_fails_for_different_names.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_scalar_type_validation_fails_for_different_names.obtained.yml
rename to tests/snapshots/test_schema_scalar_type_validation_fails_for_different_names.obtained.yml
diff --git a/tests_next/snapshots/test_schema_scalar_type_validation_fails_for_different_names.yml b/tests/snapshots/test_schema_scalar_type_validation_fails_for_different_names.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_scalar_type_validation_fails_for_different_names.yml
rename to tests/snapshots/test_schema_scalar_type_validation_fails_for_different_names.yml
diff --git a/tests_next/snapshots/test_schema_scalar_type_validation_fails_for_invalid_type_schema.obtained.yml b/tests/snapshots/test_schema_scalar_type_validation_fails_for_invalid_type_schema.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_scalar_type_validation_fails_for_invalid_type_schema.obtained.yml
rename to tests/snapshots/test_schema_scalar_type_validation_fails_for_invalid_type_schema.obtained.yml
diff --git a/tests_next/snapshots/test_schema_scalar_type_validation_fails_for_invalid_type_schema.yml b/tests/snapshots/test_schema_scalar_type_validation_fails_for_invalid_type_schema.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_scalar_type_validation_fails_for_invalid_type_schema.yml
rename to tests/snapshots/test_schema_scalar_type_validation_fails_for_invalid_type_schema.yml
diff --git a/tests_next/snapshots/test_schema_scalar_type_validation_fails_for_two_descriptions.obtained.yml b/tests/snapshots/test_schema_scalar_type_validation_fails_for_two_descriptions.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_scalar_type_validation_fails_for_two_descriptions.obtained.yml
rename to tests/snapshots/test_schema_scalar_type_validation_fails_for_two_descriptions.obtained.yml
diff --git a/tests_next/snapshots/test_schema_scalar_type_validation_fails_for_two_descriptions.yml b/tests/snapshots/test_schema_scalar_type_validation_fails_for_two_descriptions.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_scalar_type_validation_fails_for_two_descriptions.yml
rename to tests/snapshots/test_schema_scalar_type_validation_fails_for_two_descriptions.yml
diff --git a/tests_next/snapshots/test_schema_validation_fails_if_lazy_type_doesnt_exist.obtained.yml b/tests/snapshots/test_schema_validation_fails_if_lazy_type_doesnt_exist.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_validation_fails_if_lazy_type_doesnt_exist.obtained.yml
rename to tests/snapshots/test_schema_validation_fails_if_lazy_type_doesnt_exist.obtained.yml
diff --git a/tests_next/snapshots/test_schema_validation_fails_if_lazy_type_doesnt_exist.yml b/tests/snapshots/test_schema_validation_fails_if_lazy_type_doesnt_exist.yml
similarity index 100%
rename from tests_next/snapshots/test_schema_validation_fails_if_lazy_type_doesnt_exist.yml
rename to tests/snapshots/test_schema_validation_fails_if_lazy_type_doesnt_exist.yml
diff --git a/tests_next/snapshots/test_source_args_field_arg_not_dict_without_schema.obtained.yml b/tests/snapshots/test_source_args_field_arg_not_dict_without_schema.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_source_args_field_arg_not_dict_without_schema.obtained.yml
rename to tests/snapshots/test_source_args_field_arg_not_dict_without_schema.obtained.yml
diff --git a/tests_next/snapshots/test_source_args_field_arg_not_dict_without_schema.yml b/tests/snapshots/test_source_args_field_arg_not_dict_without_schema.yml
similarity index 100%
rename from tests_next/snapshots/test_source_args_field_arg_not_dict_without_schema.yml
rename to tests/snapshots/test_source_args_field_arg_not_dict_without_schema.yml
diff --git a/tests_next/snapshots/test_source_args_not_dict_without_schema.obtained.yml b/tests/snapshots/test_source_args_not_dict_without_schema.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_source_args_not_dict_without_schema.obtained.yml
rename to tests/snapshots/test_source_args_not_dict_without_schema.obtained.yml
diff --git a/tests_next/snapshots/test_source_args_not_dict_without_schema.yml b/tests/snapshots/test_source_args_not_dict_without_schema.yml
similarity index 100%
rename from tests_next/snapshots/test_source_args_not_dict_without_schema.yml
rename to tests/snapshots/test_source_args_not_dict_without_schema.yml
diff --git a/tests_next/snapshots/test_source_for_undefined_field_with_schema.obtained.yml b/tests/snapshots/test_source_for_undefined_field_with_schema.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_source_for_undefined_field_with_schema.obtained.yml
rename to tests/snapshots/test_source_for_undefined_field_with_schema.obtained.yml
diff --git a/tests_next/snapshots/test_source_for_undefined_field_with_schema.yml b/tests/snapshots/test_source_for_undefined_field_with_schema.yml
similarity index 100%
rename from tests_next/snapshots/test_source_for_undefined_field_with_schema.yml
rename to tests/snapshots/test_source_for_undefined_field_with_schema.yml
diff --git a/tests_next/snapshots/test_undefined_name_without_schema.obtained.yml b/tests/snapshots/test_undefined_name_without_schema.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_undefined_name_without_schema.obtained.yml
rename to tests/snapshots/test_undefined_name_without_schema.obtained.yml
diff --git a/tests_next/snapshots/test_undefined_name_without_schema.yml b/tests/snapshots/test_undefined_name_without_schema.yml
similarity index 100%
rename from tests_next/snapshots/test_undefined_name_without_schema.yml
rename to tests/snapshots/test_undefined_name_without_schema.yml
diff --git a/tests_next/snapshots/test_value_error_is_raised_if_exclude_and_include_members_are_combined.obtained.yml b/tests/snapshots/test_value_error_is_raised_if_exclude_and_include_members_are_combined.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_value_error_is_raised_if_exclude_and_include_members_are_combined.obtained.yml
rename to tests/snapshots/test_value_error_is_raised_if_exclude_and_include_members_are_combined.obtained.yml
diff --git a/tests_next/snapshots/test_value_error_is_raised_if_exclude_and_include_members_are_combined.yml b/tests/snapshots/test_value_error_is_raised_if_exclude_and_include_members_are_combined.yml
similarity index 100%
rename from tests_next/snapshots/test_value_error_is_raised_if_exclude_and_include_members_are_combined.yml
rename to tests/snapshots/test_value_error_is_raised_if_exclude_and_include_members_are_combined.yml
diff --git a/tests_next/snapshots/test_value_error_is_raised_if_member_description_is_set_for_excluded_item.obtained.yml b/tests/snapshots/test_value_error_is_raised_if_member_description_is_set_for_excluded_item.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_value_error_is_raised_if_member_description_is_set_for_excluded_item.obtained.yml
rename to tests/snapshots/test_value_error_is_raised_if_member_description_is_set_for_excluded_item.obtained.yml
diff --git a/tests_next/snapshots/test_value_error_is_raised_if_member_description_is_set_for_excluded_item.yml b/tests/snapshots/test_value_error_is_raised_if_member_description_is_set_for_excluded_item.yml
similarity index 100%
rename from tests_next/snapshots/test_value_error_is_raised_if_member_description_is_set_for_excluded_item.yml
rename to tests/snapshots/test_value_error_is_raised_if_member_description_is_set_for_excluded_item.yml
diff --git a/tests_next/snapshots/test_value_error_is_raised_if_member_description_is_set_for_missing_item.obtained.yml b/tests/snapshots/test_value_error_is_raised_if_member_description_is_set_for_missing_item.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_value_error_is_raised_if_member_description_is_set_for_missing_item.obtained.yml
rename to tests/snapshots/test_value_error_is_raised_if_member_description_is_set_for_missing_item.obtained.yml
diff --git a/tests_next/snapshots/test_value_error_is_raised_if_member_description_is_set_for_missing_item.yml b/tests/snapshots/test_value_error_is_raised_if_member_description_is_set_for_missing_item.yml
similarity index 100%
rename from tests_next/snapshots/test_value_error_is_raised_if_member_description_is_set_for_missing_item.yml
rename to tests/snapshots/test_value_error_is_raised_if_member_description_is_set_for_missing_item.yml
diff --git a/tests_next/snapshots/test_value_error_is_raised_if_member_description_is_set_for_omitted_item.obtained.yml b/tests/snapshots/test_value_error_is_raised_if_member_description_is_set_for_omitted_item.obtained.yml
similarity index 100%
rename from tests_next/snapshots/test_value_error_is_raised_if_member_description_is_set_for_omitted_item.obtained.yml
rename to tests/snapshots/test_value_error_is_raised_if_member_description_is_set_for_omitted_item.obtained.yml
diff --git a/tests_next/snapshots/test_value_error_is_raised_if_member_description_is_set_for_omitted_item.yml b/tests/snapshots/test_value_error_is_raised_if_member_description_is_set_for_omitted_item.yml
similarity index 100%
rename from tests_next/snapshots/test_value_error_is_raised_if_member_description_is_set_for_omitted_item.yml
rename to tests/snapshots/test_value_error_is_raised_if_member_description_is_set_for_omitted_item.yml
diff --git a/tests_next/test_compatibility_layer.py b/tests/test_compatibility_layer.py
similarity index 93%
rename from tests_next/test_compatibility_layer.py
rename to tests/test_compatibility_layer.py
index 320bdc4..90dc845 100644
--- a/tests_next/test_compatibility_layer.py
+++ b/tests/test_compatibility_layer.py
@@ -2,17 +2,17 @@
from datetime import date, datetime
from graphql import StringValueNode
-from ariadne_graphql_modules.bases import DeferredType
-from ariadne_graphql_modules.collection_type import CollectionType
-from ariadne_graphql_modules.enum_type import EnumType
-from ariadne_graphql_modules.input_type import InputType
-from ariadne_graphql_modules.interface_type import InterfaceType
-from ariadne_graphql_modules.next.compatibility_layer import wrap_legacy_types
-from ariadne_graphql_modules.next.executable_schema import make_executable_schema
-from ariadne_graphql_modules.object_type import ObjectType
-from ariadne_graphql_modules.scalar_type import ScalarType
-from ariadne_graphql_modules.subscription_type import SubscriptionType
-from ariadne_graphql_modules.union_type import UnionType
+from ariadne_graphql_modules.v1.bases import DeferredType
+from ariadne_graphql_modules.v1.collection_type import CollectionType
+from ariadne_graphql_modules.v1.enum_type import EnumType
+from ariadne_graphql_modules.v1.input_type import InputType
+from ariadne_graphql_modules.v1.interface_type import InterfaceType
+from ariadne_graphql_modules.compatibility_layer import wrap_legacy_types
+from ariadne_graphql_modules.executable_schema import make_executable_schema
+from ariadne_graphql_modules.v1.object_type import ObjectType
+from ariadne_graphql_modules.v1.scalar_type import ScalarType
+from ariadne_graphql_modules.v1.subscription_type import SubscriptionType
+from ariadne_graphql_modules.v1.union_type import UnionType
def test_object_type(
diff --git a/tests_next/test_deferred_type.py b/tests/test_deferred_type.py
similarity index 73%
rename from tests_next/test_deferred_type.py
rename to tests/test_deferred_type.py
index 964e1a3..7f72937 100644
--- a/tests_next/test_deferred_type.py
+++ b/tests/test_deferred_type.py
@@ -2,25 +2,25 @@
import pytest
-from ariadne_graphql_modules.next import deferred
+from ariadne_graphql_modules import deferred
def test_deferred_returns_deferred_type_with_abs_path():
- deferred_type = deferred("tests_next.types")
- assert deferred_type.path == "tests_next.types"
+ deferred_type = deferred("tests.types")
+ assert deferred_type.path == "tests.types"
def test_deferred_returns_deferred_type_with_relative_path():
class MockType:
deferred_type = deferred(".types")
- assert MockType.deferred_type.path == "tests_next.types"
+ assert MockType.deferred_type.path == "tests.types"
def test_deferred_returns_deferred_type_with_higher_level_relative_path(monkeypatch):
frame_mock = Mock(f_globals={"__package__": "lorem.ipsum"})
monkeypatch.setattr(
- "ariadne_graphql_modules.next.deferredtype.sys._getframe",
+ "ariadne_graphql_modules.deferredtype.sys._getframe",
Mock(return_value=frame_mock),
)
@@ -33,7 +33,7 @@ class MockType:
def test_deferred_raises_error_for_invalid_relative_path(monkeypatch, data_regression):
frame_mock = Mock(f_globals={"__package__": "lorem"})
monkeypatch.setattr(
- "ariadne_graphql_modules.next.deferredtype.sys._getframe",
+ "ariadne_graphql_modules.deferredtype.sys._getframe",
Mock(return_value=frame_mock),
)
diff --git a/tests_next/test_description_node.py b/tests/test_description_node.py
similarity index 94%
rename from tests_next/test_description_node.py
rename to tests/test_description_node.py
index e9f7101..19a6960 100644
--- a/tests_next/test_description_node.py
+++ b/tests/test_description_node.py
@@ -1,4 +1,4 @@
-from ariadne_graphql_modules.next import get_description_node
+from ariadne_graphql_modules import get_description_node
def test_no_description_is_returned_for_none():
diff --git a/tests/test_enum_type.py b/tests/test_enum_type.py
index 7ea4585..8e051d7 100644
--- a/tests/test_enum_type.py
+++ b/tests/test_enum_type.py
@@ -1,304 +1,522 @@
from enum import Enum
-import pytest
-from ariadne import SchemaDirectiveVisitor
-from graphql import GraphQLError, graphql_sync
+from graphql import graphql_sync
from ariadne_graphql_modules import (
- DirectiveType,
- EnumType,
- ObjectType,
+ GraphQLEnum,
+ GraphQLObject,
make_executable_schema,
)
-def test_enum_type_raises_attribute_error_when_defined_without_schema(data_regression):
- with pytest.raises(AttributeError) as err:
- # pylint: disable=unused-variable
- class UserRoleEnum(EnumType):
- pass
+class UserLevelEnum(Enum):
+ GUEST = 0
+ MEMBER = 1
+ ADMIN = 2
- data_regression.check(str(err.value))
+def test_enum_field_returning_enum_value(assert_schema_equals):
+ class UserLevel(GraphQLEnum):
+ __members__ = UserLevelEnum
-def test_enum_type_raises_error_when_defined_with_invalid_schema_type(data_regression):
- with pytest.raises(TypeError) as err:
- # pylint: disable=unused-variable
- class UserRoleEnum(EnumType):
- __schema__ = True
+ class QueryType(GraphQLObject):
+ level: UserLevel
- data_regression.check(str(err.value))
+ @GraphQLObject.resolver("level")
+ def resolve_level(*_) -> UserLevelEnum:
+ return UserLevelEnum.MEMBER
+ schema = make_executable_schema(QueryType)
-def test_enum_type_raises_error_when_defined_with_invalid_schema_str(data_regression):
- with pytest.raises(GraphQLError) as err:
- # pylint: disable=unused-variable
- class UserRoleEnum(EnumType):
- __schema__ = "enom UserRole"
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ level: UserLevel!
+ }
- data_regression.check(str(err.value))
+ enum UserLevel {
+ GUEST
+ MEMBER
+ ADMIN
+ }
+ """,
+ )
+ result = graphql_sync(schema, "{ level }")
-def test_enum_type_raises_error_when_defined_with_invalid_graphql_type_schema(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UserRoleEnum(EnumType):
- __schema__ = "scalar UserRole"
+ assert not result.errors
+ assert result.data == {"level": "MEMBER"}
- data_regression.check(str(err.value))
+def test_enum_field_returning_dict_value(assert_schema_equals):
+ class UserLevel(GraphQLEnum):
+ __members__ = {
+ "GUEST": 0,
+ "MEMBER": 1,
+ "ADMIN": 2,
+ }
-def test_enum_type_raises_error_when_defined_with_multiple_types_schema(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UserRoleEnum(EnumType):
- __schema__ = """
- enum UserRole {
- USER
- MOD
- ADMIN
- }
+ class QueryType(GraphQLObject):
+ level: UserLevel
+
+ @GraphQLObject.resolver("level")
+ def resolve_level(*_) -> dict:
+ return 0
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ level: UserLevel!
+ }
+
+ enum UserLevel {
+ GUEST
+ MEMBER
+ ADMIN
+ }
+ """,
+ )
+
+ result = graphql_sync(schema, "{ level }")
+
+ assert not result.errors
+ assert result.data == {"level": "GUEST"}
+
+
+def test_enum_field_returning_str_value(assert_schema_equals):
+ class UserLevel(GraphQLEnum):
+ __members__ = [
+ "GUEST",
+ "MEMBER",
+ "ADMIN",
+ ]
+
+ class QueryType(GraphQLObject):
+ level: UserLevel
+
+ @GraphQLObject.resolver("level")
+ def resolve_level(*_) -> str:
+ return "ADMIN"
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ level: UserLevel!
+ }
+
+ enum UserLevel {
+ GUEST
+ MEMBER
+ ADMIN
+ }
+ """,
+ )
+
+ result = graphql_sync(schema, "{ level }")
+
+ assert not result.errors
+ assert result.data == {"level": "ADMIN"}
+
+
+def test_enum_type_with_custom_name(assert_schema_equals):
+ class UserLevel(GraphQLEnum):
+ __graphql_name__ = "UserLevelEnum"
+ __members__ = UserLevelEnum
+
+ class QueryType(GraphQLObject):
+ level: UserLevel
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ level: UserLevelEnum!
+ }
+
+ enum UserLevelEnum {
+ GUEST
+ MEMBER
+ ADMIN
+ }
+ """,
+ )
+
+
+def test_enum_type_with_description(assert_schema_equals):
+ class UserLevel(GraphQLEnum):
+ __description__ = "Hello world."
+ __members__ = UserLevelEnum
+
+ class QueryType(GraphQLObject):
+ level: UserLevel
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ level: UserLevel!
+ }
+
+ \"\"\"Hello world.\"\"\"
+ enum UserLevel {
+ GUEST
+ MEMBER
+ ADMIN
+ }
+ """,
+ )
+
+
+def test_enum_type_with_member_description(assert_schema_equals):
+ class UserLevel(GraphQLEnum):
+ __members__ = UserLevelEnum
+ __members_descriptions__ = {"MEMBER": "Hello world."}
+
+ class QueryType(GraphQLObject):
+ level: UserLevel
- enum Category {
- CATEGORY
- LINK
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ level: UserLevel!
+ }
+
+ enum UserLevel {
+ GUEST
+
+ \"\"\"Hello world.\"\"\"
+ MEMBER
+ ADMIN
+ }
+ """,
+ )
+
+
+def test_schema_enum_field_returning_enum_value(assert_schema_equals):
+ class UserLevel(GraphQLEnum):
+ __schema__ = """
+ enum UserLevel {
+ GUEST
+ MEMBER
+ ADMIN
}
"""
+ __members__ = UserLevelEnum
+
+ class QueryType(GraphQLObject):
+ level: UserLevel
+
+ @GraphQLObject.resolver("level")
+ def resolve_level(*_) -> UserLevelEnum:
+ return UserLevelEnum.MEMBER
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ level: UserLevel!
+ }
+
+ enum UserLevel {
+ GUEST
+ MEMBER
+ ADMIN
+ }
+ """,
+ )
+
+ result = graphql_sync(schema, "{ level }")
- data_regression.check(str(err.value))
+ assert not result.errors
+ assert result.data == {"level": "MEMBER"}
-def test_enum_type_extracts_graphql_name():
- class UserRoleEnum(EnumType):
+def test_schema_enum_field_returning_dict_value(assert_schema_equals):
+ class UserLevel(GraphQLEnum):
__schema__ = """
- enum UserRole {
- USER
- MOD
- ADMIN
+ enum UserLevel {
+ GUEST
+ MEMBER
+ ADMIN
}
+ """
+ __members__ = {
+ "GUEST": 0,
+ "MEMBER": 1,
+ "ADMIN": 2,
+ }
+
+ class QueryType(GraphQLObject):
+ level: UserLevel
+
+ @GraphQLObject.resolver("level")
+ def resolve_level(*_) -> int:
+ return 2
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
"""
+ type Query {
+ level: UserLevel!
+ }
+
+ enum UserLevel {
+ GUEST
+ MEMBER
+ ADMIN
+ }
+ """,
+ )
- assert UserRoleEnum.graphql_name == "UserRole"
+ result = graphql_sync(schema, "{ level }")
+ assert not result.errors
+ assert result.data == {"level": "ADMIN"}
-def test_enum_type_can_be_extended_with_new_values():
- # pylint: disable=unused-variable
- class UserRoleEnum(EnumType):
+
+def test_schema_enum_field_returning_str_value(assert_schema_equals):
+ class UserLevel(GraphQLEnum):
__schema__ = """
- enum UserRole {
- USER
- MOD
- ADMIN
+ enum UserLevel {
+ GUEST
+ MEMBER
+ ADMIN
}
+ """
+
+ class QueryType(GraphQLObject):
+ level: UserLevel
+
+ @GraphQLObject.resolver("level")
+ def resolve_level(*_) -> str:
+ return "GUEST"
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
"""
+ type Query {
+ level: UserLevel!
+ }
- class ExtendUserRoleEnum(EnumType):
- __schema__ = """
- extend enum UserRole {
- MVP
+ enum UserLevel {
+ GUEST
+ MEMBER
+ ADMIN
}
- """
- __requires__ = [UserRoleEnum]
+ """,
+ )
+
+ result = graphql_sync(schema, "{ level }")
+ assert not result.errors
+ assert result.data == {"level": "GUEST"}
-def test_enum_type_can_be_extended_with_directive():
- # pylint: disable=unused-variable
- class ExampleDirective(DirectiveType):
- __schema__ = "directive @example on ENUM"
- __visitor__ = SchemaDirectiveVisitor
- class UserRoleEnum(EnumType):
+def test_schema_enum_with_description_attr(assert_schema_equals):
+ class UserLevel(GraphQLEnum):
__schema__ = """
- enum UserRole {
- USER
- MOD
- ADMIN
+ enum UserLevel {
+ GUEST
+ MEMBER
+ ADMIN
}
- """
+ """
+ __members__ = {
+ "GUEST": 0,
+ "MEMBER": 1,
+ "ADMIN": 2,
+ }
+ __description__ = "Hello world."
- class ExtendUserRoleEnum(EnumType):
- __schema__ = "extend enum UserRole @example"
- __requires__ = [UserRoleEnum, ExampleDirective]
+ class QueryType(GraphQLObject):
+ level: UserLevel
+ @GraphQLObject.resolver("level")
+ def resolve_level(*_) -> int:
+ return 2
-class BaseQueryType(ObjectType):
- __abstract__ = True
- __schema__ = """
- type Query {
- enumToRepr(enum: UserRole = USER): String!
- reprToEnum: UserRole!
- }
- """
- __aliases__ = {
- "enumToRepr": "enum_repr",
- }
+ schema = make_executable_schema(QueryType)
- @staticmethod
- def resolve_enum_repr(*_, enum) -> str:
- return repr(enum)
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ level: UserLevel!
+ }
+ \"\"\"Hello world.\"\"\"
+ enum UserLevel {
+ GUEST
+ MEMBER
+ ADMIN
+ }
+ """,
+ )
-def make_test_schema(enum_type):
- class QueryType(BaseQueryType):
- __requires__ = [enum_type]
+ result = graphql_sync(schema, "{ level }")
- return make_executable_schema(QueryType)
+ assert not result.errors
+ assert result.data == {"level": "ADMIN"}
-def test_enum_type_can_be_defined_with_dict_mapping():
- class UserRoleEnum(EnumType):
+def test_schema_enum_with_schema_description(assert_schema_equals):
+ class UserLevel(GraphQLEnum):
__schema__ = """
- enum UserRole {
- USER
- MOD
- ADMIN
+ \"\"\"Hello world.\"\"\"
+ enum UserLevel {
+ GUEST
+ MEMBER
+ ADMIN
}
- """
- __enum__ = {
- "USER": 0,
- "MOD": 1,
+ """
+ __members__ = {
+ "GUEST": 0,
+ "MEMBER": 1,
"ADMIN": 2,
}
- schema = make_test_schema(UserRoleEnum)
+ class QueryType(GraphQLObject):
+ level: UserLevel
- # Specfied enum value is reversed
- result = graphql_sync(schema, "{ enumToRepr(enum: MOD) }")
- assert result.data["enumToRepr"] == "1"
+ @GraphQLObject.resolver("level")
+ def resolve_level(*_) -> int:
+ return 2
- # Default enum value is reversed
- result = graphql_sync(schema, "{ enumToRepr }")
- assert result.data["enumToRepr"] == "0"
+ schema = make_executable_schema(QueryType)
- # Python value is converted to enum
- result = graphql_sync(schema, "{ reprToEnum }", root_value={"reprToEnum": 2})
- assert result.data["reprToEnum"] == "ADMIN"
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ level: UserLevel!
+ }
+ \"\"\"Hello world.\"\"\"
+ enum UserLevel {
+ GUEST
+ MEMBER
+ ADMIN
+ }
+ """,
+ )
-def test_enum_type_raises_error_when_dict_mapping_misses_items_from_definition(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UserRoleEnum(EnumType):
- __schema__ = """
- enum UserRole {
- USER
- MOD
- ADMIN
- }
- """
- __enum__ = {
- "USER": 0,
- "MODERATOR": 1,
- "ADMIN": 2,
- }
+ result = graphql_sync(schema, "{ level }")
- data_regression.check(str(err.value))
-
-
-def test_enum_type_raises_error_when_dict_mapping_has_extra_items_not_in_definition(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UserRoleEnum(EnumType):
- __schema__ = """
- enum UserRole {
- USER
- MOD
- ADMIN
- }
- """
- __enum__ = {
- "USER": 0,
- "REVIEW": 1,
- "MOD": 2,
- "ADMIN": 3,
+ assert not result.errors
+ assert result.data == {"level": "ADMIN"}
+
+
+def test_schema_enum_with_member_description(assert_schema_equals):
+ class UserLevel(GraphQLEnum):
+ __schema__ = """
+ enum UserLevel {
+ GUEST
+ MEMBER
+ ADMIN
}
+ """
+ __members__ = {
+ "GUEST": 0,
+ "MEMBER": 1,
+ "ADMIN": 2,
+ }
+ __members_descriptions__ = {"MEMBER": "Hello world."}
- data_regression.check(str(err.value))
+ class QueryType(GraphQLObject):
+ level: UserLevel
+ @GraphQLObject.resolver("level")
+ def resolve_level(*_) -> int:
+ return 2
-def test_enum_type_can_be_defined_with_str_enum_mapping():
- class RoleEnum(str, Enum):
- USER = "user"
- MOD = "moderator"
- ADMIN = "administrator"
+ schema = make_executable_schema(QueryType)
- class UserRoleEnum(EnumType):
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ level: UserLevel!
+ }
+
+ enum UserLevel {
+ GUEST
+
+ \"\"\"Hello world.\"\"\"
+ MEMBER
+ ADMIN
+ }
+ """,
+ )
+
+ result = graphql_sync(schema, "{ level }")
+
+ assert not result.errors
+ assert result.data == {"level": "ADMIN"}
+
+
+def test_schema_enum_with_member_schema_description(assert_schema_equals):
+ class UserLevel(GraphQLEnum):
__schema__ = """
- enum UserRole {
- USER
- MOD
- ADMIN
+ enum UserLevel {
+ GUEST
+ \"\"\"Hello world.\"\"\"
+ MEMBER
+ ADMIN
}
- """
- __enum__ = RoleEnum
+ """
+ __members__ = {
+ "GUEST": 0,
+ "MEMBER": 1,
+ "ADMIN": 2,
+ }
- schema = make_test_schema(UserRoleEnum)
+ class QueryType(GraphQLObject):
+ level: UserLevel
- # Specfied enum value is reversed
- result = graphql_sync(schema, "{ enumToRepr(enum: MOD) }")
- assert result.data["enumToRepr"] == repr(RoleEnum.MOD)
+ @GraphQLObject.resolver("level")
+ def resolve_level(*_) -> int:
+ return 2
- # Default enum value is reversed
- result = graphql_sync(schema, "{ enumToRepr }")
- assert result.data["enumToRepr"] == repr(RoleEnum.USER)
+ schema = make_executable_schema(QueryType)
- # Python value is converted to enum
- result = graphql_sync(
- schema, "{ reprToEnum }", root_value={"reprToEnum": "administrator"}
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ level: UserLevel!
+ }
+
+ enum UserLevel {
+ GUEST
+
+ \"\"\"Hello world.\"\"\"
+ MEMBER
+ ADMIN
+ }
+ """,
)
- assert result.data["reprToEnum"] == "ADMIN"
-
-
-def test_enum_type_raises_error_when_enum_mapping_misses_items_from_definition(
- data_regression,
-):
- class RoleEnum(str, Enum):
- USER = "user"
- MODERATOR = "moderator"
- ADMIN = "administrator"
-
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UserRoleEnum(EnumType):
- __schema__ = """
- enum UserRole {
- USER
- MOD
- ADMIN
- }
- """
- __enum__ = RoleEnum
-
- data_regression.check(str(err.value))
-
-
-def test_enum_type_raises_error_when_enum_mapping_has_extra_items_not_in_definition(
- data_regression,
-):
- class RoleEnum(str, Enum):
- USER = "user"
- REVIEW = "review"
- MOD = "moderator"
- ADMIN = "administrator"
-
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UserRoleEnum(EnumType):
- __schema__ = """
- enum UserRole {
- USER
- MOD
- ADMIN
- }
- """
- __enum__ = RoleEnum
- data_regression.check(str(err.value))
+ result = graphql_sync(schema, "{ level }")
+
+ assert not result.errors
+ assert result.data == {"level": "ADMIN"}
diff --git a/tests_next/test_enum_type_validation.py b/tests/test_enum_type_validation.py
similarity index 98%
rename from tests_next/test_enum_type_validation.py
rename to tests/test_enum_type_validation.py
index 29e983a..a5106d1 100644
--- a/tests_next/test_enum_type_validation.py
+++ b/tests/test_enum_type_validation.py
@@ -2,8 +2,8 @@
import pytest
-from ariadne_graphql_modules import gql
-from ariadne_graphql_modules.next import GraphQLEnum
+from ariadne import gql
+from ariadne_graphql_modules import GraphQLEnum
def test_schema_enum_type_validation_fails_for_invalid_type_schema(data_regression):
diff --git a/tests_next/test_get_field_args_from_resolver.py b/tests/test_get_field_args_from_resolver.py
similarity index 98%
rename from tests_next/test_get_field_args_from_resolver.py
rename to tests/test_get_field_args_from_resolver.py
index c7e0924..b281c28 100644
--- a/tests_next/test_get_field_args_from_resolver.py
+++ b/tests/test_get_field_args_from_resolver.py
@@ -1,4 +1,4 @@
-from ariadne_graphql_modules.next.graphql_object import get_field_args_from_resolver
+from ariadne_graphql_modules.object_type import get_field_args_from_resolver
def test_field_has_no_args_after_obj_and_info_args():
diff --git a/tests_next/test_id_type.py b/tests/test_id_type.py
similarity index 98%
rename from tests_next/test_id_type.py
rename to tests/test_id_type.py
index 1a4b2e1..9d53923 100644
--- a/tests_next/test_id_type.py
+++ b/tests/test_id_type.py
@@ -1,6 +1,6 @@
from graphql import graphql_sync
-from ariadne_graphql_modules.next import (
+from ariadne_graphql_modules import (
GraphQLID,
GraphQLInput,
GraphQLObject,
diff --git a/tests/test_input_type.py b/tests/test_input_type.py
index daad5e0..d5d09bd 100644
--- a/tests/test_input_type.py
+++ b/tests/test_input_type.py
@@ -1,293 +1,628 @@
+from typing import Optional
+
import pytest
-from ariadne import SchemaDirectiveVisitor
-from graphql import GraphQLError, graphql_sync
+from graphql import graphql_sync
+from ariadne import gql
from ariadne_graphql_modules import (
- DeferredType,
- DirectiveType,
- EnumType,
- InputType,
- InterfaceType,
- ObjectType,
- ScalarType,
+ GraphQLInput,
+ GraphQLObject,
make_executable_schema,
)
-def test_input_type_raises_attribute_error_when_defined_without_schema(data_regression):
- with pytest.raises(AttributeError) as err:
- # pylint: disable=unused-variable
- class UserInput(InputType):
- pass
+def test_input_type_instance_with_all_attrs_values():
+ class SearchInput(GraphQLInput):
+ query: str
+ age: int
+
+ obj = SearchInput(query="search", age=20)
+ assert obj.query == "search"
+ assert obj.age == 20
+
+
+def test_input_type_instance_with_omitted_attrs_being_none():
+ class SearchInput(GraphQLInput):
+ query: str
+ age: int
+
+ obj = SearchInput(age=20)
+ assert obj.query is None
+ assert obj.age == 20
+
+
+def test_input_type_instance_with_default_attrs_values():
+ class SearchInput(GraphQLInput):
+ query: str = "default"
+ age: int = 42
+
+ obj = SearchInput(age=20)
+ assert obj.query == "default"
+ assert obj.age == 20
+
+
+def test_input_type_instance_with_all_fields_values():
+ class SearchInput(GraphQLInput):
+ query: str = GraphQLInput.field()
+ age: int = GraphQLInput.field()
- data_regression.check(str(err.value))
+ obj = SearchInput(query="search", age=20)
+ assert obj.query == "search"
+ assert obj.age == 20
-def test_input_type_raises_error_when_defined_with_invalid_schema_type(data_regression):
- with pytest.raises(TypeError) as err:
- # pylint: disable=unused-variable
- class UserInput(InputType):
- __schema__ = True
+def test_input_type_instance_with_all_fields_default_values():
+ class SearchInput(GraphQLInput):
+ query: str = GraphQLInput.field(default_value="default")
+ age: int = GraphQLInput.field(default_value=42)
- data_regression.check(str(err.value))
+ obj = SearchInput(age=20)
+ assert obj.query == "default"
+ assert obj.age == 20
-def test_input_type_raises_error_when_defined_with_invalid_schema_str(data_regression):
- with pytest.raises(GraphQLError) as err:
- # pylint: disable=unused-variable
- class UserInput(InputType):
- __schema__ = "inpet UserInput"
+def test_input_type_instance_with_invalid_attrs_raising_error(data_regression):
+ class SearchInput(GraphQLInput):
+ query: str
+ age: int
- data_regression.check(str(err.value))
+ with pytest.raises(TypeError) as exc_info:
+ SearchInput(age=20, invalid="Ok")
+ data_regression.check(str(exc_info.value))
-def test_input_type_raises_error_when_defined_with_invalid_graphql_type_schema(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UserInput(InputType):
- __schema__ = """
- type User {
- id: ID!
+
+def test_schema_input_type_instance_with_all_attrs_values():
+ class SearchInput(GraphQLInput):
+ __schema__ = gql(
+ """
+ input Search {
+ query: String
+ age: Int
}
"""
+ )
- data_regression.check(str(err.value))
+ query: str
+ age: int
+ obj = SearchInput(query="search", age=20)
+ assert obj.query == "search"
+ assert obj.age == 20
-def test_input_type_raises_error_when_defined_with_multiple_types_schema(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UserInput(InputType):
- __schema__ = """
- input User
- input Group
+def test_schema_input_type_instance_with_omitted_attrs_being_none():
+ class SearchInput(GraphQLInput):
+ __schema__ = gql(
"""
+ input Search {
+ query: String
+ age: Int
+ }
+ """
+ )
- data_regression.check(str(err.value))
+ query: str
+ age: int
+ obj = SearchInput(age=20)
+ assert obj.query is None
+ assert obj.age == 20
-def test_input_type_raises_error_when_defined_without_fields(data_regression):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UserInput(InputType):
- __schema__ = "input User"
- data_regression.check(str(err.value))
+def test_schema_input_type_instance_with_default_attrs_values():
+ class SearchInput(GraphQLInput):
+ __schema__ = gql(
+ """
+ input Search {
+ query: String = "default"
+ age: Int = 42
+ }
+ """
+ )
+ query: str
+ age: int
-def test_input_type_extracts_graphql_name():
- class UserInput(InputType):
- __schema__ = """
- input User {
- id: ID!
- }
- """
+ obj = SearchInput(age=20)
+ assert obj.query == "default"
+ assert obj.age == 20
- assert UserInput.graphql_name == "User"
+def test_schema_input_type_instance_with_all_attrs_default_values():
+ class SearchInput(GraphQLInput):
+ __schema__ = gql(
+ """
+ input Search {
+ query: String = "default"
+ age: Int = 42
+ }
+ """
+ )
+
+ query: str
+ age: int
+
+ obj = SearchInput()
+ assert obj.query == "default"
+ assert obj.age == 42
-def test_input_type_raises_error_when_defined_without_field_type_dependency(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UserInput(InputType):
- __schema__ = """
- input User {
- id: ID!
- role: Role!
+
+def test_schema_input_type_instance_with_default_attrs_python_values():
+ class SearchInput(GraphQLInput):
+ __schema__ = gql(
+ """
+ input Search {
+ query: String
+ age: Int
}
"""
+ )
- data_regression.check(str(err.value))
+ query: str = "default"
+ age: int = 42
+ obj = SearchInput(age=20)
+ assert obj.query == "default"
+ assert obj.age == 20
-def test_input_type_verifies_field_dependency():
- # pylint: disable=unused-variable
- class RoleEnum(EnumType):
- __schema__ = """
- enum Role {
- USER
- ADMIN
- }
+
+def test_schema_input_type_instance_with_invalid_attrs_raising_error(data_regression):
+ class SearchInput(GraphQLInput):
+ __schema__ = gql(
+ """
+ input Search {
+ query: String
+ age: Int
+ }
+ """
+ )
+
+ query: str
+ age: int
+
+ with pytest.raises(TypeError) as exc_info:
+ SearchInput(age=20, invalid="Ok")
+
+ data_regression.check(str(exc_info.value))
+
+
+def test_input_type_arg(assert_schema_equals):
+ class SearchInput(GraphQLInput):
+ query: Optional[str]
+ age: Optional[int]
+
+ class QueryType(GraphQLObject):
+ search: str
+
+ @GraphQLObject.resolver("search")
+ def resolve_search(*_, input: SearchInput) -> str:
+ return f"{repr([input.query, input.age])}"
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
"""
+ type Query {
+ search(input: SearchInput!): String!
+ }
+
+ input SearchInput {
+ query: String
+ age: Int
+ }
+ """,
+ )
- class UserInput(InputType):
+ result = graphql_sync(schema, '{ search(input: { query: "Hello" }) }')
+
+ assert not result.errors
+ assert result.data == {"search": "['Hello', None]"}
+
+
+def test_schema_input_type_arg(assert_schema_equals):
+ class SearchInput(GraphQLInput):
__schema__ = """
- input User {
- id: ID!
- role: Role!
+ input SearchInput {
+ query: String
+ age: Int
}
"""
- __requires__ = [RoleEnum]
+ query: Optional[str]
+ age: Optional[int]
-def test_input_type_verifies_circular_dependency():
- # pylint: disable=unused-variable
- class UserInput(InputType):
- __schema__ = """
- input User {
- id: ID!
- patron: User
+ class QueryType(GraphQLObject):
+ search: str
+
+ @GraphQLObject.resolver("search")
+ def resolve_search(*_, input: SearchInput) -> str:
+ return f"{repr([input.query, input.age])}"
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ search(input: SearchInput!): String!
+ }
+
+ input SearchInput {
+ query: String
+ age: Int
}
+ """,
+ )
+
+ result = graphql_sync(schema, '{ search(input: { query: "Hello" }) }')
+
+ assert not result.errors
+ assert result.data == {"search": "['Hello', None]"}
+
+
+def test_input_type_automatic_out_name_arg(assert_schema_equals):
+ class SearchInput(GraphQLInput):
+ query: Optional[str]
+ min_age: Optional[int]
+
+ class QueryType(GraphQLObject):
+ search: str
+
+ @GraphQLObject.resolver("search")
+ def resolve_search(*_, input: SearchInput) -> str:
+ return f"{repr([input.query, input.min_age])}"
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
"""
+ type Query {
+ search(input: SearchInput!): String!
+ }
+
+ input SearchInput {
+ query: String
+ minAge: Int
+ }
+ """,
+ )
+
+ result = graphql_sync(schema, "{ search(input: { minAge: 21 }) }")
+
+ assert not result.errors
+ assert result.data == {"search": "[None, 21]"}
-def test_input_type_verifies_circular_dependency_using_deferred_type():
- # pylint: disable=unused-variable
- class GroupInput(InputType):
+def test_schema_input_type_automatic_out_name_arg(assert_schema_equals):
+ class SearchInput(GraphQLInput):
__schema__ = """
- input Group {
- id: ID!
- patron: User
+ input SearchInput {
+ query: String
+ minAge: Int
}
"""
- __requires__ = [DeferredType("User")]
- class UserInput(InputType):
+ query: Optional[str]
+ min_age: Optional[int]
+
+ class QueryType(GraphQLObject):
+ search: str
+
+ @GraphQLObject.resolver("search")
+ def resolve_search(*_, input: SearchInput) -> str:
+ return f"{repr([input.query, input.min_age])}"
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ search(input: SearchInput!): String!
+ }
+
+ input SearchInput {
+ query: String
+ minAge: Int
+ }
+ """,
+ )
+
+ result = graphql_sync(schema, "{ search(input: { minAge: 21 }) }")
+
+ assert not result.errors
+ assert result.data == {"search": "[None, 21]"}
+
+
+def test_schema_input_type_explicit_out_name_arg(assert_schema_equals):
+ class SearchInput(GraphQLInput):
__schema__ = """
- input User {
- id: ID!
- group: Group
+ input SearchInput {
+ query: String
+ minAge: Int
}
"""
- __requires__ = [GroupInput]
+ __out_names__ = {"minAge": "age"}
+ query: Optional[str]
+ age: Optional[int]
-def test_input_type_can_be_extended_with_new_fields():
- # pylint: disable=unused-variable
- class UserInput(InputType):
- __schema__ = """
- input User {
- id: ID!
+ class QueryType(GraphQLObject):
+ search: str
+
+ @GraphQLObject.resolver("search")
+ def resolve_search(*_, input: SearchInput) -> str:
+ return f"{repr([input.query, input.age])}"
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ search(input: SearchInput!): String!
+ }
+
+ input SearchInput {
+ query: String
+ minAge: Int
}
+ """,
+ )
+
+ result = graphql_sync(schema, "{ search(input: { minAge: 21 }) }")
+
+ assert not result.errors
+ assert result.data == {"search": "[None, 21]"}
+
+
+def test_input_type_self_reference(assert_schema_equals):
+ class SearchInput(GraphQLInput):
+ query: Optional[str]
+ extra: Optional["SearchInput"]
+
+ class QueryType(GraphQLObject):
+ search: str
+
+ @GraphQLObject.resolver("search")
+ def resolve_search(*_, input: SearchInput) -> str:
+ if input.extra:
+ extra_repr = input.extra.query
+ else:
+ extra_repr = None
+
+ return f"{repr([input.query, extra_repr])}"
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
"""
+ type Query {
+ search(input: SearchInput!): String!
+ }
- class ExtendUserInput(InputType):
- __schema__ = """
- extend input User {
- name: String!
+ input SearchInput {
+ query: String
+ extra: SearchInput
}
+ """,
+ )
+
+ result = graphql_sync(
+ schema,
"""
- __requires__ = [UserInput]
+ {
+ search(
+ input: { query: "Hello", extra: { query: "Other" } }
+ )
+ }
+ """,
+ )
+ assert not result.errors
+ assert result.data == {"search": "['Hello', 'Other']"}
-def test_input_type_can_be_extended_with_directive():
- # pylint: disable=unused-variable
- class ExampleDirective(DirectiveType):
- __schema__ = "directive @example on INPUT_OBJECT"
- __visitor__ = SchemaDirectiveVisitor
- class UserInput(InputType):
+def test_schema_input_type_with_default_value(assert_schema_equals):
+ class SearchInput(GraphQLInput):
__schema__ = """
- input User {
- id: ID!
+ input SearchInput {
+ query: String = "Search"
+ age: Int = 42
}
"""
- class ExtendUserInput(InputType):
- __schema__ = """
- extend input User @example
+ query: str
+ age: int
+
+ class QueryType(GraphQLObject):
+ search: str
+
+ @GraphQLObject.resolver("search")
+ def resolve_search(*_, input: SearchInput) -> str:
+ return f"{repr([input.query, input.age])}"
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
"""
- __requires__ = [UserInput, ExampleDirective]
-
-
-def test_input_type_raises_error_when_defined_without_extended_dependency(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ExtendUserInput(InputType):
- __schema__ = """
- extend input User {
- name: String!
- }
- """
+ type Query {
+ search(input: SearchInput!): String!
+ }
- data_regression.check(str(err.value))
+ input SearchInput {
+ query: String = "Search"
+ age: Int = 42
+ }
+ """,
+ )
+ result = graphql_sync(schema, "{ search(input: {}) }")
-def test_input_type_raises_error_when_extended_dependency_is_wrong_type(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ExampleInterface(InterfaceType):
- __schema__ = """
- interface User {
- id: ID!
- }
- """
+ assert not result.errors
+ assert result.data == {"search": "['Search', 42]"}
- class ExtendUserInput(InputType):
- __schema__ = """
- extend input User {
- name: String!
- }
- """
- __requires__ = [ExampleInterface]
- data_regression.check(str(err.value))
+def test_input_type_with_field_default_value(assert_schema_equals):
+ class SearchInput(GraphQLInput):
+ query: str = "default"
+ age: int = 42
+ flag: bool = False
+ class QueryType(GraphQLObject):
+ search: str
-def test_input_type_raises_error_when_defined_with_args_map_for_nonexisting_field(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UserInput(InputType):
- __schema__ = """
- input User {
- id: ID!
- }
- """
- __args__ = {
- "fullName": "full_name",
- }
+ @GraphQLObject.resolver("search")
+ def resolve_search(*_, input: SearchInput) -> str:
+ return f"{repr([input.query, input.age, input.flag])}"
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ search(input: SearchInput!): String!
+ }
+
+ input SearchInput {
+ query: String! = "default"
+ age: Int! = 42
+ flag: Boolean! = false
+ }
+ """,
+ )
+
+ result = graphql_sync(schema, "{ search(input: {}) }")
+
+ assert not result.errors
+ assert result.data == {"search": "['default', 42, False]"}
+
+
+def test_input_type_with_field_instance_default_value(assert_schema_equals):
+ class SearchInput(GraphQLInput):
+ query: str = GraphQLInput.field(default_value="default")
+ age: int = GraphQLInput.field(default_value=42)
+ flag: bool = GraphQLInput.field(default_value=False)
+
+ class QueryType(GraphQLObject):
+ search: str
+
+ @GraphQLObject.resolver("search")
+ def resolve_search(*_, input: SearchInput) -> str:
+ return f"{repr([input.query, input.age, input.flag])}"
- data_regression.check(str(err.value))
+ schema = make_executable_schema(QueryType)
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ search(input: SearchInput!): String!
+ }
+
+ input SearchInput {
+ query: String! = "default"
+ age: Int! = 42
+ flag: Boolean! = false
+ }
+ """,
+ )
+
+ result = graphql_sync(schema, "{ search(input: {}) }")
-class UserInput(InputType):
- __schema__ = """
- input UserInput {
- id: ID!
- fullName: String!
- }
- """
- __args__ = {
- "fullName": "full_name",
- }
+ assert not result.errors
+ assert result.data == {"search": "['default', 42, False]"}
-class GenericScalar(ScalarType):
- __schema__ = "scalar Generic"
+def test_input_type_with_field_type(assert_schema_equals):
+ class SearchInput(GraphQLInput):
+ query: str = GraphQLInput.field(graphql_type=int)
+ class QueryType(GraphQLObject):
+ search: str
-class QueryType(ObjectType):
- __schema__ = """
- type Query {
- reprInput(input: UserInput): Generic!
- }
- """
- __aliases__ = {"reprInput": "repr_input"}
- __requires__ = [GenericScalar, UserInput]
+ @GraphQLObject.resolver("search")
+ def resolve_search(*_, input: SearchInput) -> str:
+ return str(input)
- @staticmethod
- def resolve_repr_input(*_, input): # pylint: disable=redefined-builtin
- return input
+ schema = make_executable_schema(QueryType)
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ search(input: SearchInput!): String!
+ }
-schema = make_executable_schema(QueryType)
+ input SearchInput {
+ query: Int!
+ }
+ """,
+ )
-def test_input_type_maps_args_to_python_dict_keys():
- result = graphql_sync(schema, '{ reprInput(input: {id: "1", fullName: "Alice"}) }')
- assert result.data == {
- "reprInput": {"id": "1", "full_name": "Alice"},
- }
+def test_schema_input_type_with_field_description(assert_schema_equals):
+ class SearchInput(GraphQLInput):
+ __schema__ = """
+ input SearchInput {
+ \"\"\"Hello world.\"\"\"
+ query: String!
+ }
+ """
+
+ class QueryType(GraphQLObject):
+ search: str
+
+ @GraphQLObject.resolver("search")
+ def resolve_search(*_, input: SearchInput) -> str:
+ return str(input)
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ search(input: SearchInput!): String!
+ }
+
+ input SearchInput {
+ \"\"\"Hello world.\"\"\"
+ query: String!
+ }
+ """,
+ )
+
+
+def test_input_type_with_field_description(assert_schema_equals):
+ class SearchInput(GraphQLInput):
+ query: str = GraphQLInput.field(description="Hello world.")
+
+ class QueryType(GraphQLObject):
+ search: str
+
+ @GraphQLObject.resolver("search")
+ def resolve_search(*_, input: SearchInput) -> str:
+ return str(input)
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ search(input: SearchInput!): String!
+ }
+
+ input SearchInput {
+ \"\"\"Hello world.\"\"\"
+ query: String!
+ }
+ """,
+ )
diff --git a/tests_next/test_input_type_validation.py b/tests/test_input_type_validation.py
similarity index 97%
rename from tests_next/test_input_type_validation.py
rename to tests/test_input_type_validation.py
index f1e6273..94ea418 100644
--- a/tests_next/test_input_type_validation.py
+++ b/tests/test_input_type_validation.py
@@ -1,7 +1,7 @@
import pytest
-from ariadne_graphql_modules import gql
-from ariadne_graphql_modules.next import GraphQLInput
+from ariadne import gql
+from ariadne_graphql_modules import GraphQLInput
def test_schema_input_type_validation_fails_for_invalid_type_schema(data_regression):
diff --git a/tests/test_interface_type.py b/tests/test_interface_type.py
index be3637d..6ff2bbb 100644
--- a/tests/test_interface_type.py
+++ b/tests/test_interface_type.py
@@ -1,462 +1,369 @@
-from dataclasses import dataclass
+from typing import List, Union
-import pytest
-from ariadne import SchemaDirectiveVisitor
-from graphql import GraphQLError, graphql_sync
+from graphql import graphql_sync
from ariadne_graphql_modules import (
- DeferredType,
- DirectiveType,
- InterfaceType,
- ObjectType,
+ GraphQLID,
+ GraphQLObject,
+ GraphQLInterface,
+ GraphQLUnion,
make_executable_schema,
)
-def test_interface_type_raises_attribute_error_when_defined_without_schema(
- data_regression,
-):
- with pytest.raises(AttributeError) as err:
- # pylint: disable=unused-variable
- class ExampleInterface(InterfaceType):
- pass
+class CommentType(GraphQLObject):
+ id: GraphQLID
+ content: str
- data_regression.check(str(err.value))
+def test_interface_without_schema(assert_schema_equals):
+ class UserInterface(GraphQLInterface):
+ summary: str
+ score: int
-def test_interface_type_raises_error_when_defined_with_invalid_schema_type(
- data_regression,
-):
- with pytest.raises(TypeError) as err:
- # pylint: disable=unused-variable
- class ExampleInterface(InterfaceType):
- __schema__ = True
+ class UserType(GraphQLObject, UserInterface):
+ name: str
- data_regression.check(str(err.value))
+ class ResultType(GraphQLUnion):
+ __types__ = [UserType, CommentType]
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(graphql_type=List[ResultType])
+ def search(*_) -> List[Union[UserType, CommentType]]:
+ return [
+ UserType(id=1, username="Bob"),
+ CommentType(id=2, content="Hello World!"),
+ ]
-def test_interface_type_raises_error_when_defined_with_invalid_schema_str(
- data_regression,
-):
- with pytest.raises(GraphQLError) as err:
- # pylint: disable=unused-variable
- class ExampleInterface(InterfaceType):
- __schema__ = "interfaco Example"
-
- data_regression.check(str(err.value))
+ schema = make_executable_schema(QueryType, UserInterface, UserType)
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ search: [Result!]!
+ }
-def test_interface_type_raises_error_when_defined_with_invalid_graphql_type_schema(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ExampleInterface(InterfaceType):
- __schema__ = "type Example"
+ union Result = User | Comment
- data_regression.check(str(err.value))
+ type User implements UserInterface {
+ summary: String!
+ score: Int!
+ name: String!
+ }
+ type Comment {
+ id: ID!
+ content: String!
+ }
-def test_interface_type_raises_error_when_defined_with_multiple_types_schema(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ExampleInterface(InterfaceType):
- __schema__ = """
- interface Example
+ interface UserInterface {
+ summary: String!
+ score: Int!
+ }
- interface Other
- """
+ """,
+ )
+
+
+def test_interface_inheritance_without_schema(assert_schema_equals):
+ def hello_resolver(*_, name: str) -> str:
+ return f"Hello {name}!"
+
+ class UserInterface(GraphQLInterface):
+ summary: str
+ score: str = GraphQLInterface.field(
+ hello_resolver,
+ name="better_score",
+ graphql_type=str,
+ args={"name": GraphQLInterface.argument(name="json")},
+ description="desc",
+ default_value="my_json",
+ )
+
+ class UserType(GraphQLObject, UserInterface):
+ name: str = GraphQLInterface.field(
+ name="name",
+ graphql_type=str,
+ args={"name": GraphQLInterface.argument(name="json")},
+ default_value="my_json",
+ )
+
+ class ResultType(GraphQLUnion):
+ __types__ = [UserType, CommentType]
+
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(graphql_type=List[ResultType])
+ def search(*_) -> List[Union[UserType, CommentType]]:
+ return [
+ UserType(),
+ CommentType(id=2, content="Hello World!"),
+ ]
+
+ schema = make_executable_schema(QueryType, UserInterface, UserType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ search: [Result!]!
+ }
- data_regression.check(str(err.value))
+ union Result = User | Comment
+ type User implements UserInterface {
+ summary: String!
-def test_interface_type_raises_error_when_defined_without_fields(data_regression):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ExampleInterface(InterfaceType):
- __schema__ = "interface Example"
+ \"\"\"desc\"\"\"
+ better_score(json: String!): String!
+ name: String!
+ }
- data_regression.check(str(err.value))
+ type Comment {
+ id: ID!
+ content: String!
+ }
+ interface UserInterface {
+ summary: String!
-def test_interface_type_extracts_graphql_name():
- class ExampleInterface(InterfaceType):
- __schema__ = """
- interface Example {
- id: ID!
+ \"\"\"desc\"\"\"
+ better_score(json: String!): String!
}
- """
- assert ExampleInterface.graphql_name == "Example"
+ """,
+ )
+ result = graphql_sync(
+ schema, '{ search { ... on User{ better_score(json: "test") } } }'
+ )
-def test_interface_type_raises_error_when_defined_without_return_type_dependency(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ExampleInterface(InterfaceType):
- __schema__ = """
- interface Example {
- group: Group
- groups: [Group!]
- }
- """
+ assert not result.errors
+ assert result.data == {"search": [{"better_score": "Hello test!"}, {}]}
- data_regression.check(str(err.value))
-
-def test_interface_type_verifies_field_dependency():
- # pylint: disable=unused-variable
- class GroupType(ObjectType):
+def test_interface_with_schema(assert_schema_equals):
+ class UserInterface(GraphQLInterface):
__schema__ = """
- type Group {
- id: ID!
+ interface UserInterface {
+ summary: String!
+ score: Int!
}
"""
- class ExampleInterface(InterfaceType):
+ class UserType(GraphQLObject):
__schema__ = """
- interface Example {
- group: Group
- groups: [Group!]
+ type User implements UserInterface {
+ id: ID!
+ name: String!
+ summary: String!
+ score: Int!
}
"""
- __requires__ = [GroupType]
+ __implements__ = [UserInterface]
-def test_interface_type_verifies_circural_dependency():
- # pylint: disable=unused-variable
- class ExampleInterface(InterfaceType):
- __schema__ = """
- interface Example {
- parent: Example
- }
- """
+ class ResultType(GraphQLUnion):
+ __types__ = [UserType, CommentType]
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(graphql_type=List[ResultType])
+ def search(*_) -> List[Union[UserType, CommentType]]:
+ return [
+ UserType(id=1, username="Bob"),
+ CommentType(id=2, content="Hello World!"),
+ ]
-def test_interface_type_raises_error_when_defined_without_argument_type_dependency(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ExampleInterface(InterfaceType):
- __schema__ = """
- interface Example {
- actions(input: UserInput): [String!]!
- }
- """
+ schema = make_executable_schema(QueryType, UserType)
- data_regression.check(str(err.value))
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ search: [Result!]!
+ }
+ union Result = User | Comment
-def test_interface_type_verifies_circular_dependency_using_deferred_type():
- # pylint: disable=unused-variable
- class ExampleInterface(InterfaceType):
- __schema__ = """
- interface Example {
- id: ID!
- users: [User]
+ type User implements UserInterface {
+ id: ID!
+ name: String!
+ summary: String!
+ score: Int!
}
- """
- __requires__ = [DeferredType("User")]
- class UserType(ObjectType):
- __schema__ = """
- type User {
- roles: [Example]
+ interface UserInterface {
+ summary: String!
+ score: Int!
}
- """
- __requires__ = [ExampleInterface]
-
-def test_interface_type_can_be_extended_with_new_fields():
- # pylint: disable=unused-variable
- class ExampleInterface(InterfaceType):
- __schema__ = """
- interface Example {
- id: ID!
+ type Comment {
+ id: ID!
+ content: String!
}
+
+ """,
+ )
+
+
+def test_interface_inheritance2(assert_schema_equals):
+ class BaseEntityInterface(GraphQLInterface):
+ id: GraphQLID
+
+ class UserInterface(BaseEntityInterface):
+ username: str
+
+ class UserType(GraphQLObject, UserInterface):
+ name: str
+
+ class SuperUserType(UserType):
+ is_super_user: bool
+
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field
+ def users(*_) -> List[UserInterface]:
+ return [
+ UserType(id="1", username="test_user"),
+ SuperUserType(
+ id="2",
+ username="test_super_user",
+ is_super_user=True,
+ ),
+ ]
+
+ schema = make_executable_schema(
+ QueryType, BaseEntityInterface, UserInterface, UserType, SuperUserType
+ )
+
+ assert_schema_equals(
+ schema,
"""
+ type Query {
+ users: [UserInterface!]!
+ }
- class ExtendExampleInterface(InterfaceType):
- __schema__ = """
- extend interface Example {
- name: String
+ interface UserInterface {
+ id: ID!
+ username: String!
}
- """
- __requires__ = [ExampleInterface]
+ interface BaseEntityInterface {
+ id: ID!
+ }
-def test_interface_type_can_be_extended_with_directive():
- # pylint: disable=unused-variable
- class ExampleDirective(DirectiveType):
- __schema__ = "directive @example on INTERFACE"
- __visitor__ = SchemaDirectiveVisitor
+ type User implements BaseEntityInterface & UserInterface {
+ id: ID!
+ username: String!
+ name: String!
+ }
- class ExampleInterface(InterfaceType):
- __schema__ = """
- interface Example {
- id: ID!
+ type SuperUser implements BaseEntityInterface & UserInterface {
+ id: ID!
+ username: String!
+ name: String!
+ isSuperUser: Boolean!
}
- """
+ """,
+ )
- class ExtendExampleInterface(InterfaceType):
- __schema__ = """
- extend interface Example @example
+
+def test_interface_descriptions(assert_schema_equals):
+ class UserInterface(GraphQLInterface):
+ summary: str
+ score: int
+
+ __description__ = "Lorem ipsum."
+
+ class UserType(GraphQLObject, UserInterface):
+ id: GraphQLID
+ username: str
+
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field
+ def user(*_) -> UserType:
+ return UserType(id="1", username="test_user")
+
+ schema = make_executable_schema(QueryType, UserType, UserInterface)
+
+ assert_schema_equals(
+ schema,
"""
- __requires__ = [ExampleInterface, ExampleDirective]
+ type Query {
+ user: User!
+ }
+ type User implements UserInterface {
+ summary: String!
+ score: Int!
+ id: ID!
+ username: String!
+ }
-def test_interface_type_can_be_extended_with_other_interface():
- # pylint: disable=unused-variable
- class ExampleInterface(InterfaceType):
- __schema__ = """
- interface Example {
- id: ID!
+ \"\"\"Lorem ipsum.\"\"\"
+ interface UserInterface {
+ summary: String!
+ score: Int!
}
+ """,
+ )
+
+
+def test_interface_resolvers_and_field_descriptions(assert_schema_equals):
+ class UserInterface(GraphQLInterface):
+ summary: str
+ score: int
+
+ @GraphQLInterface.resolver("score", description="Lorem ipsum.")
+ def resolve_score(*_):
+ return 200
+
+ class UserType(GraphQLObject, UserInterface):
+ id: GraphQLID
+
+ class MyType(GraphQLObject, UserInterface):
+ id: GraphQLID
+ name: str
+
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(graphql_type=List[UserInterface])
+ def users(*_) -> List[UserInterface]:
+ return [MyType(id="2", name="old", summary="ss", score=22)]
+
+ schema = make_executable_schema(QueryType, UserType, MyType, UserInterface)
+
+ assert_schema_equals(
+ schema,
"""
+ type Query {
+ users: [UserInterface!]!
+ }
- class OtherInterface(InterfaceType):
- __schema__ = """
- interface Other {
- depth: Int!
+ interface UserInterface {
+ summary: String!
+
+ \"\"\"Lorem ipsum.\"\"\"
+ score: Int!
}
- """
- class ExtendExampleInterface(InterfaceType):
- __schema__ = """
- extend interface Example implements Other
- """
- __requires__ = [ExampleInterface, OtherInterface]
-
-
-def test_interface_type_raises_error_when_defined_without_extended_dependency(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ExtendExampleInterface(ObjectType):
- __schema__ = """
- extend interface Example {
- name: String
- }
- """
-
- data_regression.check(str(err.value))
-
-
-def test_interface_type_raises_error_when_extended_dependency_is_wrong_type(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ExampleType(ObjectType):
- __schema__ = """
- type Example {
- id: ID!
- }
- """
-
- class ExampleInterface(InterfaceType):
- __schema__ = """
- extend interface Example {
- name: String
- }
- """
- __requires__ = [ExampleType]
-
- data_regression.check(str(err.value))
-
-
-def test_interface_type_raises_error_when_defined_with_alias_for_nonexisting_field(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ExampleInterface(InterfaceType):
- __schema__ = """
- interface User {
- name: String
- }
- """
- __aliases__ = {
- "joinedDate": "joined_date",
- }
-
- data_regression.check(str(err.value))
-
-
-def test_interface_type_raises_error_when_defined_with_resolver_for_nonexisting_field(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ExampleInterface(InterfaceType):
- __schema__ = """
- interface User {
- name: String
- }
- """
-
- @staticmethod
- def resolve_group(*_):
- return None
-
- data_regression.check(str(err.value))
-
-
-@dataclass
-class User:
- id: int
- name: str
- summary: str
-
-
-@dataclass
-class Comment:
- id: int
- message: str
- summary: str
-
-
-class ResultInterface(InterfaceType):
- __schema__ = """
- interface Result {
- summary: String!
- score: Int!
- }
- """
-
- @staticmethod
- def resolve_type(instance, *_):
- if isinstance(instance, Comment):
- return "Comment"
-
- if isinstance(instance, User):
- return "User"
-
- return None
-
- @staticmethod
- def resolve_score(*_):
- return 42
-
-
-class UserType(ObjectType):
- __schema__ = """
- type User implements Result {
- id: ID!
- name: String!
- summary: String!
- score: Int!
- }
- """
- __requires__ = [ResultInterface]
-
-
-class CommentType(ObjectType):
- __schema__ = """
- type Comment implements Result {
- id: ID!
- message: String!
- summary: String!
- score: Int!
- }
- """
- __requires__ = [ResultInterface]
-
- @staticmethod
- def resolve_score(*_):
- return 16
-
-
-class QueryType(ObjectType):
- __schema__ = """
- type Query {
- results: [Result!]!
- }
- """
- __requires__ = [ResultInterface]
-
- @staticmethod
- def resolve_results(*_):
- return [
- User(id=1, name="Alice", summary="Summary for Alice"),
- Comment(id=1, message="Hello world!", summary="Summary for comment"),
- ]
-
-
-schema = make_executable_schema(QueryType, UserType, CommentType)
-
-
-def test_interface_type_binds_type_resolver():
- query = """
- query {
- results {
- ... on User {
- __typename
- id
- name
- summary
- }
- ... on Comment {
- __typename
- id
- message
- summary
- }
+ type User implements UserInterface {
+ summary: String!
+
+ \"\"\"Lorem ipsum.\"\"\"
+ score: Int!
+ id: ID!
}
- }
- """
-
- result = graphql_sync(schema, query)
- assert result.data == {
- "results": [
- {
- "__typename": "User",
- "id": "1",
- "name": "Alice",
- "summary": "Summary for Alice",
- },
- {
- "__typename": "Comment",
- "id": "1",
- "message": "Hello world!",
- "summary": "Summary for comment",
- },
- ],
- }
-
-
-def test_interface_type_binds_field_resolvers_to_implementing_types_fields():
- query = """
- query {
- results {
- ... on User {
- __typename
- score
- }
- ... on Comment {
- __typename
- score
- }
+
+ type My implements UserInterface {
+ summary: String!
+
+ \"\"\"Lorem ipsum.\"\"\"
+ score: Int!
+ id: ID!
+ name: String!
}
- }
- """
-
- result = graphql_sync(schema, query)
- assert result.data == {
- "results": [
- {
- "__typename": "User",
- "score": 42,
- },
- {
- "__typename": "Comment",
- "score": 16,
- },
- ],
- }
+ """,
+ )
+ result = graphql_sync(schema, "{ users { ... on My { __typename score } } }")
+
+ assert not result.errors
+ assert result.data == {"users": [{"__typename": "My", "score": 200}]}
diff --git a/tests/test_interface_type_validation.py b/tests/test_interface_type_validation.py
new file mode 100644
index 0000000..d441080
--- /dev/null
+++ b/tests/test_interface_type_validation.py
@@ -0,0 +1,23 @@
+import pytest
+
+from ariadne_graphql_modules import (
+ GraphQLID,
+ GraphQLObject,
+ GraphQLInterface,
+ make_executable_schema,
+)
+
+
+def test_interface_no_interface_in_schema(data_regression):
+ with pytest.raises(TypeError) as exc_info:
+
+ class BaseInterface(GraphQLInterface):
+ id: GraphQLID
+
+ class UserType(GraphQLObject, BaseInterface):
+ username: str
+ email: str
+
+ make_executable_schema(UserType)
+
+ data_regression.check(str(exc_info.value))
diff --git a/tests_next/test_make_executable_schema.py b/tests/test_make_executable_schema.py
similarity index 98%
rename from tests_next/test_make_executable_schema.py
rename to tests/test_make_executable_schema.py
index b927649..635901b 100644
--- a/tests_next/test_make_executable_schema.py
+++ b/tests/test_make_executable_schema.py
@@ -10,7 +10,7 @@
)
from ariadne import QueryType, SchemaDirectiveVisitor
-from ariadne_graphql_modules.next import GraphQLObject, make_executable_schema
+from ariadne_graphql_modules import GraphQLObject, make_executable_schema
def test_executable_schema_from_vanilla_schema_definition(assert_schema_equals):
diff --git a/tests_next/test_metadata.py b/tests/test_metadata.py
similarity index 96%
rename from tests_next/test_metadata.py
rename to tests/test_metadata.py
index d02f5f6..443d022 100644
--- a/tests_next/test_metadata.py
+++ b/tests/test_metadata.py
@@ -2,7 +2,7 @@
import pytest
-from ariadne_graphql_modules.next import GraphQLObject, graphql_enum
+from ariadne_graphql_modules import GraphQLObject, graphql_enum
class QueryType(GraphQLObject):
diff --git a/tests/test_object_type.py b/tests/test_object_type.py
index 8adf0e6..1d5f247 100644
--- a/tests/test_object_type.py
+++ b/tests/test_object_type.py
@@ -1,410 +1,1015 @@
+from typing import Optional
+
import pytest
-from ariadne import SchemaDirectiveVisitor
-from graphql import GraphQLError, graphql_sync
+from graphql import graphql_sync
-from ariadne_graphql_modules import (
- DeferredType,
- DirectiveType,
- InterfaceType,
- ObjectType,
- make_executable_schema,
-)
+from ariadne import gql
+from ariadne_graphql_modules import GraphQLObject, make_executable_schema
-def test_object_type_raises_attribute_error_when_defined_without_schema(
- data_regression,
-):
- with pytest.raises(AttributeError) as err:
- # pylint: disable=unused-variable
- class UserType(ObjectType):
- pass
+def test_object_type_instance_with_all_attrs_values():
+ class CategoryType(GraphQLObject):
+ name: str
+ posts: int
- data_regression.check(str(err.value))
+ obj = CategoryType(name="Welcome", posts=20)
+ assert obj.name == "Welcome"
+ assert obj.posts == 20
-def test_object_type_raises_error_when_defined_with_invalid_schema_type(
- data_regression,
-):
- with pytest.raises(TypeError) as err:
- # pylint: disable=unused-variable
- class UserType(ObjectType):
- __schema__ = True
+def test_object_type_instance_with_omitted_attrs_being_none():
+ class CategoryType(GraphQLObject):
+ name: str
+ posts: int
- data_regression.check(str(err.value))
+ obj = CategoryType(posts=20)
+ assert obj.name is None
+ assert obj.posts == 20
-def test_object_type_raises_error_when_defined_with_invalid_schema_str(data_regression):
- with pytest.raises(GraphQLError) as err:
- # pylint: disable=unused-variable
- class UserType(ObjectType):
- __schema__ = "typo User"
+def test_object_type_instance_with_aliased_attrs_values():
+ class CategoryType(GraphQLObject):
+ name: str
+ posts: int
- data_regression.check(str(err.value))
+ __aliases__ = {"name": "title"}
+ title: str
-def test_object_type_raises_error_when_defined_with_invalid_graphql_type_schema(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UserType(ObjectType):
- __schema__ = "scalar DateTime"
+ obj = CategoryType(title="Welcome", posts=20)
+ assert obj.title == "Welcome"
+ assert obj.posts == 20
- data_regression.check(str(err.value))
+def test_object_type_instance_with_omitted_attrs_being_default_values():
+ class CategoryType(GraphQLObject):
+ name: str = "Hello"
+ posts: int = 42
-def test_object_type_raises_error_when_defined_with_multiple_types_schema(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UserType(ObjectType):
- __schema__ = """
- type User
+ obj = CategoryType(posts=20)
+ assert obj.name == "Hello"
+ assert obj.posts == 20
+
+
+def test_object_type_instance_with_all_attrs_being_default_values():
+ class CategoryType(GraphQLObject):
+ name: str = "Hello"
+ posts: int = 42
+
+ obj = CategoryType()
+ assert obj.name == "Hello"
+ assert obj.posts == 42
+
+
+def test_object_type_instance_with_invalid_attrs_raising_error(data_regression):
+ class CategoryType(GraphQLObject):
+ name: str
+ posts: int
- type Group
+ with pytest.raises(TypeError) as exc_info:
+ CategoryType(name="Welcome", invalid="Ok")
+
+ data_regression.check(str(exc_info.value))
+
+
+def test_schema_object_type_instance_with_all_attrs_values():
+ class CategoryType(GraphQLObject):
+ __schema__ = gql(
+ """
+ type Category {
+ name: String
+ posts: Int
+ }
"""
+ )
+
+ name: str
+ posts: int
- data_regression.check(str(err.value))
+ obj = CategoryType(name="Welcome", posts=20)
+ assert obj.name == "Welcome"
+ assert obj.posts == 20
-def test_object_type_raises_error_when_defined_without_fields(data_regression):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UserType(ObjectType):
- __schema__ = "type User"
+def test_schema_object_type_instance_with_omitted_attrs_being_none():
+ class CategoryType(GraphQLObject):
+ __schema__ = gql(
+ """
+ type Category {
+ name: String
+ posts: Int
+ }
+ """
+ )
- data_regression.check(str(err.value))
+ name: str
+ posts: int
+ obj = CategoryType(posts=20)
+ assert obj.name is None
+ assert obj.posts == 20
-def test_object_type_extracts_graphql_name():
- class GroupType(ObjectType):
- __schema__ = """
- type Group {
- id: ID!
- }
- """
- assert GroupType.graphql_name == "Group"
+def test_schema_object_type_instance_with_omitted_attrs_being_default_values():
+ class CategoryType(GraphQLObject):
+ __schema__ = gql(
+ """
+ type Category {
+ name: String
+ posts: Int
+ }
+ """
+ )
+ name: str = "Hello"
+ posts: int = 42
-def test_object_type_accepts_all_builtin_scalar_types():
- # pylint: disable=unused-variable
- class FancyObjectType(ObjectType):
- __schema__ = """
- type FancyObject {
- id: ID!
- someInt: Int!
- someFloat: Float!
- someBoolean: Boolean!
- someString: String!
- }
- """
+ obj = CategoryType(posts=20)
+ assert obj.name == "Hello"
+ assert obj.posts == 20
-def test_object_type_raises_error_when_defined_without_return_type_dependency(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UserType(ObjectType):
- __schema__ = """
- type User {
- group: Group
- groups: [Group!]
+def test_schema_object_type_instance_with_all_attrs_being_default_values():
+ class CategoryType(GraphQLObject):
+ __schema__ = gql(
+ """
+ type Category {
+ name: String
+ posts: Int
}
"""
+ )
- data_regression.check(str(err.value))
+ name: str = "Hello"
+ posts: int = 42
+ obj = CategoryType()
+ assert obj.name == "Hello"
+ assert obj.posts == 42
-def test_object_type_verifies_field_dependency():
- # pylint: disable=unused-variable
- class GroupType(ObjectType):
- __schema__ = """
- type Group {
- id: ID!
- }
- """
- class UserType(ObjectType):
- __schema__ = """
- type User {
- group: Group
- groups: [Group!]
- }
- """
- __requires__ = [GroupType]
+def test_schema_object_type_instance_with_aliased_attrs_values():
+ class CategoryType(GraphQLObject):
+ __schema__ = gql(
+ """
+ type Category {
+ name: String
+ posts: Int
+ }
+ """
+ )
+ __aliases__ = {"name": "title"}
+ title: str = "Hello"
+ posts: int = 42
-def test_object_type_verifies_circular_dependency():
- # pylint: disable=unused-variable
- class UserType(ObjectType):
- __schema__ = """
- type User {
- follows: User
- }
- """
+ obj = CategoryType(title="Ok")
+ assert obj.title == "Ok"
+ assert obj.posts == 42
-def test_object_type_raises_error_when_defined_without_argument_type_dependency(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UserType(ObjectType):
- __schema__ = """
- type User {
- actions(input: UserInput): [String!]!
+def test_schema_object_type_instance_with_aliased_attrs_default_values():
+ class CategoryType(GraphQLObject):
+ __schema__ = gql(
+ """
+ type Category {
+ name: String
+ posts: Int
}
"""
+ )
+ __aliases__ = {"name": "title"}
- data_regression.check(str(err.value))
+ title: str = "Hello"
+ posts: int = 42
+ obj = CategoryType()
+ assert obj.title == "Hello"
+ assert obj.posts == 42
-def test_object_type_verifies_circular_dependency_using_deferred_type():
- # pylint: disable=unused-variable
- class GroupType(ObjectType):
- __schema__ = """
- type Group {
- id: ID!
- users: [User]
- }
+
+def test_schema_object_type_instance_with_invalid_attrs_raising_error(data_regression):
+ class CategoryType(GraphQLObject):
+ __schema__ = gql(
+ """
+ type Category {
+ name: String
+ posts: Int
+ }
+ """
+ )
+
+ name: str
+ posts: int
+
+ with pytest.raises(TypeError) as exc_info:
+ CategoryType(name="Welcome", invalid="Ok")
+
+ data_regression.check(str(exc_info.value))
+
+
+def test_schema_object_type_instance_with_aliased_attr_value():
+ class CategoryType(GraphQLObject):
+ __schema__ = gql(
+ """
+ type Category {
+ name: String
+ posts: Int
+ }
+ """
+ )
+ __aliases__ = {"name": "title"}
+
+ title: str
+ posts: int
+
+ obj = CategoryType(title="Welcome", posts=20)
+ assert obj.title == "Welcome"
+ assert obj.posts == 20
+
+
+def test_object_type_with_field(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ hello: str
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
"""
- __requires__ = [DeferredType("User")]
+ type Query {
+ hello: String!
+ }
+ """,
+ )
- class UserType(ObjectType):
- __schema__ = """
- type User {
- group: Group
+ result = graphql_sync(schema, "{ hello }", root_value={"hello": "Hello World!"})
+
+ assert not result.errors
+ assert result.data == {"hello": "Hello World!"}
+
+
+def test_object_type_with_alias(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ __aliases__ = {"hello": "welcome_message"}
+
+ hello: str
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ hello: String!
}
+ """,
+ )
+
+ result = graphql_sync(
+ schema, "{ hello }", root_value={"welcome_message": "Hello World!"}
+ )
+
+ assert not result.errors
+ assert result.data == {"hello": "Hello World!"}
+
+
+def test_object_type_with_alias_excludes_alias_targets(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ __aliases__ = {"hello": "welcome"}
+
+ hello: str
+ welcome: str
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
"""
- __requires__ = [GroupType]
+ type Query {
+ hello: String!
+ }
+ """,
+ )
+ result = graphql_sync(schema, "{ hello }", root_value={"welcome": "Hello World!"})
-def test_object_type_can_be_extended_with_new_fields():
- # pylint: disable=unused-variable
- class UserType(ObjectType):
- __schema__ = """
- type User {
- id: ID!
+ assert not result.errors
+ assert result.data == {"hello": "Hello World!"}
+
+
+def test_object_type_with_alias_includes_aliased_field_instances(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ __aliases__ = {"hello": "welcome"}
+
+ hello: str
+ welcome: str = GraphQLObject.field()
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ hello: String!
+ welcome: String!
}
+ """,
+ )
+
+ result = graphql_sync(
+ schema, "{ hello welcome }", root_value={"welcome": "Hello World!"}
+ )
+
+ assert not result.errors
+ assert result.data == {"hello": "Hello World!", "welcome": "Hello World!"}
+
+
+def test_object_type_with_attr_automatic_alias(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ test_message: str
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
"""
+ type Query {
+ testMessage: String!
+ }
+ """,
+ )
- class ExtendUserType(ObjectType):
- __schema__ = """
- extend type User {
- name: String
+ result = graphql_sync(
+ schema, "{ testMessage }", root_value={"test_message": "Hello World!"}
+ )
+
+ assert not result.errors
+ assert result.data == {"testMessage": "Hello World!"}
+
+
+def test_object_type_with_field_instance_automatic_alias(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ message: str = GraphQLObject.field(name="testMessage")
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ testMessage: String!
}
+ """,
+ )
+
+ result = graphql_sync(
+ schema, "{ testMessage }", root_value={"message": "Hello World!"}
+ )
+
+ assert not result.errors
+ assert result.data == {"testMessage": "Hello World!"}
+
+
+def test_object_type_with_field_resolver(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field
+ def hello(obj, info) -> str:
+ return "Hello World!"
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
"""
- __requires__ = [UserType]
+ type Query {
+ hello: String!
+ }
+ """,
+ )
+ result = graphql_sync(schema, "{ hello }")
-def test_object_type_can_be_extended_with_directive():
- # pylint: disable=unused-variable
- class ExampleDirective(DirectiveType):
- __schema__ = "directive @example on OBJECT"
- __visitor__ = SchemaDirectiveVisitor
+ assert not result.errors
+ assert result.data == {"hello": "Hello World!"}
- class UserType(ObjectType):
- __schema__ = """
- type User {
- id: ID!
+
+def test_object_type_with_typed_field_instance(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ hello = GraphQLObject.field(lambda *_: "Hello World!", graphql_type=str)
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ hello: String!
}
+ """,
+ )
+
+ result = graphql_sync(schema, "{ hello }")
+
+ assert not result.errors
+ assert result.data == {"hello": "Hello World!"}
+
+
+def test_object_type_with_annotated_field_instance(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ hello: str = GraphQLObject.field(lambda *_: "Hello World!")
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
"""
+ type Query {
+ hello: String!
+ }
+ """,
+ )
+
+ result = graphql_sync(schema, "{ hello }")
+
+ assert not result.errors
+ assert result.data == {"hello": "Hello World!"}
- class ExtendUserType(ObjectType):
- __schema__ = """
- extend type User @example
+
+def test_object_type_with_typed_field_and_field_resolver(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ name: str
+
+ @GraphQLObject.field
+ def hello(obj, info) -> str:
+ return "Hello World!"
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
"""
- __requires__ = [UserType, ExampleDirective]
+ type Query {
+ name: String!
+ hello: String!
+ }
+ """,
+ )
+
+ result = graphql_sync(schema, "{ name hello }", root_value={"name": "Ok"})
+
+ assert not result.errors
+ assert result.data == {"name": "Ok", "hello": "Hello World!"}
-def test_object_type_can_be_extended_with_interface():
- # pylint: disable=unused-variable
- class ExampleInterface(InterfaceType):
- __schema__ = """
- interface Interface {
- id: ID!
+def test_object_type_with_schema(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ __schema__ = gql(
+ """
+ type Query {
+ hello: String!
+ }
+ """
+ )
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ hello: String!
}
+ """,
+ )
+
+ result = graphql_sync(schema, "{ hello }", root_value={"hello": "Hello World!"})
+
+ assert not result.errors
+ assert result.data == {"hello": "Hello World!"}
+
+
+def test_object_type_with_nested_types(assert_schema_equals):
+ class UserType(GraphQLObject):
+ name: str
+
+ class PostType(GraphQLObject):
+ message: str
+
+ class QueryType(GraphQLObject):
+ user: UserType
+
+ @GraphQLObject.field(graphql_type=PostType)
+ def post(obj, info):
+ return {"message": "test"}
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
"""
+ type Query {
+ user: User!
+ post: Post!
+ }
- class UserType(ObjectType):
- __schema__ = """
type User {
- id: ID!
+ name: String!
+ }
+
+ type Post {
+ message: String!
}
+ """,
+ )
+
+ result = graphql_sync(
+ schema,
+ "{ user { name } post { message } }",
+ root_value={"user": {"name": "Bob"}},
+ )
+
+ assert not result.errors
+ assert result.data == {
+ "user": {
+ "name": "Bob",
+ },
+ "post": {"message": "test"},
+ }
+
+
+def test_resolver_decorator_sets_resolver_for_type_hint_field(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ hello: str
+
+ @GraphQLObject.resolver("hello")
+ def resolve_hello(*_):
+ return "Hello World!"
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
"""
+ type Query {
+ hello: String!
+ }
+ """,
+ )
+
+ result = graphql_sync(schema, "{ hello }")
+
+ assert not result.errors
+ assert result.data == {"hello": "Hello World!"}
+
+
+def test_resolver_decorator_sets_resolver_for_instance_field(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ hello: str = GraphQLObject.field(name="hello")
- class ExtendUserType(ObjectType):
- __schema__ = """
- extend type User implements Interface
+ @GraphQLObject.resolver("hello")
+ def resolve_hello(*_):
+ return "Hello World!"
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
"""
- __requires__ = [UserType, ExampleInterface]
+ type Query {
+ hello: String!
+ }
+ """,
+ )
+ result = graphql_sync(schema, "{ hello }")
-def test_object_type_raises_error_when_defined_without_extended_dependency(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ExtendUserType(ObjectType):
- __schema__ = """
- extend type User {
- name: String
+ assert not result.errors
+ assert result.data == {"hello": "Hello World!"}
+
+
+def test_resolver_decorator_sets_resolver_for_field_in_schema(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ __schema__ = gql(
+ """
+ type Query {
+ hello: String!
}
"""
+ )
- data_regression.check(str(err.value))
+ @GraphQLObject.resolver("hello")
+ def resolve_hello(*_):
+ return "Hello World!"
+ schema = make_executable_schema(QueryType)
-def test_object_type_raises_error_when_extended_dependency_is_wrong_type(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ExampleInterface(InterfaceType):
- __schema__ = """
- interface Example {
- id: ID!
- }
- """
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ hello: String!
+ }
+ """,
+ )
- class ExampleType(ObjectType):
- __schema__ = """
- extend type Example {
- name: String
- }
- """
- __requires__ = [ExampleInterface]
+ result = graphql_sync(schema, "{ hello }")
- data_regression.check(str(err.value))
+ assert not result.errors
+ assert result.data == {"hello": "Hello World!"}
-def test_object_type_raises_error_when_defined_with_alias_for_nonexisting_field(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UserType(ObjectType):
- __schema__ = """
- type User {
- name: String
- }
+def test_object_type_with_description(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ __description__ = "Lorem ipsum."
+
+ hello: str
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ \"\"\"Lorem ipsum.\"\"\"
+ type Query {
+ hello: String!
+ }
+ """,
+ )
+
+ result = graphql_sync(schema, "{ hello }", root_value={"hello": "Hello World!"})
+
+ assert not result.errors
+ assert result.data == {"hello": "Hello World!"}
+
+
+def test_field_decorator_sets_description_for_field(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(description="Lorem ipsum.")
+ def hello(obj, info) -> str:
+ return "Hello World!"
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ \"\"\"Lorem ipsum.\"\"\"
+ hello: String!
+ }
+ """,
+ )
+
+ result = graphql_sync(schema, "{ hello }")
+
+ assert not result.errors
+ assert result.data == {"hello": "Hello World!"}
+
+
+def test_field_decorator_sets_description_for_field_arg(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(
+ args={"name": GraphQLObject.argument(description="Lorem ipsum.")}
+ )
+ def hello(obj, info, name: str) -> str:
+ return f"Hello {name}!"
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ hello(
+ \"\"\"Lorem ipsum.\"\"\"
+ name: String!
+ ): String!
+ }
+ """,
+ )
+
+ result = graphql_sync(schema, '{ hello(name: "Bob") }')
+
+ assert not result.errors
+ assert result.data == {"hello": "Hello Bob!"}
+
+
+def test_resolver_decorator_sets_description_for_type_hint_field(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ hello: str
+
+ @GraphQLObject.resolver("hello", description="Lorem ipsum.")
+ def resolve_hello(*_):
+ return "Hello World!"
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ \"\"\"Lorem ipsum.\"\"\"
+ hello: String!
+ }
+ """,
+ )
+
+ result = graphql_sync(schema, "{ hello }")
+
+ assert not result.errors
+ assert result.data == {"hello": "Hello World!"}
+
+
+def test_resolver_decorator_sets_description_for_field_in_schema(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ __schema__ = gql(
"""
- __aliases__ = {
- "joinedDate": "joined_date",
+ type Query {
+ hello: String!
}
+ """
+ )
- data_regression.check(str(err.value))
+ @GraphQLObject.resolver("hello", description="Lorem ipsum.")
+ def resolve_hello(*_):
+ return "Hello World!"
+ schema = make_executable_schema(QueryType)
-def test_object_type_raises_error_when_defined_with_resolver_for_nonexisting_field(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UserType(ObjectType):
- __schema__ = """
- type User {
- name: String
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ \"\"\"Lorem ipsum.\"\"\"
+ hello: String!
+ }
+ """,
+ )
+
+ result = graphql_sync(schema, "{ hello }")
+
+ assert not result.errors
+ assert result.data == {"hello": "Hello World!"}
+
+
+def test_resolver_decorator_sets_description_for_field_arg(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ hello: str
+
+ @GraphQLObject.resolver(
+ "hello", args={"name": GraphQLObject.argument(description="Lorem ipsum.")}
+ )
+ def resolve_hello(obj, info, name: str) -> str:
+ return f"Hello {name}!"
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ hello(
+ \"\"\"Lorem ipsum.\"\"\"
+ name: String!
+ ): String!
+ }
+ """,
+ )
+
+ result = graphql_sync(schema, '{ hello(name: "Bob") }')
+
+ assert not result.errors
+ assert result.data == {"hello": "Hello Bob!"}
+
+
+def test_schema_sets_description_for_field_arg(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ __schema__ = gql(
+ """
+ type Query {
+ hello(
+ \"\"\"Lorem ipsum.\"\"\"
+ name: String!
+ ): String!
}
"""
+ )
- @staticmethod
- def resolve_group(*_):
- return None
+ @GraphQLObject.resolver("hello")
+ def resolve_hello(*_, name: str):
+ return f"Hello {name}!"
- data_regression.check(str(err.value))
+ schema = make_executable_schema(QueryType)
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ hello(
+ \"\"\"Lorem ipsum.\"\"\"
+ name: String!
+ ): String!
+ }
+ """,
+ )
-def test_object_type_raises_error_when_defined_with_field_args_for_nonexisting_field(
- data_regression,
+ result = graphql_sync(schema, '{ hello(name: "Bob") }')
+
+ assert not result.errors
+ assert result.data == {"hello": "Hello Bob!"}
+
+
+def test_resolver_decorator_sets_description_for_field_arg_in_schema(
+ assert_schema_equals,
):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UserType(ObjectType):
- __schema__ = """
- type User {
- name: String
+ class QueryType(GraphQLObject):
+ __schema__ = gql(
+ """
+ type Query {
+ hello(name: String!): String!
}
"""
- __fields_args__ = {"group": {}}
+ )
+
+ @GraphQLObject.resolver(
+ "hello", args={"name": GraphQLObject.argument(description="Description")}
+ )
+ def resolve_hello(*_, name: str):
+ return f"Hello {name}!"
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ hello(
+ \"\"\"Description\"\"\"
+ name: String!
+ ): String!
+ }
+ """,
+ )
+
+ result = graphql_sync(schema, '{ hello(name: "Bob") }')
- data_regression.check(str(err.value))
+ assert not result.errors
+ assert result.data == {"hello": "Hello Bob!"}
-def test_object_type_raises_error_when_defined_with_field_args_for_nonexisting_arg(
- data_regression,
+def test_object_type_self_reference(
+ assert_schema_equals,
):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UserType(ObjectType):
- __schema__ = """
- type User {
- name: String
- }
- """
- __fields_args__ = {"name": {"arg": "arg2"}}
+ class CategoryType(GraphQLObject):
+ name: str
+ parent: Optional["CategoryType"]
- data_regression.check(str(err.value))
+ class QueryType(GraphQLObject):
+ category: CategoryType
+ schema = make_executable_schema(QueryType)
-class QueryType(ObjectType):
- __schema__ = """
- type Query {
- field: String!
- other: String!
- firstField: String!
- secondField: String!
- fieldWithArg(someArg: String): String!
- }
- """
- __aliases__ = {
- "firstField": "first_field",
- "secondField": "second_field",
- "fieldWithArg": "field_with_arg",
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ category: Category!
+ }
+
+ type Category {
+ name: String!
+ parent: Category
+ }
+ """,
+ )
+
+ result = graphql_sync(
+ schema,
+ "{ category { name parent { name } } }",
+ root_value={
+ "category": {
+ "name": "Lorem",
+ "parent": {
+ "name": "Ipsum",
+ },
+ },
+ },
+ )
+
+ assert not result.errors
+ assert result.data == {
+ "category": {
+ "name": "Lorem",
+ "parent": {
+ "name": "Ipsum",
+ },
+ },
}
- __fields_args__ = {"fieldWithArg": {"someArg": "some_arg"}}
- @staticmethod
- def resolve_other(*_):
- return "Word Up!"
- @staticmethod
- def resolve_second_field(obj, *_):
- return "Obj: %s" % obj["secondField"]
+def test_object_type_return_instance(
+ assert_schema_equals,
+):
+ class CategoryType(GraphQLObject):
+ name: str
+ color: str
+
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field()
+ def category(*_) -> CategoryType:
+ return CategoryType(
+ name="Welcome",
+ color="#FF00FF",
+ )
+
+ schema = make_executable_schema(QueryType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ category: Category!
+ }
- @staticmethod
- def resolve_field_with_arg(*_, some_arg):
- return some_arg
+ type Category {
+ name: String!
+ color: String!
+ }
+ """,
+ )
+ result = graphql_sync(schema, "{ category { name color } }")
-schema = make_executable_schema(QueryType)
+ assert not result.errors
+ assert result.data == {
+ "category": {
+ "name": "Welcome",
+ "color": "#FF00FF",
+ },
+ }
-def test_object_resolves_field_with_default_resolver():
- result = graphql_sync(schema, "{ field }", root_value={"field": "Hello!"})
- assert result.data["field"] == "Hello!"
+def test_object_type_nested_type(
+ assert_schema_equals,
+):
+ class UserType(GraphQLObject):
+ username: str
+ class CategoryType(GraphQLObject):
+ name: str
+ parent: Optional["CategoryType"]
+ owner: UserType
-def test_object_resolves_field_with_custom_resolver():
- result = graphql_sync(schema, "{ other }")
- assert result.data["other"] == "Word Up!"
+ class QueryType(GraphQLObject):
+ category: CategoryType
+ schema = make_executable_schema(QueryType)
-def test_object_resolves_field_with_aliased_default_resolver():
- result = graphql_sync(
- schema, "{ firstField }", root_value={"first_field": "Howdy?"}
- )
- assert result.data["firstField"] == "Howdy?"
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ category: Category!
+ }
+ type Category {
+ name: String!
+ parent: Category
+ owner: User!
+ }
-def test_object_resolves_field_with_aliased_custom_resolver():
- result = graphql_sync(schema, "{ secondField }", root_value={"secondField": "Hey!"})
- assert result.data["secondField"] == "Obj: Hey!"
+ type User {
+ username: String!
+ }
+ """,
+ )
+ result = graphql_sync(
+ schema,
+ "{ category { name parent { name } owner { username } } }",
+ root_value={
+ "category": {
+ "name": "Lorem",
+ "parent": {
+ "name": "Ipsum",
+ },
+ "owner": {
+ "username": "John",
+ },
+ },
+ },
+ )
-def test_object_resolves_field_with_arg_out_name_customized():
- result = graphql_sync(schema, '{ fieldWithArg(someArg: "test") }')
- assert result.data["fieldWithArg"] == "test"
+ assert not result.errors
+ assert result.data == {
+ "category": {
+ "name": "Lorem",
+ "parent": {
+ "name": "Ipsum",
+ },
+ "owner": {
+ "username": "John",
+ },
+ },
+ }
diff --git a/tests_next/test_object_type_field_args.py b/tests/test_object_type_field_args.py
similarity index 99%
rename from tests_next/test_object_type_field_args.py
rename to tests/test_object_type_field_args.py
index 2a358cb..10e815b 100644
--- a/tests_next/test_object_type_field_args.py
+++ b/tests/test_object_type_field_args.py
@@ -1,6 +1,6 @@
from graphql import GraphQLResolveInfo, graphql_sync
-from ariadne_graphql_modules.next import GraphQLObject, make_executable_schema
+from ariadne_graphql_modules import GraphQLObject, make_executable_schema
def test_object_type_field_resolver_with_scalar_arg(assert_schema_equals):
diff --git a/tests_next/test_object_type_validation.py b/tests/test_object_type_validation.py
similarity index 99%
rename from tests_next/test_object_type_validation.py
rename to tests/test_object_type_validation.py
index 2fcf813..4396a51 100644
--- a/tests_next/test_object_type_validation.py
+++ b/tests/test_object_type_validation.py
@@ -1,7 +1,7 @@
import pytest
-from ariadne_graphql_modules import gql
-from ariadne_graphql_modules.next import GraphQLObject
+from ariadne import gql
+from ariadne_graphql_modules import GraphQLObject
def test_schema_object_type_validation_fails_for_invalid_type_schema(data_regression):
diff --git a/tests/test_scalar_type.py b/tests/test_scalar_type.py
index ec85340..a880d5b 100644
--- a/tests/test_scalar_type.py
+++ b/tests/test_scalar_type.py
@@ -1,287 +1,111 @@
-from datetime import date, datetime
+from datetime import date
-import pytest
-from ariadne import SchemaDirectiveVisitor
-from graphql import GraphQLError, StringValueNode, graphql_sync
+from graphql import graphql_sync
+from ariadne import gql
from ariadne_graphql_modules import (
- DirectiveType,
- ObjectType,
- ScalarType,
+ GraphQLObject,
+ GraphQLScalar,
make_executable_schema,
)
-def test_scalar_type_raises_attribute_error_when_defined_without_schema(
- data_regression,
-):
- with pytest.raises(AttributeError) as err:
- # pylint: disable=unused-variable
- class DateScalar(ScalarType):
- pass
+class DateScalar(GraphQLScalar[date]):
+ @classmethod
+ def serialize(cls, value):
+ if isinstance(value, cls):
+ return str(value.unwrap())
- data_regression.check(str(err.value))
+ return str(value)
-def test_scalar_type_raises_error_when_defined_with_invalid_schema_type(
- data_regression,
-):
- with pytest.raises(TypeError) as err:
- # pylint: disable=unused-variable
- class DateScalar(ScalarType):
- __schema__ = True
+def test_scalar_field_returning_scalar_instance(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ date: DateScalar
- data_regression.check(str(err.value))
+ @GraphQLObject.resolver("date")
+ def resolve_date(*_) -> DateScalar:
+ return DateScalar(date(1989, 10, 30))
+ schema = make_executable_schema(QueryType)
-def test_scalar_type_raises_error_when_defined_with_invalid_schema_str(data_regression):
- with pytest.raises(GraphQLError) as err:
- # pylint: disable=unused-variable
- class DateScalar(ScalarType):
- __schema__ = "scalor Date"
-
- data_regression.check(str(err.value))
-
-
-def test_scalar_type_raises_error_when_defined_with_invalid_graphql_type_schema(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class DateScalar(ScalarType):
- __schema__ = "type DateTime"
-
- data_regression.check(str(err.value))
-
-
-def test_scalar_type_raises_error_when_defined_with_multiple_types_schema(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class DateScalar(ScalarType):
- __schema__ = """
- scalar Date
-
- scalar DateTime
- """
-
- data_regression.check(str(err.value))
-
-
-def test_scalar_type_extracts_graphql_name():
- class DateScalar(ScalarType):
- __schema__ = "scalar Date"
-
- assert DateScalar.graphql_name == "Date"
-
-
-def test_scalar_type_can_be_extended_with_directive():
- # pylint: disable=unused-variable
- class ExampleDirective(DirectiveType):
- __schema__ = "directive @example on SCALAR"
- __visitor__ = SchemaDirectiveVisitor
-
- class DateScalar(ScalarType):
- __schema__ = "scalar Date"
-
- class ExtendDateScalar(ScalarType):
- __schema__ = "extend scalar Date @example"
- __requires__ = [DateScalar, ExampleDirective]
-
-
-class DateReadOnlyScalar(ScalarType):
- __schema__ = "scalar DateReadOnly"
-
- @staticmethod
- def serialize(date):
- return date.strftime("%Y-%m-%d")
-
-
-class DateInputScalar(ScalarType):
- __schema__ = "scalar DateInput"
-
- @staticmethod
- def parse_value(formatted_date):
- parsed_datetime = datetime.strptime(formatted_date, "%Y-%m-%d")
- return parsed_datetime.date()
-
- @staticmethod
- def parse_literal(ast, variable_values=None): # pylint: disable=unused-argument
- if not isinstance(ast, StringValueNode):
- raise ValueError()
-
- formatted_date = ast.value
- parsed_datetime = datetime.strptime(formatted_date, "%Y-%m-%d")
- return parsed_datetime.date()
-
-
-class DefaultParserScalar(ScalarType):
- __schema__ = "scalar DefaultParser"
-
- @staticmethod
- def parse_value(value):
- return type(value).__name__
-
-
-TEST_DATE = date(2006, 9, 13)
-TEST_DATE_SERIALIZED = TEST_DATE.strftime("%Y-%m-%d")
-
-
-class QueryType(ObjectType):
- __schema__ = """
- type Query {
- testSerialize: DateReadOnly!
- testInput(value: DateInput!): Boolean!
- testInputValueType(value: DefaultParser!): String!
- }
- """
- __requires__ = [
- DateReadOnlyScalar,
- DateInputScalar,
- DefaultParserScalar,
- ]
- __aliases__ = {
- "testSerialize": "test_serialize",
- "testInput": "test_input",
- "testInputValueType": "test_input_value_type",
- }
-
- @staticmethod
- def resolve_test_serialize(*_):
- return TEST_DATE
-
- @staticmethod
- def resolve_test_input(*_, value):
- assert value == TEST_DATE
- return True
-
- @staticmethod
- def resolve_test_input_value_type(*_, value):
- return value
-
-
-schema = make_executable_schema(QueryType)
-
-
-def test_attempt_deserialize_str_literal_without_valid_date_raises_error():
- test_input = "invalid string"
- result = graphql_sync(schema, '{ testInput(value: "%s") }' % test_input)
- assert result.errors is not None
- assert str(result.errors[0]).splitlines()[:1] == [
- "Expected value of type 'DateInput!', found \"invalid string\"; "
- "time data 'invalid string' does not match format '%Y-%m-%d'"
- ]
-
-
-def test_attempt_deserialize_wrong_type_literal_raises_error():
- test_input = 123
- result = graphql_sync(schema, "{ testInput(value: %s) }" % test_input)
- assert result.errors is not None
- assert str(result.errors[0]).splitlines()[:1] == [
- "Expected value of type 'DateInput!', found 123; "
- ]
-
-
-def test_default_literal_parser_is_used_to_extract_value_str_from_ast_node():
- class ValueParserOnlyScalar(ScalarType):
- __schema__ = "scalar DateInput"
-
- @staticmethod
- def parse_value(formatted_date):
- parsed_datetime = datetime.strptime(formatted_date, "%Y-%m-%d")
- return parsed_datetime.date()
+ assert_schema_equals(
+ schema,
+ """
+ scalar Date
- class ValueParserOnlyQueryType(ObjectType):
- __schema__ = """
type Query {
- parse(value: DateInput!): String!
+ date: Date!
}
- """
- __requires__ = [ValueParserOnlyScalar]
-
- @staticmethod
- def resolve_parse(*_, value):
- return value
-
- schema = make_executable_schema(ValueParserOnlyQueryType)
- result = graphql_sync(schema, """{ parse(value: "%s") }""" % TEST_DATE_SERIALIZED)
- assert result.errors is None
- assert result.data == {"parse": "2006-09-13"}
+ """,
+ )
+ result = graphql_sync(schema, "{ date }")
-parametrized_query = """
- query parseValueTest($value: DateInput!) {
- testInput(value: $value)
- }
-"""
+ assert not result.errors
+ assert result.data == {"date": "1989-10-30"}
-def test_variable_with_valid_date_string_is_deserialized_to_python_date():
- variables = {"value": TEST_DATE_SERIALIZED}
- result = graphql_sync(schema, parametrized_query, variable_values=variables)
- assert result.errors is None
- assert result.data == {"testInput": True}
+def test_scalar_field_returning_scalar_wrapped_type(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ scalar_date: DateScalar
+ @GraphQLObject.resolver("scalar_date", graphql_type=DateScalar)
+ def resolve_date(*_) -> date:
+ return date(1989, 10, 30)
-def test_attempt_deserialize_str_variable_without_valid_date_raises_error():
- variables = {"value": "invalid string"}
- result = graphql_sync(schema, parametrized_query, variable_values=variables)
- assert result.errors is not None
- assert str(result.errors[0]).splitlines()[:1] == [
- "Variable '$value' got invalid value 'invalid string'; "
- "Expected type 'DateInput'. "
- "time data 'invalid string' does not match format '%Y-%m-%d'"
- ]
+ schema = make_executable_schema(QueryType)
+ assert_schema_equals(
+ schema,
+ """
+ scalar Date
-def test_attempt_deserialize_wrong_type_variable_raises_error():
- variables = {"value": 123}
- result = graphql_sync(schema, parametrized_query, variable_values=variables)
- assert result.errors is not None
- assert str(result.errors[0]).splitlines()[:1] == [
- "Variable '$value' got invalid value 123; Expected type 'DateInput'. "
- "strptime() argument 1 must be str, not int"
- ]
+ type Query {
+ scalarDate: Date!
+ }
+ """,
+ )
+ result = graphql_sync(schema, "{ scalarDate }")
-def test_literal_string_is_deserialized_by_default_parser():
- result = graphql_sync(schema, '{ testInputValueType(value: "test") }')
- assert result.errors is None
- assert result.data == {"testInputValueType": "str"}
+ assert not result.errors
+ assert result.data == {"scalarDate": "1989-10-30"}
-def test_literal_int_is_deserialized_by_default_parser():
- result = graphql_sync(schema, "{ testInputValueType(value: 123) }")
- assert result.errors is None
- assert result.data == {"testInputValueType": "int"}
+class SchemaDateScalar(GraphQLScalar[date]):
+ __schema__ = gql("scalar Date")
+ @classmethod
+ def serialize(cls, value):
+ if isinstance(value, cls):
+ return str(value.unwrap())
-def test_literal_float_is_deserialized_by_default_parser():
- result = graphql_sync(schema, "{ testInputValueType(value: 1.5) }")
- assert result.errors is None
- assert result.data == {"testInputValueType": "float"}
+ return str(value)
-def test_literal_bool_true_is_deserialized_by_default_parser():
- result = graphql_sync(schema, "{ testInputValueType(value: true) }")
- assert result.errors is None
- assert result.data == {"testInputValueType": "bool"}
+def test_schema_scalar_field_returning_scalar_instance(assert_schema_equals):
+ class QueryType(GraphQLObject):
+ date: SchemaDateScalar
+ @GraphQLObject.resolver("date")
+ def resolve_date(*_) -> SchemaDateScalar:
+ return SchemaDateScalar(date(1989, 10, 30))
-def test_literal_bool_false_is_deserialized_by_default_parser():
- result = graphql_sync(schema, "{ testInputValueType(value: false) }")
- assert result.errors is None
- assert result.data == {"testInputValueType": "bool"}
+ schema = make_executable_schema(QueryType)
+ assert_schema_equals(
+ schema,
+ """
+ scalar Date
-def test_literal_object_is_deserialized_by_default_parser():
- result = graphql_sync(schema, "{ testInputValueType(value: {}) }")
- assert result.errors is None
- assert result.data == {"testInputValueType": "dict"}
+ type Query {
+ date: Date!
+ }
+ """,
+ )
+ result = graphql_sync(schema, "{ date }")
-def test_literal_list_is_deserialized_by_default_parser():
- result = graphql_sync(schema, "{ testInputValueType(value: []) }")
- assert result.errors is None
- assert result.data == {"testInputValueType": "list"}
+ assert not result.errors
+ assert result.data == {"date": "1989-10-30"}
diff --git a/tests_next/test_scalar_type_validation.py b/tests/test_scalar_type_validation.py
similarity index 91%
rename from tests_next/test_scalar_type_validation.py
rename to tests/test_scalar_type_validation.py
index d473cb7..edd193e 100644
--- a/tests_next/test_scalar_type_validation.py
+++ b/tests/test_scalar_type_validation.py
@@ -1,7 +1,7 @@
import pytest
-from ariadne_graphql_modules import gql
-from ariadne_graphql_modules.next import GraphQLScalar
+from ariadne import gql
+from ariadne_graphql_modules import GraphQLScalar
def test_schema_scalar_type_validation_fails_for_invalid_type_schema(data_regression):
diff --git a/tests_next/test_standard_enum.py b/tests/test_standard_enum.py
similarity index 99%
rename from tests_next/test_standard_enum.py
rename to tests/test_standard_enum.py
index 9f8eded..ca95562 100644
--- a/tests_next/test_standard_enum.py
+++ b/tests/test_standard_enum.py
@@ -3,7 +3,7 @@
import pytest
from graphql import graphql_sync
-from ariadne_graphql_modules.next import (
+from ariadne_graphql_modules import (
GraphQLObject,
create_graphql_enum_model,
graphql_enum,
diff --git a/tests/test_subscription_type.py b/tests/test_subscription_type.py
index c0067cf..bb43729 100644
--- a/tests/test_subscription_type.py
+++ b/tests/test_subscription_type.py
@@ -1,325 +1,754 @@
-import pytest
-from ariadne import SchemaDirectiveVisitor
-from graphql import GraphQLError, build_schema
+from typing import List
+from ariadne import gql
+from graphql import subscribe, parse
+import pytest
from ariadne_graphql_modules import (
- DirectiveType,
- InterfaceType,
- ObjectType,
- SubscriptionType,
+ GraphQLID,
+ GraphQLObject,
+ GraphQLSubscription,
+ GraphQLUnion,
+ make_executable_schema,
)
-def test_subscription_type_raises_attribute_error_when_defined_without_schema(
- data_regression,
-):
- with pytest.raises(AttributeError) as err:
- # pylint: disable=unused-variable
- class UsersSubscription(SubscriptionType):
- pass
+class Message(GraphQLObject):
+ id: GraphQLID
+ content: str
+ author: str
- data_regression.check(str(err.value))
+class User(GraphQLObject):
+ id: GraphQLID
+ username: str
-def test_subscription_type_raises_error_when_defined_with_invalid_schema_type(
- data_regression,
-):
- with pytest.raises(TypeError) as err:
- # pylint: disable=unused-variable
- class UsersSubscription(SubscriptionType):
- __schema__ = True
- data_regression.check(str(err.value))
+class Notification(GraphQLUnion):
+ __types__ = [Message, User]
-def test_subscription_type_raises_error_when_defined_with_invalid_schema_str(
- data_regression,
-):
- with pytest.raises(GraphQLError) as err:
- # pylint: disable=unused-variable
- class UsersSubscription(SubscriptionType):
- __schema__ = "typo Subscription"
+@pytest.mark.asyncio
+async def test_basic_subscription_without_schema(assert_schema_equals):
+ class SubscriptionType(GraphQLSubscription):
+ message_added: Message
- data_regression.check(str(err.value))
+ @GraphQLSubscription.source("message_added")
+ async def message_added_generator(obj, info):
+ while True:
+ yield {"id": "some_id", "content": "message", "author": "Anon"}
+ @GraphQLSubscription.resolver("message_added", graphql_type=Message)
+ async def resolve_message_added(message, info):
+ return message
-def test_subscription_type_raises_error_when_defined_with_invalid_graphql_type_schema(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UsersSubscription(SubscriptionType):
- __schema__ = "scalar Subscription"
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(graphql_type=str)
+ def search_sth(*_) -> str:
+ return "search"
- data_regression.check(str(err.value))
+ schema = make_executable_schema(QueryType, SubscriptionType)
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ searchSth: String!
+ }
-def test_subscription_type_raises_error_when_defined_with_invalid_graphql_type_name(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UsersSubscription(SubscriptionType):
- __schema__ = "type Other"
+ type Subscription {
+ messageAdded: Message!
+ }
- data_regression.check(str(err.value))
+ type Message {
+ id: ID!
+ content: String!
+ author: String!
+ }
+ """,
+ )
+ query = parse("subscription { messageAdded {id content author} }")
+ sub = await subscribe(schema, query)
+
+ # Ensure the subscription is an async iterator
+ assert hasattr(sub, "__aiter__")
+
+ # Fetch the first result
+ result = await sub.__anext__()
+
+ # Validate the result
+ assert not result.errors
+ assert result.data == {
+ "messageAdded": {"id": "some_id", "content": "message", "author": "Anon"}
+ }
+
+
+@pytest.mark.asyncio
+async def test_subscription_with_arguments_without_schema(assert_schema_equals):
+ class SubscriptionType(GraphQLSubscription):
+ message_added: Message
+
+ @GraphQLSubscription.source(
+ "message_added",
+ args={"channel": GraphQLObject.argument(description="Lorem ipsum.")},
+ )
+ async def message_added_generator(obj, info, channel: GraphQLID):
+ while True:
+ yield {
+ "id": "some_id",
+ "content": f"message_{channel}",
+ "author": "Anon",
+ }
+
+ @GraphQLSubscription.resolver(
+ "message_added",
+ graphql_type=Message,
+ )
+ async def resolve_message_added(message, *_, channel: GraphQLID):
+ return message
+
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(graphql_type=str)
+ def search_sth(*_) -> str:
+ return "search"
+
+ schema = make_executable_schema(QueryType, SubscriptionType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ searchSth: String!
+ }
-def test_subscription_type_raises_error_when_defined_without_fields(data_regression):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class UsersSubscription(SubscriptionType):
- __schema__ = "type Subscription"
+ type Subscription {
+ messageAdded(
+ \"\"\"Lorem ipsum.\"\"\"
+ channel: ID!
+ ): Message!
+ }
- data_regression.check(str(err.value))
+ type Message {
+ id: ID!
+ content: String!
+ author: String!
+ }
+ """,
+ )
+ query = parse('subscription { messageAdded(channel: "123") {id content author} }')
+ sub = await subscribe(schema, query)
+
+ # Ensure the subscription is an async iterator
+ assert hasattr(sub, "__aiter__")
+
+ # Fetch the first result
+ result = await sub.__anext__()
+
+ # Validate the result
+ assert not result.errors
+ assert result.data == {
+ "messageAdded": {"id": "some_id", "content": "message_123", "author": "Anon"}
+ }
+
+
+@pytest.mark.asyncio
+async def test_multiple_supscriptions_without_schema(assert_schema_equals):
+ class SubscriptionType(GraphQLSubscription):
+ message_added: Message
+ user_joined: User
+
+ @GraphQLSubscription.source(
+ "message_added",
+ args={"channel": GraphQLObject.argument(description="Lorem ipsum.")},
+ )
+ async def message_added_generator(obj, info, channel: GraphQLID):
+ while True:
+ yield {
+ "id": "some_id",
+ "content": f"message_{channel}",
+ "author": "Anon",
+ }
+
+ @GraphQLSubscription.resolver(
+ "message_added",
+ graphql_type=Message,
+ )
+ async def resolve_message_added(message, *_, channel: GraphQLID):
+ return message
+
+ @GraphQLSubscription.source(
+ "user_joined",
+ )
+ async def user_joined_generator(obj, info):
+ while True:
+ yield {
+ "id": "some_id",
+ "username": "username",
+ }
+
+ @GraphQLSubscription.resolver(
+ "user_joined",
+ graphql_type=Message,
+ )
+ async def resolve_user_joined(user, *_):
+ return user
+
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(graphql_type=str)
+ def search_sth(*_) -> str:
+ return "search"
+
+ schema = make_executable_schema(QueryType, SubscriptionType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ searchSth: String!
+ }
-def test_subscription_type_extracts_graphql_name():
- class UsersSubscription(SubscriptionType):
- __schema__ = """
type Subscription {
- thread: ID!
+ messageAdded(
+ \"\"\"Lorem ipsum.\"\"\"
+ channel: ID!
+ ): Message!
+ userJoined: User!
+ }
+
+ type Message {
+ id: ID!
+ content: String!
+ author: String!
}
+
+ type User {
+ id: ID!
+ username: String!
+ }
+ """,
+ )
+
+ query = parse("subscription { userJoined {id username} }")
+ sub = await subscribe(schema, query)
+
+ # Ensure the subscription is an async iterator
+ assert hasattr(sub, "__aiter__")
+
+ # Fetch the first result
+ result = await sub.__anext__()
+
+ # Validate the result
+ assert not result.errors
+ assert result.data == {"userJoined": {"id": "some_id", "username": "username"}}
+
+
+@pytest.mark.asyncio
+async def test_subscription_with_complex_data_without_schema(assert_schema_equals):
+ class SubscriptionType(GraphQLSubscription):
+ messages_in_channel: List[Message]
+
+ @GraphQLSubscription.source(
+ "messages_in_channel",
+ args={"channel_id": GraphQLObject.argument(description="Lorem ipsum.")},
+ )
+ async def message_added_generator(obj, info, channel_id: GraphQLID):
+ while True:
+ yield [
+ {
+ "id": "some_id",
+ "content": f"message_{channel_id}",
+ "author": "Anon",
+ }
+ ]
+
+ @GraphQLSubscription.resolver(
+ "messages_in_channel",
+ graphql_type=Message,
+ )
+ async def resolve_message_added(message, *_, channel_id: GraphQLID):
+ return message
+
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(graphql_type=str)
+ def search_sth(*_) -> str:
+ return "search"
+
+ schema = make_executable_schema(QueryType, SubscriptionType)
+
+ assert_schema_equals(
+ schema,
"""
+ type Query {
+ searchSth: String!
+ }
- assert UsersSubscription.graphql_name == "Subscription"
+ type Subscription {
+ messagesInChannel(
+ \"\"\"Lorem ipsum.\"\"\"
+ channelId: ID!
+ ): [Message!]!
+ }
+ type Message {
+ id: ID!
+ content: String!
+ author: String!
+ }
+ """,
+ )
-def test_subscription_type_raises_error_when_defined_without_return_type_dependency(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ChatSubscription(SubscriptionType):
- __schema__ = """
- type Subscription {
- chat: Chat
- Chats: [Chat!]
- }
- """
+ query = parse(
+ 'subscription { messagesInChannel(channelId: "123") {id content author} }'
+ )
+ sub = await subscribe(schema, query)
+
+ # Ensure the subscription is an async iterator
+ assert hasattr(sub, "__aiter__")
+
+ # Fetch the first result
+ result = await sub.__anext__()
+
+ # Validate the result
+ assert not result.errors
+ assert result.data == {
+ "messagesInChannel": [
+ {"id": "some_id", "content": "message_123", "author": "Anon"}
+ ]
+ }
+
+
+@pytest.mark.asyncio
+async def test_subscription_with_union_without_schema(assert_schema_equals):
+ class SubscriptionType(GraphQLSubscription):
+ notification_received: Notification
+
+ @GraphQLSubscription.source(
+ "notification_received",
+ )
+ async def message_added_generator(obj, info):
+ while True:
+ yield Message(id=1, content="content", author="anon")
+
+ @GraphQLSubscription.resolver(
+ "notification_received",
+ )
+ async def resolve_message_added(message, *_):
+ return message
+
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(graphql_type=str)
+ def search_sth(*_) -> str:
+ return "search"
+
+ schema = make_executable_schema(QueryType, SubscriptionType)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ searchSth: String!
+ }
- data_regression.check(str(err.value))
+ type Subscription {
+ notificationReceived: Notification!
+ }
+ union Notification = Message | User
-def test_subscription_type_verifies_field_dependency():
- # pylint: disable=unused-variable
- class ChatType(ObjectType):
- __schema__ = """
- type Chat {
- id: ID!
+ type Message {
+ id: ID!
+ content: String!
+ author: String!
}
- """
- class ChatSubscription(SubscriptionType):
- __schema__ = """
- type Subscription {
- chat: Chat
- Chats: [Chat!]
+ type User {
+ id: ID!
+ username: String!
}
- """
- __requires__ = [ChatType]
+ """,
+ )
+
+ query = parse("subscription { notificationReceived { ... on Message { id } } }")
+ sub = await subscribe(schema, query)
+
+ # Ensure the subscription is an async iterator
+ assert hasattr(sub, "__aiter__")
+
+ # Fetch the first result
+ result = await sub.__anext__()
+ # Validate the result
+ assert not result.errors
+ assert result.data == {"notificationReceived": {"id": "1"}}
-def test_subscription_type_raises_error_when_defined_without_argument_type_dependency(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ChatSubscription(SubscriptionType):
- __schema__ = """
+
+@pytest.mark.asyncio
+async def test_basic_subscription_with_schema(assert_schema_equals):
+ class SubscriptionType(GraphQLSubscription):
+ __schema__ = gql(
+ """
type Subscription {
- chat(input: ChannelInput): [String!]!
+ messageAdded: Message!
}
"""
+ )
+
+ @GraphQLSubscription.source("messageAdded")
+ async def message_added_generator(obj, info):
+ while True:
+ yield {"id": "some_id", "content": "message", "author": "Anon"}
+
+ @GraphQLSubscription.resolver("messageAdded", graphql_type=Message)
+ async def resolve_message_added(message, info):
+ return message
- data_regression.check(str(err.value))
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(graphql_type=str)
+ def search_sth(*_) -> str:
+ return "search"
+ schema = make_executable_schema(QueryType, SubscriptionType, Message)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ searchSth: String!
+ }
-def test_subscription_type_can_be_extended_with_new_fields():
- # pylint: disable=unused-variable
- class ChatSubscription(SubscriptionType):
- __schema__ = """
type Subscription {
- chat: ID!
+ messageAdded: Message!
}
- """
- class ExtendChatSubscription(SubscriptionType):
- __schema__ = """
- extend type Subscription {
- thread: ID!
+ type Message {
+ id: ID!
+ content: String!
+ author: String!
}
- """
- __requires__ = [ChatSubscription]
+ """,
+ )
+ query = parse("subscription { messageAdded {id content author} }")
+ sub = await subscribe(schema, query)
-def test_subscription_type_can_be_extended_with_directive():
- # pylint: disable=unused-variable
- class ExampleDirective(DirectiveType):
- __schema__ = "directive @example on OBJECT"
- __visitor__ = SchemaDirectiveVisitor
+ # Ensure the subscription is an async iterator
+ assert hasattr(sub, "__aiter__")
- class ChatSubscription(SubscriptionType):
- __schema__ = """
- type Subscription {
- chat: ID!
- }
- """
+ # Fetch the first result
+ result = await sub.__anext__()
- class ExtendChatSubscription(SubscriptionType):
- __schema__ = "extend type Subscription @example"
- __requires__ = [ChatSubscription, ExampleDirective]
+ # Validate the result
+ assert not result.errors
+ assert result.data == {
+ "messageAdded": {"id": "some_id", "content": "message", "author": "Anon"}
+ }
-def test_subscription_type_can_be_extended_with_interface():
- # pylint: disable=unused-variable
- class ExampleInterface(InterfaceType):
- __schema__ = """
- interface Interface {
- threads: ID!
- }
+@pytest.mark.asyncio
+async def test_subscription_with_arguments_with_schema(assert_schema_equals):
+ class SubscriptionType(GraphQLSubscription):
+ __schema__ = gql(
+ """
+ type Subscription {
+ messageAdded(channel: ID!): Message!
+ }
+ """
+ )
+
+ @GraphQLSubscription.source(
+ "messageAdded",
+ )
+ async def message_added_generator(obj, info, channel: GraphQLID):
+ while True:
+ yield {
+ "id": "some_id",
+ "content": f"message_{channel}",
+ "author": "Anon",
+ }
+
+ @GraphQLSubscription.resolver(
+ "messageAdded",
+ graphql_type=Message,
+ )
+ async def resolve_message_added(message, *_, channel: GraphQLID):
+ return message
+
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(graphql_type=str)
+ def search_sth(*_) -> str:
+ return "search"
+
+ schema = make_executable_schema(QueryType, SubscriptionType, Message)
+
+ assert_schema_equals(
+ schema,
"""
+ type Query {
+ searchSth: String!
+ }
- class ChatSubscription(SubscriptionType):
- __schema__ = """
type Subscription {
- chat: ID!
+ messageAdded(channel: ID!): Message!
}
- """
- class ExtendChatSubscription(SubscriptionType):
- __schema__ = """
- extend type Subscription implements Interface {
- threads: ID!
+ type Message {
+ id: ID!
+ content: String!
+ author: String!
}
- """
- __requires__ = [ChatSubscription, ExampleInterface]
-
-
-def test_subscription_type_raises_error_when_defined_without_extended_dependency(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ExtendChatSubscription(SubscriptionType):
- __schema__ = """
- extend type Subscription {
- thread: ID!
- }
- """
+ """,
+ )
- data_regression.check(str(err.value))
+ query = parse('subscription { messageAdded(channel: "123") {id content author} }')
+ sub = await subscribe(schema, query)
+ # Ensure the subscription is an async iterator
+ assert hasattr(sub, "__aiter__")
-def test_subscription_type_raises_error_when_extended_dependency_is_wrong_type(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ExampleInterface(InterfaceType):
- __schema__ = """
- interface Subscription {
- id: ID!
- }
- """
+ # Fetch the first result
+ result = await sub.__anext__()
- class ExtendChatSubscription(SubscriptionType):
- __schema__ = """
- extend type Subscription {
- thread: ID!
- }
- """
- __requires__ = [ExampleInterface]
-
- data_regression.check(str(err.value))
+ # Validate the result
+ assert not result.errors
+ assert result.data == {
+ "messageAdded": {"id": "some_id", "content": "message_123", "author": "Anon"}
+ }
-def test_subscription_type_raises_error_when_defined_with_alias_for_nonexisting_field(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ChatSubscription(SubscriptionType):
- __schema__ = """
+@pytest.mark.asyncio
+async def test_multiple_supscriptions_with_schema(assert_schema_equals):
+ class SubscriptionType(GraphQLSubscription):
+ __schema__ = gql(
+ """
type Subscription {
- chat: ID!
+ messageAdded: Message!
+ userJoined: User!
}
"""
- __aliases__ = {
- "userAlerts": "user_alerts",
- }
+ )
+
+ @GraphQLSubscription.source(
+ "messageAdded",
+ )
+ async def message_added_generator(obj, info):
+ while True:
+ yield {
+ "id": "some_id",
+ "content": "message",
+ "author": "Anon",
+ }
+
+ @GraphQLSubscription.resolver(
+ "messageAdded",
+ )
+ async def resolve_message_added(message, *_):
+ return message
+
+ @GraphQLSubscription.source(
+ "userJoined",
+ )
+ async def user_joined_generator(obj, info):
+ while True:
+ yield {
+ "id": "some_id",
+ "username": "username",
+ }
+
+ @GraphQLSubscription.resolver(
+ "userJoined",
+ )
+ async def resolve_user_joined(user, *_):
+ return user
+
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(graphql_type=str)
+ def search_sth(*_) -> str:
+ return "search"
+
+ schema = make_executable_schema(QueryType, SubscriptionType, Message, User)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ searchSth: String!
+ }
- data_regression.check(str(err.value))
+ type Subscription {
+ messageAdded: Message!
+ userJoined: User!
+ }
+ type Message {
+ id: ID!
+ content: String!
+ author: String!
+ }
-def test_subscription_type_raises_error_when_defined_with_resolver_for_nonexisting_field(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ChatSubscription(SubscriptionType):
- __schema__ = """
- type Subscription {
- chat: ID!
- }
- """
+ type User {
+ id: ID!
+ username: String!
+ }
+ """,
+ )
+
+ query = parse("subscription { userJoined {id username} }")
+ sub = await subscribe(schema, query)
- @staticmethod
- def resolve_group(*_):
- return None
+ # Ensure the subscription is an async iterator
+ assert hasattr(sub, "__aiter__")
- data_regression.check(str(err.value))
+ # Fetch the first result
+ result = await sub.__anext__()
+ # Validate the result
+ assert not result.errors
+ assert result.data == {"userJoined": {"id": "some_id", "username": "username"}}
-def test_subscription_type_raises_error_when_defined_with_sub_for_nonexisting_field(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ChatSubscription(SubscriptionType):
- __schema__ = """
+
+@pytest.mark.asyncio
+async def test_subscription_with_complex_data_with_schema(assert_schema_equals):
+ class SubscriptionType(GraphQLSubscription):
+ __schema__ = gql(
+ """
type Subscription {
- chat: ID!
+ messagesInChannel(channelId: ID!): [Message!]!
}
"""
+ )
+
+ @GraphQLSubscription.source(
+ "messagesInChannel",
+ )
+ async def message_added_generator(obj, info, channelId: GraphQLID):
+ while True:
+ yield [
+ {
+ "id": "some_id",
+ "content": f"message_{channelId}",
+ "author": "Anon",
+ }
+ ]
+
+ @GraphQLSubscription.resolver(
+ "messagesInChannel",
+ )
+ async def resolve_message_added(message, *_, channelId: GraphQLID):
+ return message
+
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(graphql_type=str)
+ def search_sth(*_) -> str:
+ return "search"
+
+ schema = make_executable_schema(QueryType, SubscriptionType, Message)
+
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ searchSth: String!
+ }
+
+ type Subscription {
+ messagesInChannel(channelId: ID!): [Message!]!
+ }
- @staticmethod
- def subscribe_group(*_):
- return None
+ type Message {
+ id: ID!
+ content: String!
+ author: String!
+ }
+ """,
+ )
- data_regression.check(str(err.value))
+ query = parse(
+ 'subscription { messagesInChannel(channelId: "123") {id content author} }'
+ )
+ sub = await subscribe(schema, query)
+ # Ensure the subscription is an async iterator
+ assert hasattr(sub, "__aiter__")
-def test_subscription_type_binds_resolver_and_subscriber_to_schema():
- schema = build_schema(
- """
- type Query {
- hello: String
- }
+ # Fetch the first result
+ result = await sub.__anext__()
+ # Validate the result
+ assert not result.errors
+ assert result.data == {
+ "messagesInChannel": [
+ {"id": "some_id", "content": "message_123", "author": "Anon"}
+ ]
+ }
+
+
+@pytest.mark.asyncio
+async def test_subscription_with_union_with_schema(assert_schema_equals):
+ class SubscriptionType(GraphQLSubscription):
+ __schema__ = gql(
+ """
type Subscription {
- chat: ID!
+ notificationReceived: Notification!
}
+ """
+ )
+
+ @GraphQLSubscription.source(
+ "notificationReceived",
+ )
+ async def message_added_generator(obj, info):
+ while True:
+ yield Message(id=1, content="content", author="anon")
+
+ @GraphQLSubscription.resolver(
+ "notificationReceived",
+ )
+ async def resolve_message_added(message, *_):
+ return message
+
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(graphql_type=str)
+ def search_sth(*_) -> str:
+ return "search"
+
+ schema = make_executable_schema(QueryType, SubscriptionType, Notification)
+
+ assert_schema_equals(
+ schema,
"""
- )
+ type Query {
+ searchSth: String!
+ }
- class ChatSubscription(SubscriptionType):
- __schema__ = """
type Subscription {
- chat: ID!
+ notificationReceived: Notification!
}
- """
- @staticmethod
- def resolve_chat(*_):
- return None
+ union Notification = Message | User
+
+ type Message {
+ id: ID!
+ content: String!
+ author: String!
+ }
+
+ type User {
+ id: ID!
+ username: String!
+ }
+ """,
+ )
+
+ query = parse("subscription { notificationReceived { ... on Message { id } } }")
+ sub = await subscribe(schema, query)
- @staticmethod
- def subscribe_chat(*_):
- return None
+ # Ensure the subscription is an async iterator
+ assert hasattr(sub, "__aiter__")
- ChatSubscription.__bind_to_schema__(schema)
+ # Fetch the first result
+ result = await sub.__anext__()
- field = schema.type_map.get("Subscription").fields["chat"]
- assert field.resolve is ChatSubscription.resolve_chat
- assert field.subscribe is ChatSubscription.subscribe_chat
+ # Validate the result
+ assert not result.errors
+ assert result.data == {"notificationReceived": {"id": "1"}}
diff --git a/tests_next/test_subscription_type_validation.py b/tests/test_subscription_type_validation.py
similarity index 99%
rename from tests_next/test_subscription_type_validation.py
rename to tests/test_subscription_type_validation.py
index 4b59cc7..2f5d1df 100644
--- a/tests_next/test_subscription_type_validation.py
+++ b/tests/test_subscription_type_validation.py
@@ -1,6 +1,6 @@
from ariadne import gql
import pytest
-from ariadne_graphql_modules.next import (
+from ariadne_graphql_modules import (
GraphQLID,
GraphQLObject,
GraphQLSubscription,
diff --git a/tests_next/test_typing.py b/tests/test_typing.py
similarity index 95%
rename from tests_next/test_typing.py
rename to tests/test_typing.py
index 9e4e3fb..3723470 100644
--- a/tests_next/test_typing.py
+++ b/tests/test_typing.py
@@ -5,8 +5,8 @@
from graphql import ListTypeNode, NameNode, NamedTypeNode, NonNullTypeNode
import pytest
-from ariadne_graphql_modules.next import GraphQLObject, deferred, graphql_enum
-from ariadne_graphql_modules.next.typing import get_graphql_type, get_type_node
+from ariadne_graphql_modules import GraphQLObject, deferred, graphql_enum
+from ariadne_graphql_modules.typing import get_graphql_type, get_type_node
if TYPE_CHECKING:
from .types import ForwardEnum, ForwardScalar
@@ -124,7 +124,7 @@ def test_get_non_null_graphql_list_type_node_from_python_builtin_type(metadata):
def test_get_graphql_type_node_from_annotated_type(metadata):
class MockType(GraphQLObject):
- field: Annotated["ForwardScalar", deferred("tests_next.types")]
+ field: Annotated["ForwardScalar", deferred("tests.types")]
assert_non_null_type(
get_type_node(metadata, MockType.__annotations__["field"]), "Forward"
@@ -142,7 +142,7 @@ class MockType(GraphQLObject):
def test_get_graphql_type_node_from_nullable_annotated_type(metadata):
class MockType(GraphQLObject):
- field: Optional[Annotated["ForwardScalar", deferred("tests_next.types")]]
+ field: Optional[Annotated["ForwardScalar", deferred("tests.types")]]
assert_named_type(
get_type_node(metadata, MockType.__annotations__["field"]), "Forward"
@@ -151,7 +151,7 @@ class MockType(GraphQLObject):
def test_get_graphql_type_node_from_annotated_enum(metadata):
class MockType(GraphQLObject):
- field: Annotated["ForwardEnum", deferred("tests_next.types")]
+ field: Annotated["ForwardEnum", deferred("tests.types")]
assert_non_null_type(
get_type_node(metadata, MockType.__annotations__["field"]), "ForwardEnum"
diff --git a/tests/test_union_type.py b/tests/test_union_type.py
index 61c8a3a..da926c5 100644
--- a/tests/test_union_type.py
+++ b/tests/test_union_type.py
@@ -1,251 +1,223 @@
-from dataclasses import dataclass
+from typing import List, Union
-import pytest
-from ariadne import SchemaDirectiveVisitor
-from graphql import GraphQLError, graphql_sync
+from graphql import graphql_sync
from ariadne_graphql_modules import (
- DirectiveType,
- ObjectType,
- UnionType,
+ GraphQLID,
+ GraphQLObject,
+ GraphQLUnion,
make_executable_schema,
)
-def test_union_type_raises_attribute_error_when_defined_without_schema(data_regression):
- with pytest.raises(AttributeError) as err:
- # pylint: disable=unused-variable
- class ExampleUnion(UnionType):
- pass
+class UserType(GraphQLObject):
+ id: GraphQLID
+ username: str
- data_regression.check(str(err.value))
+class CommentType(GraphQLObject):
+ id: GraphQLID
+ content: str
-def test_union_type_raises_error_when_defined_with_invalid_schema_type(data_regression):
- with pytest.raises(TypeError) as err:
- # pylint: disable=unused-variable
- class ExampleUnion(UnionType):
- __schema__ = True
- data_regression.check(str(err.value))
+def test_union_field_returning_object_instance(assert_schema_equals):
+ class ResultType(GraphQLUnion):
+ __types__ = [UserType, CommentType]
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(graphql_type=List[ResultType])
+ def search(*_) -> List[Union[UserType, CommentType]]:
+ return [
+ UserType(id=1, username="Bob"),
+ CommentType(id=2, content="Hello World!"),
+ ]
-def test_union_type_raises_error_when_defined_with_invalid_schema_str(data_regression):
- with pytest.raises(GraphQLError) as err:
- # pylint: disable=unused-variable
- class ExampleUnion(UnionType):
- __schema__ = "unien Example = A | B"
-
- data_regression.check(str(err.value))
-
-
-def test_union_type_raises_error_when_defined_with_invalid_graphql_type_schema(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ExampleUnion(UnionType):
- __schema__ = "scalar DateTime"
-
- data_regression.check(str(err.value))
-
-
-def test_union_type_raises_error_when_defined_with_multiple_types_schema(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ExampleUnion(UnionType):
- __schema__ = """
- union A = C | D
-
- union B = C | D
- """
-
- data_regression.check(str(err.value))
-
-
-@dataclass
-class User:
- id: int
- name: str
+ schema = make_executable_schema(QueryType)
+ assert_schema_equals(
+ schema,
+ """
+ type Query {
+ search: [Result!]!
+ }
-@dataclass
-class Comment:
- id: int
- message: str
+ union Result = User | Comment
+ type User {
+ id: ID!
+ username: String!
+ }
-class UserType(ObjectType):
- __schema__ = """
- type User {
- id: ID!
- name: String!
- }
- """
+ type Comment {
+ id: ID!
+ content: String!
+ }
+ """,
+ )
+ result = graphql_sync(
+ schema,
+ """
+ {
+ search {
+ ... on User {
+ id
+ username
+ }
+ ... on Comment {
+ id
+ content
+ }
+ }
+ }
+ """,
+ )
-class CommentType(ObjectType):
- __schema__ = """
- type Comment {
- id: ID!
- message: String!
+ assert not result.errors
+ assert result.data == {
+ "search": [
+ {"id": "1", "username": "Bob"},
+ {"id": "2", "content": "Hello World!"},
+ ]
}
- """
-
-class ResultUnion(UnionType):
- __schema__ = "union Result = Comment | User"
- __requires__ = [CommentType, UserType]
- @staticmethod
- def resolve_type(instance, *_):
- if isinstance(instance, Comment):
- return "Comment"
+def test_union_field_returning_empty_list():
+ class ResultType(GraphQLUnion):
+ __types__ = [UserType, CommentType]
- if isinstance(instance, User):
- return "User"
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(graphql_type=List[ResultType])
+ def search(*_) -> List[Union[UserType, CommentType]]:
+ return []
- return None
+ schema = make_executable_schema(QueryType)
+ result = graphql_sync(
+ schema,
+ """
+ {
+ search {
+ ... on User {
+ id
+ username
+ }
+ ... on Comment {
+ id
+ content
+ }
+ }
+ }
+ """,
+ )
+ assert not result.errors
+ assert result.data == {"search": []}
-class QueryType(ObjectType):
- __schema__ = """
- type Query {
- results: [Result!]!
- }
- """
- __requires__ = [ResultUnion]
-
- @staticmethod
- def resolve_results(*_):
- return [
- User(id=1, name="Alice"),
- Comment(id=1, message="Hello world!"),
- ]
+def test_union_field_with_invalid_type_access(assert_schema_equals):
+ class ResultType(GraphQLUnion):
+ __types__ = [UserType, CommentType]
-schema = make_executable_schema(QueryType, UserType, CommentType)
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(graphql_type=List[ResultType])
+ def search(*_) -> List[Union[UserType, CommentType]]:
+ return [
+ UserType(id=1, username="Bob"),
+ "InvalidType",
+ ]
+ schema = make_executable_schema(QueryType)
-def test_union_type_extracts_graphql_name():
- class ExampleUnion(UnionType):
- __schema__ = "union Example = User | Comment"
- __requires__ = [UserType, CommentType]
+ result = graphql_sync(
+ schema,
+ """
+ {
+ search {
+ ... on User {
+ id
+ username
+ }
+ ... on Comment {
+ id
+ content
+ }
+ }
+ }
+ """,
+ )
+ assert result.errors
+ assert "InvalidType" in str(result.errors)
- assert ExampleUnion.graphql_name == "Example"
+def test_serialization_error_handling(assert_schema_equals):
+ class InvalidType:
+ def __init__(self, value):
+ self.value = value
-def test_union_type_raises_error_when_defined_without_member_type_dependency(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ExampleUnion(UnionType):
- __schema__ = "union Example = User | Comment"
- __requires__ = [UserType]
+ class ResultType(GraphQLUnion):
+ __types__ = [UserType, CommentType]
- data_regression.check(str(err.value))
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(graphql_type=List[ResultType])
+ def search(*_) -> List[Union[UserType, CommentType, InvalidType]]:
+ return [InvalidType("This should cause an error")]
+ schema = make_executable_schema(QueryType)
-def test_interface_type_binds_type_resolver():
- query = """
- query {
- results {
- ... on User {
- __typename
- id
- name
- }
- ... on Comment {
- __typename
- id
- message
+ result = graphql_sync(
+ schema,
+ """
+ {
+ search {
+ ... on User {
+ id
+ username
+ }
}
}
- }
- """
-
- result = graphql_sync(schema, query)
- assert result.data == {
- "results": [
- {
- "__typename": "User",
- "id": "1",
- "name": "Alice",
- },
- {
- "__typename": "Comment",
- "id": "1",
- "message": "Hello world!",
- },
- ],
- }
+ """,
+ )
+ assert result.errors
-def test_union_type_can_be_extended_with_new_types():
- # pylint: disable=unused-variable
- class ExampleUnion(UnionType):
- __schema__ = "union Result = User | Comment"
- __requires__ = [UserType, CommentType]
-
- class ThreadType(ObjectType):
+def test_union_with_schema_definition(assert_schema_equals):
+ class SearchResultUnion(GraphQLUnion):
__schema__ = """
- type Thread {
- id: ID!
- title: String!
- }
+ union SearchResult = User | Comment
"""
+ __types__ = [UserType, CommentType]
- class ExtendExampleUnion(UnionType):
- __schema__ = "union Result = Thread"
- __requires__ = [ExampleUnion, ThreadType]
-
+ class QueryType(GraphQLObject):
+ @GraphQLObject.field(graphql_type=List[SearchResultUnion])
+ def search(*_) -> List[Union[UserType, CommentType]]:
+ return [
+ UserType(id="1", username="Alice"),
+ CommentType(id="2", content="Test post"),
+ ]
-def test_union_type_can_be_extended_with_directive():
- # pylint: disable=unused-variable
- class ExampleDirective(DirectiveType):
- __schema__ = "directive @example on UNION"
- __visitor__ = SchemaDirectiveVisitor
+ schema = make_executable_schema(QueryType, SearchResultUnion)
- class ExampleUnion(UnionType):
- __schema__ = "union Result = User | Comment"
- __requires__ = [UserType, CommentType]
-
- class ExtendExampleUnion(UnionType):
- __schema__ = """
- extend union Result @example
+ result = graphql_sync(
+ schema,
"""
- __requires__ = [ExampleUnion, ExampleDirective]
-
-
-def test_union_type_raises_error_when_defined_without_extended_dependency(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ExtendExampleUnion(UnionType):
- __schema__ = "extend union Result = User"
- __requires__ = [UserType]
-
- data_regression.check(str(err.value))
-
-
-def test_union_type_raises_error_when_extended_dependency_is_wrong_type(
- data_regression,
-):
- with pytest.raises(ValueError) as err:
- # pylint: disable=unused-variable
- class ExampleType(ObjectType):
- __schema__ = """
- type Example {
- id: ID!
+ {
+ search {
+ ... on User {
+ id
+ username
+ }
+ ... on Comment {
+ id
+ content
+ }
}
- """
-
- class ExtendExampleUnion(UnionType):
- __schema__ = "extend union Example = User"
- __requires__ = [ExampleType, UserType]
-
- data_regression.check(str(err.value))
+ }
+ """,
+ )
+ assert not result.errors
+ assert result.data == {
+ "search": [
+ {"id": "1", "username": "Alice"},
+ {"id": "2", "content": "Test post"},
+ ]
+ }
diff --git a/tests_next/test_union_type_validation.py b/tests/test_union_type_validation.py
similarity index 92%
rename from tests_next/test_union_type_validation.py
rename to tests/test_union_type_validation.py
index f9930d4..fac5b1f 100644
--- a/tests_next/test_union_type_validation.py
+++ b/tests/test_union_type_validation.py
@@ -1,9 +1,9 @@
-from ariadne_graphql_modules.next import (
+from ariadne_graphql_modules import (
GraphQLID,
GraphQLObject,
GraphQLUnion,
)
-from ariadne_graphql_modules.next.graphql_union.validators import (
+from ariadne_graphql_modules.union_type.validators import (
validate_union_type_with_schema,
)
import pytest
diff --git a/tests_next/test_validators.py b/tests/test_validators.py
similarity index 92%
rename from tests_next/test_validators.py
rename to tests/test_validators.py
index 45f4948..bdb50e2 100644
--- a/tests_next/test_validators.py
+++ b/tests/test_validators.py
@@ -1,8 +1,7 @@
import pytest
from graphql import parse
-from ariadne_graphql_modules import gql
-from ariadne_graphql_modules.next.validators import validate_description, validate_name
+from ariadne_graphql_modules.validators import validate_description, validate_name
def test_description_validator_passes_type_without_description():
diff --git a/tests_next/test_value_node.py b/tests/test_value_node.py
similarity index 96%
rename from tests_next/test_value_node.py
rename to tests/test_value_node.py
index 48c754b..e557438 100644
--- a/tests_next/test_value_node.py
+++ b/tests/test_value_node.py
@@ -14,7 +14,7 @@
print_ast,
)
-from ariadne_graphql_modules.next import get_value_from_node, get_value_node
+from ariadne_graphql_modules import get_value_from_node, get_value_node
def test_get_false_value():
@@ -121,7 +121,7 @@ class CustomType:
get_value_node(CustomType())
error_message = str(exc_info.value)
- assert error_message.startswith("Python value '' can't be represented as a GraphQL value node.")
diff --git a/tests_next/types.py b/tests/types.py
similarity index 73%
rename from tests_next/types.py
rename to tests/types.py
index 02761c7..96233ee 100644
--- a/tests_next/types.py
+++ b/tests/types.py
@@ -1,6 +1,6 @@
from enum import Enum
-from ariadne_graphql_modules.next import GraphQLScalar
+from ariadne_graphql_modules import GraphQLScalar
class ForwardScalar(GraphQLScalar):
diff --git a/tests_next/conftest.py b/tests_next/conftest.py
deleted file mode 100644
index 46da232..0000000
--- a/tests_next/conftest.py
+++ /dev/null
@@ -1,40 +0,0 @@
-from pathlib import Path
-from textwrap import dedent
-
-import pytest
-from graphql import TypeDefinitionNode, GraphQLSchema, print_ast, print_schema
-
-from ariadne_graphql_modules.next import GraphQLMetadata
-
-
-@pytest.fixture
-def assert_schema_equals():
- def schema_equals_assertion(schema: GraphQLSchema, target: str):
- schema_str = print_schema(schema)
- assert schema_str == dedent(target).strip()
-
- return schema_equals_assertion
-
-
-@pytest.fixture
-def assert_ast_equals():
- def ast_equals_assertion(ast: TypeDefinitionNode, target: str):
- ast_str = print_ast(ast)
- assert ast_str == dedent(target).strip()
-
- return ast_equals_assertion
-
-
-@pytest.fixture
-def metadata():
- return GraphQLMetadata()
-
-
-@pytest.fixture(scope="session")
-def datadir() -> Path:
- return Path(__file__).parent / "snapshots"
-
-
-@pytest.fixture(scope="session")
-def original_datadir() -> Path:
- return Path(__file__).parent / "snapshots"
diff --git a/tests_next/snapshots/test_interface_with_different_types.obtained.yml b/tests_next/snapshots/test_interface_with_different_types.obtained.yml
deleted file mode 100644
index f10dac9..0000000
--- a/tests_next/snapshots/test_interface_with_different_types.obtained.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-'Query root type must be provided.
-
-
- Interface field UserInterface.score expects type String! but User.score is type
- Int!.'
diff --git a/tests_next/snapshots/test_metadata_raises_key_error_for_unset_data.obtained.yml b/tests_next/snapshots/test_metadata_raises_key_error_for_unset_data.obtained.yml
deleted file mode 100644
index d7bf90b..0000000
--- a/tests_next/snapshots/test_metadata_raises_key_error_for_unset_data.obtained.yml
+++ /dev/null
@@ -1 +0,0 @@
-'"No data is set for ''''."'
diff --git a/tests_next/snapshots/test_metadata_raises_key_error_for_unset_data.yml b/tests_next/snapshots/test_metadata_raises_key_error_for_unset_data.yml
deleted file mode 100644
index d7bf90b..0000000
--- a/tests_next/snapshots/test_metadata_raises_key_error_for_unset_data.yml
+++ /dev/null
@@ -1 +0,0 @@
-'"No data is set for ''''."'
diff --git a/tests_next/snapshots/test_multiple_roots_fail_validation_if_merge_roots_is_disabled.obtained.yml b/tests_next/snapshots/test_multiple_roots_fail_validation_if_merge_roots_is_disabled.obtained.yml
deleted file mode 100644
index 4eccfe9..0000000
--- a/tests_next/snapshots/test_multiple_roots_fail_validation_if_merge_roots_is_disabled.obtained.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-Types 'SecondRoot' and '.FirstRoot'>'
- both define GraphQL type with name 'Query'.
-...
diff --git a/tests_next/snapshots/test_multiple_roots_fail_validation_if_merge_roots_is_disabled.yml b/tests_next/snapshots/test_multiple_roots_fail_validation_if_merge_roots_is_disabled.yml
deleted file mode 100644
index 4eccfe9..0000000
--- a/tests_next/snapshots/test_multiple_roots_fail_validation_if_merge_roots_is_disabled.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-Types 'SecondRoot' and '.FirstRoot'>'
- both define GraphQL type with name 'Query'.
-...
diff --git a/tests_next/test_enum_type.py b/tests_next/test_enum_type.py
deleted file mode 100644
index e4bf3c0..0000000
--- a/tests_next/test_enum_type.py
+++ /dev/null
@@ -1,522 +0,0 @@
-from enum import Enum
-
-from graphql import graphql_sync
-
-from ariadne_graphql_modules.next import (
- GraphQLEnum,
- GraphQLObject,
- make_executable_schema,
-)
-
-
-class UserLevelEnum(Enum):
- GUEST = 0
- MEMBER = 1
- ADMIN = 2
-
-
-def test_enum_field_returning_enum_value(assert_schema_equals):
- class UserLevel(GraphQLEnum):
- __members__ = UserLevelEnum
-
- class QueryType(GraphQLObject):
- level: UserLevel
-
- @GraphQLObject.resolver("level")
- def resolve_level(*_) -> UserLevelEnum:
- return UserLevelEnum.MEMBER
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- level: UserLevel!
- }
-
- enum UserLevel {
- GUEST
- MEMBER
- ADMIN
- }
- """,
- )
-
- result = graphql_sync(schema, "{ level }")
-
- assert not result.errors
- assert result.data == {"level": "MEMBER"}
-
-
-def test_enum_field_returning_dict_value(assert_schema_equals):
- class UserLevel(GraphQLEnum):
- __members__ = {
- "GUEST": 0,
- "MEMBER": 1,
- "ADMIN": 2,
- }
-
- class QueryType(GraphQLObject):
- level: UserLevel
-
- @GraphQLObject.resolver("level")
- def resolve_level(*_) -> dict:
- return 0
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- level: UserLevel!
- }
-
- enum UserLevel {
- GUEST
- MEMBER
- ADMIN
- }
- """,
- )
-
- result = graphql_sync(schema, "{ level }")
-
- assert not result.errors
- assert result.data == {"level": "GUEST"}
-
-
-def test_enum_field_returning_str_value(assert_schema_equals):
- class UserLevel(GraphQLEnum):
- __members__ = [
- "GUEST",
- "MEMBER",
- "ADMIN",
- ]
-
- class QueryType(GraphQLObject):
- level: UserLevel
-
- @GraphQLObject.resolver("level")
- def resolve_level(*_) -> str:
- return "ADMIN"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- level: UserLevel!
- }
-
- enum UserLevel {
- GUEST
- MEMBER
- ADMIN
- }
- """,
- )
-
- result = graphql_sync(schema, "{ level }")
-
- assert not result.errors
- assert result.data == {"level": "ADMIN"}
-
-
-def test_enum_type_with_custom_name(assert_schema_equals):
- class UserLevel(GraphQLEnum):
- __graphql_name__ = "UserLevelEnum"
- __members__ = UserLevelEnum
-
- class QueryType(GraphQLObject):
- level: UserLevel
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- level: UserLevelEnum!
- }
-
- enum UserLevelEnum {
- GUEST
- MEMBER
- ADMIN
- }
- """,
- )
-
-
-def test_enum_type_with_description(assert_schema_equals):
- class UserLevel(GraphQLEnum):
- __description__ = "Hello world."
- __members__ = UserLevelEnum
-
- class QueryType(GraphQLObject):
- level: UserLevel
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- level: UserLevel!
- }
-
- \"\"\"Hello world.\"\"\"
- enum UserLevel {
- GUEST
- MEMBER
- ADMIN
- }
- """,
- )
-
-
-def test_enum_type_with_member_description(assert_schema_equals):
- class UserLevel(GraphQLEnum):
- __members__ = UserLevelEnum
- __members_descriptions__ = {"MEMBER": "Hello world."}
-
- class QueryType(GraphQLObject):
- level: UserLevel
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- level: UserLevel!
- }
-
- enum UserLevel {
- GUEST
-
- \"\"\"Hello world.\"\"\"
- MEMBER
- ADMIN
- }
- """,
- )
-
-
-def test_schema_enum_field_returning_enum_value(assert_schema_equals):
- class UserLevel(GraphQLEnum):
- __schema__ = """
- enum UserLevel {
- GUEST
- MEMBER
- ADMIN
- }
- """
- __members__ = UserLevelEnum
-
- class QueryType(GraphQLObject):
- level: UserLevel
-
- @GraphQLObject.resolver("level")
- def resolve_level(*_) -> UserLevelEnum:
- return UserLevelEnum.MEMBER
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- level: UserLevel!
- }
-
- enum UserLevel {
- GUEST
- MEMBER
- ADMIN
- }
- """,
- )
-
- result = graphql_sync(schema, "{ level }")
-
- assert not result.errors
- assert result.data == {"level": "MEMBER"}
-
-
-def test_schema_enum_field_returning_dict_value(assert_schema_equals):
- class UserLevel(GraphQLEnum):
- __schema__ = """
- enum UserLevel {
- GUEST
- MEMBER
- ADMIN
- }
- """
- __members__ = {
- "GUEST": 0,
- "MEMBER": 1,
- "ADMIN": 2,
- }
-
- class QueryType(GraphQLObject):
- level: UserLevel
-
- @GraphQLObject.resolver("level")
- def resolve_level(*_) -> int:
- return 2
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- level: UserLevel!
- }
-
- enum UserLevel {
- GUEST
- MEMBER
- ADMIN
- }
- """,
- )
-
- result = graphql_sync(schema, "{ level }")
-
- assert not result.errors
- assert result.data == {"level": "ADMIN"}
-
-
-def test_schema_enum_field_returning_str_value(assert_schema_equals):
- class UserLevel(GraphQLEnum):
- __schema__ = """
- enum UserLevel {
- GUEST
- MEMBER
- ADMIN
- }
- """
-
- class QueryType(GraphQLObject):
- level: UserLevel
-
- @GraphQLObject.resolver("level")
- def resolve_level(*_) -> str:
- return "GUEST"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- level: UserLevel!
- }
-
- enum UserLevel {
- GUEST
- MEMBER
- ADMIN
- }
- """,
- )
-
- result = graphql_sync(schema, "{ level }")
-
- assert not result.errors
- assert result.data == {"level": "GUEST"}
-
-
-def test_schema_enum_with_description_attr(assert_schema_equals):
- class UserLevel(GraphQLEnum):
- __schema__ = """
- enum UserLevel {
- GUEST
- MEMBER
- ADMIN
- }
- """
- __members__ = {
- "GUEST": 0,
- "MEMBER": 1,
- "ADMIN": 2,
- }
- __description__ = "Hello world."
-
- class QueryType(GraphQLObject):
- level: UserLevel
-
- @GraphQLObject.resolver("level")
- def resolve_level(*_) -> int:
- return 2
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- level: UserLevel!
- }
-
- \"\"\"Hello world.\"\"\"
- enum UserLevel {
- GUEST
- MEMBER
- ADMIN
- }
- """,
- )
-
- result = graphql_sync(schema, "{ level }")
-
- assert not result.errors
- assert result.data == {"level": "ADMIN"}
-
-
-def test_schema_enum_with_schema_description(assert_schema_equals):
- class UserLevel(GraphQLEnum):
- __schema__ = """
- \"\"\"Hello world.\"\"\"
- enum UserLevel {
- GUEST
- MEMBER
- ADMIN
- }
- """
- __members__ = {
- "GUEST": 0,
- "MEMBER": 1,
- "ADMIN": 2,
- }
-
- class QueryType(GraphQLObject):
- level: UserLevel
-
- @GraphQLObject.resolver("level")
- def resolve_level(*_) -> int:
- return 2
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- level: UserLevel!
- }
-
- \"\"\"Hello world.\"\"\"
- enum UserLevel {
- GUEST
- MEMBER
- ADMIN
- }
- """,
- )
-
- result = graphql_sync(schema, "{ level }")
-
- assert not result.errors
- assert result.data == {"level": "ADMIN"}
-
-
-def test_schema_enum_with_member_description(assert_schema_equals):
- class UserLevel(GraphQLEnum):
- __schema__ = """
- enum UserLevel {
- GUEST
- MEMBER
- ADMIN
- }
- """
- __members__ = {
- "GUEST": 0,
- "MEMBER": 1,
- "ADMIN": 2,
- }
- __members_descriptions__ = {"MEMBER": "Hello world."}
-
- class QueryType(GraphQLObject):
- level: UserLevel
-
- @GraphQLObject.resolver("level")
- def resolve_level(*_) -> int:
- return 2
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- level: UserLevel!
- }
-
- enum UserLevel {
- GUEST
-
- \"\"\"Hello world.\"\"\"
- MEMBER
- ADMIN
- }
- """,
- )
-
- result = graphql_sync(schema, "{ level }")
-
- assert not result.errors
- assert result.data == {"level": "ADMIN"}
-
-
-def test_schema_enum_with_member_schema_description(assert_schema_equals):
- class UserLevel(GraphQLEnum):
- __schema__ = """
- enum UserLevel {
- GUEST
- \"\"\"Hello world.\"\"\"
- MEMBER
- ADMIN
- }
- """
- __members__ = {
- "GUEST": 0,
- "MEMBER": 1,
- "ADMIN": 2,
- }
-
- class QueryType(GraphQLObject):
- level: UserLevel
-
- @GraphQLObject.resolver("level")
- def resolve_level(*_) -> int:
- return 2
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- level: UserLevel!
- }
-
- enum UserLevel {
- GUEST
-
- \"\"\"Hello world.\"\"\"
- MEMBER
- ADMIN
- }
- """,
- )
-
- result = graphql_sync(schema, "{ level }")
-
- assert not result.errors
- assert result.data == {"level": "ADMIN"}
diff --git a/tests_next/test_input_type.py b/tests_next/test_input_type.py
deleted file mode 100644
index 977dfcb..0000000
--- a/tests_next/test_input_type.py
+++ /dev/null
@@ -1,628 +0,0 @@
-from typing import Optional
-
-import pytest
-from graphql import graphql_sync
-
-from ariadne_graphql_modules import gql
-from ariadne_graphql_modules.next import (
- GraphQLInput,
- GraphQLObject,
- make_executable_schema,
-)
-
-
-def test_input_type_instance_with_all_attrs_values():
- class SearchInput(GraphQLInput):
- query: str
- age: int
-
- obj = SearchInput(query="search", age=20)
- assert obj.query == "search"
- assert obj.age == 20
-
-
-def test_input_type_instance_with_omitted_attrs_being_none():
- class SearchInput(GraphQLInput):
- query: str
- age: int
-
- obj = SearchInput(age=20)
- assert obj.query is None
- assert obj.age == 20
-
-
-def test_input_type_instance_with_default_attrs_values():
- class SearchInput(GraphQLInput):
- query: str = "default"
- age: int = 42
-
- obj = SearchInput(age=20)
- assert obj.query == "default"
- assert obj.age == 20
-
-
-def test_input_type_instance_with_all_fields_values():
- class SearchInput(GraphQLInput):
- query: str = GraphQLInput.field()
- age: int = GraphQLInput.field()
-
- obj = SearchInput(query="search", age=20)
- assert obj.query == "search"
- assert obj.age == 20
-
-
-def test_input_type_instance_with_all_fields_default_values():
- class SearchInput(GraphQLInput):
- query: str = GraphQLInput.field(default_value="default")
- age: int = GraphQLInput.field(default_value=42)
-
- obj = SearchInput(age=20)
- assert obj.query == "default"
- assert obj.age == 20
-
-
-def test_input_type_instance_with_invalid_attrs_raising_error(data_regression):
- class SearchInput(GraphQLInput):
- query: str
- age: int
-
- with pytest.raises(TypeError) as exc_info:
- SearchInput(age=20, invalid="Ok")
-
- data_regression.check(str(exc_info.value))
-
-
-def test_schema_input_type_instance_with_all_attrs_values():
- class SearchInput(GraphQLInput):
- __schema__ = gql(
- """
- input Search {
- query: String
- age: Int
- }
- """
- )
-
- query: str
- age: int
-
- obj = SearchInput(query="search", age=20)
- assert obj.query == "search"
- assert obj.age == 20
-
-
-def test_schema_input_type_instance_with_omitted_attrs_being_none():
- class SearchInput(GraphQLInput):
- __schema__ = gql(
- """
- input Search {
- query: String
- age: Int
- }
- """
- )
-
- query: str
- age: int
-
- obj = SearchInput(age=20)
- assert obj.query is None
- assert obj.age == 20
-
-
-def test_schema_input_type_instance_with_default_attrs_values():
- class SearchInput(GraphQLInput):
- __schema__ = gql(
- """
- input Search {
- query: String = "default"
- age: Int = 42
- }
- """
- )
-
- query: str
- age: int
-
- obj = SearchInput(age=20)
- assert obj.query == "default"
- assert obj.age == 20
-
-
-def test_schema_input_type_instance_with_all_attrs_default_values():
- class SearchInput(GraphQLInput):
- __schema__ = gql(
- """
- input Search {
- query: String = "default"
- age: Int = 42
- }
- """
- )
-
- query: str
- age: int
-
- obj = SearchInput()
- assert obj.query == "default"
- assert obj.age == 42
-
-
-def test_schema_input_type_instance_with_default_attrs_python_values():
- class SearchInput(GraphQLInput):
- __schema__ = gql(
- """
- input Search {
- query: String
- age: Int
- }
- """
- )
-
- query: str = "default"
- age: int = 42
-
- obj = SearchInput(age=20)
- assert obj.query == "default"
- assert obj.age == 20
-
-
-def test_schema_input_type_instance_with_invalid_attrs_raising_error(data_regression):
- class SearchInput(GraphQLInput):
- __schema__ = gql(
- """
- input Search {
- query: String
- age: Int
- }
- """
- )
-
- query: str
- age: int
-
- with pytest.raises(TypeError) as exc_info:
- SearchInput(age=20, invalid="Ok")
-
- data_regression.check(str(exc_info.value))
-
-
-def test_input_type_arg(assert_schema_equals):
- class SearchInput(GraphQLInput):
- query: Optional[str]
- age: Optional[int]
-
- class QueryType(GraphQLObject):
- search: str
-
- @GraphQLObject.resolver("search")
- def resolve_search(*_, input: SearchInput) -> str:
- return f"{repr([input.query, input.age])}"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- search(input: SearchInput!): String!
- }
-
- input SearchInput {
- query: String
- age: Int
- }
- """,
- )
-
- result = graphql_sync(schema, '{ search(input: { query: "Hello" }) }')
-
- assert not result.errors
- assert result.data == {"search": "['Hello', None]"}
-
-
-def test_schema_input_type_arg(assert_schema_equals):
- class SearchInput(GraphQLInput):
- __schema__ = """
- input SearchInput {
- query: String
- age: Int
- }
- """
-
- query: Optional[str]
- age: Optional[int]
-
- class QueryType(GraphQLObject):
- search: str
-
- @GraphQLObject.resolver("search")
- def resolve_search(*_, input: SearchInput) -> str:
- return f"{repr([input.query, input.age])}"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- search(input: SearchInput!): String!
- }
-
- input SearchInput {
- query: String
- age: Int
- }
- """,
- )
-
- result = graphql_sync(schema, '{ search(input: { query: "Hello" }) }')
-
- assert not result.errors
- assert result.data == {"search": "['Hello', None]"}
-
-
-def test_input_type_automatic_out_name_arg(assert_schema_equals):
- class SearchInput(GraphQLInput):
- query: Optional[str]
- min_age: Optional[int]
-
- class QueryType(GraphQLObject):
- search: str
-
- @GraphQLObject.resolver("search")
- def resolve_search(*_, input: SearchInput) -> str:
- return f"{repr([input.query, input.min_age])}"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- search(input: SearchInput!): String!
- }
-
- input SearchInput {
- query: String
- minAge: Int
- }
- """,
- )
-
- result = graphql_sync(schema, "{ search(input: { minAge: 21 }) }")
-
- assert not result.errors
- assert result.data == {"search": "[None, 21]"}
-
-
-def test_schema_input_type_automatic_out_name_arg(assert_schema_equals):
- class SearchInput(GraphQLInput):
- __schema__ = """
- input SearchInput {
- query: String
- minAge: Int
- }
- """
-
- query: Optional[str]
- min_age: Optional[int]
-
- class QueryType(GraphQLObject):
- search: str
-
- @GraphQLObject.resolver("search")
- def resolve_search(*_, input: SearchInput) -> str:
- return f"{repr([input.query, input.min_age])}"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- search(input: SearchInput!): String!
- }
-
- input SearchInput {
- query: String
- minAge: Int
- }
- """,
- )
-
- result = graphql_sync(schema, "{ search(input: { minAge: 21 }) }")
-
- assert not result.errors
- assert result.data == {"search": "[None, 21]"}
-
-
-def test_schema_input_type_explicit_out_name_arg(assert_schema_equals):
- class SearchInput(GraphQLInput):
- __schema__ = """
- input SearchInput {
- query: String
- minAge: Int
- }
- """
- __out_names__ = {"minAge": "age"}
-
- query: Optional[str]
- age: Optional[int]
-
- class QueryType(GraphQLObject):
- search: str
-
- @GraphQLObject.resolver("search")
- def resolve_search(*_, input: SearchInput) -> str:
- return f"{repr([input.query, input.age])}"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- search(input: SearchInput!): String!
- }
-
- input SearchInput {
- query: String
- minAge: Int
- }
- """,
- )
-
- result = graphql_sync(schema, "{ search(input: { minAge: 21 }) }")
-
- assert not result.errors
- assert result.data == {"search": "[None, 21]"}
-
-
-def test_input_type_self_reference(assert_schema_equals):
- class SearchInput(GraphQLInput):
- query: Optional[str]
- extra: Optional["SearchInput"]
-
- class QueryType(GraphQLObject):
- search: str
-
- @GraphQLObject.resolver("search")
- def resolve_search(*_, input: SearchInput) -> str:
- if input.extra:
- extra_repr = input.extra.query
- else:
- extra_repr = None
-
- return f"{repr([input.query, extra_repr])}"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- search(input: SearchInput!): String!
- }
-
- input SearchInput {
- query: String
- extra: SearchInput
- }
- """,
- )
-
- result = graphql_sync(
- schema,
- """
- {
- search(
- input: { query: "Hello", extra: { query: "Other" } }
- )
- }
- """,
- )
-
- assert not result.errors
- assert result.data == {"search": "['Hello', 'Other']"}
-
-
-def test_schema_input_type_with_default_value(assert_schema_equals):
- class SearchInput(GraphQLInput):
- __schema__ = """
- input SearchInput {
- query: String = "Search"
- age: Int = 42
- }
- """
-
- query: str
- age: int
-
- class QueryType(GraphQLObject):
- search: str
-
- @GraphQLObject.resolver("search")
- def resolve_search(*_, input: SearchInput) -> str:
- return f"{repr([input.query, input.age])}"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- search(input: SearchInput!): String!
- }
-
- input SearchInput {
- query: String = "Search"
- age: Int = 42
- }
- """,
- )
-
- result = graphql_sync(schema, "{ search(input: {}) }")
-
- assert not result.errors
- assert result.data == {"search": "['Search', 42]"}
-
-
-def test_input_type_with_field_default_value(assert_schema_equals):
- class SearchInput(GraphQLInput):
- query: str = "default"
- age: int = 42
- flag: bool = False
-
- class QueryType(GraphQLObject):
- search: str
-
- @GraphQLObject.resolver("search")
- def resolve_search(*_, input: SearchInput) -> str:
- return f"{repr([input.query, input.age, input.flag])}"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- search(input: SearchInput!): String!
- }
-
- input SearchInput {
- query: String! = "default"
- age: Int! = 42
- flag: Boolean! = false
- }
- """,
- )
-
- result = graphql_sync(schema, "{ search(input: {}) }")
-
- assert not result.errors
- assert result.data == {"search": "['default', 42, False]"}
-
-
-def test_input_type_with_field_instance_default_value(assert_schema_equals):
- class SearchInput(GraphQLInput):
- query: str = GraphQLInput.field(default_value="default")
- age: int = GraphQLInput.field(default_value=42)
- flag: bool = GraphQLInput.field(default_value=False)
-
- class QueryType(GraphQLObject):
- search: str
-
- @GraphQLObject.resolver("search")
- def resolve_search(*_, input: SearchInput) -> str:
- return f"{repr([input.query, input.age, input.flag])}"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- search(input: SearchInput!): String!
- }
-
- input SearchInput {
- query: String! = "default"
- age: Int! = 42
- flag: Boolean! = false
- }
- """,
- )
-
- result = graphql_sync(schema, "{ search(input: {}) }")
-
- assert not result.errors
- assert result.data == {"search": "['default', 42, False]"}
-
-
-def test_input_type_with_field_type(assert_schema_equals):
- class SearchInput(GraphQLInput):
- query: str = GraphQLInput.field(graphql_type=int)
-
- class QueryType(GraphQLObject):
- search: str
-
- @GraphQLObject.resolver("search")
- def resolve_search(*_, input: SearchInput) -> str:
- return str(input)
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- search(input: SearchInput!): String!
- }
-
- input SearchInput {
- query: Int!
- }
- """,
- )
-
-
-def test_schema_input_type_with_field_description(assert_schema_equals):
- class SearchInput(GraphQLInput):
- __schema__ = """
- input SearchInput {
- \"\"\"Hello world.\"\"\"
- query: String!
- }
- """
-
- class QueryType(GraphQLObject):
- search: str
-
- @GraphQLObject.resolver("search")
- def resolve_search(*_, input: SearchInput) -> str:
- return str(input)
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- search(input: SearchInput!): String!
- }
-
- input SearchInput {
- \"\"\"Hello world.\"\"\"
- query: String!
- }
- """,
- )
-
-
-def test_input_type_with_field_description(assert_schema_equals):
- class SearchInput(GraphQLInput):
- query: str = GraphQLInput.field(description="Hello world.")
-
- class QueryType(GraphQLObject):
- search: str
-
- @GraphQLObject.resolver("search")
- def resolve_search(*_, input: SearchInput) -> str:
- return str(input)
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- search(input: SearchInput!): String!
- }
-
- input SearchInput {
- \"\"\"Hello world.\"\"\"
- query: String!
- }
- """,
- )
diff --git a/tests_next/test_interface_type.py b/tests_next/test_interface_type.py
deleted file mode 100644
index 74064ad..0000000
--- a/tests_next/test_interface_type.py
+++ /dev/null
@@ -1,366 +0,0 @@
-from typing import List, Union
-
-from graphql import graphql_sync
-
-from ariadne_graphql_modules.next import (
- GraphQLID,
- GraphQLObject,
- GraphQLInterface,
- GraphQLUnion,
- make_executable_schema,
-)
-
-
-class CommentType(GraphQLObject):
- id: GraphQLID
- content: str
-
-
-def test_interface_without_schema(assert_schema_equals):
- class UserInterface(GraphQLInterface):
- summary: str
- score: int
-
- class UserType(GraphQLObject):
- name: str
- summary: str
- score: int
-
- __implements__ = [UserInterface]
-
- class ResultType(GraphQLUnion):
- __types__ = [UserType, CommentType]
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field(graphql_type=List[ResultType])
- def search(*_) -> List[Union[UserType, CommentType]]:
- return [
- UserType(id=1, username="Bob"),
- CommentType(id=2, content="Hello World!"),
- ]
-
- schema = make_executable_schema(QueryType, UserInterface, UserType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- search: [Result!]!
- }
-
- union Result = User | Comment
-
- type User implements UserInterface {
- summary: String!
- score: Int!
- name: String!
- }
-
- type Comment {
- id: ID!
- content: String!
- }
-
- interface UserInterface {
- summary: String!
- score: Int!
- }
-
- """,
- )
-
-
-def test_interface_inheritance_without_schema(assert_schema_equals):
- def hello_resolver(*_, name: str) -> str:
- return f"Hello {name}!"
-
- class UserInterface(GraphQLInterface):
- summary: str
- score: str = GraphQLInterface.field(
- hello_resolver,
- name="better_score",
- graphql_type=str,
- args={"name": GraphQLInterface.argument(name="json")},
- description="desc",
- default_value="my_json",
- )
-
- class UserType(GraphQLObject):
- name: str = GraphQLInterface.field(
- name="name",
- graphql_type=str,
- args={"name": GraphQLInterface.argument(name="json")},
- default_value="my_json",
- )
-
- __implements__ = [UserInterface]
-
- class ResultType(GraphQLUnion):
- __types__ = [UserType, CommentType]
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field(graphql_type=List[ResultType])
- def search(*_) -> List[Union[UserType, CommentType]]:
- return [
- UserType(),
- CommentType(id=2, content="Hello World!"),
- ]
-
- schema = make_executable_schema(QueryType, UserInterface, UserType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- search: [Result!]!
- }
-
- union Result = User | Comment
-
- type User implements UserInterface {
- summary: String!
-
- \"\"\"desc\"\"\"
- better_score(json: String!): String!
- name: String!
- }
-
- type Comment {
- id: ID!
- content: String!
- }
-
- interface UserInterface {
- summary: String!
-
- \"\"\"desc\"\"\"
- better_score(json: String!): String!
- }
-
- """,
- )
-
- result = graphql_sync(
- schema, '{ search { ... on User{ better_score(json: "test") } } }'
- )
-
- assert not result.errors
- assert result.data == {"search": [{"better_score": "Hello test!"}, {}]}
-
-
-def test_interface_with_schema(assert_schema_equals):
- class UserInterface(GraphQLInterface):
- __schema__ = """
- interface UserInterface {
- summary: String!
- score: Int!
- }
- """
-
- class UserType(GraphQLObject):
- __schema__ = """
- type User implements UserInterface {
- id: ID!
- name: String!
- summary: String!
- score: Int!
- }
- """
-
- __implements__ = [UserInterface]
-
- class ResultType(GraphQLUnion):
- __types__ = [UserType, CommentType]
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field(graphql_type=List[ResultType])
- def search(*_) -> List[Union[UserType, CommentType]]:
- return [
- UserType(id=1, username="Bob"),
- CommentType(id=2, content="Hello World!"),
- ]
-
- schema = make_executable_schema(QueryType, UserType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- search: [Result!]!
- }
-
- union Result = User | Comment
-
- type User implements UserInterface {
- id: ID!
- name: String!
- summary: String!
- score: Int!
- }
-
- interface UserInterface {
- summary: String!
- score: Int!
- }
-
- type Comment {
- id: ID!
- content: String!
- }
-
- """,
- )
-
-
-def test_interface_inheritance(assert_schema_equals):
- class BaseEntityInterface(GraphQLInterface):
- id: GraphQLID
-
- class UserInterface(GraphQLInterface):
- username: str
-
- __implements__ = [BaseEntityInterface]
-
- class UserType(GraphQLObject):
-
- __implements__ = [UserInterface, BaseEntityInterface]
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field
- def user(*_) -> UserType:
- return UserType(id="1", username="test_user")
-
- schema = make_executable_schema(
- QueryType, BaseEntityInterface, UserInterface, UserType
- )
-
- assert_schema_equals(
- schema,
- """
- type Query {
- user: User!
- }
-
- type User implements UserInterface & BaseEntityInterface {
- id: ID!
- username: String!
- }
-
- interface UserInterface implements BaseEntityInterface {
- id: ID!
- username: String!
- }
-
- interface BaseEntityInterface {
- id: ID!
- }
- """,
- )
-
-
-def test_interface_descriptions(assert_schema_equals):
- class UserInterface(GraphQLInterface):
- summary: str
- score: int
-
- __description__ = "Lorem ipsum."
-
- class UserType(GraphQLObject):
- id: GraphQLID
- username: str
-
- __implements__ = [UserInterface]
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field
- def user(*_) -> UserType:
- return UserType(id="1", username="test_user")
-
- schema = make_executable_schema(QueryType, UserType, UserInterface)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- user: User!
- }
-
- type User implements UserInterface {
- summary: String!
- score: Int!
- id: ID!
- username: String!
- }
-
- \"\"\"Lorem ipsum.\"\"\"
- interface UserInterface {
- summary: String!
- score: Int!
- }
- """,
- )
-
-
-def test_interface_resolvers_and_field_descriptions(assert_schema_equals):
- class UserInterface(GraphQLInterface):
- summary: str
- score: int
-
- @GraphQLInterface.resolver("score", description="Lorem ipsum.")
- def resolve_score(*_):
- return 200
-
- class UserType(GraphQLObject):
- id: GraphQLID
-
- __implements__ = [UserInterface]
-
- class MyType(GraphQLObject):
- id: GraphQLID
- name: str
-
- __implements__ = [UserInterface]
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field(graphql_type=List[UserInterface])
- def users(*_) -> List[Union[UserType, MyType]]:
- return [MyType(id="2", name="old", summary="ss", score=22)]
-
- schema = make_executable_schema(QueryType, UserType, MyType, UserInterface)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- users: [UserInterface!]!
- }
-
- interface UserInterface {
- summary: String!
-
- \"\"\"Lorem ipsum.\"\"\"
- score: Int!
- }
-
- type User implements UserInterface {
- summary: String!
-
- \"\"\"Lorem ipsum.\"\"\"
- score: Int!
- id: ID!
- }
-
- type My implements UserInterface {
- summary: String!
-
- \"\"\"Lorem ipsum.\"\"\"
- score: Int!
- id: ID!
- name: String!
- }
- """,
- )
- result = graphql_sync(schema, "{ users { ... on My { __typename score } } }")
-
- assert not result.errors
- assert result.data == {"users": [{"__typename": "My", "score": 200}]}
diff --git a/tests_next/test_interface_type_validation.py b/tests_next/test_interface_type_validation.py
deleted file mode 100644
index 0c96f8e..0000000
--- a/tests_next/test_interface_type_validation.py
+++ /dev/null
@@ -1,45 +0,0 @@
-import pytest
-
-from ariadne_graphql_modules.next import (
- GraphQLID,
- GraphQLObject,
- GraphQLInterface,
- make_executable_schema,
-)
-
-
-def test_interface_with_different_types(data_regression):
- with pytest.raises(TypeError) as exc_info:
-
- class UserInterface(GraphQLInterface):
- summary: str
- score: str
-
- class UserType(GraphQLObject):
- name: str
- summary: str
- score: int
-
- __implements__ = [UserInterface]
-
- make_executable_schema(UserType, UserInterface)
-
- data_regression.check(str(exc_info.value))
-
-
-def test_interface_no_interface_in_schema(data_regression):
- with pytest.raises(TypeError) as exc_info:
-
- class BaseInterface(GraphQLInterface):
- id: GraphQLID
-
- class UserType(GraphQLObject):
- id: GraphQLID
- username: str
- email: str
-
- __implements__ = [BaseInterface]
-
- make_executable_schema(UserType)
-
- data_regression.check(str(exc_info.value))
diff --git a/tests_next/test_object_type.py b/tests_next/test_object_type.py
deleted file mode 100644
index 6655bec..0000000
--- a/tests_next/test_object_type.py
+++ /dev/null
@@ -1,1015 +0,0 @@
-from typing import Optional
-
-import pytest
-from graphql import graphql_sync
-
-from ariadne_graphql_modules import gql
-from ariadne_graphql_modules.next import GraphQLObject, make_executable_schema
-
-
-def test_object_type_instance_with_all_attrs_values():
- class CategoryType(GraphQLObject):
- name: str
- posts: int
-
- obj = CategoryType(name="Welcome", posts=20)
- assert obj.name == "Welcome"
- assert obj.posts == 20
-
-
-def test_object_type_instance_with_omitted_attrs_being_none():
- class CategoryType(GraphQLObject):
- name: str
- posts: int
-
- obj = CategoryType(posts=20)
- assert obj.name is None
- assert obj.posts == 20
-
-
-def test_object_type_instance_with_aliased_attrs_values():
- class CategoryType(GraphQLObject):
- name: str
- posts: int
-
- __aliases__ = {"name": "title"}
-
- title: str
-
- obj = CategoryType(title="Welcome", posts=20)
- assert obj.title == "Welcome"
- assert obj.posts == 20
-
-
-def test_object_type_instance_with_omitted_attrs_being_default_values():
- class CategoryType(GraphQLObject):
- name: str = "Hello"
- posts: int = 42
-
- obj = CategoryType(posts=20)
- assert obj.name == "Hello"
- assert obj.posts == 20
-
-
-def test_object_type_instance_with_all_attrs_being_default_values():
- class CategoryType(GraphQLObject):
- name: str = "Hello"
- posts: int = 42
-
- obj = CategoryType()
- assert obj.name == "Hello"
- assert obj.posts == 42
-
-
-def test_object_type_instance_with_invalid_attrs_raising_error(data_regression):
- class CategoryType(GraphQLObject):
- name: str
- posts: int
-
- with pytest.raises(TypeError) as exc_info:
- CategoryType(name="Welcome", invalid="Ok")
-
- data_regression.check(str(exc_info.value))
-
-
-def test_schema_object_type_instance_with_all_attrs_values():
- class CategoryType(GraphQLObject):
- __schema__ = gql(
- """
- type Category {
- name: String
- posts: Int
- }
- """
- )
-
- name: str
- posts: int
-
- obj = CategoryType(name="Welcome", posts=20)
- assert obj.name == "Welcome"
- assert obj.posts == 20
-
-
-def test_schema_object_type_instance_with_omitted_attrs_being_none():
- class CategoryType(GraphQLObject):
- __schema__ = gql(
- """
- type Category {
- name: String
- posts: Int
- }
- """
- )
-
- name: str
- posts: int
-
- obj = CategoryType(posts=20)
- assert obj.name is None
- assert obj.posts == 20
-
-
-def test_schema_object_type_instance_with_omitted_attrs_being_default_values():
- class CategoryType(GraphQLObject):
- __schema__ = gql(
- """
- type Category {
- name: String
- posts: Int
- }
- """
- )
-
- name: str = "Hello"
- posts: int = 42
-
- obj = CategoryType(posts=20)
- assert obj.name == "Hello"
- assert obj.posts == 20
-
-
-def test_schema_object_type_instance_with_all_attrs_being_default_values():
- class CategoryType(GraphQLObject):
- __schema__ = gql(
- """
- type Category {
- name: String
- posts: Int
- }
- """
- )
-
- name: str = "Hello"
- posts: int = 42
-
- obj = CategoryType()
- assert obj.name == "Hello"
- assert obj.posts == 42
-
-
-def test_schema_object_type_instance_with_aliased_attrs_values():
- class CategoryType(GraphQLObject):
- __schema__ = gql(
- """
- type Category {
- name: String
- posts: Int
- }
- """
- )
- __aliases__ = {"name": "title"}
-
- title: str = "Hello"
- posts: int = 42
-
- obj = CategoryType(title="Ok")
- assert obj.title == "Ok"
- assert obj.posts == 42
-
-
-def test_schema_object_type_instance_with_aliased_attrs_default_values():
- class CategoryType(GraphQLObject):
- __schema__ = gql(
- """
- type Category {
- name: String
- posts: Int
- }
- """
- )
- __aliases__ = {"name": "title"}
-
- title: str = "Hello"
- posts: int = 42
-
- obj = CategoryType()
- assert obj.title == "Hello"
- assert obj.posts == 42
-
-
-def test_schema_object_type_instance_with_invalid_attrs_raising_error(data_regression):
- class CategoryType(GraphQLObject):
- __schema__ = gql(
- """
- type Category {
- name: String
- posts: Int
- }
- """
- )
-
- name: str
- posts: int
-
- with pytest.raises(TypeError) as exc_info:
- CategoryType(name="Welcome", invalid="Ok")
-
- data_regression.check(str(exc_info.value))
-
-
-def test_schema_object_type_instance_with_aliased_attr_value():
- class CategoryType(GraphQLObject):
- __schema__ = gql(
- """
- type Category {
- name: String
- posts: Int
- }
- """
- )
- __aliases__ = {"name": "title"}
-
- title: str
- posts: int
-
- obj = CategoryType(title="Welcome", posts=20)
- assert obj.title == "Welcome"
- assert obj.posts == 20
-
-
-def test_object_type_with_field(assert_schema_equals):
- class QueryType(GraphQLObject):
- hello: str
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- hello: String!
- }
- """,
- )
-
- result = graphql_sync(schema, "{ hello }", root_value={"hello": "Hello World!"})
-
- assert not result.errors
- assert result.data == {"hello": "Hello World!"}
-
-
-def test_object_type_with_alias(assert_schema_equals):
- class QueryType(GraphQLObject):
- __aliases__ = {"hello": "welcome_message"}
-
- hello: str
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- hello: String!
- }
- """,
- )
-
- result = graphql_sync(
- schema, "{ hello }", root_value={"welcome_message": "Hello World!"}
- )
-
- assert not result.errors
- assert result.data == {"hello": "Hello World!"}
-
-
-def test_object_type_with_alias_excludes_alias_targets(assert_schema_equals):
- class QueryType(GraphQLObject):
- __aliases__ = {"hello": "welcome"}
-
- hello: str
- welcome: str
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- hello: String!
- }
- """,
- )
-
- result = graphql_sync(schema, "{ hello }", root_value={"welcome": "Hello World!"})
-
- assert not result.errors
- assert result.data == {"hello": "Hello World!"}
-
-
-def test_object_type_with_alias_includes_aliased_field_instances(assert_schema_equals):
- class QueryType(GraphQLObject):
- __aliases__ = {"hello": "welcome"}
-
- hello: str
- welcome: str = GraphQLObject.field()
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- hello: String!
- welcome: String!
- }
- """,
- )
-
- result = graphql_sync(
- schema, "{ hello welcome }", root_value={"welcome": "Hello World!"}
- )
-
- assert not result.errors
- assert result.data == {"hello": "Hello World!", "welcome": "Hello World!"}
-
-
-def test_object_type_with_attr_automatic_alias(assert_schema_equals):
- class QueryType(GraphQLObject):
- test_message: str
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- testMessage: String!
- }
- """,
- )
-
- result = graphql_sync(
- schema, "{ testMessage }", root_value={"test_message": "Hello World!"}
- )
-
- assert not result.errors
- assert result.data == {"testMessage": "Hello World!"}
-
-
-def test_object_type_with_field_instance_automatic_alias(assert_schema_equals):
- class QueryType(GraphQLObject):
- message: str = GraphQLObject.field(name="testMessage")
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- testMessage: String!
- }
- """,
- )
-
- result = graphql_sync(
- schema, "{ testMessage }", root_value={"message": "Hello World!"}
- )
-
- assert not result.errors
- assert result.data == {"testMessage": "Hello World!"}
-
-
-def test_object_type_with_field_resolver(assert_schema_equals):
- class QueryType(GraphQLObject):
- @GraphQLObject.field
- def hello(obj, info) -> str:
- return "Hello World!"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- hello: String!
- }
- """,
- )
-
- result = graphql_sync(schema, "{ hello }")
-
- assert not result.errors
- assert result.data == {"hello": "Hello World!"}
-
-
-def test_object_type_with_typed_field_instance(assert_schema_equals):
- class QueryType(GraphQLObject):
- hello = GraphQLObject.field(lambda *_: "Hello World!", graphql_type=str)
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- hello: String!
- }
- """,
- )
-
- result = graphql_sync(schema, "{ hello }")
-
- assert not result.errors
- assert result.data == {"hello": "Hello World!"}
-
-
-def test_object_type_with_annotated_field_instance(assert_schema_equals):
- class QueryType(GraphQLObject):
- hello: str = GraphQLObject.field(lambda *_: "Hello World!")
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- hello: String!
- }
- """,
- )
-
- result = graphql_sync(schema, "{ hello }")
-
- assert not result.errors
- assert result.data == {"hello": "Hello World!"}
-
-
-def test_object_type_with_typed_field_and_field_resolver(assert_schema_equals):
- class QueryType(GraphQLObject):
- name: str
-
- @GraphQLObject.field
- def hello(obj, info) -> str:
- return "Hello World!"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- name: String!
- hello: String!
- }
- """,
- )
-
- result = graphql_sync(schema, "{ name hello }", root_value={"name": "Ok"})
-
- assert not result.errors
- assert result.data == {"name": "Ok", "hello": "Hello World!"}
-
-
-def test_object_type_with_schema(assert_schema_equals):
- class QueryType(GraphQLObject):
- __schema__ = gql(
- """
- type Query {
- hello: String!
- }
- """
- )
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- hello: String!
- }
- """,
- )
-
- result = graphql_sync(schema, "{ hello }", root_value={"hello": "Hello World!"})
-
- assert not result.errors
- assert result.data == {"hello": "Hello World!"}
-
-
-def test_object_type_with_nested_types(assert_schema_equals):
- class UserType(GraphQLObject):
- name: str
-
- class PostType(GraphQLObject):
- message: str
-
- class QueryType(GraphQLObject):
- user: UserType
-
- @GraphQLObject.field(graphql_type=PostType)
- def post(obj, info):
- return {"message": "test"}
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- user: User!
- post: Post!
- }
-
- type User {
- name: String!
- }
-
- type Post {
- message: String!
- }
- """,
- )
-
- result = graphql_sync(
- schema,
- "{ user { name } post { message } }",
- root_value={"user": {"name": "Bob"}},
- )
-
- assert not result.errors
- assert result.data == {
- "user": {
- "name": "Bob",
- },
- "post": {"message": "test"},
- }
-
-
-def test_resolver_decorator_sets_resolver_for_type_hint_field(assert_schema_equals):
- class QueryType(GraphQLObject):
- hello: str
-
- @GraphQLObject.resolver("hello")
- def resolve_hello(*_):
- return "Hello World!"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- hello: String!
- }
- """,
- )
-
- result = graphql_sync(schema, "{ hello }")
-
- assert not result.errors
- assert result.data == {"hello": "Hello World!"}
-
-
-def test_resolver_decorator_sets_resolver_for_instance_field(assert_schema_equals):
- class QueryType(GraphQLObject):
- hello: str = GraphQLObject.field(name="hello")
-
- @GraphQLObject.resolver("hello")
- def resolve_hello(*_):
- return "Hello World!"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- hello: String!
- }
- """,
- )
-
- result = graphql_sync(schema, "{ hello }")
-
- assert not result.errors
- assert result.data == {"hello": "Hello World!"}
-
-
-def test_resolver_decorator_sets_resolver_for_field_in_schema(assert_schema_equals):
- class QueryType(GraphQLObject):
- __schema__ = gql(
- """
- type Query {
- hello: String!
- }
- """
- )
-
- @GraphQLObject.resolver("hello")
- def resolve_hello(*_):
- return "Hello World!"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- hello: String!
- }
- """,
- )
-
- result = graphql_sync(schema, "{ hello }")
-
- assert not result.errors
- assert result.data == {"hello": "Hello World!"}
-
-
-def test_object_type_with_description(assert_schema_equals):
- class QueryType(GraphQLObject):
- __description__ = "Lorem ipsum."
-
- hello: str
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- \"\"\"Lorem ipsum.\"\"\"
- type Query {
- hello: String!
- }
- """,
- )
-
- result = graphql_sync(schema, "{ hello }", root_value={"hello": "Hello World!"})
-
- assert not result.errors
- assert result.data == {"hello": "Hello World!"}
-
-
-def test_field_decorator_sets_description_for_field(assert_schema_equals):
- class QueryType(GraphQLObject):
- @GraphQLObject.field(description="Lorem ipsum.")
- def hello(obj, info) -> str:
- return "Hello World!"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- \"\"\"Lorem ipsum.\"\"\"
- hello: String!
- }
- """,
- )
-
- result = graphql_sync(schema, "{ hello }")
-
- assert not result.errors
- assert result.data == {"hello": "Hello World!"}
-
-
-def test_field_decorator_sets_description_for_field_arg(assert_schema_equals):
- class QueryType(GraphQLObject):
- @GraphQLObject.field(
- args={"name": GraphQLObject.argument(description="Lorem ipsum.")}
- )
- def hello(obj, info, name: str) -> str:
- return f"Hello {name}!"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- hello(
- \"\"\"Lorem ipsum.\"\"\"
- name: String!
- ): String!
- }
- """,
- )
-
- result = graphql_sync(schema, '{ hello(name: "Bob") }')
-
- assert not result.errors
- assert result.data == {"hello": "Hello Bob!"}
-
-
-def test_resolver_decorator_sets_description_for_type_hint_field(assert_schema_equals):
- class QueryType(GraphQLObject):
- hello: str
-
- @GraphQLObject.resolver("hello", description="Lorem ipsum.")
- def resolve_hello(*_):
- return "Hello World!"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- \"\"\"Lorem ipsum.\"\"\"
- hello: String!
- }
- """,
- )
-
- result = graphql_sync(schema, "{ hello }")
-
- assert not result.errors
- assert result.data == {"hello": "Hello World!"}
-
-
-def test_resolver_decorator_sets_description_for_field_in_schema(assert_schema_equals):
- class QueryType(GraphQLObject):
- __schema__ = gql(
- """
- type Query {
- hello: String!
- }
- """
- )
-
- @GraphQLObject.resolver("hello", description="Lorem ipsum.")
- def resolve_hello(*_):
- return "Hello World!"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- \"\"\"Lorem ipsum.\"\"\"
- hello: String!
- }
- """,
- )
-
- result = graphql_sync(schema, "{ hello }")
-
- assert not result.errors
- assert result.data == {"hello": "Hello World!"}
-
-
-def test_resolver_decorator_sets_description_for_field_arg(assert_schema_equals):
- class QueryType(GraphQLObject):
- hello: str
-
- @GraphQLObject.resolver(
- "hello", args={"name": GraphQLObject.argument(description="Lorem ipsum.")}
- )
- def resolve_hello(obj, info, name: str) -> str:
- return f"Hello {name}!"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- hello(
- \"\"\"Lorem ipsum.\"\"\"
- name: String!
- ): String!
- }
- """,
- )
-
- result = graphql_sync(schema, '{ hello(name: "Bob") }')
-
- assert not result.errors
- assert result.data == {"hello": "Hello Bob!"}
-
-
-def test_schema_sets_description_for_field_arg(assert_schema_equals):
- class QueryType(GraphQLObject):
- __schema__ = gql(
- """
- type Query {
- hello(
- \"\"\"Lorem ipsum.\"\"\"
- name: String!
- ): String!
- }
- """
- )
-
- @GraphQLObject.resolver("hello")
- def resolve_hello(*_, name: str):
- return f"Hello {name}!"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- hello(
- \"\"\"Lorem ipsum.\"\"\"
- name: String!
- ): String!
- }
- """,
- )
-
- result = graphql_sync(schema, '{ hello(name: "Bob") }')
-
- assert not result.errors
- assert result.data == {"hello": "Hello Bob!"}
-
-
-def test_resolver_decorator_sets_description_for_field_arg_in_schema(
- assert_schema_equals,
-):
- class QueryType(GraphQLObject):
- __schema__ = gql(
- """
- type Query {
- hello(name: String!): String!
- }
- """
- )
-
- @GraphQLObject.resolver(
- "hello", args={"name": GraphQLObject.argument(description="Description")}
- )
- def resolve_hello(*_, name: str):
- return f"Hello {name}!"
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- hello(
- \"\"\"Description\"\"\"
- name: String!
- ): String!
- }
- """,
- )
-
- result = graphql_sync(schema, '{ hello(name: "Bob") }')
-
- assert not result.errors
- assert result.data == {"hello": "Hello Bob!"}
-
-
-def test_object_type_self_reference(
- assert_schema_equals,
-):
- class CategoryType(GraphQLObject):
- name: str
- parent: Optional["CategoryType"]
-
- class QueryType(GraphQLObject):
- category: CategoryType
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- category: Category!
- }
-
- type Category {
- name: String!
- parent: Category
- }
- """,
- )
-
- result = graphql_sync(
- schema,
- "{ category { name parent { name } } }",
- root_value={
- "category": {
- "name": "Lorem",
- "parent": {
- "name": "Ipsum",
- },
- },
- },
- )
-
- assert not result.errors
- assert result.data == {
- "category": {
- "name": "Lorem",
- "parent": {
- "name": "Ipsum",
- },
- },
- }
-
-
-def test_object_type_return_instance(
- assert_schema_equals,
-):
- class CategoryType(GraphQLObject):
- name: str
- color: str
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field()
- def category(*_) -> CategoryType:
- return CategoryType(
- name="Welcome",
- color="#FF00FF",
- )
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- category: Category!
- }
-
- type Category {
- name: String!
- color: String!
- }
- """,
- )
-
- result = graphql_sync(schema, "{ category { name color } }")
-
- assert not result.errors
- assert result.data == {
- "category": {
- "name": "Welcome",
- "color": "#FF00FF",
- },
- }
-
-
-def test_object_type_nested_type(
- assert_schema_equals,
-):
- class UserType(GraphQLObject):
- username: str
-
- class CategoryType(GraphQLObject):
- name: str
- parent: Optional["CategoryType"]
- owner: UserType
-
- class QueryType(GraphQLObject):
- category: CategoryType
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- category: Category!
- }
-
- type Category {
- name: String!
- parent: Category
- owner: User!
- }
-
- type User {
- username: String!
- }
- """,
- )
-
- result = graphql_sync(
- schema,
- "{ category { name parent { name } owner { username } } }",
- root_value={
- "category": {
- "name": "Lorem",
- "parent": {
- "name": "Ipsum",
- },
- "owner": {
- "username": "John",
- },
- },
- },
- )
-
- assert not result.errors
- assert result.data == {
- "category": {
- "name": "Lorem",
- "parent": {
- "name": "Ipsum",
- },
- "owner": {
- "username": "John",
- },
- },
- }
diff --git a/tests_next/test_scalar_type.py b/tests_next/test_scalar_type.py
deleted file mode 100644
index 2f578c6..0000000
--- a/tests_next/test_scalar_type.py
+++ /dev/null
@@ -1,111 +0,0 @@
-from datetime import date
-
-from graphql import graphql_sync
-
-from ariadne_graphql_modules import gql
-from ariadne_graphql_modules.next import (
- GraphQLObject,
- GraphQLScalar,
- make_executable_schema,
-)
-
-
-class DateScalar(GraphQLScalar[date]):
- @classmethod
- def serialize(cls, value):
- if isinstance(value, cls):
- return str(value.unwrap())
-
- return str(value)
-
-
-def test_scalar_field_returning_scalar_instance(assert_schema_equals):
- class QueryType(GraphQLObject):
- date: DateScalar
-
- @GraphQLObject.resolver("date")
- def resolve_date(*_) -> DateScalar:
- return DateScalar(date(1989, 10, 30))
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- scalar Date
-
- type Query {
- date: Date!
- }
- """,
- )
-
- result = graphql_sync(schema, "{ date }")
-
- assert not result.errors
- assert result.data == {"date": "1989-10-30"}
-
-
-def test_scalar_field_returning_scalar_wrapped_type(assert_schema_equals):
- class QueryType(GraphQLObject):
- scalar_date: DateScalar
-
- @GraphQLObject.resolver("scalar_date", graphql_type=DateScalar)
- def resolve_date(*_) -> date:
- return date(1989, 10, 30)
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- scalar Date
-
- type Query {
- scalarDate: Date!
- }
- """,
- )
-
- result = graphql_sync(schema, "{ scalarDate }")
-
- assert not result.errors
- assert result.data == {"scalarDate": "1989-10-30"}
-
-
-class SchemaDateScalar(GraphQLScalar[date]):
- __schema__ = gql("scalar Date")
-
- @classmethod
- def serialize(cls, value):
- if isinstance(value, cls):
- return str(value.unwrap())
-
- return str(value)
-
-
-def test_schema_scalar_field_returning_scalar_instance(assert_schema_equals):
- class QueryType(GraphQLObject):
- date: SchemaDateScalar
-
- @GraphQLObject.resolver("date")
- def resolve_date(*_) -> SchemaDateScalar:
- return SchemaDateScalar(date(1989, 10, 30))
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- scalar Date
-
- type Query {
- date: Date!
- }
- """,
- )
-
- result = graphql_sync(schema, "{ date }")
-
- assert not result.errors
- assert result.data == {"date": "1989-10-30"}
diff --git a/tests_next/test_subscription_type.py b/tests_next/test_subscription_type.py
deleted file mode 100644
index b8bd2a5..0000000
--- a/tests_next/test_subscription_type.py
+++ /dev/null
@@ -1,754 +0,0 @@
-from typing import List
-
-from ariadne import gql
-from graphql import subscribe, parse
-import pytest
-from ariadne_graphql_modules.next import (
- GraphQLID,
- GraphQLObject,
- GraphQLSubscription,
- GraphQLUnion,
- make_executable_schema,
-)
-
-
-class Message(GraphQLObject):
- id: GraphQLID
- content: str
- author: str
-
-
-class User(GraphQLObject):
- id: GraphQLID
- username: str
-
-
-class Notification(GraphQLUnion):
- __types__ = [Message, User]
-
-
-@pytest.mark.asyncio
-async def test_basic_subscription_without_schema(assert_schema_equals):
- class SubscriptionType(GraphQLSubscription):
- message_added: Message
-
- @GraphQLSubscription.source("message_added")
- async def message_added_generator(obj, info):
- while True:
- yield {"id": "some_id", "content": "message", "author": "Anon"}
-
- @GraphQLSubscription.resolver("message_added", graphql_type=Message)
- async def resolve_message_added(message, info):
- return message
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field(graphql_type=str)
- def search_sth(*_) -> str:
- return "search"
-
- schema = make_executable_schema(QueryType, SubscriptionType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- searchSth: String!
- }
-
- type Subscription {
- messageAdded: Message!
- }
-
- type Message {
- id: ID!
- content: String!
- author: String!
- }
- """,
- )
-
- query = parse("subscription { messageAdded {id content author} }")
- sub = await subscribe(schema, query)
-
- # Ensure the subscription is an async iterator
- assert hasattr(sub, "__aiter__")
-
- # Fetch the first result
- result = await sub.__anext__()
-
- # Validate the result
- assert not result.errors
- assert result.data == {
- "messageAdded": {"id": "some_id", "content": "message", "author": "Anon"}
- }
-
-
-@pytest.mark.asyncio
-async def test_subscription_with_arguments_without_schema(assert_schema_equals):
- class SubscriptionType(GraphQLSubscription):
- message_added: Message
-
- @GraphQLSubscription.source(
- "message_added",
- args={"channel": GraphQLObject.argument(description="Lorem ipsum.")},
- )
- async def message_added_generator(obj, info, channel: GraphQLID):
- while True:
- yield {
- "id": "some_id",
- "content": f"message_{channel}",
- "author": "Anon",
- }
-
- @GraphQLSubscription.resolver(
- "message_added",
- graphql_type=Message,
- )
- async def resolve_message_added(message, *_, channel: GraphQLID):
- return message
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field(graphql_type=str)
- def search_sth(*_) -> str:
- return "search"
-
- schema = make_executable_schema(QueryType, SubscriptionType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- searchSth: String!
- }
-
- type Subscription {
- messageAdded(
- \"\"\"Lorem ipsum.\"\"\"
- channel: ID!
- ): Message!
- }
-
- type Message {
- id: ID!
- content: String!
- author: String!
- }
- """,
- )
-
- query = parse('subscription { messageAdded(channel: "123") {id content author} }')
- sub = await subscribe(schema, query)
-
- # Ensure the subscription is an async iterator
- assert hasattr(sub, "__aiter__")
-
- # Fetch the first result
- result = await sub.__anext__()
-
- # Validate the result
- assert not result.errors
- assert result.data == {
- "messageAdded": {"id": "some_id", "content": "message_123", "author": "Anon"}
- }
-
-
-@pytest.mark.asyncio
-async def test_multiple_supscriptions_without_schema(assert_schema_equals):
- class SubscriptionType(GraphQLSubscription):
- message_added: Message
- user_joined: User
-
- @GraphQLSubscription.source(
- "message_added",
- args={"channel": GraphQLObject.argument(description="Lorem ipsum.")},
- )
- async def message_added_generator(obj, info, channel: GraphQLID):
- while True:
- yield {
- "id": "some_id",
- "content": f"message_{channel}",
- "author": "Anon",
- }
-
- @GraphQLSubscription.resolver(
- "message_added",
- graphql_type=Message,
- )
- async def resolve_message_added(message, *_, channel: GraphQLID):
- return message
-
- @GraphQLSubscription.source(
- "user_joined",
- )
- async def user_joined_generator(obj, info):
- while True:
- yield {
- "id": "some_id",
- "username": "username",
- }
-
- @GraphQLSubscription.resolver(
- "user_joined",
- graphql_type=Message,
- )
- async def resolve_user_joined(user, *_):
- return user
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field(graphql_type=str)
- def search_sth(*_) -> str:
- return "search"
-
- schema = make_executable_schema(QueryType, SubscriptionType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- searchSth: String!
- }
-
- type Subscription {
- messageAdded(
- \"\"\"Lorem ipsum.\"\"\"
- channel: ID!
- ): Message!
- userJoined: User!
- }
-
- type Message {
- id: ID!
- content: String!
- author: String!
- }
-
- type User {
- id: ID!
- username: String!
- }
- """,
- )
-
- query = parse("subscription { userJoined {id username} }")
- sub = await subscribe(schema, query)
-
- # Ensure the subscription is an async iterator
- assert hasattr(sub, "__aiter__")
-
- # Fetch the first result
- result = await sub.__anext__()
-
- # Validate the result
- assert not result.errors
- assert result.data == {"userJoined": {"id": "some_id", "username": "username"}}
-
-
-@pytest.mark.asyncio
-async def test_subscription_with_complex_data_without_schema(assert_schema_equals):
- class SubscriptionType(GraphQLSubscription):
- messages_in_channel: List[Message]
-
- @GraphQLSubscription.source(
- "messages_in_channel",
- args={"channel_id": GraphQLObject.argument(description="Lorem ipsum.")},
- )
- async def message_added_generator(obj, info, channel_id: GraphQLID):
- while True:
- yield [
- {
- "id": "some_id",
- "content": f"message_{channel_id}",
- "author": "Anon",
- }
- ]
-
- @GraphQLSubscription.resolver(
- "messages_in_channel",
- graphql_type=Message,
- )
- async def resolve_message_added(message, *_, channel_id: GraphQLID):
- return message
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field(graphql_type=str)
- def search_sth(*_) -> str:
- return "search"
-
- schema = make_executable_schema(QueryType, SubscriptionType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- searchSth: String!
- }
-
- type Subscription {
- messagesInChannel(
- \"\"\"Lorem ipsum.\"\"\"
- channelId: ID!
- ): [Message!]!
- }
-
- type Message {
- id: ID!
- content: String!
- author: String!
- }
- """,
- )
-
- query = parse(
- 'subscription { messagesInChannel(channelId: "123") {id content author} }'
- )
- sub = await subscribe(schema, query)
-
- # Ensure the subscription is an async iterator
- assert hasattr(sub, "__aiter__")
-
- # Fetch the first result
- result = await sub.__anext__()
-
- # Validate the result
- assert not result.errors
- assert result.data == {
- "messagesInChannel": [
- {"id": "some_id", "content": "message_123", "author": "Anon"}
- ]
- }
-
-
-@pytest.mark.asyncio
-async def test_subscription_with_union_without_schema(assert_schema_equals):
- class SubscriptionType(GraphQLSubscription):
- notification_received: Notification
-
- @GraphQLSubscription.source(
- "notification_received",
- )
- async def message_added_generator(obj, info):
- while True:
- yield Message(id=1, content="content", author="anon")
-
- @GraphQLSubscription.resolver(
- "notification_received",
- )
- async def resolve_message_added(message, *_):
- return message
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field(graphql_type=str)
- def search_sth(*_) -> str:
- return "search"
-
- schema = make_executable_schema(QueryType, SubscriptionType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- searchSth: String!
- }
-
- type Subscription {
- notificationReceived: Notification!
- }
-
- union Notification = Message | User
-
- type Message {
- id: ID!
- content: String!
- author: String!
- }
-
- type User {
- id: ID!
- username: String!
- }
- """,
- )
-
- query = parse("subscription { notificationReceived { ... on Message { id } } }")
- sub = await subscribe(schema, query)
-
- # Ensure the subscription is an async iterator
- assert hasattr(sub, "__aiter__")
-
- # Fetch the first result
- result = await sub.__anext__()
-
- # Validate the result
- assert not result.errors
- assert result.data == {"notificationReceived": {"id": "1"}}
-
-
-@pytest.mark.asyncio
-async def test_basic_subscription_with_schema(assert_schema_equals):
- class SubscriptionType(GraphQLSubscription):
- __schema__ = gql(
- """
- type Subscription {
- messageAdded: Message!
- }
- """
- )
-
- @GraphQLSubscription.source("messageAdded")
- async def message_added_generator(obj, info):
- while True:
- yield {"id": "some_id", "content": "message", "author": "Anon"}
-
- @GraphQLSubscription.resolver("messageAdded", graphql_type=Message)
- async def resolve_message_added(message, info):
- return message
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field(graphql_type=str)
- def search_sth(*_) -> str:
- return "search"
-
- schema = make_executable_schema(QueryType, SubscriptionType, Message)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- searchSth: String!
- }
-
- type Subscription {
- messageAdded: Message!
- }
-
- type Message {
- id: ID!
- content: String!
- author: String!
- }
- """,
- )
-
- query = parse("subscription { messageAdded {id content author} }")
- sub = await subscribe(schema, query)
-
- # Ensure the subscription is an async iterator
- assert hasattr(sub, "__aiter__")
-
- # Fetch the first result
- result = await sub.__anext__()
-
- # Validate the result
- assert not result.errors
- assert result.data == {
- "messageAdded": {"id": "some_id", "content": "message", "author": "Anon"}
- }
-
-
-@pytest.mark.asyncio
-async def test_subscription_with_arguments_with_schema(assert_schema_equals):
- class SubscriptionType(GraphQLSubscription):
- __schema__ = gql(
- """
- type Subscription {
- messageAdded(channel: ID!): Message!
- }
- """
- )
-
- @GraphQLSubscription.source(
- "messageAdded",
- )
- async def message_added_generator(obj, info, channel: GraphQLID):
- while True:
- yield {
- "id": "some_id",
- "content": f"message_{channel}",
- "author": "Anon",
- }
-
- @GraphQLSubscription.resolver(
- "messageAdded",
- graphql_type=Message,
- )
- async def resolve_message_added(message, *_, channel: GraphQLID):
- return message
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field(graphql_type=str)
- def search_sth(*_) -> str:
- return "search"
-
- schema = make_executable_schema(QueryType, SubscriptionType, Message)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- searchSth: String!
- }
-
- type Subscription {
- messageAdded(channel: ID!): Message!
- }
-
- type Message {
- id: ID!
- content: String!
- author: String!
- }
- """,
- )
-
- query = parse('subscription { messageAdded(channel: "123") {id content author} }')
- sub = await subscribe(schema, query)
-
- # Ensure the subscription is an async iterator
- assert hasattr(sub, "__aiter__")
-
- # Fetch the first result
- result = await sub.__anext__()
-
- # Validate the result
- assert not result.errors
- assert result.data == {
- "messageAdded": {"id": "some_id", "content": "message_123", "author": "Anon"}
- }
-
-
-@pytest.mark.asyncio
-async def test_multiple_supscriptions_with_schema(assert_schema_equals):
- class SubscriptionType(GraphQLSubscription):
- __schema__ = gql(
- """
- type Subscription {
- messageAdded: Message!
- userJoined: User!
- }
- """
- )
-
- @GraphQLSubscription.source(
- "messageAdded",
- )
- async def message_added_generator(obj, info):
- while True:
- yield {
- "id": "some_id",
- "content": "message",
- "author": "Anon",
- }
-
- @GraphQLSubscription.resolver(
- "messageAdded",
- )
- async def resolve_message_added(message, *_):
- return message
-
- @GraphQLSubscription.source(
- "userJoined",
- )
- async def user_joined_generator(obj, info):
- while True:
- yield {
- "id": "some_id",
- "username": "username",
- }
-
- @GraphQLSubscription.resolver(
- "userJoined",
- )
- async def resolve_user_joined(user, *_):
- return user
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field(graphql_type=str)
- def search_sth(*_) -> str:
- return "search"
-
- schema = make_executable_schema(QueryType, SubscriptionType, Message, User)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- searchSth: String!
- }
-
- type Subscription {
- messageAdded: Message!
- userJoined: User!
- }
-
- type Message {
- id: ID!
- content: String!
- author: String!
- }
-
- type User {
- id: ID!
- username: String!
- }
- """,
- )
-
- query = parse("subscription { userJoined {id username} }")
- sub = await subscribe(schema, query)
-
- # Ensure the subscription is an async iterator
- assert hasattr(sub, "__aiter__")
-
- # Fetch the first result
- result = await sub.__anext__()
-
- # Validate the result
- assert not result.errors
- assert result.data == {"userJoined": {"id": "some_id", "username": "username"}}
-
-
-@pytest.mark.asyncio
-async def test_subscription_with_complex_data_with_schema(assert_schema_equals):
- class SubscriptionType(GraphQLSubscription):
- __schema__ = gql(
- """
- type Subscription {
- messagesInChannel(channelId: ID!): [Message!]!
- }
- """
- )
-
- @GraphQLSubscription.source(
- "messagesInChannel",
- )
- async def message_added_generator(obj, info, channelId: GraphQLID):
- while True:
- yield [
- {
- "id": "some_id",
- "content": f"message_{channelId}",
- "author": "Anon",
- }
- ]
-
- @GraphQLSubscription.resolver(
- "messagesInChannel",
- )
- async def resolve_message_added(message, *_, channelId: GraphQLID):
- return message
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field(graphql_type=str)
- def search_sth(*_) -> str:
- return "search"
-
- schema = make_executable_schema(QueryType, SubscriptionType, Message)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- searchSth: String!
- }
-
- type Subscription {
- messagesInChannel(channelId: ID!): [Message!]!
- }
-
- type Message {
- id: ID!
- content: String!
- author: String!
- }
- """,
- )
-
- query = parse(
- 'subscription { messagesInChannel(channelId: "123") {id content author} }'
- )
- sub = await subscribe(schema, query)
-
- # Ensure the subscription is an async iterator
- assert hasattr(sub, "__aiter__")
-
- # Fetch the first result
- result = await sub.__anext__()
-
- # Validate the result
- assert not result.errors
- assert result.data == {
- "messagesInChannel": [
- {"id": "some_id", "content": "message_123", "author": "Anon"}
- ]
- }
-
-
-@pytest.mark.asyncio
-async def test_subscription_with_union_with_schema(assert_schema_equals):
- class SubscriptionType(GraphQLSubscription):
- __schema__ = gql(
- """
- type Subscription {
- notificationReceived: Notification!
- }
- """
- )
-
- @GraphQLSubscription.source(
- "notificationReceived",
- )
- async def message_added_generator(obj, info):
- while True:
- yield Message(id=1, content="content", author="anon")
-
- @GraphQLSubscription.resolver(
- "notificationReceived",
- )
- async def resolve_message_added(message, *_):
- return message
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field(graphql_type=str)
- def search_sth(*_) -> str:
- return "search"
-
- schema = make_executable_schema(QueryType, SubscriptionType, Notification)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- searchSth: String!
- }
-
- type Subscription {
- notificationReceived: Notification!
- }
-
- union Notification = Message | User
-
- type Message {
- id: ID!
- content: String!
- author: String!
- }
-
- type User {
- id: ID!
- username: String!
- }
- """,
- )
-
- query = parse("subscription { notificationReceived { ... on Message { id } } }")
- sub = await subscribe(schema, query)
-
- # Ensure the subscription is an async iterator
- assert hasattr(sub, "__aiter__")
-
- # Fetch the first result
- result = await sub.__anext__()
-
- # Validate the result
- assert not result.errors
- assert result.data == {"notificationReceived": {"id": "1"}}
diff --git a/tests_next/test_union_type.py b/tests_next/test_union_type.py
deleted file mode 100644
index 6d20267..0000000
--- a/tests_next/test_union_type.py
+++ /dev/null
@@ -1,223 +0,0 @@
-from typing import List, Union
-
-from graphql import graphql_sync
-
-from ariadne_graphql_modules.next import (
- GraphQLID,
- GraphQLObject,
- GraphQLUnion,
- make_executable_schema,
-)
-
-
-class UserType(GraphQLObject):
- id: GraphQLID
- username: str
-
-
-class CommentType(GraphQLObject):
- id: GraphQLID
- content: str
-
-
-def test_union_field_returning_object_instance(assert_schema_equals):
- class ResultType(GraphQLUnion):
- __types__ = [UserType, CommentType]
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field(graphql_type=List[ResultType])
- def search(*_) -> List[Union[UserType, CommentType]]:
- return [
- UserType(id=1, username="Bob"),
- CommentType(id=2, content="Hello World!"),
- ]
-
- schema = make_executable_schema(QueryType)
-
- assert_schema_equals(
- schema,
- """
- type Query {
- search: [Result!]!
- }
-
- union Result = User | Comment
-
- type User {
- id: ID!
- username: String!
- }
-
- type Comment {
- id: ID!
- content: String!
- }
- """,
- )
-
- result = graphql_sync(
- schema,
- """
- {
- search {
- ... on User {
- id
- username
- }
- ... on Comment {
- id
- content
- }
- }
- }
- """,
- )
-
- assert not result.errors
- assert result.data == {
- "search": [
- {"id": "1", "username": "Bob"},
- {"id": "2", "content": "Hello World!"},
- ]
- }
-
-
-def test_union_field_returning_empty_list():
- class ResultType(GraphQLUnion):
- __types__ = [UserType, CommentType]
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field(graphql_type=List[ResultType])
- def search(*_) -> List[Union[UserType, CommentType]]:
- return []
-
- schema = make_executable_schema(QueryType)
-
- result = graphql_sync(
- schema,
- """
- {
- search {
- ... on User {
- id
- username
- }
- ... on Comment {
- id
- content
- }
- }
- }
- """,
- )
- assert not result.errors
- assert result.data == {"search": []}
-
-
-def test_union_field_with_invalid_type_access(assert_schema_equals):
- class ResultType(GraphQLUnion):
- __types__ = [UserType, CommentType]
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field(graphql_type=List[ResultType])
- def search(*_) -> List[Union[UserType, CommentType]]:
- return [
- UserType(id=1, username="Bob"),
- "InvalidType",
- ]
-
- schema = make_executable_schema(QueryType)
-
- result = graphql_sync(
- schema,
- """
- {
- search {
- ... on User {
- id
- username
- }
- ... on Comment {
- id
- content
- }
- }
- }
- """,
- )
- assert result.errors
- assert "InvalidType" in str(result.errors)
-
-
-def test_serialization_error_handling(assert_schema_equals):
- class InvalidType:
- def __init__(self, value):
- self.value = value
-
- class ResultType(GraphQLUnion):
- __types__ = [UserType, CommentType]
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field(graphql_type=List[ResultType])
- def search(*_) -> List[Union[UserType, CommentType, InvalidType]]:
- return [InvalidType("This should cause an error")]
-
- schema = make_executable_schema(QueryType)
-
- result = graphql_sync(
- schema,
- """
- {
- search {
- ... on User {
- id
- username
- }
- }
- }
- """,
- )
- assert result.errors
-
-
-def test_union_with_schema_definition(assert_schema_equals):
- class SearchResultUnion(GraphQLUnion):
- __schema__ = """
- union SearchResult = User | Comment
- """
- __types__ = [UserType, CommentType]
-
- class QueryType(GraphQLObject):
- @GraphQLObject.field(graphql_type=List[SearchResultUnion])
- def search(*_) -> List[Union[UserType, CommentType]]:
- return [
- UserType(id="1", username="Alice"),
- CommentType(id="2", content="Test post"),
- ]
-
- schema = make_executable_schema(QueryType, SearchResultUnion)
-
- result = graphql_sync(
- schema,
- """
- {
- search {
- ... on User {
- id
- username
- }
- ... on Comment {
- id
- content
- }
- }
- }
- """,
- )
- assert not result.errors
- assert result.data == {
- "search": [
- {"id": "1", "username": "Alice"},
- {"id": "2", "content": "Test post"},
- ]
- }
diff --git a/tests_next/__init__.py b/tests_v1/__init__.py
similarity index 100%
rename from tests_next/__init__.py
rename to tests_v1/__init__.py
diff --git a/tests_v1/conftest.py b/tests_v1/conftest.py
new file mode 100644
index 0000000..0f16709
--- /dev/null
+++ b/tests_v1/conftest.py
@@ -0,0 +1,12 @@
+from pathlib import Path
+import pytest
+
+
+@pytest.fixture(scope="session")
+def datadir() -> Path:
+ return Path(__file__).parent / "snapshots"
+
+
+@pytest.fixture(scope="session")
+def original_datadir() -> Path:
+ return Path(__file__).parent / "snapshots"
diff --git a/tests/snapshots/test_definition_parser_raises_error_schema_str_contains_multiple_types.obtained.yml b/tests_v1/snapshots/test_definition_parser_raises_error_schema_str_contains_multiple_types.obtained.yml
similarity index 100%
rename from tests/snapshots/test_definition_parser_raises_error_schema_str_contains_multiple_types.obtained.yml
rename to tests_v1/snapshots/test_definition_parser_raises_error_schema_str_contains_multiple_types.obtained.yml
diff --git a/tests/snapshots/test_definition_parser_raises_error_schema_str_contains_multiple_types.yml b/tests_v1/snapshots/test_definition_parser_raises_error_schema_str_contains_multiple_types.yml
similarity index 100%
rename from tests/snapshots/test_definition_parser_raises_error_schema_str_contains_multiple_types.yml
rename to tests_v1/snapshots/test_definition_parser_raises_error_schema_str_contains_multiple_types.yml
diff --git a/tests/snapshots/test_definition_parser_raises_error_when_schema_str_has_invalid_syntax.obtained.yml b/tests_v1/snapshots/test_definition_parser_raises_error_when_schema_str_has_invalid_syntax.obtained.yml
similarity index 100%
rename from tests/snapshots/test_definition_parser_raises_error_when_schema_str_has_invalid_syntax.obtained.yml
rename to tests_v1/snapshots/test_definition_parser_raises_error_when_schema_str_has_invalid_syntax.obtained.yml
diff --git a/tests/snapshots/test_definition_parser_raises_error_when_schema_str_has_invalid_syntax.yml b/tests_v1/snapshots/test_definition_parser_raises_error_when_schema_str_has_invalid_syntax.yml
similarity index 100%
rename from tests/snapshots/test_definition_parser_raises_error_when_schema_str_has_invalid_syntax.yml
rename to tests_v1/snapshots/test_definition_parser_raises_error_when_schema_str_has_invalid_syntax.yml
diff --git a/tests/snapshots/test_definition_parser_raises_error_when_schema_type_is_invalid.obtained.yml b/tests_v1/snapshots/test_definition_parser_raises_error_when_schema_type_is_invalid.obtained.yml
similarity index 100%
rename from tests/snapshots/test_definition_parser_raises_error_when_schema_type_is_invalid.obtained.yml
rename to tests_v1/snapshots/test_definition_parser_raises_error_when_schema_type_is_invalid.obtained.yml
diff --git a/tests/snapshots/test_definition_parser_raises_error_when_schema_type_is_invalid.yml b/tests_v1/snapshots/test_definition_parser_raises_error_when_schema_type_is_invalid.yml
similarity index 100%
rename from tests/snapshots/test_definition_parser_raises_error_when_schema_type_is_invalid.yml
rename to tests_v1/snapshots/test_definition_parser_raises_error_when_schema_type_is_invalid.yml
diff --git a/tests/snapshots/test_directive_type_raises_attribute_error_when_defined_without_schema.obtained.yml b/tests_v1/snapshots/test_directive_type_raises_attribute_error_when_defined_without_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_directive_type_raises_attribute_error_when_defined_without_schema.obtained.yml
rename to tests_v1/snapshots/test_directive_type_raises_attribute_error_when_defined_without_schema.obtained.yml
diff --git a/tests/snapshots/test_directive_type_raises_attribute_error_when_defined_without_schema.yml b/tests_v1/snapshots/test_directive_type_raises_attribute_error_when_defined_without_schema.yml
similarity index 100%
rename from tests/snapshots/test_directive_type_raises_attribute_error_when_defined_without_schema.yml
rename to tests_v1/snapshots/test_directive_type_raises_attribute_error_when_defined_without_schema.yml
diff --git a/tests/snapshots/test_directive_type_raises_attribute_error_when_defined_without_visitor.obtained.yml b/tests_v1/snapshots/test_directive_type_raises_attribute_error_when_defined_without_visitor.obtained.yml
similarity index 100%
rename from tests/snapshots/test_directive_type_raises_attribute_error_when_defined_without_visitor.obtained.yml
rename to tests_v1/snapshots/test_directive_type_raises_attribute_error_when_defined_without_visitor.obtained.yml
diff --git a/tests/snapshots/test_directive_type_raises_attribute_error_when_defined_without_visitor.yml b/tests_v1/snapshots/test_directive_type_raises_attribute_error_when_defined_without_visitor.yml
similarity index 100%
rename from tests/snapshots/test_directive_type_raises_attribute_error_when_defined_without_visitor.yml
rename to tests_v1/snapshots/test_directive_type_raises_attribute_error_when_defined_without_visitor.yml
diff --git a/tests/snapshots/test_directive_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml b/tests_v1/snapshots/test_directive_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_directive_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
rename to tests_v1/snapshots/test_directive_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
diff --git a/tests/snapshots/test_directive_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml b/tests_v1/snapshots/test_directive_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
similarity index 100%
rename from tests/snapshots/test_directive_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
rename to tests_v1/snapshots/test_directive_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
diff --git a/tests/snapshots/test_directive_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml b/tests_v1/snapshots/test_directive_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
similarity index 100%
rename from tests/snapshots/test_directive_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
rename to tests_v1/snapshots/test_directive_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
diff --git a/tests/snapshots/test_directive_type_raises_error_when_defined_with_invalid_schema_str.yml b/tests_v1/snapshots/test_directive_type_raises_error_when_defined_with_invalid_schema_str.yml
similarity index 100%
rename from tests/snapshots/test_directive_type_raises_error_when_defined_with_invalid_schema_str.yml
rename to tests_v1/snapshots/test_directive_type_raises_error_when_defined_with_invalid_schema_str.yml
diff --git a/tests/snapshots/test_directive_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml b/tests_v1/snapshots/test_directive_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
similarity index 100%
rename from tests/snapshots/test_directive_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
rename to tests_v1/snapshots/test_directive_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
diff --git a/tests/snapshots/test_directive_type_raises_error_when_defined_with_invalid_schema_type.yml b/tests_v1/snapshots/test_directive_type_raises_error_when_defined_with_invalid_schema_type.yml
similarity index 100%
rename from tests/snapshots/test_directive_type_raises_error_when_defined_with_invalid_schema_type.yml
rename to tests_v1/snapshots/test_directive_type_raises_error_when_defined_with_invalid_schema_type.yml
diff --git a/tests/snapshots/test_directive_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml b/tests_v1/snapshots/test_directive_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_directive_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
rename to tests_v1/snapshots/test_directive_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
diff --git a/tests/snapshots/test_directive_type_raises_error_when_defined_with_multiple_types_schema.yml b/tests_v1/snapshots/test_directive_type_raises_error_when_defined_with_multiple_types_schema.yml
similarity index 100%
rename from tests/snapshots/test_directive_type_raises_error_when_defined_with_multiple_types_schema.yml
rename to tests_v1/snapshots/test_directive_type_raises_error_when_defined_with_multiple_types_schema.yml
diff --git a/tests/snapshots/test_enum_type_raises_attribute_error_when_defined_without_schema.obtained.yml b/tests_v1/snapshots/test_enum_type_raises_attribute_error_when_defined_without_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_enum_type_raises_attribute_error_when_defined_without_schema.obtained.yml
rename to tests_v1/snapshots/test_enum_type_raises_attribute_error_when_defined_without_schema.obtained.yml
diff --git a/tests/snapshots/test_enum_type_raises_attribute_error_when_defined_without_schema.yml b/tests_v1/snapshots/test_enum_type_raises_attribute_error_when_defined_without_schema.yml
similarity index 100%
rename from tests/snapshots/test_enum_type_raises_attribute_error_when_defined_without_schema.yml
rename to tests_v1/snapshots/test_enum_type_raises_attribute_error_when_defined_without_schema.yml
diff --git a/tests/snapshots/test_enum_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml b/tests_v1/snapshots/test_enum_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_enum_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
rename to tests_v1/snapshots/test_enum_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
diff --git a/tests/snapshots/test_enum_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml b/tests_v1/snapshots/test_enum_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
similarity index 100%
rename from tests/snapshots/test_enum_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
rename to tests_v1/snapshots/test_enum_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
diff --git a/tests/snapshots/test_enum_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml b/tests_v1/snapshots/test_enum_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
similarity index 100%
rename from tests/snapshots/test_enum_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
rename to tests_v1/snapshots/test_enum_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
diff --git a/tests/snapshots/test_enum_type_raises_error_when_defined_with_invalid_schema_str.yml b/tests_v1/snapshots/test_enum_type_raises_error_when_defined_with_invalid_schema_str.yml
similarity index 100%
rename from tests/snapshots/test_enum_type_raises_error_when_defined_with_invalid_schema_str.yml
rename to tests_v1/snapshots/test_enum_type_raises_error_when_defined_with_invalid_schema_str.yml
diff --git a/tests/snapshots/test_enum_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml b/tests_v1/snapshots/test_enum_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
similarity index 100%
rename from tests/snapshots/test_enum_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
rename to tests_v1/snapshots/test_enum_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
diff --git a/tests/snapshots/test_enum_type_raises_error_when_defined_with_invalid_schema_type.yml b/tests_v1/snapshots/test_enum_type_raises_error_when_defined_with_invalid_schema_type.yml
similarity index 100%
rename from tests/snapshots/test_enum_type_raises_error_when_defined_with_invalid_schema_type.yml
rename to tests_v1/snapshots/test_enum_type_raises_error_when_defined_with_invalid_schema_type.yml
diff --git a/tests/snapshots/test_enum_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml b/tests_v1/snapshots/test_enum_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_enum_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
rename to tests_v1/snapshots/test_enum_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
diff --git a/tests/snapshots/test_enum_type_raises_error_when_defined_with_multiple_types_schema.yml b/tests_v1/snapshots/test_enum_type_raises_error_when_defined_with_multiple_types_schema.yml
similarity index 100%
rename from tests/snapshots/test_enum_type_raises_error_when_defined_with_multiple_types_schema.yml
rename to tests_v1/snapshots/test_enum_type_raises_error_when_defined_with_multiple_types_schema.yml
diff --git a/tests/snapshots/test_enum_type_raises_error_when_dict_mapping_has_extra_items_not_in_definition.obtained.yml b/tests_v1/snapshots/test_enum_type_raises_error_when_dict_mapping_has_extra_items_not_in_definition.obtained.yml
similarity index 100%
rename from tests/snapshots/test_enum_type_raises_error_when_dict_mapping_has_extra_items_not_in_definition.obtained.yml
rename to tests_v1/snapshots/test_enum_type_raises_error_when_dict_mapping_has_extra_items_not_in_definition.obtained.yml
diff --git a/tests/snapshots/test_enum_type_raises_error_when_dict_mapping_has_extra_items_not_in_definition.yml b/tests_v1/snapshots/test_enum_type_raises_error_when_dict_mapping_has_extra_items_not_in_definition.yml
similarity index 100%
rename from tests/snapshots/test_enum_type_raises_error_when_dict_mapping_has_extra_items_not_in_definition.yml
rename to tests_v1/snapshots/test_enum_type_raises_error_when_dict_mapping_has_extra_items_not_in_definition.yml
diff --git a/tests/snapshots/test_enum_type_raises_error_when_dict_mapping_misses_items_from_definition.obtained.yml b/tests_v1/snapshots/test_enum_type_raises_error_when_dict_mapping_misses_items_from_definition.obtained.yml
similarity index 100%
rename from tests/snapshots/test_enum_type_raises_error_when_dict_mapping_misses_items_from_definition.obtained.yml
rename to tests_v1/snapshots/test_enum_type_raises_error_when_dict_mapping_misses_items_from_definition.obtained.yml
diff --git a/tests/snapshots/test_enum_type_raises_error_when_dict_mapping_misses_items_from_definition.yml b/tests_v1/snapshots/test_enum_type_raises_error_when_dict_mapping_misses_items_from_definition.yml
similarity index 100%
rename from tests/snapshots/test_enum_type_raises_error_when_dict_mapping_misses_items_from_definition.yml
rename to tests_v1/snapshots/test_enum_type_raises_error_when_dict_mapping_misses_items_from_definition.yml
diff --git a/tests/snapshots/test_enum_type_raises_error_when_enum_mapping_has_extra_items_not_in_definition.obtained.yml b/tests_v1/snapshots/test_enum_type_raises_error_when_enum_mapping_has_extra_items_not_in_definition.obtained.yml
similarity index 100%
rename from tests/snapshots/test_enum_type_raises_error_when_enum_mapping_has_extra_items_not_in_definition.obtained.yml
rename to tests_v1/snapshots/test_enum_type_raises_error_when_enum_mapping_has_extra_items_not_in_definition.obtained.yml
diff --git a/tests/snapshots/test_enum_type_raises_error_when_enum_mapping_has_extra_items_not_in_definition.yml b/tests_v1/snapshots/test_enum_type_raises_error_when_enum_mapping_has_extra_items_not_in_definition.yml
similarity index 100%
rename from tests/snapshots/test_enum_type_raises_error_when_enum_mapping_has_extra_items_not_in_definition.yml
rename to tests_v1/snapshots/test_enum_type_raises_error_when_enum_mapping_has_extra_items_not_in_definition.yml
diff --git a/tests/snapshots/test_enum_type_raises_error_when_enum_mapping_misses_items_from_definition.obtained.yml b/tests_v1/snapshots/test_enum_type_raises_error_when_enum_mapping_misses_items_from_definition.obtained.yml
similarity index 100%
rename from tests/snapshots/test_enum_type_raises_error_when_enum_mapping_misses_items_from_definition.obtained.yml
rename to tests_v1/snapshots/test_enum_type_raises_error_when_enum_mapping_misses_items_from_definition.obtained.yml
diff --git a/tests/snapshots/test_enum_type_raises_error_when_enum_mapping_misses_items_from_definition.yml b/tests_v1/snapshots/test_enum_type_raises_error_when_enum_mapping_misses_items_from_definition.yml
similarity index 100%
rename from tests/snapshots/test_enum_type_raises_error_when_enum_mapping_misses_items_from_definition.yml
rename to tests_v1/snapshots/test_enum_type_raises_error_when_enum_mapping_misses_items_from_definition.yml
diff --git a/tests/snapshots/test_executable_schema_raises_value_error_if_merged_types_define_same_field.obtained.yml b/tests_v1/snapshots/test_executable_schema_raises_value_error_if_merged_types_define_same_field.obtained.yml
similarity index 100%
rename from tests/snapshots/test_executable_schema_raises_value_error_if_merged_types_define_same_field.obtained.yml
rename to tests_v1/snapshots/test_executable_schema_raises_value_error_if_merged_types_define_same_field.obtained.yml
diff --git a/tests/snapshots/test_executable_schema_raises_value_error_if_merged_types_define_same_field.yml b/tests_v1/snapshots/test_executable_schema_raises_value_error_if_merged_types_define_same_field.yml
similarity index 100%
rename from tests/snapshots/test_executable_schema_raises_value_error_if_merged_types_define_same_field.yml
rename to tests_v1/snapshots/test_executable_schema_raises_value_error_if_merged_types_define_same_field.yml
diff --git a/tests/snapshots/test_input_type_raises_attribute_error_when_defined_without_schema.obtained.yml b/tests_v1/snapshots/test_input_type_raises_attribute_error_when_defined_without_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_input_type_raises_attribute_error_when_defined_without_schema.obtained.yml
rename to tests_v1/snapshots/test_input_type_raises_attribute_error_when_defined_without_schema.obtained.yml
diff --git a/tests/snapshots/test_input_type_raises_attribute_error_when_defined_without_schema.yml b/tests_v1/snapshots/test_input_type_raises_attribute_error_when_defined_without_schema.yml
similarity index 100%
rename from tests/snapshots/test_input_type_raises_attribute_error_when_defined_without_schema.yml
rename to tests_v1/snapshots/test_input_type_raises_attribute_error_when_defined_without_schema.yml
diff --git a/tests/snapshots/test_input_type_raises_error_when_defined_with_args_map_for_nonexisting_field.obtained.yml b/tests_v1/snapshots/test_input_type_raises_error_when_defined_with_args_map_for_nonexisting_field.obtained.yml
similarity index 100%
rename from tests/snapshots/test_input_type_raises_error_when_defined_with_args_map_for_nonexisting_field.obtained.yml
rename to tests_v1/snapshots/test_input_type_raises_error_when_defined_with_args_map_for_nonexisting_field.obtained.yml
diff --git a/tests/snapshots/test_input_type_raises_error_when_defined_with_args_map_for_nonexisting_field.yml b/tests_v1/snapshots/test_input_type_raises_error_when_defined_with_args_map_for_nonexisting_field.yml
similarity index 100%
rename from tests/snapshots/test_input_type_raises_error_when_defined_with_args_map_for_nonexisting_field.yml
rename to tests_v1/snapshots/test_input_type_raises_error_when_defined_with_args_map_for_nonexisting_field.yml
diff --git a/tests/snapshots/test_input_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml b/tests_v1/snapshots/test_input_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_input_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
rename to tests_v1/snapshots/test_input_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
diff --git a/tests/snapshots/test_input_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml b/tests_v1/snapshots/test_input_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
similarity index 100%
rename from tests/snapshots/test_input_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
rename to tests_v1/snapshots/test_input_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
diff --git a/tests/snapshots/test_input_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml b/tests_v1/snapshots/test_input_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
similarity index 100%
rename from tests/snapshots/test_input_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
rename to tests_v1/snapshots/test_input_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
diff --git a/tests/snapshots/test_input_type_raises_error_when_defined_with_invalid_schema_str.yml b/tests_v1/snapshots/test_input_type_raises_error_when_defined_with_invalid_schema_str.yml
similarity index 100%
rename from tests/snapshots/test_input_type_raises_error_when_defined_with_invalid_schema_str.yml
rename to tests_v1/snapshots/test_input_type_raises_error_when_defined_with_invalid_schema_str.yml
diff --git a/tests/snapshots/test_input_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml b/tests_v1/snapshots/test_input_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
similarity index 100%
rename from tests/snapshots/test_input_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
rename to tests_v1/snapshots/test_input_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
diff --git a/tests/snapshots/test_input_type_raises_error_when_defined_with_invalid_schema_type.yml b/tests_v1/snapshots/test_input_type_raises_error_when_defined_with_invalid_schema_type.yml
similarity index 100%
rename from tests/snapshots/test_input_type_raises_error_when_defined_with_invalid_schema_type.yml
rename to tests_v1/snapshots/test_input_type_raises_error_when_defined_with_invalid_schema_type.yml
diff --git a/tests/snapshots/test_input_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml b/tests_v1/snapshots/test_input_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_input_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
rename to tests_v1/snapshots/test_input_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
diff --git a/tests/snapshots/test_input_type_raises_error_when_defined_with_multiple_types_schema.yml b/tests_v1/snapshots/test_input_type_raises_error_when_defined_with_multiple_types_schema.yml
similarity index 100%
rename from tests/snapshots/test_input_type_raises_error_when_defined_with_multiple_types_schema.yml
rename to tests_v1/snapshots/test_input_type_raises_error_when_defined_with_multiple_types_schema.yml
diff --git a/tests/snapshots/test_input_type_raises_error_when_defined_without_extended_dependency.obtained.yml b/tests_v1/snapshots/test_input_type_raises_error_when_defined_without_extended_dependency.obtained.yml
similarity index 100%
rename from tests/snapshots/test_input_type_raises_error_when_defined_without_extended_dependency.obtained.yml
rename to tests_v1/snapshots/test_input_type_raises_error_when_defined_without_extended_dependency.obtained.yml
diff --git a/tests/snapshots/test_input_type_raises_error_when_defined_without_extended_dependency.yml b/tests_v1/snapshots/test_input_type_raises_error_when_defined_without_extended_dependency.yml
similarity index 100%
rename from tests/snapshots/test_input_type_raises_error_when_defined_without_extended_dependency.yml
rename to tests_v1/snapshots/test_input_type_raises_error_when_defined_without_extended_dependency.yml
diff --git a/tests/snapshots/test_input_type_raises_error_when_defined_without_field_type_dependency.obtained.yml b/tests_v1/snapshots/test_input_type_raises_error_when_defined_without_field_type_dependency.obtained.yml
similarity index 100%
rename from tests/snapshots/test_input_type_raises_error_when_defined_without_field_type_dependency.obtained.yml
rename to tests_v1/snapshots/test_input_type_raises_error_when_defined_without_field_type_dependency.obtained.yml
diff --git a/tests/snapshots/test_input_type_raises_error_when_defined_without_field_type_dependency.yml b/tests_v1/snapshots/test_input_type_raises_error_when_defined_without_field_type_dependency.yml
similarity index 100%
rename from tests/snapshots/test_input_type_raises_error_when_defined_without_field_type_dependency.yml
rename to tests_v1/snapshots/test_input_type_raises_error_when_defined_without_field_type_dependency.yml
diff --git a/tests/snapshots/test_input_type_raises_error_when_defined_without_fields.obtained.yml b/tests_v1/snapshots/test_input_type_raises_error_when_defined_without_fields.obtained.yml
similarity index 100%
rename from tests/snapshots/test_input_type_raises_error_when_defined_without_fields.obtained.yml
rename to tests_v1/snapshots/test_input_type_raises_error_when_defined_without_fields.obtained.yml
diff --git a/tests/snapshots/test_input_type_raises_error_when_defined_without_fields.yml b/tests_v1/snapshots/test_input_type_raises_error_when_defined_without_fields.yml
similarity index 100%
rename from tests/snapshots/test_input_type_raises_error_when_defined_without_fields.yml
rename to tests_v1/snapshots/test_input_type_raises_error_when_defined_without_fields.yml
diff --git a/tests/snapshots/test_input_type_raises_error_when_extended_dependency_is_wrong_type.obtained.yml b/tests_v1/snapshots/test_input_type_raises_error_when_extended_dependency_is_wrong_type.obtained.yml
similarity index 100%
rename from tests/snapshots/test_input_type_raises_error_when_extended_dependency_is_wrong_type.obtained.yml
rename to tests_v1/snapshots/test_input_type_raises_error_when_extended_dependency_is_wrong_type.obtained.yml
diff --git a/tests/snapshots/test_input_type_raises_error_when_extended_dependency_is_wrong_type.yml b/tests_v1/snapshots/test_input_type_raises_error_when_extended_dependency_is_wrong_type.yml
similarity index 100%
rename from tests/snapshots/test_input_type_raises_error_when_extended_dependency_is_wrong_type.yml
rename to tests_v1/snapshots/test_input_type_raises_error_when_extended_dependency_is_wrong_type.yml
diff --git a/tests/snapshots/test_interface_type_raises_attribute_error_when_defined_without_schema.obtained.yml b/tests_v1/snapshots/test_interface_type_raises_attribute_error_when_defined_without_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_attribute_error_when_defined_without_schema.obtained.yml
rename to tests_v1/snapshots/test_interface_type_raises_attribute_error_when_defined_without_schema.obtained.yml
diff --git a/tests/snapshots/test_interface_type_raises_attribute_error_when_defined_without_schema.yml b/tests_v1/snapshots/test_interface_type_raises_attribute_error_when_defined_without_schema.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_attribute_error_when_defined_without_schema.yml
rename to tests_v1/snapshots/test_interface_type_raises_attribute_error_when_defined_without_schema.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_defined_with_alias_for_nonexisting_field.obtained.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_alias_for_nonexisting_field.obtained.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_defined_with_alias_for_nonexisting_field.obtained.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_alias_for_nonexisting_field.obtained.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_defined_with_alias_for_nonexisting_field.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_alias_for_nonexisting_field.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_defined_with_alias_for_nonexisting_field.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_alias_for_nonexisting_field.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_defined_with_invalid_schema_str.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_invalid_schema_str.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_defined_with_invalid_schema_str.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_invalid_schema_str.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_defined_with_invalid_schema_type.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_invalid_schema_type.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_defined_with_invalid_schema_type.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_invalid_schema_type.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_defined_with_multiple_types_schema.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_multiple_types_schema.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_defined_with_multiple_types_schema.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_multiple_types_schema.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_defined_with_resolver_for_nonexisting_field.obtained.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_resolver_for_nonexisting_field.obtained.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_defined_with_resolver_for_nonexisting_field.obtained.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_resolver_for_nonexisting_field.obtained.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_defined_with_resolver_for_nonexisting_field.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_resolver_for_nonexisting_field.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_defined_with_resolver_for_nonexisting_field.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_defined_with_resolver_for_nonexisting_field.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_defined_without_argument_type_dependency.obtained.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_defined_without_argument_type_dependency.obtained.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_defined_without_argument_type_dependency.obtained.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_defined_without_argument_type_dependency.obtained.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_defined_without_argument_type_dependency.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_defined_without_argument_type_dependency.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_defined_without_argument_type_dependency.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_defined_without_argument_type_dependency.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_defined_without_extended_dependency.obtained.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_defined_without_extended_dependency.obtained.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_defined_without_extended_dependency.obtained.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_defined_without_extended_dependency.obtained.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_defined_without_extended_dependency.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_defined_without_extended_dependency.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_defined_without_extended_dependency.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_defined_without_extended_dependency.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_defined_without_fields.obtained.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_defined_without_fields.obtained.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_defined_without_fields.obtained.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_defined_without_fields.obtained.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_defined_without_fields.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_defined_without_fields.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_defined_without_fields.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_defined_without_fields.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_defined_without_return_type_dependency.obtained.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_defined_without_return_type_dependency.obtained.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_defined_without_return_type_dependency.obtained.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_defined_without_return_type_dependency.obtained.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_defined_without_return_type_dependency.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_defined_without_return_type_dependency.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_defined_without_return_type_dependency.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_defined_without_return_type_dependency.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_extended_dependency_is_wrong_type.obtained.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_extended_dependency_is_wrong_type.obtained.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_extended_dependency_is_wrong_type.obtained.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_extended_dependency_is_wrong_type.obtained.yml
diff --git a/tests/snapshots/test_interface_type_raises_error_when_extended_dependency_is_wrong_type.yml b/tests_v1/snapshots/test_interface_type_raises_error_when_extended_dependency_is_wrong_type.yml
similarity index 100%
rename from tests/snapshots/test_interface_type_raises_error_when_extended_dependency_is_wrong_type.yml
rename to tests_v1/snapshots/test_interface_type_raises_error_when_extended_dependency_is_wrong_type.yml
diff --git a/tests/snapshots/test_mutation_type_raises_attribute_error_when_defined_without_schema.obtained.yml b/tests_v1/snapshots/test_mutation_type_raises_attribute_error_when_defined_without_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_attribute_error_when_defined_without_schema.obtained.yml
rename to tests_v1/snapshots/test_mutation_type_raises_attribute_error_when_defined_without_schema.obtained.yml
diff --git a/tests/snapshots/test_mutation_type_raises_attribute_error_when_defined_without_schema.yml b/tests_v1/snapshots/test_mutation_type_raises_attribute_error_when_defined_without_schema.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_attribute_error_when_defined_without_schema.yml
rename to tests_v1/snapshots/test_mutation_type_raises_attribute_error_when_defined_without_schema.yml
diff --git a/tests/snapshots/test_mutation_type_raises_error_when_defined_for_different_type_name.obtained.yml b/tests_v1/snapshots/test_mutation_type_raises_error_when_defined_for_different_type_name.obtained.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_error_when_defined_for_different_type_name.obtained.yml
rename to tests_v1/snapshots/test_mutation_type_raises_error_when_defined_for_different_type_name.obtained.yml
diff --git a/tests/snapshots/test_mutation_type_raises_error_when_defined_for_different_type_name.yml b/tests_v1/snapshots/test_mutation_type_raises_error_when_defined_for_different_type_name.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_error_when_defined_for_different_type_name.yml
rename to tests_v1/snapshots/test_mutation_type_raises_error_when_defined_for_different_type_name.yml
diff --git a/tests/snapshots/test_mutation_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml b/tests_v1/snapshots/test_mutation_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
rename to tests_v1/snapshots/test_mutation_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
diff --git a/tests/snapshots/test_mutation_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml b/tests_v1/snapshots/test_mutation_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
rename to tests_v1/snapshots/test_mutation_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
diff --git a/tests/snapshots/test_mutation_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml b/tests_v1/snapshots/test_mutation_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
rename to tests_v1/snapshots/test_mutation_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
diff --git a/tests/snapshots/test_mutation_type_raises_error_when_defined_with_invalid_schema_type.yml b/tests_v1/snapshots/test_mutation_type_raises_error_when_defined_with_invalid_schema_type.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_error_when_defined_with_invalid_schema_type.yml
rename to tests_v1/snapshots/test_mutation_type_raises_error_when_defined_with_invalid_schema_type.yml
diff --git a/tests/snapshots/test_mutation_type_raises_error_when_defined_with_multiple_fields.obtained.yml b/tests_v1/snapshots/test_mutation_type_raises_error_when_defined_with_multiple_fields.obtained.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_error_when_defined_with_multiple_fields.obtained.yml
rename to tests_v1/snapshots/test_mutation_type_raises_error_when_defined_with_multiple_fields.obtained.yml
diff --git a/tests/snapshots/test_mutation_type_raises_error_when_defined_with_multiple_fields.yml b/tests_v1/snapshots/test_mutation_type_raises_error_when_defined_with_multiple_fields.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_error_when_defined_with_multiple_fields.yml
rename to tests_v1/snapshots/test_mutation_type_raises_error_when_defined_with_multiple_fields.yml
diff --git a/tests/snapshots/test_mutation_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml b/tests_v1/snapshots/test_mutation_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
rename to tests_v1/snapshots/test_mutation_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
diff --git a/tests/snapshots/test_mutation_type_raises_error_when_defined_with_multiple_types_schema.yml b/tests_v1/snapshots/test_mutation_type_raises_error_when_defined_with_multiple_types_schema.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_error_when_defined_with_multiple_types_schema.yml
rename to tests_v1/snapshots/test_mutation_type_raises_error_when_defined_with_multiple_types_schema.yml
diff --git a/tests/snapshots/test_mutation_type_raises_error_when_defined_with_nonexistant_args.obtained.yml b/tests_v1/snapshots/test_mutation_type_raises_error_when_defined_with_nonexistant_args.obtained.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_error_when_defined_with_nonexistant_args.obtained.yml
rename to tests_v1/snapshots/test_mutation_type_raises_error_when_defined_with_nonexistant_args.obtained.yml
diff --git a/tests/snapshots/test_mutation_type_raises_error_when_defined_with_nonexistant_args.yml b/tests_v1/snapshots/test_mutation_type_raises_error_when_defined_with_nonexistant_args.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_error_when_defined_with_nonexistant_args.yml
rename to tests_v1/snapshots/test_mutation_type_raises_error_when_defined_with_nonexistant_args.yml
diff --git a/tests/snapshots/test_mutation_type_raises_error_when_defined_without_callable_resolve_mutation_attr.obtained.yml b/tests_v1/snapshots/test_mutation_type_raises_error_when_defined_without_callable_resolve_mutation_attr.obtained.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_error_when_defined_without_callable_resolve_mutation_attr.obtained.yml
rename to tests_v1/snapshots/test_mutation_type_raises_error_when_defined_without_callable_resolve_mutation_attr.obtained.yml
diff --git a/tests/snapshots/test_mutation_type_raises_error_when_defined_without_callable_resolve_mutation_attr.yml b/tests_v1/snapshots/test_mutation_type_raises_error_when_defined_without_callable_resolve_mutation_attr.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_error_when_defined_without_callable_resolve_mutation_attr.yml
rename to tests_v1/snapshots/test_mutation_type_raises_error_when_defined_without_callable_resolve_mutation_attr.yml
diff --git a/tests/snapshots/test_mutation_type_raises_error_when_defined_without_fields.obtained.yml b/tests_v1/snapshots/test_mutation_type_raises_error_when_defined_without_fields.obtained.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_error_when_defined_without_fields.obtained.yml
rename to tests_v1/snapshots/test_mutation_type_raises_error_when_defined_without_fields.obtained.yml
diff --git a/tests/snapshots/test_mutation_type_raises_error_when_defined_without_fields.yml b/tests_v1/snapshots/test_mutation_type_raises_error_when_defined_without_fields.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_error_when_defined_without_fields.yml
rename to tests_v1/snapshots/test_mutation_type_raises_error_when_defined_without_fields.yml
diff --git a/tests/snapshots/test_mutation_type_raises_error_when_defined_without_resolve_mutation_attr.obtained.yml b/tests_v1/snapshots/test_mutation_type_raises_error_when_defined_without_resolve_mutation_attr.obtained.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_error_when_defined_without_resolve_mutation_attr.obtained.yml
rename to tests_v1/snapshots/test_mutation_type_raises_error_when_defined_without_resolve_mutation_attr.obtained.yml
diff --git a/tests/snapshots/test_mutation_type_raises_error_when_defined_without_resolve_mutation_attr.yml b/tests_v1/snapshots/test_mutation_type_raises_error_when_defined_without_resolve_mutation_attr.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_error_when_defined_without_resolve_mutation_attr.yml
rename to tests_v1/snapshots/test_mutation_type_raises_error_when_defined_without_resolve_mutation_attr.yml
diff --git a/tests/snapshots/test_mutation_type_raises_error_when_defined_without_return_type_dependency.obtained.yml b/tests_v1/snapshots/test_mutation_type_raises_error_when_defined_without_return_type_dependency.obtained.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_error_when_defined_without_return_type_dependency.obtained.yml
rename to tests_v1/snapshots/test_mutation_type_raises_error_when_defined_without_return_type_dependency.obtained.yml
diff --git a/tests/snapshots/test_mutation_type_raises_error_when_defined_without_return_type_dependency.yml b/tests_v1/snapshots/test_mutation_type_raises_error_when_defined_without_return_type_dependency.yml
similarity index 100%
rename from tests/snapshots/test_mutation_type_raises_error_when_defined_without_return_type_dependency.yml
rename to tests_v1/snapshots/test_mutation_type_raises_error_when_defined_without_return_type_dependency.yml
diff --git a/tests/snapshots/test_object_type_raises_attribute_error_when_defined_without_schema.obtained.yml b/tests_v1/snapshots/test_object_type_raises_attribute_error_when_defined_without_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_attribute_error_when_defined_without_schema.obtained.yml
rename to tests_v1/snapshots/test_object_type_raises_attribute_error_when_defined_without_schema.obtained.yml
diff --git a/tests/snapshots/test_object_type_raises_attribute_error_when_defined_without_schema.yml b/tests_v1/snapshots/test_object_type_raises_attribute_error_when_defined_without_schema.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_attribute_error_when_defined_without_schema.yml
rename to tests_v1/snapshots/test_object_type_raises_attribute_error_when_defined_without_schema.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_with_alias_for_nonexisting_field.obtained.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_with_alias_for_nonexisting_field.obtained.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_with_alias_for_nonexisting_field.obtained.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_with_alias_for_nonexisting_field.obtained.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_with_alias_for_nonexisting_field.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_with_alias_for_nonexisting_field.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_with_alias_for_nonexisting_field.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_with_alias_for_nonexisting_field.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_with_field_args_for_nonexisting_arg.obtained.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_with_field_args_for_nonexisting_arg.obtained.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_with_field_args_for_nonexisting_arg.obtained.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_with_field_args_for_nonexisting_arg.obtained.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_with_field_args_for_nonexisting_arg.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_with_field_args_for_nonexisting_arg.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_with_field_args_for_nonexisting_arg.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_with_field_args_for_nonexisting_arg.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_with_field_args_for_nonexisting_field.obtained.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_with_field_args_for_nonexisting_field.obtained.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_with_field_args_for_nonexisting_field.obtained.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_with_field_args_for_nonexisting_field.obtained.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_with_field_args_for_nonexisting_field.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_with_field_args_for_nonexisting_field.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_with_field_args_for_nonexisting_field.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_with_field_args_for_nonexisting_field.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_with_invalid_schema_str.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_with_invalid_schema_str.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_with_invalid_schema_str.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_with_invalid_schema_str.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_with_invalid_schema_type.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_with_invalid_schema_type.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_with_invalid_schema_type.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_with_invalid_schema_type.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_with_multiple_types_schema.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_with_multiple_types_schema.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_with_multiple_types_schema.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_with_multiple_types_schema.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_with_resolver_for_nonexisting_field.obtained.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_with_resolver_for_nonexisting_field.obtained.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_with_resolver_for_nonexisting_field.obtained.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_with_resolver_for_nonexisting_field.obtained.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_with_resolver_for_nonexisting_field.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_with_resolver_for_nonexisting_field.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_with_resolver_for_nonexisting_field.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_with_resolver_for_nonexisting_field.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_without_argument_type_dependency.obtained.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_without_argument_type_dependency.obtained.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_without_argument_type_dependency.obtained.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_without_argument_type_dependency.obtained.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_without_argument_type_dependency.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_without_argument_type_dependency.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_without_argument_type_dependency.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_without_argument_type_dependency.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_without_extended_dependency.obtained.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_without_extended_dependency.obtained.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_without_extended_dependency.obtained.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_without_extended_dependency.obtained.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_without_extended_dependency.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_without_extended_dependency.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_without_extended_dependency.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_without_extended_dependency.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_without_fields.obtained.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_without_fields.obtained.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_without_fields.obtained.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_without_fields.obtained.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_without_fields.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_without_fields.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_without_fields.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_without_fields.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_without_return_type_dependency.obtained.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_without_return_type_dependency.obtained.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_without_return_type_dependency.obtained.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_without_return_type_dependency.obtained.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_defined_without_return_type_dependency.yml b/tests_v1/snapshots/test_object_type_raises_error_when_defined_without_return_type_dependency.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_defined_without_return_type_dependency.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_defined_without_return_type_dependency.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_extended_dependency_is_wrong_type.obtained.yml b/tests_v1/snapshots/test_object_type_raises_error_when_extended_dependency_is_wrong_type.obtained.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_extended_dependency_is_wrong_type.obtained.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_extended_dependency_is_wrong_type.obtained.yml
diff --git a/tests/snapshots/test_object_type_raises_error_when_extended_dependency_is_wrong_type.yml b/tests_v1/snapshots/test_object_type_raises_error_when_extended_dependency_is_wrong_type.yml
similarity index 100%
rename from tests/snapshots/test_object_type_raises_error_when_extended_dependency_is_wrong_type.yml
rename to tests_v1/snapshots/test_object_type_raises_error_when_extended_dependency_is_wrong_type.yml
diff --git a/tests/snapshots/test_scalar_type_raises_attribute_error_when_defined_without_schema.obtained.yml b/tests_v1/snapshots/test_scalar_type_raises_attribute_error_when_defined_without_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_scalar_type_raises_attribute_error_when_defined_without_schema.obtained.yml
rename to tests_v1/snapshots/test_scalar_type_raises_attribute_error_when_defined_without_schema.obtained.yml
diff --git a/tests/snapshots/test_scalar_type_raises_attribute_error_when_defined_without_schema.yml b/tests_v1/snapshots/test_scalar_type_raises_attribute_error_when_defined_without_schema.yml
similarity index 100%
rename from tests/snapshots/test_scalar_type_raises_attribute_error_when_defined_without_schema.yml
rename to tests_v1/snapshots/test_scalar_type_raises_attribute_error_when_defined_without_schema.yml
diff --git a/tests/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml b/tests_v1/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
rename to tests_v1/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
diff --git a/tests/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml b/tests_v1/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
similarity index 100%
rename from tests/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
rename to tests_v1/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
diff --git a/tests/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml b/tests_v1/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
similarity index 100%
rename from tests/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
rename to tests_v1/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
diff --git a/tests/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_schema_str.yml b/tests_v1/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_schema_str.yml
similarity index 100%
rename from tests/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_schema_str.yml
rename to tests_v1/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_schema_str.yml
diff --git a/tests/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml b/tests_v1/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
similarity index 100%
rename from tests/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
rename to tests_v1/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
diff --git a/tests/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_schema_type.yml b/tests_v1/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_schema_type.yml
similarity index 100%
rename from tests/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_schema_type.yml
rename to tests_v1/snapshots/test_scalar_type_raises_error_when_defined_with_invalid_schema_type.yml
diff --git a/tests/snapshots/test_scalar_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml b/tests_v1/snapshots/test_scalar_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_scalar_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
rename to tests_v1/snapshots/test_scalar_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
diff --git a/tests/snapshots/test_scalar_type_raises_error_when_defined_with_multiple_types_schema.yml b/tests_v1/snapshots/test_scalar_type_raises_error_when_defined_with_multiple_types_schema.yml
similarity index 100%
rename from tests/snapshots/test_scalar_type_raises_error_when_defined_with_multiple_types_schema.yml
rename to tests_v1/snapshots/test_scalar_type_raises_error_when_defined_with_multiple_types_schema.yml
diff --git a/tests/snapshots/test_subscription_type_raises_attribute_error_when_defined_without_schema.obtained.yml b/tests_v1/snapshots/test_subscription_type_raises_attribute_error_when_defined_without_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_attribute_error_when_defined_without_schema.obtained.yml
rename to tests_v1/snapshots/test_subscription_type_raises_attribute_error_when_defined_without_schema.obtained.yml
diff --git a/tests/snapshots/test_subscription_type_raises_attribute_error_when_defined_without_schema.yml b/tests_v1/snapshots/test_subscription_type_raises_attribute_error_when_defined_without_schema.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_attribute_error_when_defined_without_schema.yml
rename to tests_v1/snapshots/test_subscription_type_raises_attribute_error_when_defined_without_schema.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_with_alias_for_nonexisting_field.obtained.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_alias_for_nonexisting_field.obtained.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_with_alias_for_nonexisting_field.obtained.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_alias_for_nonexisting_field.obtained.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_with_alias_for_nonexisting_field.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_alias_for_nonexisting_field.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_with_alias_for_nonexisting_field.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_alias_for_nonexisting_field.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_graphql_type_name.obtained.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_graphql_type_name.obtained.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_graphql_type_name.obtained.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_graphql_type_name.obtained.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_graphql_type_name.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_graphql_type_name.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_graphql_type_name.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_graphql_type_name.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_schema_str.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_schema_str.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_schema_str.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_schema_str.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_schema_type.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_schema_type.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_schema_type.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_invalid_schema_type.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_with_resolver_for_nonexisting_field.obtained.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_resolver_for_nonexisting_field.obtained.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_with_resolver_for_nonexisting_field.obtained.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_resolver_for_nonexisting_field.obtained.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_with_resolver_for_nonexisting_field.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_resolver_for_nonexisting_field.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_with_resolver_for_nonexisting_field.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_resolver_for_nonexisting_field.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_with_sub_for_nonexisting_field.obtained.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_sub_for_nonexisting_field.obtained.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_with_sub_for_nonexisting_field.obtained.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_sub_for_nonexisting_field.obtained.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_with_sub_for_nonexisting_field.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_sub_for_nonexisting_field.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_with_sub_for_nonexisting_field.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_with_sub_for_nonexisting_field.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_without_argument_type_dependency.obtained.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_without_argument_type_dependency.obtained.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_without_argument_type_dependency.obtained.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_without_argument_type_dependency.obtained.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_without_argument_type_dependency.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_without_argument_type_dependency.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_without_argument_type_dependency.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_without_argument_type_dependency.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_without_extended_dependency.obtained.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_without_extended_dependency.obtained.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_without_extended_dependency.obtained.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_without_extended_dependency.obtained.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_without_extended_dependency.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_without_extended_dependency.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_without_extended_dependency.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_without_extended_dependency.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_without_fields.obtained.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_without_fields.obtained.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_without_fields.obtained.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_without_fields.obtained.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_without_fields.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_without_fields.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_without_fields.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_without_fields.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_without_return_type_dependency.obtained.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_without_return_type_dependency.obtained.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_without_return_type_dependency.obtained.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_without_return_type_dependency.obtained.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_defined_without_return_type_dependency.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_defined_without_return_type_dependency.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_defined_without_return_type_dependency.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_defined_without_return_type_dependency.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_extended_dependency_is_wrong_type.obtained.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_extended_dependency_is_wrong_type.obtained.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_extended_dependency_is_wrong_type.obtained.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_extended_dependency_is_wrong_type.obtained.yml
diff --git a/tests/snapshots/test_subscription_type_raises_error_when_extended_dependency_is_wrong_type.yml b/tests_v1/snapshots/test_subscription_type_raises_error_when_extended_dependency_is_wrong_type.yml
similarity index 100%
rename from tests/snapshots/test_subscription_type_raises_error_when_extended_dependency_is_wrong_type.yml
rename to tests_v1/snapshots/test_subscription_type_raises_error_when_extended_dependency_is_wrong_type.yml
diff --git a/tests/snapshots/test_union_type_raises_attribute_error_when_defined_without_schema.obtained.yml b/tests_v1/snapshots/test_union_type_raises_attribute_error_when_defined_without_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_union_type_raises_attribute_error_when_defined_without_schema.obtained.yml
rename to tests_v1/snapshots/test_union_type_raises_attribute_error_when_defined_without_schema.obtained.yml
diff --git a/tests/snapshots/test_union_type_raises_attribute_error_when_defined_without_schema.yml b/tests_v1/snapshots/test_union_type_raises_attribute_error_when_defined_without_schema.yml
similarity index 100%
rename from tests/snapshots/test_union_type_raises_attribute_error_when_defined_without_schema.yml
rename to tests_v1/snapshots/test_union_type_raises_attribute_error_when_defined_without_schema.yml
diff --git a/tests/snapshots/test_union_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml b/tests_v1/snapshots/test_union_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_union_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
rename to tests_v1/snapshots/test_union_type_raises_error_when_defined_with_invalid_graphql_type_schema.obtained.yml
diff --git a/tests/snapshots/test_union_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml b/tests_v1/snapshots/test_union_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
similarity index 100%
rename from tests/snapshots/test_union_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
rename to tests_v1/snapshots/test_union_type_raises_error_when_defined_with_invalid_graphql_type_schema.yml
diff --git a/tests/snapshots/test_union_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml b/tests_v1/snapshots/test_union_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
similarity index 100%
rename from tests/snapshots/test_union_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
rename to tests_v1/snapshots/test_union_type_raises_error_when_defined_with_invalid_schema_str.obtained.yml
diff --git a/tests/snapshots/test_union_type_raises_error_when_defined_with_invalid_schema_str.yml b/tests_v1/snapshots/test_union_type_raises_error_when_defined_with_invalid_schema_str.yml
similarity index 100%
rename from tests/snapshots/test_union_type_raises_error_when_defined_with_invalid_schema_str.yml
rename to tests_v1/snapshots/test_union_type_raises_error_when_defined_with_invalid_schema_str.yml
diff --git a/tests/snapshots/test_union_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml b/tests_v1/snapshots/test_union_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
similarity index 100%
rename from tests/snapshots/test_union_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
rename to tests_v1/snapshots/test_union_type_raises_error_when_defined_with_invalid_schema_type.obtained.yml
diff --git a/tests/snapshots/test_union_type_raises_error_when_defined_with_invalid_schema_type.yml b/tests_v1/snapshots/test_union_type_raises_error_when_defined_with_invalid_schema_type.yml
similarity index 100%
rename from tests/snapshots/test_union_type_raises_error_when_defined_with_invalid_schema_type.yml
rename to tests_v1/snapshots/test_union_type_raises_error_when_defined_with_invalid_schema_type.yml
diff --git a/tests/snapshots/test_union_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml b/tests_v1/snapshots/test_union_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
similarity index 100%
rename from tests/snapshots/test_union_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
rename to tests_v1/snapshots/test_union_type_raises_error_when_defined_with_multiple_types_schema.obtained.yml
diff --git a/tests/snapshots/test_union_type_raises_error_when_defined_with_multiple_types_schema.yml b/tests_v1/snapshots/test_union_type_raises_error_when_defined_with_multiple_types_schema.yml
similarity index 100%
rename from tests/snapshots/test_union_type_raises_error_when_defined_with_multiple_types_schema.yml
rename to tests_v1/snapshots/test_union_type_raises_error_when_defined_with_multiple_types_schema.yml
diff --git a/tests/snapshots/test_union_type_raises_error_when_defined_without_extended_dependency.obtained.yml b/tests_v1/snapshots/test_union_type_raises_error_when_defined_without_extended_dependency.obtained.yml
similarity index 100%
rename from tests/snapshots/test_union_type_raises_error_when_defined_without_extended_dependency.obtained.yml
rename to tests_v1/snapshots/test_union_type_raises_error_when_defined_without_extended_dependency.obtained.yml
diff --git a/tests/snapshots/test_union_type_raises_error_when_defined_without_extended_dependency.yml b/tests_v1/snapshots/test_union_type_raises_error_when_defined_without_extended_dependency.yml
similarity index 100%
rename from tests/snapshots/test_union_type_raises_error_when_defined_without_extended_dependency.yml
rename to tests_v1/snapshots/test_union_type_raises_error_when_defined_without_extended_dependency.yml
diff --git a/tests/snapshots/test_union_type_raises_error_when_defined_without_member_type_dependency.obtained.yml b/tests_v1/snapshots/test_union_type_raises_error_when_defined_without_member_type_dependency.obtained.yml
similarity index 100%
rename from tests/snapshots/test_union_type_raises_error_when_defined_without_member_type_dependency.obtained.yml
rename to tests_v1/snapshots/test_union_type_raises_error_when_defined_without_member_type_dependency.obtained.yml
diff --git a/tests/snapshots/test_union_type_raises_error_when_defined_without_member_type_dependency.yml b/tests_v1/snapshots/test_union_type_raises_error_when_defined_without_member_type_dependency.yml
similarity index 100%
rename from tests/snapshots/test_union_type_raises_error_when_defined_without_member_type_dependency.yml
rename to tests_v1/snapshots/test_union_type_raises_error_when_defined_without_member_type_dependency.yml
diff --git a/tests/snapshots/test_union_type_raises_error_when_extended_dependency_is_wrong_type.obtained.yml b/tests_v1/snapshots/test_union_type_raises_error_when_extended_dependency_is_wrong_type.obtained.yml
similarity index 100%
rename from tests/snapshots/test_union_type_raises_error_when_extended_dependency_is_wrong_type.obtained.yml
rename to tests_v1/snapshots/test_union_type_raises_error_when_extended_dependency_is_wrong_type.obtained.yml
diff --git a/tests/snapshots/test_union_type_raises_error_when_extended_dependency_is_wrong_type.yml b/tests_v1/snapshots/test_union_type_raises_error_when_extended_dependency_is_wrong_type.yml
similarity index 100%
rename from tests/snapshots/test_union_type_raises_error_when_extended_dependency_is_wrong_type.yml
rename to tests_v1/snapshots/test_union_type_raises_error_when_extended_dependency_is_wrong_type.yml
diff --git a/tests/test_collection_type.py b/tests_v1/test_collection_type.py
similarity index 100%
rename from tests/test_collection_type.py
rename to tests_v1/test_collection_type.py
diff --git a/tests/test_convert_case.py b/tests_v1/test_convert_case.py
similarity index 100%
rename from tests/test_convert_case.py
rename to tests_v1/test_convert_case.py
diff --git a/tests/test_definition_parser.py b/tests_v1/test_definition_parser.py
similarity index 100%
rename from tests/test_definition_parser.py
rename to tests_v1/test_definition_parser.py
diff --git a/tests/test_directive_type.py b/tests_v1/test_directive_type.py
similarity index 100%
rename from tests/test_directive_type.py
rename to tests_v1/test_directive_type.py
diff --git a/tests_v1/test_enum_type.py b/tests_v1/test_enum_type.py
new file mode 100644
index 0000000..7ea4585
--- /dev/null
+++ b/tests_v1/test_enum_type.py
@@ -0,0 +1,304 @@
+from enum import Enum
+
+import pytest
+from ariadne import SchemaDirectiveVisitor
+from graphql import GraphQLError, graphql_sync
+
+from ariadne_graphql_modules import (
+ DirectiveType,
+ EnumType,
+ ObjectType,
+ make_executable_schema,
+)
+
+
+def test_enum_type_raises_attribute_error_when_defined_without_schema(data_regression):
+ with pytest.raises(AttributeError) as err:
+ # pylint: disable=unused-variable
+ class UserRoleEnum(EnumType):
+ pass
+
+ data_regression.check(str(err.value))
+
+
+def test_enum_type_raises_error_when_defined_with_invalid_schema_type(data_regression):
+ with pytest.raises(TypeError) as err:
+ # pylint: disable=unused-variable
+ class UserRoleEnum(EnumType):
+ __schema__ = True
+
+ data_regression.check(str(err.value))
+
+
+def test_enum_type_raises_error_when_defined_with_invalid_schema_str(data_regression):
+ with pytest.raises(GraphQLError) as err:
+ # pylint: disable=unused-variable
+ class UserRoleEnum(EnumType):
+ __schema__ = "enom UserRole"
+
+ data_regression.check(str(err.value))
+
+
+def test_enum_type_raises_error_when_defined_with_invalid_graphql_type_schema(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UserRoleEnum(EnumType):
+ __schema__ = "scalar UserRole"
+
+ data_regression.check(str(err.value))
+
+
+def test_enum_type_raises_error_when_defined_with_multiple_types_schema(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UserRoleEnum(EnumType):
+ __schema__ = """
+ enum UserRole {
+ USER
+ MOD
+ ADMIN
+ }
+
+ enum Category {
+ CATEGORY
+ LINK
+ }
+ """
+
+ data_regression.check(str(err.value))
+
+
+def test_enum_type_extracts_graphql_name():
+ class UserRoleEnum(EnumType):
+ __schema__ = """
+ enum UserRole {
+ USER
+ MOD
+ ADMIN
+ }
+ """
+
+ assert UserRoleEnum.graphql_name == "UserRole"
+
+
+def test_enum_type_can_be_extended_with_new_values():
+ # pylint: disable=unused-variable
+ class UserRoleEnum(EnumType):
+ __schema__ = """
+ enum UserRole {
+ USER
+ MOD
+ ADMIN
+ }
+ """
+
+ class ExtendUserRoleEnum(EnumType):
+ __schema__ = """
+ extend enum UserRole {
+ MVP
+ }
+ """
+ __requires__ = [UserRoleEnum]
+
+
+def test_enum_type_can_be_extended_with_directive():
+ # pylint: disable=unused-variable
+ class ExampleDirective(DirectiveType):
+ __schema__ = "directive @example on ENUM"
+ __visitor__ = SchemaDirectiveVisitor
+
+ class UserRoleEnum(EnumType):
+ __schema__ = """
+ enum UserRole {
+ USER
+ MOD
+ ADMIN
+ }
+ """
+
+ class ExtendUserRoleEnum(EnumType):
+ __schema__ = "extend enum UserRole @example"
+ __requires__ = [UserRoleEnum, ExampleDirective]
+
+
+class BaseQueryType(ObjectType):
+ __abstract__ = True
+ __schema__ = """
+ type Query {
+ enumToRepr(enum: UserRole = USER): String!
+ reprToEnum: UserRole!
+ }
+ """
+ __aliases__ = {
+ "enumToRepr": "enum_repr",
+ }
+
+ @staticmethod
+ def resolve_enum_repr(*_, enum) -> str:
+ return repr(enum)
+
+
+def make_test_schema(enum_type):
+ class QueryType(BaseQueryType):
+ __requires__ = [enum_type]
+
+ return make_executable_schema(QueryType)
+
+
+def test_enum_type_can_be_defined_with_dict_mapping():
+ class UserRoleEnum(EnumType):
+ __schema__ = """
+ enum UserRole {
+ USER
+ MOD
+ ADMIN
+ }
+ """
+ __enum__ = {
+ "USER": 0,
+ "MOD": 1,
+ "ADMIN": 2,
+ }
+
+ schema = make_test_schema(UserRoleEnum)
+
+ # Specfied enum value is reversed
+ result = graphql_sync(schema, "{ enumToRepr(enum: MOD) }")
+ assert result.data["enumToRepr"] == "1"
+
+ # Default enum value is reversed
+ result = graphql_sync(schema, "{ enumToRepr }")
+ assert result.data["enumToRepr"] == "0"
+
+ # Python value is converted to enum
+ result = graphql_sync(schema, "{ reprToEnum }", root_value={"reprToEnum": 2})
+ assert result.data["reprToEnum"] == "ADMIN"
+
+
+def test_enum_type_raises_error_when_dict_mapping_misses_items_from_definition(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UserRoleEnum(EnumType):
+ __schema__ = """
+ enum UserRole {
+ USER
+ MOD
+ ADMIN
+ }
+ """
+ __enum__ = {
+ "USER": 0,
+ "MODERATOR": 1,
+ "ADMIN": 2,
+ }
+
+ data_regression.check(str(err.value))
+
+
+def test_enum_type_raises_error_when_dict_mapping_has_extra_items_not_in_definition(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UserRoleEnum(EnumType):
+ __schema__ = """
+ enum UserRole {
+ USER
+ MOD
+ ADMIN
+ }
+ """
+ __enum__ = {
+ "USER": 0,
+ "REVIEW": 1,
+ "MOD": 2,
+ "ADMIN": 3,
+ }
+
+ data_regression.check(str(err.value))
+
+
+def test_enum_type_can_be_defined_with_str_enum_mapping():
+ class RoleEnum(str, Enum):
+ USER = "user"
+ MOD = "moderator"
+ ADMIN = "administrator"
+
+ class UserRoleEnum(EnumType):
+ __schema__ = """
+ enum UserRole {
+ USER
+ MOD
+ ADMIN
+ }
+ """
+ __enum__ = RoleEnum
+
+ schema = make_test_schema(UserRoleEnum)
+
+ # Specfied enum value is reversed
+ result = graphql_sync(schema, "{ enumToRepr(enum: MOD) }")
+ assert result.data["enumToRepr"] == repr(RoleEnum.MOD)
+
+ # Default enum value is reversed
+ result = graphql_sync(schema, "{ enumToRepr }")
+ assert result.data["enumToRepr"] == repr(RoleEnum.USER)
+
+ # Python value is converted to enum
+ result = graphql_sync(
+ schema, "{ reprToEnum }", root_value={"reprToEnum": "administrator"}
+ )
+ assert result.data["reprToEnum"] == "ADMIN"
+
+
+def test_enum_type_raises_error_when_enum_mapping_misses_items_from_definition(
+ data_regression,
+):
+ class RoleEnum(str, Enum):
+ USER = "user"
+ MODERATOR = "moderator"
+ ADMIN = "administrator"
+
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UserRoleEnum(EnumType):
+ __schema__ = """
+ enum UserRole {
+ USER
+ MOD
+ ADMIN
+ }
+ """
+ __enum__ = RoleEnum
+
+ data_regression.check(str(err.value))
+
+
+def test_enum_type_raises_error_when_enum_mapping_has_extra_items_not_in_definition(
+ data_regression,
+):
+ class RoleEnum(str, Enum):
+ USER = "user"
+ REVIEW = "review"
+ MOD = "moderator"
+ ADMIN = "administrator"
+
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UserRoleEnum(EnumType):
+ __schema__ = """
+ enum UserRole {
+ USER
+ MOD
+ ADMIN
+ }
+ """
+ __enum__ = RoleEnum
+
+ data_regression.check(str(err.value))
diff --git a/tests/test_executable_schema.py b/tests_v1/test_executable_schema.py
similarity index 100%
rename from tests/test_executable_schema.py
rename to tests_v1/test_executable_schema.py
diff --git a/tests/test_executable_schema_compat.py b/tests_v1/test_executable_schema_compat.py
similarity index 100%
rename from tests/test_executable_schema_compat.py
rename to tests_v1/test_executable_schema_compat.py
diff --git a/tests_v1/test_input_type.py b/tests_v1/test_input_type.py
new file mode 100644
index 0000000..daad5e0
--- /dev/null
+++ b/tests_v1/test_input_type.py
@@ -0,0 +1,293 @@
+import pytest
+from ariadne import SchemaDirectiveVisitor
+from graphql import GraphQLError, graphql_sync
+
+from ariadne_graphql_modules import (
+ DeferredType,
+ DirectiveType,
+ EnumType,
+ InputType,
+ InterfaceType,
+ ObjectType,
+ ScalarType,
+ make_executable_schema,
+)
+
+
+def test_input_type_raises_attribute_error_when_defined_without_schema(data_regression):
+ with pytest.raises(AttributeError) as err:
+ # pylint: disable=unused-variable
+ class UserInput(InputType):
+ pass
+
+ data_regression.check(str(err.value))
+
+
+def test_input_type_raises_error_when_defined_with_invalid_schema_type(data_regression):
+ with pytest.raises(TypeError) as err:
+ # pylint: disable=unused-variable
+ class UserInput(InputType):
+ __schema__ = True
+
+ data_regression.check(str(err.value))
+
+
+def test_input_type_raises_error_when_defined_with_invalid_schema_str(data_regression):
+ with pytest.raises(GraphQLError) as err:
+ # pylint: disable=unused-variable
+ class UserInput(InputType):
+ __schema__ = "inpet UserInput"
+
+ data_regression.check(str(err.value))
+
+
+def test_input_type_raises_error_when_defined_with_invalid_graphql_type_schema(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UserInput(InputType):
+ __schema__ = """
+ type User {
+ id: ID!
+ }
+ """
+
+ data_regression.check(str(err.value))
+
+
+def test_input_type_raises_error_when_defined_with_multiple_types_schema(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UserInput(InputType):
+ __schema__ = """
+ input User
+
+ input Group
+ """
+
+ data_regression.check(str(err.value))
+
+
+def test_input_type_raises_error_when_defined_without_fields(data_regression):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UserInput(InputType):
+ __schema__ = "input User"
+
+ data_regression.check(str(err.value))
+
+
+def test_input_type_extracts_graphql_name():
+ class UserInput(InputType):
+ __schema__ = """
+ input User {
+ id: ID!
+ }
+ """
+
+ assert UserInput.graphql_name == "User"
+
+
+def test_input_type_raises_error_when_defined_without_field_type_dependency(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UserInput(InputType):
+ __schema__ = """
+ input User {
+ id: ID!
+ role: Role!
+ }
+ """
+
+ data_regression.check(str(err.value))
+
+
+def test_input_type_verifies_field_dependency():
+ # pylint: disable=unused-variable
+ class RoleEnum(EnumType):
+ __schema__ = """
+ enum Role {
+ USER
+ ADMIN
+ }
+ """
+
+ class UserInput(InputType):
+ __schema__ = """
+ input User {
+ id: ID!
+ role: Role!
+ }
+ """
+ __requires__ = [RoleEnum]
+
+
+def test_input_type_verifies_circular_dependency():
+ # pylint: disable=unused-variable
+ class UserInput(InputType):
+ __schema__ = """
+ input User {
+ id: ID!
+ patron: User
+ }
+ """
+
+
+def test_input_type_verifies_circular_dependency_using_deferred_type():
+ # pylint: disable=unused-variable
+ class GroupInput(InputType):
+ __schema__ = """
+ input Group {
+ id: ID!
+ patron: User
+ }
+ """
+ __requires__ = [DeferredType("User")]
+
+ class UserInput(InputType):
+ __schema__ = """
+ input User {
+ id: ID!
+ group: Group
+ }
+ """
+ __requires__ = [GroupInput]
+
+
+def test_input_type_can_be_extended_with_new_fields():
+ # pylint: disable=unused-variable
+ class UserInput(InputType):
+ __schema__ = """
+ input User {
+ id: ID!
+ }
+ """
+
+ class ExtendUserInput(InputType):
+ __schema__ = """
+ extend input User {
+ name: String!
+ }
+ """
+ __requires__ = [UserInput]
+
+
+def test_input_type_can_be_extended_with_directive():
+ # pylint: disable=unused-variable
+ class ExampleDirective(DirectiveType):
+ __schema__ = "directive @example on INPUT_OBJECT"
+ __visitor__ = SchemaDirectiveVisitor
+
+ class UserInput(InputType):
+ __schema__ = """
+ input User {
+ id: ID!
+ }
+ """
+
+ class ExtendUserInput(InputType):
+ __schema__ = """
+ extend input User @example
+ """
+ __requires__ = [UserInput, ExampleDirective]
+
+
+def test_input_type_raises_error_when_defined_without_extended_dependency(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ExtendUserInput(InputType):
+ __schema__ = """
+ extend input User {
+ name: String!
+ }
+ """
+
+ data_regression.check(str(err.value))
+
+
+def test_input_type_raises_error_when_extended_dependency_is_wrong_type(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ExampleInterface(InterfaceType):
+ __schema__ = """
+ interface User {
+ id: ID!
+ }
+ """
+
+ class ExtendUserInput(InputType):
+ __schema__ = """
+ extend input User {
+ name: String!
+ }
+ """
+ __requires__ = [ExampleInterface]
+
+ data_regression.check(str(err.value))
+
+
+def test_input_type_raises_error_when_defined_with_args_map_for_nonexisting_field(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UserInput(InputType):
+ __schema__ = """
+ input User {
+ id: ID!
+ }
+ """
+ __args__ = {
+ "fullName": "full_name",
+ }
+
+ data_regression.check(str(err.value))
+
+
+class UserInput(InputType):
+ __schema__ = """
+ input UserInput {
+ id: ID!
+ fullName: String!
+ }
+ """
+ __args__ = {
+ "fullName": "full_name",
+ }
+
+
+class GenericScalar(ScalarType):
+ __schema__ = "scalar Generic"
+
+
+class QueryType(ObjectType):
+ __schema__ = """
+ type Query {
+ reprInput(input: UserInput): Generic!
+ }
+ """
+ __aliases__ = {"reprInput": "repr_input"}
+ __requires__ = [GenericScalar, UserInput]
+
+ @staticmethod
+ def resolve_repr_input(*_, input): # pylint: disable=redefined-builtin
+ return input
+
+
+schema = make_executable_schema(QueryType)
+
+
+def test_input_type_maps_args_to_python_dict_keys():
+ result = graphql_sync(schema, '{ reprInput(input: {id: "1", fullName: "Alice"}) }')
+ assert result.data == {
+ "reprInput": {"id": "1", "full_name": "Alice"},
+ }
diff --git a/tests_v1/test_interface_type.py b/tests_v1/test_interface_type.py
new file mode 100644
index 0000000..be3637d
--- /dev/null
+++ b/tests_v1/test_interface_type.py
@@ -0,0 +1,462 @@
+from dataclasses import dataclass
+
+import pytest
+from ariadne import SchemaDirectiveVisitor
+from graphql import GraphQLError, graphql_sync
+
+from ariadne_graphql_modules import (
+ DeferredType,
+ DirectiveType,
+ InterfaceType,
+ ObjectType,
+ make_executable_schema,
+)
+
+
+def test_interface_type_raises_attribute_error_when_defined_without_schema(
+ data_regression,
+):
+ with pytest.raises(AttributeError) as err:
+ # pylint: disable=unused-variable
+ class ExampleInterface(InterfaceType):
+ pass
+
+ data_regression.check(str(err.value))
+
+
+def test_interface_type_raises_error_when_defined_with_invalid_schema_type(
+ data_regression,
+):
+ with pytest.raises(TypeError) as err:
+ # pylint: disable=unused-variable
+ class ExampleInterface(InterfaceType):
+ __schema__ = True
+
+ data_regression.check(str(err.value))
+
+
+def test_interface_type_raises_error_when_defined_with_invalid_schema_str(
+ data_regression,
+):
+ with pytest.raises(GraphQLError) as err:
+ # pylint: disable=unused-variable
+ class ExampleInterface(InterfaceType):
+ __schema__ = "interfaco Example"
+
+ data_regression.check(str(err.value))
+
+
+def test_interface_type_raises_error_when_defined_with_invalid_graphql_type_schema(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ExampleInterface(InterfaceType):
+ __schema__ = "type Example"
+
+ data_regression.check(str(err.value))
+
+
+def test_interface_type_raises_error_when_defined_with_multiple_types_schema(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ExampleInterface(InterfaceType):
+ __schema__ = """
+ interface Example
+
+ interface Other
+ """
+
+ data_regression.check(str(err.value))
+
+
+def test_interface_type_raises_error_when_defined_without_fields(data_regression):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ExampleInterface(InterfaceType):
+ __schema__ = "interface Example"
+
+ data_regression.check(str(err.value))
+
+
+def test_interface_type_extracts_graphql_name():
+ class ExampleInterface(InterfaceType):
+ __schema__ = """
+ interface Example {
+ id: ID!
+ }
+ """
+
+ assert ExampleInterface.graphql_name == "Example"
+
+
+def test_interface_type_raises_error_when_defined_without_return_type_dependency(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ExampleInterface(InterfaceType):
+ __schema__ = """
+ interface Example {
+ group: Group
+ groups: [Group!]
+ }
+ """
+
+ data_regression.check(str(err.value))
+
+
+def test_interface_type_verifies_field_dependency():
+ # pylint: disable=unused-variable
+ class GroupType(ObjectType):
+ __schema__ = """
+ type Group {
+ id: ID!
+ }
+ """
+
+ class ExampleInterface(InterfaceType):
+ __schema__ = """
+ interface Example {
+ group: Group
+ groups: [Group!]
+ }
+ """
+ __requires__ = [GroupType]
+
+
+def test_interface_type_verifies_circural_dependency():
+ # pylint: disable=unused-variable
+ class ExampleInterface(InterfaceType):
+ __schema__ = """
+ interface Example {
+ parent: Example
+ }
+ """
+
+
+def test_interface_type_raises_error_when_defined_without_argument_type_dependency(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ExampleInterface(InterfaceType):
+ __schema__ = """
+ interface Example {
+ actions(input: UserInput): [String!]!
+ }
+ """
+
+ data_regression.check(str(err.value))
+
+
+def test_interface_type_verifies_circular_dependency_using_deferred_type():
+ # pylint: disable=unused-variable
+ class ExampleInterface(InterfaceType):
+ __schema__ = """
+ interface Example {
+ id: ID!
+ users: [User]
+ }
+ """
+ __requires__ = [DeferredType("User")]
+
+ class UserType(ObjectType):
+ __schema__ = """
+ type User {
+ roles: [Example]
+ }
+ """
+ __requires__ = [ExampleInterface]
+
+
+def test_interface_type_can_be_extended_with_new_fields():
+ # pylint: disable=unused-variable
+ class ExampleInterface(InterfaceType):
+ __schema__ = """
+ interface Example {
+ id: ID!
+ }
+ """
+
+ class ExtendExampleInterface(InterfaceType):
+ __schema__ = """
+ extend interface Example {
+ name: String
+ }
+ """
+ __requires__ = [ExampleInterface]
+
+
+def test_interface_type_can_be_extended_with_directive():
+ # pylint: disable=unused-variable
+ class ExampleDirective(DirectiveType):
+ __schema__ = "directive @example on INTERFACE"
+ __visitor__ = SchemaDirectiveVisitor
+
+ class ExampleInterface(InterfaceType):
+ __schema__ = """
+ interface Example {
+ id: ID!
+ }
+ """
+
+ class ExtendExampleInterface(InterfaceType):
+ __schema__ = """
+ extend interface Example @example
+ """
+ __requires__ = [ExampleInterface, ExampleDirective]
+
+
+def test_interface_type_can_be_extended_with_other_interface():
+ # pylint: disable=unused-variable
+ class ExampleInterface(InterfaceType):
+ __schema__ = """
+ interface Example {
+ id: ID!
+ }
+ """
+
+ class OtherInterface(InterfaceType):
+ __schema__ = """
+ interface Other {
+ depth: Int!
+ }
+ """
+
+ class ExtendExampleInterface(InterfaceType):
+ __schema__ = """
+ extend interface Example implements Other
+ """
+ __requires__ = [ExampleInterface, OtherInterface]
+
+
+def test_interface_type_raises_error_when_defined_without_extended_dependency(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ExtendExampleInterface(ObjectType):
+ __schema__ = """
+ extend interface Example {
+ name: String
+ }
+ """
+
+ data_regression.check(str(err.value))
+
+
+def test_interface_type_raises_error_when_extended_dependency_is_wrong_type(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ExampleType(ObjectType):
+ __schema__ = """
+ type Example {
+ id: ID!
+ }
+ """
+
+ class ExampleInterface(InterfaceType):
+ __schema__ = """
+ extend interface Example {
+ name: String
+ }
+ """
+ __requires__ = [ExampleType]
+
+ data_regression.check(str(err.value))
+
+
+def test_interface_type_raises_error_when_defined_with_alias_for_nonexisting_field(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ExampleInterface(InterfaceType):
+ __schema__ = """
+ interface User {
+ name: String
+ }
+ """
+ __aliases__ = {
+ "joinedDate": "joined_date",
+ }
+
+ data_regression.check(str(err.value))
+
+
+def test_interface_type_raises_error_when_defined_with_resolver_for_nonexisting_field(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ExampleInterface(InterfaceType):
+ __schema__ = """
+ interface User {
+ name: String
+ }
+ """
+
+ @staticmethod
+ def resolve_group(*_):
+ return None
+
+ data_regression.check(str(err.value))
+
+
+@dataclass
+class User:
+ id: int
+ name: str
+ summary: str
+
+
+@dataclass
+class Comment:
+ id: int
+ message: str
+ summary: str
+
+
+class ResultInterface(InterfaceType):
+ __schema__ = """
+ interface Result {
+ summary: String!
+ score: Int!
+ }
+ """
+
+ @staticmethod
+ def resolve_type(instance, *_):
+ if isinstance(instance, Comment):
+ return "Comment"
+
+ if isinstance(instance, User):
+ return "User"
+
+ return None
+
+ @staticmethod
+ def resolve_score(*_):
+ return 42
+
+
+class UserType(ObjectType):
+ __schema__ = """
+ type User implements Result {
+ id: ID!
+ name: String!
+ summary: String!
+ score: Int!
+ }
+ """
+ __requires__ = [ResultInterface]
+
+
+class CommentType(ObjectType):
+ __schema__ = """
+ type Comment implements Result {
+ id: ID!
+ message: String!
+ summary: String!
+ score: Int!
+ }
+ """
+ __requires__ = [ResultInterface]
+
+ @staticmethod
+ def resolve_score(*_):
+ return 16
+
+
+class QueryType(ObjectType):
+ __schema__ = """
+ type Query {
+ results: [Result!]!
+ }
+ """
+ __requires__ = [ResultInterface]
+
+ @staticmethod
+ def resolve_results(*_):
+ return [
+ User(id=1, name="Alice", summary="Summary for Alice"),
+ Comment(id=1, message="Hello world!", summary="Summary for comment"),
+ ]
+
+
+schema = make_executable_schema(QueryType, UserType, CommentType)
+
+
+def test_interface_type_binds_type_resolver():
+ query = """
+ query {
+ results {
+ ... on User {
+ __typename
+ id
+ name
+ summary
+ }
+ ... on Comment {
+ __typename
+ id
+ message
+ summary
+ }
+ }
+ }
+ """
+
+ result = graphql_sync(schema, query)
+ assert result.data == {
+ "results": [
+ {
+ "__typename": "User",
+ "id": "1",
+ "name": "Alice",
+ "summary": "Summary for Alice",
+ },
+ {
+ "__typename": "Comment",
+ "id": "1",
+ "message": "Hello world!",
+ "summary": "Summary for comment",
+ },
+ ],
+ }
+
+
+def test_interface_type_binds_field_resolvers_to_implementing_types_fields():
+ query = """
+ query {
+ results {
+ ... on User {
+ __typename
+ score
+ }
+ ... on Comment {
+ __typename
+ score
+ }
+ }
+ }
+ """
+
+ result = graphql_sync(schema, query)
+ assert result.data == {
+ "results": [
+ {
+ "__typename": "User",
+ "score": 42,
+ },
+ {
+ "__typename": "Comment",
+ "score": 16,
+ },
+ ],
+ }
diff --git a/tests/test_mutation_type.py b/tests_v1/test_mutation_type.py
similarity index 100%
rename from tests/test_mutation_type.py
rename to tests_v1/test_mutation_type.py
diff --git a/tests_v1/test_object_type.py b/tests_v1/test_object_type.py
new file mode 100644
index 0000000..8adf0e6
--- /dev/null
+++ b/tests_v1/test_object_type.py
@@ -0,0 +1,410 @@
+import pytest
+from ariadne import SchemaDirectiveVisitor
+from graphql import GraphQLError, graphql_sync
+
+from ariadne_graphql_modules import (
+ DeferredType,
+ DirectiveType,
+ InterfaceType,
+ ObjectType,
+ make_executable_schema,
+)
+
+
+def test_object_type_raises_attribute_error_when_defined_without_schema(
+ data_regression,
+):
+ with pytest.raises(AttributeError) as err:
+ # pylint: disable=unused-variable
+ class UserType(ObjectType):
+ pass
+
+ data_regression.check(str(err.value))
+
+
+def test_object_type_raises_error_when_defined_with_invalid_schema_type(
+ data_regression,
+):
+ with pytest.raises(TypeError) as err:
+ # pylint: disable=unused-variable
+ class UserType(ObjectType):
+ __schema__ = True
+
+ data_regression.check(str(err.value))
+
+
+def test_object_type_raises_error_when_defined_with_invalid_schema_str(data_regression):
+ with pytest.raises(GraphQLError) as err:
+ # pylint: disable=unused-variable
+ class UserType(ObjectType):
+ __schema__ = "typo User"
+
+ data_regression.check(str(err.value))
+
+
+def test_object_type_raises_error_when_defined_with_invalid_graphql_type_schema(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UserType(ObjectType):
+ __schema__ = "scalar DateTime"
+
+ data_regression.check(str(err.value))
+
+
+def test_object_type_raises_error_when_defined_with_multiple_types_schema(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UserType(ObjectType):
+ __schema__ = """
+ type User
+
+ type Group
+ """
+
+ data_regression.check(str(err.value))
+
+
+def test_object_type_raises_error_when_defined_without_fields(data_regression):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UserType(ObjectType):
+ __schema__ = "type User"
+
+ data_regression.check(str(err.value))
+
+
+def test_object_type_extracts_graphql_name():
+ class GroupType(ObjectType):
+ __schema__ = """
+ type Group {
+ id: ID!
+ }
+ """
+
+ assert GroupType.graphql_name == "Group"
+
+
+def test_object_type_accepts_all_builtin_scalar_types():
+ # pylint: disable=unused-variable
+ class FancyObjectType(ObjectType):
+ __schema__ = """
+ type FancyObject {
+ id: ID!
+ someInt: Int!
+ someFloat: Float!
+ someBoolean: Boolean!
+ someString: String!
+ }
+ """
+
+
+def test_object_type_raises_error_when_defined_without_return_type_dependency(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UserType(ObjectType):
+ __schema__ = """
+ type User {
+ group: Group
+ groups: [Group!]
+ }
+ """
+
+ data_regression.check(str(err.value))
+
+
+def test_object_type_verifies_field_dependency():
+ # pylint: disable=unused-variable
+ class GroupType(ObjectType):
+ __schema__ = """
+ type Group {
+ id: ID!
+ }
+ """
+
+ class UserType(ObjectType):
+ __schema__ = """
+ type User {
+ group: Group
+ groups: [Group!]
+ }
+ """
+ __requires__ = [GroupType]
+
+
+def test_object_type_verifies_circular_dependency():
+ # pylint: disable=unused-variable
+ class UserType(ObjectType):
+ __schema__ = """
+ type User {
+ follows: User
+ }
+ """
+
+
+def test_object_type_raises_error_when_defined_without_argument_type_dependency(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UserType(ObjectType):
+ __schema__ = """
+ type User {
+ actions(input: UserInput): [String!]!
+ }
+ """
+
+ data_regression.check(str(err.value))
+
+
+def test_object_type_verifies_circular_dependency_using_deferred_type():
+ # pylint: disable=unused-variable
+ class GroupType(ObjectType):
+ __schema__ = """
+ type Group {
+ id: ID!
+ users: [User]
+ }
+ """
+ __requires__ = [DeferredType("User")]
+
+ class UserType(ObjectType):
+ __schema__ = """
+ type User {
+ group: Group
+ }
+ """
+ __requires__ = [GroupType]
+
+
+def test_object_type_can_be_extended_with_new_fields():
+ # pylint: disable=unused-variable
+ class UserType(ObjectType):
+ __schema__ = """
+ type User {
+ id: ID!
+ }
+ """
+
+ class ExtendUserType(ObjectType):
+ __schema__ = """
+ extend type User {
+ name: String
+ }
+ """
+ __requires__ = [UserType]
+
+
+def test_object_type_can_be_extended_with_directive():
+ # pylint: disable=unused-variable
+ class ExampleDirective(DirectiveType):
+ __schema__ = "directive @example on OBJECT"
+ __visitor__ = SchemaDirectiveVisitor
+
+ class UserType(ObjectType):
+ __schema__ = """
+ type User {
+ id: ID!
+ }
+ """
+
+ class ExtendUserType(ObjectType):
+ __schema__ = """
+ extend type User @example
+ """
+ __requires__ = [UserType, ExampleDirective]
+
+
+def test_object_type_can_be_extended_with_interface():
+ # pylint: disable=unused-variable
+ class ExampleInterface(InterfaceType):
+ __schema__ = """
+ interface Interface {
+ id: ID!
+ }
+ """
+
+ class UserType(ObjectType):
+ __schema__ = """
+ type User {
+ id: ID!
+ }
+ """
+
+ class ExtendUserType(ObjectType):
+ __schema__ = """
+ extend type User implements Interface
+ """
+ __requires__ = [UserType, ExampleInterface]
+
+
+def test_object_type_raises_error_when_defined_without_extended_dependency(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ExtendUserType(ObjectType):
+ __schema__ = """
+ extend type User {
+ name: String
+ }
+ """
+
+ data_regression.check(str(err.value))
+
+
+def test_object_type_raises_error_when_extended_dependency_is_wrong_type(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ExampleInterface(InterfaceType):
+ __schema__ = """
+ interface Example {
+ id: ID!
+ }
+ """
+
+ class ExampleType(ObjectType):
+ __schema__ = """
+ extend type Example {
+ name: String
+ }
+ """
+ __requires__ = [ExampleInterface]
+
+ data_regression.check(str(err.value))
+
+
+def test_object_type_raises_error_when_defined_with_alias_for_nonexisting_field(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UserType(ObjectType):
+ __schema__ = """
+ type User {
+ name: String
+ }
+ """
+ __aliases__ = {
+ "joinedDate": "joined_date",
+ }
+
+ data_regression.check(str(err.value))
+
+
+def test_object_type_raises_error_when_defined_with_resolver_for_nonexisting_field(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UserType(ObjectType):
+ __schema__ = """
+ type User {
+ name: String
+ }
+ """
+
+ @staticmethod
+ def resolve_group(*_):
+ return None
+
+ data_regression.check(str(err.value))
+
+
+def test_object_type_raises_error_when_defined_with_field_args_for_nonexisting_field(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UserType(ObjectType):
+ __schema__ = """
+ type User {
+ name: String
+ }
+ """
+ __fields_args__ = {"group": {}}
+
+ data_regression.check(str(err.value))
+
+
+def test_object_type_raises_error_when_defined_with_field_args_for_nonexisting_arg(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UserType(ObjectType):
+ __schema__ = """
+ type User {
+ name: String
+ }
+ """
+ __fields_args__ = {"name": {"arg": "arg2"}}
+
+ data_regression.check(str(err.value))
+
+
+class QueryType(ObjectType):
+ __schema__ = """
+ type Query {
+ field: String!
+ other: String!
+ firstField: String!
+ secondField: String!
+ fieldWithArg(someArg: String): String!
+ }
+ """
+ __aliases__ = {
+ "firstField": "first_field",
+ "secondField": "second_field",
+ "fieldWithArg": "field_with_arg",
+ }
+ __fields_args__ = {"fieldWithArg": {"someArg": "some_arg"}}
+
+ @staticmethod
+ def resolve_other(*_):
+ return "Word Up!"
+
+ @staticmethod
+ def resolve_second_field(obj, *_):
+ return "Obj: %s" % obj["secondField"]
+
+ @staticmethod
+ def resolve_field_with_arg(*_, some_arg):
+ return some_arg
+
+
+schema = make_executable_schema(QueryType)
+
+
+def test_object_resolves_field_with_default_resolver():
+ result = graphql_sync(schema, "{ field }", root_value={"field": "Hello!"})
+ assert result.data["field"] == "Hello!"
+
+
+def test_object_resolves_field_with_custom_resolver():
+ result = graphql_sync(schema, "{ other }")
+ assert result.data["other"] == "Word Up!"
+
+
+def test_object_resolves_field_with_aliased_default_resolver():
+ result = graphql_sync(
+ schema, "{ firstField }", root_value={"first_field": "Howdy?"}
+ )
+ assert result.data["firstField"] == "Howdy?"
+
+
+def test_object_resolves_field_with_aliased_custom_resolver():
+ result = graphql_sync(schema, "{ secondField }", root_value={"secondField": "Hey!"})
+ assert result.data["secondField"] == "Obj: Hey!"
+
+
+def test_object_resolves_field_with_arg_out_name_customized():
+ result = graphql_sync(schema, '{ fieldWithArg(someArg: "test") }')
+ assert result.data["fieldWithArg"] == "test"
diff --git a/tests_v1/test_scalar_type.py b/tests_v1/test_scalar_type.py
new file mode 100644
index 0000000..ec85340
--- /dev/null
+++ b/tests_v1/test_scalar_type.py
@@ -0,0 +1,287 @@
+from datetime import date, datetime
+
+import pytest
+from ariadne import SchemaDirectiveVisitor
+from graphql import GraphQLError, StringValueNode, graphql_sync
+
+from ariadne_graphql_modules import (
+ DirectiveType,
+ ObjectType,
+ ScalarType,
+ make_executable_schema,
+)
+
+
+def test_scalar_type_raises_attribute_error_when_defined_without_schema(
+ data_regression,
+):
+ with pytest.raises(AttributeError) as err:
+ # pylint: disable=unused-variable
+ class DateScalar(ScalarType):
+ pass
+
+ data_regression.check(str(err.value))
+
+
+def test_scalar_type_raises_error_when_defined_with_invalid_schema_type(
+ data_regression,
+):
+ with pytest.raises(TypeError) as err:
+ # pylint: disable=unused-variable
+ class DateScalar(ScalarType):
+ __schema__ = True
+
+ data_regression.check(str(err.value))
+
+
+def test_scalar_type_raises_error_when_defined_with_invalid_schema_str(data_regression):
+ with pytest.raises(GraphQLError) as err:
+ # pylint: disable=unused-variable
+ class DateScalar(ScalarType):
+ __schema__ = "scalor Date"
+
+ data_regression.check(str(err.value))
+
+
+def test_scalar_type_raises_error_when_defined_with_invalid_graphql_type_schema(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class DateScalar(ScalarType):
+ __schema__ = "type DateTime"
+
+ data_regression.check(str(err.value))
+
+
+def test_scalar_type_raises_error_when_defined_with_multiple_types_schema(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class DateScalar(ScalarType):
+ __schema__ = """
+ scalar Date
+
+ scalar DateTime
+ """
+
+ data_regression.check(str(err.value))
+
+
+def test_scalar_type_extracts_graphql_name():
+ class DateScalar(ScalarType):
+ __schema__ = "scalar Date"
+
+ assert DateScalar.graphql_name == "Date"
+
+
+def test_scalar_type_can_be_extended_with_directive():
+ # pylint: disable=unused-variable
+ class ExampleDirective(DirectiveType):
+ __schema__ = "directive @example on SCALAR"
+ __visitor__ = SchemaDirectiveVisitor
+
+ class DateScalar(ScalarType):
+ __schema__ = "scalar Date"
+
+ class ExtendDateScalar(ScalarType):
+ __schema__ = "extend scalar Date @example"
+ __requires__ = [DateScalar, ExampleDirective]
+
+
+class DateReadOnlyScalar(ScalarType):
+ __schema__ = "scalar DateReadOnly"
+
+ @staticmethod
+ def serialize(date):
+ return date.strftime("%Y-%m-%d")
+
+
+class DateInputScalar(ScalarType):
+ __schema__ = "scalar DateInput"
+
+ @staticmethod
+ def parse_value(formatted_date):
+ parsed_datetime = datetime.strptime(formatted_date, "%Y-%m-%d")
+ return parsed_datetime.date()
+
+ @staticmethod
+ def parse_literal(ast, variable_values=None): # pylint: disable=unused-argument
+ if not isinstance(ast, StringValueNode):
+ raise ValueError()
+
+ formatted_date = ast.value
+ parsed_datetime = datetime.strptime(formatted_date, "%Y-%m-%d")
+ return parsed_datetime.date()
+
+
+class DefaultParserScalar(ScalarType):
+ __schema__ = "scalar DefaultParser"
+
+ @staticmethod
+ def parse_value(value):
+ return type(value).__name__
+
+
+TEST_DATE = date(2006, 9, 13)
+TEST_DATE_SERIALIZED = TEST_DATE.strftime("%Y-%m-%d")
+
+
+class QueryType(ObjectType):
+ __schema__ = """
+ type Query {
+ testSerialize: DateReadOnly!
+ testInput(value: DateInput!): Boolean!
+ testInputValueType(value: DefaultParser!): String!
+ }
+ """
+ __requires__ = [
+ DateReadOnlyScalar,
+ DateInputScalar,
+ DefaultParserScalar,
+ ]
+ __aliases__ = {
+ "testSerialize": "test_serialize",
+ "testInput": "test_input",
+ "testInputValueType": "test_input_value_type",
+ }
+
+ @staticmethod
+ def resolve_test_serialize(*_):
+ return TEST_DATE
+
+ @staticmethod
+ def resolve_test_input(*_, value):
+ assert value == TEST_DATE
+ return True
+
+ @staticmethod
+ def resolve_test_input_value_type(*_, value):
+ return value
+
+
+schema = make_executable_schema(QueryType)
+
+
+def test_attempt_deserialize_str_literal_without_valid_date_raises_error():
+ test_input = "invalid string"
+ result = graphql_sync(schema, '{ testInput(value: "%s") }' % test_input)
+ assert result.errors is not None
+ assert str(result.errors[0]).splitlines()[:1] == [
+ "Expected value of type 'DateInput!', found \"invalid string\"; "
+ "time data 'invalid string' does not match format '%Y-%m-%d'"
+ ]
+
+
+def test_attempt_deserialize_wrong_type_literal_raises_error():
+ test_input = 123
+ result = graphql_sync(schema, "{ testInput(value: %s) }" % test_input)
+ assert result.errors is not None
+ assert str(result.errors[0]).splitlines()[:1] == [
+ "Expected value of type 'DateInput!', found 123; "
+ ]
+
+
+def test_default_literal_parser_is_used_to_extract_value_str_from_ast_node():
+ class ValueParserOnlyScalar(ScalarType):
+ __schema__ = "scalar DateInput"
+
+ @staticmethod
+ def parse_value(formatted_date):
+ parsed_datetime = datetime.strptime(formatted_date, "%Y-%m-%d")
+ return parsed_datetime.date()
+
+ class ValueParserOnlyQueryType(ObjectType):
+ __schema__ = """
+ type Query {
+ parse(value: DateInput!): String!
+ }
+ """
+ __requires__ = [ValueParserOnlyScalar]
+
+ @staticmethod
+ def resolve_parse(*_, value):
+ return value
+
+ schema = make_executable_schema(ValueParserOnlyQueryType)
+ result = graphql_sync(schema, """{ parse(value: "%s") }""" % TEST_DATE_SERIALIZED)
+ assert result.errors is None
+ assert result.data == {"parse": "2006-09-13"}
+
+
+parametrized_query = """
+ query parseValueTest($value: DateInput!) {
+ testInput(value: $value)
+ }
+"""
+
+
+def test_variable_with_valid_date_string_is_deserialized_to_python_date():
+ variables = {"value": TEST_DATE_SERIALIZED}
+ result = graphql_sync(schema, parametrized_query, variable_values=variables)
+ assert result.errors is None
+ assert result.data == {"testInput": True}
+
+
+def test_attempt_deserialize_str_variable_without_valid_date_raises_error():
+ variables = {"value": "invalid string"}
+ result = graphql_sync(schema, parametrized_query, variable_values=variables)
+ assert result.errors is not None
+ assert str(result.errors[0]).splitlines()[:1] == [
+ "Variable '$value' got invalid value 'invalid string'; "
+ "Expected type 'DateInput'. "
+ "time data 'invalid string' does not match format '%Y-%m-%d'"
+ ]
+
+
+def test_attempt_deserialize_wrong_type_variable_raises_error():
+ variables = {"value": 123}
+ result = graphql_sync(schema, parametrized_query, variable_values=variables)
+ assert result.errors is not None
+ assert str(result.errors[0]).splitlines()[:1] == [
+ "Variable '$value' got invalid value 123; Expected type 'DateInput'. "
+ "strptime() argument 1 must be str, not int"
+ ]
+
+
+def test_literal_string_is_deserialized_by_default_parser():
+ result = graphql_sync(schema, '{ testInputValueType(value: "test") }')
+ assert result.errors is None
+ assert result.data == {"testInputValueType": "str"}
+
+
+def test_literal_int_is_deserialized_by_default_parser():
+ result = graphql_sync(schema, "{ testInputValueType(value: 123) }")
+ assert result.errors is None
+ assert result.data == {"testInputValueType": "int"}
+
+
+def test_literal_float_is_deserialized_by_default_parser():
+ result = graphql_sync(schema, "{ testInputValueType(value: 1.5) }")
+ assert result.errors is None
+ assert result.data == {"testInputValueType": "float"}
+
+
+def test_literal_bool_true_is_deserialized_by_default_parser():
+ result = graphql_sync(schema, "{ testInputValueType(value: true) }")
+ assert result.errors is None
+ assert result.data == {"testInputValueType": "bool"}
+
+
+def test_literal_bool_false_is_deserialized_by_default_parser():
+ result = graphql_sync(schema, "{ testInputValueType(value: false) }")
+ assert result.errors is None
+ assert result.data == {"testInputValueType": "bool"}
+
+
+def test_literal_object_is_deserialized_by_default_parser():
+ result = graphql_sync(schema, "{ testInputValueType(value: {}) }")
+ assert result.errors is None
+ assert result.data == {"testInputValueType": "dict"}
+
+
+def test_literal_list_is_deserialized_by_default_parser():
+ result = graphql_sync(schema, "{ testInputValueType(value: []) }")
+ assert result.errors is None
+ assert result.data == {"testInputValueType": "list"}
diff --git a/tests_v1/test_subscription_type.py b/tests_v1/test_subscription_type.py
new file mode 100644
index 0000000..c0067cf
--- /dev/null
+++ b/tests_v1/test_subscription_type.py
@@ -0,0 +1,325 @@
+import pytest
+from ariadne import SchemaDirectiveVisitor
+from graphql import GraphQLError, build_schema
+
+from ariadne_graphql_modules import (
+ DirectiveType,
+ InterfaceType,
+ ObjectType,
+ SubscriptionType,
+)
+
+
+def test_subscription_type_raises_attribute_error_when_defined_without_schema(
+ data_regression,
+):
+ with pytest.raises(AttributeError) as err:
+ # pylint: disable=unused-variable
+ class UsersSubscription(SubscriptionType):
+ pass
+
+ data_regression.check(str(err.value))
+
+
+def test_subscription_type_raises_error_when_defined_with_invalid_schema_type(
+ data_regression,
+):
+ with pytest.raises(TypeError) as err:
+ # pylint: disable=unused-variable
+ class UsersSubscription(SubscriptionType):
+ __schema__ = True
+
+ data_regression.check(str(err.value))
+
+
+def test_subscription_type_raises_error_when_defined_with_invalid_schema_str(
+ data_regression,
+):
+ with pytest.raises(GraphQLError) as err:
+ # pylint: disable=unused-variable
+ class UsersSubscription(SubscriptionType):
+ __schema__ = "typo Subscription"
+
+ data_regression.check(str(err.value))
+
+
+def test_subscription_type_raises_error_when_defined_with_invalid_graphql_type_schema(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UsersSubscription(SubscriptionType):
+ __schema__ = "scalar Subscription"
+
+ data_regression.check(str(err.value))
+
+
+def test_subscription_type_raises_error_when_defined_with_invalid_graphql_type_name(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UsersSubscription(SubscriptionType):
+ __schema__ = "type Other"
+
+ data_regression.check(str(err.value))
+
+
+def test_subscription_type_raises_error_when_defined_without_fields(data_regression):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class UsersSubscription(SubscriptionType):
+ __schema__ = "type Subscription"
+
+ data_regression.check(str(err.value))
+
+
+def test_subscription_type_extracts_graphql_name():
+ class UsersSubscription(SubscriptionType):
+ __schema__ = """
+ type Subscription {
+ thread: ID!
+ }
+ """
+
+ assert UsersSubscription.graphql_name == "Subscription"
+
+
+def test_subscription_type_raises_error_when_defined_without_return_type_dependency(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ChatSubscription(SubscriptionType):
+ __schema__ = """
+ type Subscription {
+ chat: Chat
+ Chats: [Chat!]
+ }
+ """
+
+ data_regression.check(str(err.value))
+
+
+def test_subscription_type_verifies_field_dependency():
+ # pylint: disable=unused-variable
+ class ChatType(ObjectType):
+ __schema__ = """
+ type Chat {
+ id: ID!
+ }
+ """
+
+ class ChatSubscription(SubscriptionType):
+ __schema__ = """
+ type Subscription {
+ chat: Chat
+ Chats: [Chat!]
+ }
+ """
+ __requires__ = [ChatType]
+
+
+def test_subscription_type_raises_error_when_defined_without_argument_type_dependency(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ChatSubscription(SubscriptionType):
+ __schema__ = """
+ type Subscription {
+ chat(input: ChannelInput): [String!]!
+ }
+ """
+
+ data_regression.check(str(err.value))
+
+
+def test_subscription_type_can_be_extended_with_new_fields():
+ # pylint: disable=unused-variable
+ class ChatSubscription(SubscriptionType):
+ __schema__ = """
+ type Subscription {
+ chat: ID!
+ }
+ """
+
+ class ExtendChatSubscription(SubscriptionType):
+ __schema__ = """
+ extend type Subscription {
+ thread: ID!
+ }
+ """
+ __requires__ = [ChatSubscription]
+
+
+def test_subscription_type_can_be_extended_with_directive():
+ # pylint: disable=unused-variable
+ class ExampleDirective(DirectiveType):
+ __schema__ = "directive @example on OBJECT"
+ __visitor__ = SchemaDirectiveVisitor
+
+ class ChatSubscription(SubscriptionType):
+ __schema__ = """
+ type Subscription {
+ chat: ID!
+ }
+ """
+
+ class ExtendChatSubscription(SubscriptionType):
+ __schema__ = "extend type Subscription @example"
+ __requires__ = [ChatSubscription, ExampleDirective]
+
+
+def test_subscription_type_can_be_extended_with_interface():
+ # pylint: disable=unused-variable
+ class ExampleInterface(InterfaceType):
+ __schema__ = """
+ interface Interface {
+ threads: ID!
+ }
+ """
+
+ class ChatSubscription(SubscriptionType):
+ __schema__ = """
+ type Subscription {
+ chat: ID!
+ }
+ """
+
+ class ExtendChatSubscription(SubscriptionType):
+ __schema__ = """
+ extend type Subscription implements Interface {
+ threads: ID!
+ }
+ """
+ __requires__ = [ChatSubscription, ExampleInterface]
+
+
+def test_subscription_type_raises_error_when_defined_without_extended_dependency(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ExtendChatSubscription(SubscriptionType):
+ __schema__ = """
+ extend type Subscription {
+ thread: ID!
+ }
+ """
+
+ data_regression.check(str(err.value))
+
+
+def test_subscription_type_raises_error_when_extended_dependency_is_wrong_type(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ExampleInterface(InterfaceType):
+ __schema__ = """
+ interface Subscription {
+ id: ID!
+ }
+ """
+
+ class ExtendChatSubscription(SubscriptionType):
+ __schema__ = """
+ extend type Subscription {
+ thread: ID!
+ }
+ """
+ __requires__ = [ExampleInterface]
+
+ data_regression.check(str(err.value))
+
+
+def test_subscription_type_raises_error_when_defined_with_alias_for_nonexisting_field(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ChatSubscription(SubscriptionType):
+ __schema__ = """
+ type Subscription {
+ chat: ID!
+ }
+ """
+ __aliases__ = {
+ "userAlerts": "user_alerts",
+ }
+
+ data_regression.check(str(err.value))
+
+
+def test_subscription_type_raises_error_when_defined_with_resolver_for_nonexisting_field(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ChatSubscription(SubscriptionType):
+ __schema__ = """
+ type Subscription {
+ chat: ID!
+ }
+ """
+
+ @staticmethod
+ def resolve_group(*_):
+ return None
+
+ data_regression.check(str(err.value))
+
+
+def test_subscription_type_raises_error_when_defined_with_sub_for_nonexisting_field(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ChatSubscription(SubscriptionType):
+ __schema__ = """
+ type Subscription {
+ chat: ID!
+ }
+ """
+
+ @staticmethod
+ def subscribe_group(*_):
+ return None
+
+ data_regression.check(str(err.value))
+
+
+def test_subscription_type_binds_resolver_and_subscriber_to_schema():
+ schema = build_schema(
+ """
+ type Query {
+ hello: String
+ }
+
+ type Subscription {
+ chat: ID!
+ }
+ """
+ )
+
+ class ChatSubscription(SubscriptionType):
+ __schema__ = """
+ type Subscription {
+ chat: ID!
+ }
+ """
+
+ @staticmethod
+ def resolve_chat(*_):
+ return None
+
+ @staticmethod
+ def subscribe_chat(*_):
+ return None
+
+ ChatSubscription.__bind_to_schema__(schema)
+
+ field = schema.type_map.get("Subscription").fields["chat"]
+ assert field.resolve is ChatSubscription.resolve_chat
+ assert field.subscribe is ChatSubscription.subscribe_chat
diff --git a/tests_v1/test_union_type.py b/tests_v1/test_union_type.py
new file mode 100644
index 0000000..61c8a3a
--- /dev/null
+++ b/tests_v1/test_union_type.py
@@ -0,0 +1,251 @@
+from dataclasses import dataclass
+
+import pytest
+from ariadne import SchemaDirectiveVisitor
+from graphql import GraphQLError, graphql_sync
+
+from ariadne_graphql_modules import (
+ DirectiveType,
+ ObjectType,
+ UnionType,
+ make_executable_schema,
+)
+
+
+def test_union_type_raises_attribute_error_when_defined_without_schema(data_regression):
+ with pytest.raises(AttributeError) as err:
+ # pylint: disable=unused-variable
+ class ExampleUnion(UnionType):
+ pass
+
+ data_regression.check(str(err.value))
+
+
+def test_union_type_raises_error_when_defined_with_invalid_schema_type(data_regression):
+ with pytest.raises(TypeError) as err:
+ # pylint: disable=unused-variable
+ class ExampleUnion(UnionType):
+ __schema__ = True
+
+ data_regression.check(str(err.value))
+
+
+def test_union_type_raises_error_when_defined_with_invalid_schema_str(data_regression):
+ with pytest.raises(GraphQLError) as err:
+ # pylint: disable=unused-variable
+ class ExampleUnion(UnionType):
+ __schema__ = "unien Example = A | B"
+
+ data_regression.check(str(err.value))
+
+
+def test_union_type_raises_error_when_defined_with_invalid_graphql_type_schema(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ExampleUnion(UnionType):
+ __schema__ = "scalar DateTime"
+
+ data_regression.check(str(err.value))
+
+
+def test_union_type_raises_error_when_defined_with_multiple_types_schema(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ExampleUnion(UnionType):
+ __schema__ = """
+ union A = C | D
+
+ union B = C | D
+ """
+
+ data_regression.check(str(err.value))
+
+
+@dataclass
+class User:
+ id: int
+ name: str
+
+
+@dataclass
+class Comment:
+ id: int
+ message: str
+
+
+class UserType(ObjectType):
+ __schema__ = """
+ type User {
+ id: ID!
+ name: String!
+ }
+ """
+
+
+class CommentType(ObjectType):
+ __schema__ = """
+ type Comment {
+ id: ID!
+ message: String!
+ }
+ """
+
+
+class ResultUnion(UnionType):
+ __schema__ = "union Result = Comment | User"
+ __requires__ = [CommentType, UserType]
+
+ @staticmethod
+ def resolve_type(instance, *_):
+ if isinstance(instance, Comment):
+ return "Comment"
+
+ if isinstance(instance, User):
+ return "User"
+
+ return None
+
+
+class QueryType(ObjectType):
+ __schema__ = """
+ type Query {
+ results: [Result!]!
+ }
+ """
+ __requires__ = [ResultUnion]
+
+ @staticmethod
+ def resolve_results(*_):
+ return [
+ User(id=1, name="Alice"),
+ Comment(id=1, message="Hello world!"),
+ ]
+
+
+schema = make_executable_schema(QueryType, UserType, CommentType)
+
+
+def test_union_type_extracts_graphql_name():
+ class ExampleUnion(UnionType):
+ __schema__ = "union Example = User | Comment"
+ __requires__ = [UserType, CommentType]
+
+ assert ExampleUnion.graphql_name == "Example"
+
+
+def test_union_type_raises_error_when_defined_without_member_type_dependency(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ExampleUnion(UnionType):
+ __schema__ = "union Example = User | Comment"
+ __requires__ = [UserType]
+
+ data_regression.check(str(err.value))
+
+
+def test_interface_type_binds_type_resolver():
+ query = """
+ query {
+ results {
+ ... on User {
+ __typename
+ id
+ name
+ }
+ ... on Comment {
+ __typename
+ id
+ message
+ }
+ }
+ }
+ """
+
+ result = graphql_sync(schema, query)
+ assert result.data == {
+ "results": [
+ {
+ "__typename": "User",
+ "id": "1",
+ "name": "Alice",
+ },
+ {
+ "__typename": "Comment",
+ "id": "1",
+ "message": "Hello world!",
+ },
+ ],
+ }
+
+
+def test_union_type_can_be_extended_with_new_types():
+ # pylint: disable=unused-variable
+ class ExampleUnion(UnionType):
+ __schema__ = "union Result = User | Comment"
+ __requires__ = [UserType, CommentType]
+
+ class ThreadType(ObjectType):
+ __schema__ = """
+ type Thread {
+ id: ID!
+ title: String!
+ }
+ """
+
+ class ExtendExampleUnion(UnionType):
+ __schema__ = "union Result = Thread"
+ __requires__ = [ExampleUnion, ThreadType]
+
+
+def test_union_type_can_be_extended_with_directive():
+ # pylint: disable=unused-variable
+ class ExampleDirective(DirectiveType):
+ __schema__ = "directive @example on UNION"
+ __visitor__ = SchemaDirectiveVisitor
+
+ class ExampleUnion(UnionType):
+ __schema__ = "union Result = User | Comment"
+ __requires__ = [UserType, CommentType]
+
+ class ExtendExampleUnion(UnionType):
+ __schema__ = """
+ extend union Result @example
+ """
+ __requires__ = [ExampleUnion, ExampleDirective]
+
+
+def test_union_type_raises_error_when_defined_without_extended_dependency(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ExtendExampleUnion(UnionType):
+ __schema__ = "extend union Result = User"
+ __requires__ = [UserType]
+
+ data_regression.check(str(err.value))
+
+
+def test_union_type_raises_error_when_extended_dependency_is_wrong_type(
+ data_regression,
+):
+ with pytest.raises(ValueError) as err:
+ # pylint: disable=unused-variable
+ class ExampleType(ObjectType):
+ __schema__ = """
+ type Example {
+ id: ID!
+ }
+ """
+
+ class ExtendExampleUnion(UnionType):
+ __schema__ = "extend union Example = User"
+ __requires__ = [ExampleType, UserType]
+
+ data_regression.check(str(err.value))