@@ -499,7 +499,7 @@ describe("GraphQL Mutation Engine - Unions", () => {
499499 // T | null is replaced with the inner type (string scalar)
500500 expect ( mutation . mutatedType . kind ) . toBe ( "Scalar" ) ;
501501 expect ( mutation . wrapperModels ) . toHaveLength ( 0 ) ;
502- expect ( isNullable ( tester . program , mutation . mutatedType ) ) . toBe ( true ) ;
502+ expect ( isNullable ( mutation . mutatedType ) ) . toBe ( true ) ;
503503 } ) ;
504504
505505 it ( "replaces nullable model union with inner type" , async ( ) => {
@@ -516,7 +516,7 @@ describe("GraphQL Mutation Engine - Unions", () => {
516516 // Dog | null is replaced with the inner type (Dog model)
517517 expect ( mutation . mutatedType . kind ) . toBe ( "Model" ) ;
518518 expect ( mutation . wrapperModels ) . toHaveLength ( 0 ) ;
519- expect ( isNullable ( tester . program , mutation . mutatedType ) ) . toBe ( true ) ;
519+ expect ( isNullable ( mutation . mutatedType ) ) . toBe ( true ) ;
520520 } ) ;
521521
522522 it ( "creates wrapper models for scalar variants" , async ( ) => {
@@ -610,7 +610,7 @@ describe("GraphQL Mutation Engine - Unions", () => {
610610 expect ( nameProp ! . type . kind ) . toBe ( "Scalar" ) ;
611611
612612 // The inner type should be marked as nullable
613- expect ( isNullable ( tester . program , nameProp ! . type ) ) . toBe ( true ) ;
613+ expect ( isNullable ( nameProp ! . type ) ) . toBe ( true ) ;
614614 } ) ;
615615} ) ;
616616
@@ -770,7 +770,7 @@ describe("GraphQL Mutation Engine - Operation Context Propagation", () => {
770770 const unionMutation = engine . mutateUnion ( Pet , GraphQLTypeContext . Input ) ;
771771 expect ( unionMutation . mutatedType . kind ) . toBe ( "Model" ) ;
772772 expect ( unionMutation . mutatedType . name ) . toBe ( "PetInput" ) ;
773- expect ( isOneOf ( tester . program , unionMutation . mutatedType as Model ) ) . toBe ( true ) ;
773+ expect ( isOneOf ( unionMutation . mutatedType as Model ) ) . toBe ( true ) ;
774774 } ) ;
775775
776776 it ( "keeps union return type as union via operation mutation" , async ( ) => {
@@ -813,7 +813,7 @@ describe("GraphQL Mutation Engine - oneOf Input Objects", () => {
813813 // Union is replaced with a Model in the type graph
814814 expect ( mutation . mutatedType . kind ) . toBe ( "Model" ) ;
815815 expect ( mutation . mutatedType . name ) . toBe ( "PetInput" ) ;
816- expect ( isOneOf ( tester . program , mutation . mutatedType as Model ) ) . toBe ( true ) ;
816+ expect ( isOneOf ( mutation . mutatedType as Model ) ) . toBe ( true ) ;
817817 } ) ;
818818
819819 it ( "oneOf model has one field per variant, all optional" , async ( ) => {
@@ -914,7 +914,7 @@ describe("GraphQL Mutation Engine - oneOf Input Objects", () => {
914914 expect ( mutatedUnion . variants . size ) . toBe ( 2 ) ;
915915
916916 // The result should be marked as nullable
917- expect ( isNullable ( tester . program , mutatedUnion ) ) . toBe ( true ) ;
917+ expect ( isNullable ( mutatedUnion ) ) . toBe ( true ) ;
918918 } ) ;
919919
920920 it ( "strips null from multi-variant union in input context" , async ( ) => {
@@ -937,8 +937,8 @@ describe("GraphQL Mutation Engine - oneOf Input Objects", () => {
937937 expect ( model . properties . has ( "dog" ) ) . toBe ( true ) ;
938938
939939 // Should be marked as both @oneOf and nullable
940- expect ( isOneOf ( tester . program , model ) ) . toBe ( true ) ;
941- expect ( isNullable ( tester . program , model ) ) . toBe ( true ) ;
940+ expect ( isOneOf ( model ) ) . toBe ( true ) ;
941+ expect ( isNullable ( model ) ) . toBe ( true ) ;
942942 } ) ;
943943
944944 it ( "non-nullable union is not marked as nullable" , async ( ) => {
@@ -953,7 +953,7 @@ describe("GraphQL Mutation Engine - oneOf Input Objects", () => {
953953 const engine = createTestEngine ( tester . program ) ;
954954 const mutation = engine . mutateUnion ( Pet , GraphQLTypeContext . Output ) ;
955955
956- expect ( isNullable ( tester . program , mutation . mutatedType ) ) . toBe ( false ) ;
956+ expect ( isNullable ( mutation . mutatedType ) ) . toBe ( false ) ;
957957 } ) ;
958958
959959 it ( "exposes typeContext on union mutation" , async ( ) => {
@@ -971,4 +971,20 @@ describe("GraphQL Mutation Engine - oneOf Input Objects", () => {
971971 expect ( inputMutation . typeContext ) . toBe ( GraphQLTypeContext . Input ) ;
972972 expect ( outputMutation . typeContext ) . toBe ( GraphQLTypeContext . Output ) ;
973973 } ) ;
974+
975+ it ( "nullable decorator survives type cloning" , async ( ) => {
976+ const { NullableString } = await tester . compile (
977+ t . code `union ${ t . union ( "NullableString" ) } { string, null }` ,
978+ ) ;
979+
980+ const engine = createTestEngine ( tester . program ) ;
981+ const mutation = engine . mutateUnion ( NullableString , GraphQLTypeContext . Output ) ;
982+
983+ // Mutation engine strips null and marks the result as nullable
984+ expect ( isNullable ( mutation . mutatedType ) ) . toBe ( true ) ;
985+
986+ // Simulate a downstream mutation stage cloning the type
987+ const clone = tester . program . checker . cloneType ( mutation . mutatedType ) ;
988+ expect ( isNullable ( clone ) ) . toBe ( true ) ;
989+ } ) ;
974990} ) ;
0 commit comments