-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Open
Description
Describe the bug
The spec grammar:
(UnionTypeDefinition : Description? union Name Directives[Const]? UnionMemberTypes?)
makes UnionMemberTypes optional. SchemaParser correctly parses this SDL and TypeDefinitionRegistry correctly shows the union extensions. However, SchemaGenerator.makeExecutableSchema() fails validation with:
SchemaProblem{errors=[Union type 'Pet' must include one or more member types.]}
Root cause is that the validation checks the base definition before merging extension members (which isn't done for other types like interfaces). For deeper dive on root cause see this link.
(GraphQL Java 25.0)
To Reproduce
import graphql.schema.idl.SchemaParser
import graphql.schema.idl.UnExecutableSchemaGenerator
import org.junit.jupiter.api.Test
/**
* Demonstrates a graphql-java bug: empty union base definitions with members
* added via extensions are rejected, even though the GraphQL spec allows this.
*
* The spec grammar (UnionTypeDefinition : Description? union Name Directives[Const]? UnionMemberTypes?)
* makes UnionMemberTypes optional. SchemaParser correctly parses this SDL and
* TypeDefinitionRegistry correctly shows the union extensions. However,
* SchemaGenerator.makeExecutableSchema() fails validation with:
*
* SchemaProblem{errors=[Union type 'Pet' must include one or more member types.]}
*
* The validation checks the base definition before merging extension members.
*/
class UnionTest {
@Test
fun `test empty union base`() {
val sdl = """
type Cat { meow: String }
type Dog { bark: String }
union Pet
extend union Pet = Cat | Dog
type Query { pet: Pet }
""".trimIndent()
val registry = SchemaParser().parse(sdl)
println("=== Registry parsed successfully ===")
println("Types: ${registry.types().keys}")
println("Union extensions: ${registry.unionTypeExtensions()}")
try {
val schema = UnExecutableSchemaGenerator.makeUnExecutableSchema(registry)
println("=== Schema built successfully ===")
} catch (e: Exception) {
println("=== Exception ===")
println("Class: ${e.javaClass.name}")
println("Message: ${e.message}")
e.printStackTrace()
throw e
}
}
}
Metadata
Metadata
Assignees
Labels
No labels