diff --git a/packages/graphql/src/translate/create-projection-and-params.ts b/packages/graphql/src/translate/create-projection-and-params.ts index 9c782b6843..94e7676a7e 100644 --- a/packages/graphql/src/translate/create-projection-and-params.ts +++ b/packages/graphql/src/translate/create-projection-and-params.ts @@ -259,10 +259,19 @@ function createProjectionAndParams({ const isArray = relationField.typeMeta.array; if (relationField.union) { - const referenceNodes = context.neoSchema.nodes.filter((x) => - relationField.union?.nodes?.includes(x.name) + let referenceNodes = context.neoSchema.nodes.filter( + (x) => + relationField.union?.nodes?.includes(x.name) && + Object.prototype.hasOwnProperty.call(fieldFields, x.name) ); + // If for example, just selecting __typename, error will be thrown without this + if (!referenceNodes.length) { + referenceNodes = context.neoSchema.nodes.filter((x) => + relationField.union?.nodes?.includes(x.name) + ); + } + const unionStrs: string[] = [ `${key}: ${!isArray ? "head(" : ""} [(${ chainStr || varName diff --git a/packages/graphql/tests/integration/nested-unions.int.test.ts b/packages/graphql/tests/integration/nested-unions.int.test.ts index d1292e7683..4c3e9e36a4 100644 --- a/packages/graphql/tests/integration/nested-unions.int.test.ts +++ b/packages/graphql/tests/integration/nested-unions.int.test.ts @@ -117,27 +117,21 @@ describe("Nested unions", () => { contextValue: { driver }, }); expect(gqlResult.errors).toBeFalsy(); - // expect(gqlResult.data?.updateMovies.movies).toEqual([ - // { - // title: movieTitle, - // actors: [ - // { - // name: actorName, - // actedIn: [ - // {}, - // { - // name: seriesName, - // }, - // ], - // }, - // ], - // }, - // ]); - expect(gqlResult.data?.updateMovies.movies[0].title).toEqual(movieTitle); - expect(gqlResult.data?.updateMovies.movies[0].actors[0].name).toEqual(actorName); - expect(gqlResult.data?.updateMovies.movies[0].actors[0].actedIn).toContainEqual({ - name: seriesName, - }); + expect(gqlResult.data?.updateMovies.movies).toEqual([ + { + title: movieTitle, + actors: [ + { + name: actorName, + actedIn: [ + { + name: seriesName, + }, + ], + }, + ], + }, + ]); } finally { await session.close(); } @@ -383,27 +377,21 @@ describe("Nested unions", () => { contextValue: { driver }, }); expect(gqlResult.errors).toBeFalsy(); - // expect(gqlResult.data?.updateMovies.movies).toEqual([ - // { - // title: movieTitle, - // actors: [ - // { - // name: actorName, - // actedIn: [ - // {}, - // { - // name: seriesName, - // }, - // ], - // }, - // ], - // }, - // ]); - expect(gqlResult.data?.updateMovies.movies[0].title).toEqual(movieTitle); - expect(gqlResult.data?.updateMovies.movies[0].actors[0].name).toEqual(actorName); - expect(gqlResult.data?.updateMovies.movies[0].actors[0].actedIn).toContainEqual({ - name: seriesName, - }); + expect(gqlResult.data?.updateMovies.movies).toEqual([ + { + title: movieTitle, + actors: [ + { + name: actorName, + actedIn: [ + { + name: seriesName, + }, + ], + }, + ], + }, + ]); const cypherMovie = ` MATCH (m:Movie {title: $movieTitle}) diff --git a/packages/graphql/tests/tck/tck-test-files/cypher/nested-unions.md b/packages/graphql/tests/tck/tck-test-files/cypher/nested-unions.md index bf88220f41..710796068a 100644 --- a/packages/graphql/tests/tck/tck-test-files/cypher/nested-unions.md +++ b/packages/graphql/tests/tck/tck-test-files/cypher/nested-unions.md @@ -83,7 +83,7 @@ WITH this, this_connect_actors_LeadActor0_node OPTIONAL MATCH (this_connect_actors_LeadActor0_node_actedIn_Series0_node:Series) WHERE this_connect_actors_LeadActor0_node_actedIn_Series0_node.name = $this_connect_actors_LeadActor0_node_actedIn_Series0_node_name FOREACH(_ IN CASE this_connect_actors_LeadActor0_node_actedIn_Series0_node WHEN NULL THEN [] ELSE [1] END | MERGE (this_connect_actors_LeadActor0_node)-[:ACTED_IN]->(this_connect_actors_LeadActor0_node_actedIn_Series0_node) ) -RETURN this { .title, actors: [(this)<-[:ACTED_IN]-(this_actors) WHERE "LeadActor" IN labels(this_actors) OR "Extra" IN labels(this_actors) | head( [ this_actors IN [this_actors] WHERE "LeadActor" IN labels (this_actors) | this_actors { __resolveType: "LeadActor", .name, actedIn: [(this_actors)-[:ACTED_IN]->(this_actors_actedIn) WHERE "Movie" IN labels(this_actors_actedIn) OR "Series" IN labels(this_actors_actedIn) | head( [ this_actors_actedIn IN [this_actors_actedIn] WHERE "Movie" IN labels (this_actors_actedIn) | this_actors_actedIn { __resolveType: "Movie" } ] + [ this_actors_actedIn IN [this_actors_actedIn] WHERE "Series" IN labels (this_actors_actedIn) | this_actors_actedIn { __resolveType: "Series", .name } ] ) ] } ] + [ this_actors IN [this_actors] WHERE "Extra" IN labels (this_actors) | this_actors { __resolveType: "Extra" } ] ) ] } AS this +RETURN this { .title, actors: [(this)<-[:ACTED_IN]-(this_actors) WHERE "LeadActor" IN labels(this_actors) | head( [ this_actors IN [this_actors] WHERE "LeadActor" IN labels (this_actors) | this_actors { __resolveType: "LeadActor", .name, actedIn: [(this_actors)-[:ACTED_IN]->(this_actors_actedIn) WHERE "Series" IN labels(this_actors_actedIn) | head( [ this_actors_actedIn IN [this_actors_actedIn] WHERE "Series" IN labels (this_actors_actedIn) | this_actors_actedIn { __resolveType: "Series", .name } ] ) ] } ] ) ] } AS this ``` **Expected Cypher params** @@ -148,7 +148,7 @@ WITH this, this_disconnect_actors_LeadActor0 OPTIONAL MATCH (this_disconnect_actors_LeadActor0)-[this_disconnect_actors_LeadActor0_actedIn_Series0_rel:ACTED_IN]->(this_disconnect_actors_LeadActor0_actedIn_Series0:Series) WHERE this_disconnect_actors_LeadActor0_actedIn_Series0.name = $updateMovies.args.disconnect.actors.LeadActor[0].disconnect.actedIn.Series[0].where.node.name FOREACH(_ IN CASE this_disconnect_actors_LeadActor0_actedIn_Series0 WHEN NULL THEN [] ELSE [1] END | DELETE this_disconnect_actors_LeadActor0_actedIn_Series0_rel ) -RETURN this { .title, actors: [(this)<-[:ACTED_IN]-(this_actors) WHERE "LeadActor" IN labels(this_actors) OR "Extra" IN labels(this_actors) | head( [ this_actors IN [this_actors] WHERE "LeadActor" IN labels (this_actors) | this_actors { __resolveType: "LeadActor", .name, actedIn: [(this_actors)-[:ACTED_IN]->(this_actors_actedIn) WHERE "Movie" IN labels(this_actors_actedIn) OR "Series" IN labels(this_actors_actedIn) | head( [ this_actors_actedIn IN [this_actors_actedIn] WHERE "Movie" IN labels (this_actors_actedIn) | this_actors_actedIn { __resolveType: "Movie" } ] + [ this_actors_actedIn IN [this_actors_actedIn] WHERE "Series" IN labels (this_actors_actedIn) | this_actors_actedIn { __resolveType: "Series", .name } ] ) ] } ] + [ this_actors IN [this_actors] WHERE "Extra" IN labels (this_actors) | this_actors { __resolveType: "Extra" } ] ) ] } AS this +RETURN this { .title, actors: [(this)<-[:ACTED_IN]-(this_actors) WHERE "LeadActor" IN labels(this_actors) | head( [ this_actors IN [this_actors] WHERE "LeadActor" IN labels (this_actors) | this_actors { __resolveType: "LeadActor", .name, actedIn: [(this_actors)-[:ACTED_IN]->(this_actors_actedIn) WHERE "Series" IN labels(this_actors_actedIn) | head( [ this_actors_actedIn IN [this_actors_actedIn] WHERE "Series" IN labels (this_actors_actedIn) | this_actors_actedIn { __resolveType: "Series", .name } ] ) ] } ] ) ] } AS this ``` **Expected Cypher params**