Skip to content

Commit 8c42414

Browse files
a-alleangrykoala
andauthored
6981 update of relationship properties via set operation does not work in update mutations (#6986)
* test for 6981 * fix set hardcoded on node * improve test expect for list in different order * add changeset * fix includesamemembers on wrong level in jest expect * added wrapper over toIncludeSameMembers, hopefully the expect passes now.. --------- Co-authored-by: angrykoala <angrykoala@outlook.es>
1 parent 1799a61 commit 8c42414

File tree

4 files changed

+175
-1
lines changed

4 files changed

+175
-1
lines changed

.changeset/afraid-mugs-cheer.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@neo4j/graphql": patch
3+
---
4+
5+
Fix set properties always targeting nodes

packages/graphql/src/translate/queryAST/factory/Operations/UpdateFactory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,7 @@ export class UpdateFactory {
667667
switch (operator) {
668668
case "set":
669669
return new ParamInputField({
670-
attachedTo: "node",
670+
attachedTo,
671671
attribute,
672672
inputValue: value,
673673
});
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
20+
import type { UniqueType } from "../../utils/graphql-types";
21+
import { TestHelper } from "../../utils/tests-helper";
22+
23+
describe("https://github.com/neo4j/graphql/issues/6981", () => {
24+
let TypeCodePlaceholder: UniqueType;
25+
let TypeCodeValue: UniqueType;
26+
27+
const testHelper = new TestHelper();
28+
29+
beforeAll(async () => {
30+
TypeCodePlaceholder = testHelper.createUniqueType("TypeCodePlaceholder");
31+
TypeCodeValue = testHelper.createUniqueType("TypeCodeValue");
32+
33+
const typeDefs = /* GraphQL */ `
34+
type ${TypeCodePlaceholder} @mutation(operations: [CREATE, UPDATE, DELETE]) @node @subscription(events: []) {
35+
id: String!
36+
values: [${TypeCodeValue}!]!
37+
@relationship(
38+
type: "TYPECODEPLACEHOLDER_HAS_TYPECODEVALUE"
39+
properties: "TypecodeplaceholderHasTypecodevalueProperties"
40+
direction: OUT
41+
nestedOperations: [CREATE, UPDATE, DELETE, CONNECT, DISCONNECT]
42+
queryDirection: DIRECTED
43+
)
44+
@settable(onCreate: true, onUpdate: true)
45+
}
46+
47+
type ${TypeCodeValue} @mutation(operations: [CREATE, UPDATE, DELETE]) @node @subscription(events: []) {
48+
id: String!
49+
}
50+
51+
type TypecodeplaceholderHasTypecodevalueProperties @relationshipProperties {
52+
order: Int!
53+
}
54+
`;
55+
56+
await testHelper.initNeo4jGraphQL({
57+
typeDefs,
58+
});
59+
60+
await testHelper.executeCypher(`
61+
CREATE (tcp:${TypeCodePlaceholder} {id: "A"})
62+
CREATE (tcp)-[:TYPECODEPLACEHOLDER_HAS_TYPECODEVALUE {order: 1}]->(:${TypeCodeValue} {id: "B"})
63+
CREATE (tcp)-[:TYPECODEPLACEHOLDER_HAS_TYPECODEVALUE {order: 2}]->(:${TypeCodeValue} {id: "C"})
64+
65+
`);
66+
});
67+
68+
afterAll(async () => {
69+
await testHelper.close();
70+
});
71+
72+
test("should match 1 edge by node filter, aggregate count 1", async () => {
73+
const query = /* GraphQL */ `
74+
mutation {
75+
${TypeCodePlaceholder.operations.update}(
76+
where: { id: { eq: "A" } }
77+
update: {
78+
values: [
79+
{ update: { where: { node: { id: { eq: "B" } } }, edge: { order: { set: 2 } } } }
80+
{ update: { where: { node: { id: { eq: "C" } } }, edge: { order: { set: 1 } } } }
81+
]
82+
}
83+
) {
84+
${TypeCodePlaceholder.plural} {
85+
valuesConnection {
86+
edges {
87+
properties {
88+
order
89+
}
90+
node {
91+
id
92+
}
93+
}
94+
}
95+
}
96+
}
97+
}
98+
`;
99+
100+
const result = await testHelper.executeGraphQL(query);
101+
expect(result.errors).toBeUndefined();
102+
103+
expect(result.data).toEqual({
104+
[TypeCodePlaceholder.operations.update]: {
105+
[TypeCodePlaceholder.plural]: [
106+
{
107+
valuesConnection: {
108+
edges: expect.toIncludeSameMembers([
109+
{
110+
properties: {
111+
order: 2,
112+
},
113+
node: {
114+
id: "B",
115+
},
116+
},
117+
{
118+
properties: {
119+
order: 1,
120+
},
121+
node: {
122+
id: "C",
123+
},
124+
},
125+
]),
126+
},
127+
},
128+
],
129+
},
130+
});
131+
132+
await testHelper.expectRelationship(TypeCodePlaceholder, TypeCodeValue).toIncludeSameMembers([
133+
{
134+
from: {
135+
id: "A",
136+
},
137+
relationship: {
138+
order: 2,
139+
},
140+
to: {
141+
id: "B",
142+
},
143+
},
144+
{
145+
from: {
146+
id: "A",
147+
},
148+
relationship: {
149+
order: 1,
150+
},
151+
to: {
152+
id: "C",
153+
},
154+
},
155+
]);
156+
});
157+
});

packages/graphql/tests/utils/neo-expect/expect-relationship.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,18 @@ export class NeoExpectRelationship extends NeoExpect {
5656
}
5757
}
5858

59+
/** Use this if expectation is a list an elements order does not matter */
60+
public async toIncludeSameMembers(expectation: any[]): Promise<void> {
61+
const result = await this.getAll();
62+
try {
63+
expect(result).toIncludeSameMembers(expectation);
64+
} catch (err: any) {
65+
const typeStr = this.type ? `[${this.type}]` : "-";
66+
err.message = `Error on ${this.from} ${typeStr} ${this.to}\n\n ${err.message}`;
67+
throw err;
68+
}
69+
}
70+
5971
public async count(expected: number): Promise<void> {
6072
const count = await this.getCount();
6173
if (count !== expected) {

0 commit comments

Comments
 (0)