Skip to content

Commit 4ec470f

Browse files
authored
Merge pull request #57 from postmanlabs/feature/fix-union-self-ref-past-depth
Fixed an issue where GQL definition of having Union self refs past depth limit was failing with RangeError.
2 parents 35ff42e + 09f04c1 commit 4ec470f

File tree

4 files changed

+79
-7
lines changed

4 files changed

+79
-7
lines changed

.github/workflows/test.yml

+13-6
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
1-
name: Tests
1+
name: Test
22

33
on:
4-
[pull_request]
4+
push:
5+
branches: [develop, master]
6+
pull_request:
57

68
jobs:
79
Unit-Tests:
810
runs-on: ubuntu-latest
11+
strategy:
12+
matrix:
13+
node-version: [16.x, 18.x]
914
steps:
10-
- uses: actions/checkout@v2
11-
- uses: actions/setup-node@v1
15+
- uses: actions/checkout@v3
16+
- name: Use Node.js ${{ matrix.node-version }}
17+
uses: actions/setup-node@v3
1218
with:
13-
node-version: '14.x'
19+
node-version: ${{ matrix.node-version }}
1420
- run: npm ci
15-
- run: npm run test
21+
- run: npm run test-lint
22+
- run: npm run test-unit

lib/assets/gql-generator.js

+10
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,16 @@ module.exports = {
281281

282282
/* Union types */
283283
if (curType.astNode && curType.astNode.kind === 'UnionTypeDefinition') {
284+
285+
/* Make sure UnionTypeDefinition are also not circularly referenced */
286+
if ((crossReferenceKeyList.hasOwnProperty(crossReferenceKey) && crossReferenceKeyList[crossReferenceKey]) ||
287+
curDepth > depthLimit
288+
) {
289+
crossReferenceKeyList[crossReferenceKey] = false;
290+
return '';
291+
}
292+
crossReferenceKeyList[crossReferenceKey] = true;
293+
284294
const types = curType.getTypes();
285295
if (types && types.length) {
286296
const indent = `${' '.repeat(curDepth)}`,

test/unit/converter.test.js

+26-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ var converter = require('../../index'),
1717
invalidSchemaJson = require('./fixtures/invalidSchema.json'),
1818
validSchemaSDL = fs.readFileSync(path.join(__dirname, './fixtures/validSchemaSDL.graphql')).toString(),
1919
selfRefSchema = fs.readFileSync(path.join(__dirname, './fixtures/selfRefUnionTypeExample.graphql')).toString(),
20+
seflRefDepthUnionSchema = fs.readFileSync(
21+
path.join(__dirname, './fixtures/seflRefDepthUnionSchema.graphql')
22+
).toString(),
2023
customTypeNames = fs.readFileSync(path.join(__dirname, './fixtures/custom-queryname.gql')).toString(),
2124
issue10 = fs.readFileSync(path.join(__dirname, './fixtures/issue#10.graphql')).toString(),
2225
circularInput = fs.readFileSync(path.join(__dirname, './fixtures/circularInput.graphql')).toString(),
@@ -120,7 +123,7 @@ describe('Converter tests', function () {
120123
it('should generate a collection for a valid SDL schema with a union type self referencing', function (done) {
121124
convert({ type: 'string',
122125
data: selfRefSchema
123-
}, {}, function (error, result) {
126+
}, { depth: 3 }, function (error, result) {
124127
if (error) {
125128
expect.fail(null, null, error);
126129
return done();
@@ -268,6 +271,28 @@ describe('Converter tests', function () {
268271
return done();
269272
});
270273
});
274+
275+
it('should generate a collection for a valid SDL schema with a union type self referencing' +
276+
' and past allowed depth limit', function (done) {
277+
convert({ type: 'string',
278+
data: seflRefDepthUnionSchema
279+
}, { depth: 3 }, function (error, result) {
280+
if (error) {
281+
expect.fail(null, null, error);
282+
return done();
283+
}
284+
const collection = result.output[0].data;
285+
expect(collection.item[0].item[0].request.body.mode).to.be.equal('graphql');
286+
expect(collection.item[0].item[0].request.body.graphql).to.be.an('object');
287+
expect(collection.item[0].item[0].request.body.graphql.query).to.be.a('string');
288+
expect(collection.item[0].item[0].request.body.graphql.variables).to.be.a('string');
289+
expect(collection.item[0].item[0].request.body.graphql.query).to.contain('# self reference detected');
290+
expect(collection.item[0].item[0].request.body.graphql.query).to.contain('# skipping "createdBy"');
291+
expect(collection.item[0].item[0].request.body.graphql.query).to.contain('# skipping "updatedBy"');
292+
293+
return done();
294+
});
295+
});
271296
});
272297

273298
describe('Validate function', function () {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format.
2+
scalar DateTime
3+
4+
type Organization {
5+
id: ID!
6+
createdBy: User!
7+
updatedBy: User!
8+
name: String!
9+
avatarUrl: String
10+
owner: String!
11+
}
12+
13+
# User
14+
type User {
15+
id: ID!
16+
organization: OrganizationOrStringUnion
17+
idpId: String!
18+
firstName: String!
19+
lastName: String!
20+
createdBy: UserOrStringUnion
21+
updatedBy: UserOrStringUnion
22+
}
23+
24+
union OrganizationOrStringUnion = Organization
25+
26+
union UserOrStringUnion = User
27+
28+
type Query {
29+
User(id: String!): User!
30+
}

0 commit comments

Comments
 (0)