1- import { visit , DocumentNode , Kind } from "graphql" ;
2- import { TypeInfo , visitWithTypeInfo , coerceInputValue } from "graphql" ;
31import {
2+ coerceInputValue ,
3+ DocumentNode ,
4+ getNamedType ,
5+ getNullableType ,
6+ GraphQLCompositeType ,
7+ GraphQLList ,
8+ GraphQLNamedType ,
9+ GraphQLSchema ,
10+ isAbstractType ,
411 isInputType ,
512 isListType ,
613 isNullableType ,
7- GraphQLSchema ,
8- GraphQLList ,
9- getNullableType ,
10- isAbstractType ,
1114 isObjectType ,
12- getNamedType ,
13- GraphQLCompositeType ,
15+ Kind ,
16+ TypeInfo ,
17+ visit ,
18+ visitWithTypeInfo ,
1419} from "graphql" ;
1520import { inlineNamedFragmentSpreads } from "../utils/inline-named-fragment-spreads.js" ;
1621
@@ -38,9 +43,11 @@ export function validateFixtureInput(
3843 const inlineFragmentSpreadsAst = inlineNamedFragmentSpreads ( queryAST ) ;
3944 const typeInfo = new TypeInfo ( schema ) ;
4045 const valueStack : any [ ] [ ] = [ [ value ] ] ;
41- const errors : string [ ] = [ ] ;
46+ const typeStack : ( GraphQLNamedType | undefined ) [ ] = [ ] ;
4247 const typenameResponseKeyStack : ( string | undefined ) [ ] = [ ] ;
4348
49+ const errors : string [ ] = [ ] ;
50+
4451 visit (
4552 inlineFragmentSpreadsAst ,
4653 visitWithTypeInfo ( typeInfo , {
@@ -54,6 +61,8 @@ export function validateFixtureInput(
5461 const fieldDefinition = typeInfo . getFieldDef ( ) ;
5562 const fieldType = fieldDefinition ?. type ;
5663
64+ typeStack . push ( getNamedType ( fieldType ) ) ;
65+
5766 for ( const currentValue of currentValues ) {
5867 const valueForResponseKey = currentValue [ responseKey ] ;
5968
@@ -67,7 +76,8 @@ export function validateFixtureInput(
6776 errors . push ( `Cannot validate ${ responseKey } : missing parent type information` ) ;
6877 } else {
6978 const typenameResponseKey = typenameResponseKeyStack [ typenameResponseKeyStack . length - 1 ] ;
70- if ( isValueExpectedForType ( currentValue , parentType , schema , typeInfo , typenameResponseKey ) ) {
79+ const grandparentType = typeStack [ typeStack . length - 2 ] ;
80+ if ( isValueExpectedForType ( currentValue , parentType , grandparentType , schema , typenameResponseKey ) ) {
7181 errors . push ( `Missing expected fixture data for ${ responseKey } ` ) ;
7282 }
7383 }
@@ -138,6 +148,7 @@ export function validateFixtureInput(
138148 } ,
139149 leave ( ) {
140150 valueStack . pop ( ) ;
151+ typeStack . pop ( ) ;
141152 } ,
142153 } ,
143154 SelectionSet : {
@@ -254,8 +265,8 @@ function processNestedArrays(
254265 *
255266 * @param fixtureValue - The fixture value to check
256267 * @param parentType - The parent type from typeInfo
268+ * @param grandparentType - The type returned by the grandparent field (used to detect union/interface contexts)
257269 * @param schema - The GraphQL schema to resolve possible types for abstract types
258- * @param typeInfo - TypeInfo instance to check for abstract types in ancestry
259270 * @param typenameKey - The response key for the __typename field (supports aliases like `type: __typename`)
260271 * @returns True if the value is expected for the parent type, false otherwise
261272 *
@@ -272,16 +283,13 @@ function processNestedArrays(
272283function isValueExpectedForType (
273284 fixtureValue : any ,
274285 parentType : GraphQLCompositeType ,
286+ grandparentType : GraphQLNamedType | undefined ,
275287 schema : GraphQLSchema ,
276- typeInfo : TypeInfo ,
277288 typenameKey ?: string
278289) : boolean {
279290 // If __typename wasn't selected in the query, we can't discriminate
280291 if ( ! typenameKey ) {
281- // Empty objects {} are valid if the parent field returns a union/interface
282- // Check if the grandparent type (one level back in the stack) is abstract
283- const parentStack = ( typeInfo as any ) . _parentTypeStack ;
284- const grandparentType = parentStack [ parentStack . length - 2 ] ;
292+ // Empty objects {} are valid if the grandparent type is a union/interface
285293 if ( grandparentType && isAbstractType ( grandparentType ) && Object . keys ( fixtureValue ) . length === 0 ) {
286294 return false ; // Don't expect any fields on empty objects in union/interface contexts
287295 }
0 commit comments