diff --git a/lib/src/main/java/graphql/nadel/validation/NadelFieldValidation.kt b/lib/src/main/java/graphql/nadel/validation/NadelFieldValidation.kt index fb8e4052d..8464e1536 100644 --- a/lib/src/main/java/graphql/nadel/validation/NadelFieldValidation.kt +++ b/lib/src/main/java/graphql/nadel/validation/NadelFieldValidation.kt @@ -1,6 +1,7 @@ package graphql.nadel.validation import graphql.nadel.engine.util.unwrapAll +import graphql.nadel.schema.NadelDirectives import graphql.nadel.validation.NadelSchemaValidationError.IncompatibleArgumentInputType import graphql.nadel.validation.NadelSchemaValidationError.IncompatibleFieldOutputType import graphql.nadel.validation.NadelSchemaValidationError.MissingArgumentOnUnderlying @@ -36,6 +37,9 @@ class NadelFieldValidation internal constructor( parent: NadelServiceSchemaElement.FieldsContainer, overallFields: List, ): NadelSchemaValidationResult { + if(areAllFieldsHidden(overallFields)) { + return NadelSchemaValidationError.AllFieldsUsingHiddenDirective(parent) + } return overallFields .asSequence() .let { fieldSequence -> @@ -53,6 +57,10 @@ class NadelFieldValidation internal constructor( .toResult() } + private fun areAllFieldsHidden(overallFields: List): Boolean { + return overallFields.all { it.hasAppliedDirective(NadelDirectives.hiddenDirectiveDefinition.name) }; + } + context(NadelValidationContext) fun validate( parent: NadelServiceSchemaElement.FieldsContainer, diff --git a/lib/src/main/java/graphql/nadel/validation/NadelSchemaValidationError.kt b/lib/src/main/java/graphql/nadel/validation/NadelSchemaValidationError.kt index 0f23ee69a..c88669efe 100644 --- a/lib/src/main/java/graphql/nadel/validation/NadelSchemaValidationError.kt +++ b/lib/src/main/java/graphql/nadel/validation/NadelSchemaValidationError.kt @@ -409,6 +409,19 @@ sealed interface NadelSchemaValidationError : NadelSchemaValidationResult { override val subject = overallField } + + data class AllFieldsUsingHiddenDirective( + val parentType: NadelServiceSchemaElement, + ) : NadelSchemaValidationError { + val service: Service get() = parentType.service + + override val message = run { + val ot = parentType.overall.name + "Must have at least one field without @hidden on type $ot" + } + + override val subject = parentType.overall + } } private fun toString(element: GraphQLNamedSchemaElement): String { diff --git a/lib/src/test/kotlin/graphql/nadel/validation/NadelFieldValidationTest.kt b/lib/src/test/kotlin/graphql/nadel/validation/NadelFieldValidationTest.kt index c560435bc..f8a8964a4 100644 --- a/lib/src/test/kotlin/graphql/nadel/validation/NadelFieldValidationTest.kt +++ b/lib/src/test/kotlin/graphql/nadel/validation/NadelFieldValidationTest.kt @@ -676,5 +676,55 @@ class NadelFieldValidationTest : DescribeSpec({ assert(error.message == "The overall field Query.fieldA defines argument id which does not exist in service test field Query.fieldA") } + + it("fails if schema contains all fields as hidden") { + val fixture = NadelValidationTestFixture( + overallSchema = mapOf( + "test" to """ + type Query { + echo: String @hidden + } + """.trimIndent(), + ), + underlyingSchema = mapOf( + "test" to """ + type Query { + echo: String + } + """.trimIndent(), + ), + ) + + val errors = validate(fixture) + assert(errors.map { it.message }.isNotEmpty()) + + val error = errors.assertSingleOfType() + assert(error.message == "Must have at least one field without @hidden on type Query") + } + + it("passes if schema contains at least one field as not hidden") { + val fixture = NadelValidationTestFixture( + overallSchema = mapOf( + "test" to """ + type Query { + echo: String @hidden + hello: String + + } + """.trimIndent(), + ), + underlyingSchema = mapOf( + "test" to """ + type Query { + echo: String + hello: String + } + """.trimIndent(), + ), + ) + + val errors = validate(fixture) + assert(errors.isEmpty()) + } } })