diff --git a/CHANGELOG.md b/CHANGELOG.md index 6268b2e9..6bdf3a03 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 5300c88f..7d76d7dc 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 85440b4f..3759b575 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