From 5a0f35879953e4786b771be5f74ae665beb46b21 Mon Sep 17 00:00:00 2001 From: DamianCzajkowski <43958031+DamianCzajkowski@users.noreply.github.com> Date: Wed, 3 Apr 2024 17:37:33 +0200 Subject: [PATCH] raise-error-when-directive-declaration-is-missing (#1173) --- CHANGELOG.md | 5 +++++ ariadne/schema_visitor.py | 9 +++++++++ tests/test_directives.py | 15 +++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6268b2e94..6bdf3a035 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +## 0.24 (UNRELEASED) + +- Added validation for directive declarations in `make_executable_schema` to prevent schema creation with undeclared directives. + + ## 0.23 (2024-03-18) - Added `execute_get_queries` setting to the `GraphQL` apps that controls execution of the GraphQL "query" operations made with GET requests. Defaults to `False`. diff --git a/ariadne/schema_visitor.py b/ariadne/schema_visitor.py index 5300c88f9..7d76d7dcf 100644 --- a/ariadne/schema_visitor.py +++ b/ariadne/schema_visitor.py @@ -468,6 +468,15 @@ def _add_directive(decl): each(schema.directives, _add_directive) + missing_directives = [ + name for name in directive_visitors if name not in declared_directives + ] + + if missing_directives: + raise ValueError( + f"Missing directive declarations for: {', '.join(missing_directives)}" + ) + # If the visitor subclass overrides get_directive_declaration, and it # returns a non-null GraphQLDirective, use that instead of any directive # declared in the schema itself. Reasoning: if a SchemaDirectiveVisitor diff --git a/tests/test_directives.py b/tests/test_directives.py index 85440b4fa..3759b575a 100644 --- a/tests/test_directives.py +++ b/tests/test_directives.py @@ -178,6 +178,21 @@ def test_directive_raises_type_error_if_required_argument_is_not_given(): make_executable_schema(type_defs, directives={"test": ReturnValueDirective}) +def test_directive_raises_type_error_if_there_is_typo(): + type_defs = """ + directive @test on FIELD_DEFINITION + + type Query { + hello: String! @test, + } + """ + + with pytest.raises(ValueError): + make_executable_schema( + type_defs, directives={"test_typo": ReturnValueDirective} + ) + + def test_can_implement_unique_id_directive(): type_defs = """ directive @uniqueID(name: String, from: [String]) on OBJECT