From 098d649c6ac6f68c2febc668135ba557fab194f4 Mon Sep 17 00:00:00 2001 From: Stewart Parry Date: Fri, 17 Jun 2022 14:56:15 -0400 Subject: [PATCH 1/4] Add test for seed collisions --- .../graphql-fixtures/src/tests/fill.test.ts | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/packages/graphql-fixtures/src/tests/fill.test.ts b/packages/graphql-fixtures/src/tests/fill.test.ts index d42e61123f..b9612c2b42 100644 --- a/packages/graphql-fixtures/src/tests/fill.test.ts +++ b/packages/graphql-fixtures/src/tests/fill.test.ts @@ -1324,6 +1324,53 @@ describe('createFiller()', () => { people: [{name: expect.any(String)}, {name: 'Chris'}], }); }); + + it('has no duplicate ids in nested fields', () => { + const fill = createFillerForSchema(` + type Pet { + id: ID! + } + + type Person { + pets: [Pet]! + } + + type Query { + people: [Person!]! + } + `); + + const document = createDocument< + {people: {name: string}[]}, + {people?: {name?: string | null}[] | null} + >(` + query Details { + people { + pets { + id + } + } + } + `); + + const result = fill(document, { + people: [{pets: [{}, {}]}, {pets: [{}, {}]}], + }) as any; + + const allIds = result.people + .flatMap((person) => person.pets) + .map((pet) => pet.id); + + const collisions = allIds.reduce((collisions, id) => { + const matchingIds = allIds.filter((otherId) => otherId === id); + if (matchingIds.length > 1) { + collisions.push(id); + } + return collisions; + }, []); + + expect(collisions).toHaveLength(0); + }); }); }); From bf6eea0f630258791a8617bc18bd4f6f57563aac Mon Sep 17 00:00:00 2001 From: Stewart Parry Date: Fri, 17 Jun 2022 15:53:36 -0400 Subject: [PATCH 2/4] Generate keypath seed from hash of path elements --- packages/graphql-fixtures/src/fill.ts | 12 ++++++------ packages/graphql-fixtures/src/tests/fill.test.ts | 15 +++++---------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/packages/graphql-fixtures/src/fill.ts b/packages/graphql-fixtures/src/fill.ts index 15e7be70d0..451ae4121e 100644 --- a/packages/graphql-fixtures/src/fill.ts +++ b/packages/graphql-fixtures/src/fill.ts @@ -495,14 +495,14 @@ function randomEnumValue(enumType: GraphQLEnumType) { } function seedFromKeypath(keypath: string[]) { - return keypath.reduce((sum, key) => sum + seedFromKey(key), 0); + return keypath.reduce((sum, key) => hashCode(key, sum), 0); } -function seedFromKey(key: string) { - return [...key].reduce( - (sum, character) => sum + character.charCodeAt(0), - 0, - ); +function hashCode(data: string, initialHash = 0) { + let newHash = initialHash; + for (let i = 0; i < data.length; i++) + newHash = (Math.imul(31, newHash) + data.charCodeAt(i)) | 0; + return newHash; } export function list( diff --git a/packages/graphql-fixtures/src/tests/fill.test.ts b/packages/graphql-fixtures/src/tests/fill.test.ts index b9612c2b42..fd623b0313 100644 --- a/packages/graphql-fixtures/src/tests/fill.test.ts +++ b/packages/graphql-fixtures/src/tests/fill.test.ts @@ -1354,22 +1354,17 @@ describe('createFiller()', () => { `); const result = fill(document, { - people: [{pets: [{}, {}]}, {pets: [{}, {}]}], + people: Array.from(Array(100)).map(() => ({ + pets: Array.from(Array(100)).map(() => ({})), + })), }) as any; const allIds = result.people .flatMap((person) => person.pets) .map((pet) => pet.id); - const collisions = allIds.reduce((collisions, id) => { - const matchingIds = allIds.filter((otherId) => otherId === id); - if (matchingIds.length > 1) { - collisions.push(id); - } - return collisions; - }, []); - - expect(collisions).toHaveLength(0); + const allIdSet = new Set(allIds); + expect(allIdSet.size).toBe(allIds.length); }); }); }); From 191bd772178145a2285b6646f214be94c8f2b04c Mon Sep 17 00:00:00 2001 From: Ben Scott Date: Wed, 22 Jun 2022 16:21:37 -0700 Subject: [PATCH 3/4] Remove need for typecast --- packages/graphql-fixtures/src/tests/fill.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/graphql-fixtures/src/tests/fill.test.ts b/packages/graphql-fixtures/src/tests/fill.test.ts index fd623b0313..c6e27ce158 100644 --- a/packages/graphql-fixtures/src/tests/fill.test.ts +++ b/packages/graphql-fixtures/src/tests/fill.test.ts @@ -1341,8 +1341,8 @@ describe('createFiller()', () => { `); const document = createDocument< - {people: {name: string}[]}, - {people?: {name?: string | null}[] | null} + {people: {pets: {id: string}[]}[]}, + {people?: {pets?: {id?: string | null}[] | null}[] | null} >(` query Details { people { @@ -1357,7 +1357,7 @@ describe('createFiller()', () => { people: Array.from(Array(100)).map(() => ({ pets: Array.from(Array(100)).map(() => ({})), })), - }) as any; + }); const allIds = result.people .flatMap((person) => person.pets) From cf48ecf239f3e868764ce3c8fe84554b3e0f313d Mon Sep 17 00:00:00 2001 From: Ben Scott Date: Thu, 23 Jun 2022 09:15:40 -0700 Subject: [PATCH 4/4] add changeset --- .changeset/honest-ads-fry.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/honest-ads-fry.md diff --git a/.changeset/honest-ads-fry.md b/.changeset/honest-ads-fry.md new file mode 100644 index 0000000000..f8fea78333 --- /dev/null +++ b/.changeset/honest-ads-fry.md @@ -0,0 +1,5 @@ +--- +'graphql-fixtures': patch +--- + +Change how seeds are generated to reduce the chance of clashes