Repository: kamilkisiela/graphql-inspector (ts)

Issue:
Enforce all fragment names across the projects to be unique

Pull request:
Name of fragments should be unique
Closes #55 

Patch:
diff --git a/packages/core/src/validate/index.ts b/packages/core/src/validate/index.ts
index cedbb0e4..728591b8 100644
--- a/packages/core/src/validate/index.ts
+++ b/packages/core/src/validate/index.ts
@@ -27,10 +27,12 @@ export function validate(
   const documents = sources.map(readDocument);
   // keep all named fragments
   const fragments: Array<{node: FragmentDefinitionNode; source: string}> = [];
+  const fragmentNames: string[] = [];
   const graph = new DepGraph<FragmentDefinitionNode>({circular: true});
 
   documents.forEach(doc => {
     doc.fragments.forEach(fragment => {
+      fragmentNames.push(fragment.node.name.value);
       fragments.push(fragment);
       graph.addNode(fragment.node.name.value, fragment.node);
     });
@@ -79,11 +81,12 @@ export function validate(
 
       const errors = validateDocument(schema, parse(merged)) as GraphQLError[];
       const deprecated = findDeprecatedUsages(schema, parse(doc.source.body));
+      const duplicatedFragments = findDuplicatedFragments(fragmentNames);
 
-      if (errors || deprecated) {
+      if (errors || deprecated || duplicatedFragments) {
         invalidDocuments.push({
           source: doc.source,
-          errors,
+          errors: [...errors, ...duplicatedFragments],
           deprecated,
         });
       }
@@ -92,6 +95,12 @@ export function validate(
   return invalidDocuments;
 }
 
+function findDuplicatedFragments(fragmentNames: string[]) {
+  return fragmentNames
+    .filter((name, i, all) => all.indexOf(name) !== i)
+    .map(name => new GraphQLError(`Name of '${name}' fragment is not unique`));
+}
+
 //
 // PostInfo -> AuthorInfo
 // AuthorInfo -> None


Test patch:
diff --git a/packages/core/__tests__/validate.ts b/packages/core/__tests__/validate.ts
index 5ee51309..a6a86ce3 100644
--- a/packages/core/__tests__/validate.ts
+++ b/packages/core/__tests__/validate.ts
@@ -95,3 +95,53 @@ test('multiple fragments across multiple files with nested fragments (#36)', asy
   expect(results[0].errors.length).toEqual(0);
   expect(results[0].deprecated.length).toEqual(0);
 });
+
+test('fail on non unique fragment names', async () => {
+  const schema = buildASTSchema(gql`
+    type Post {
+      id: ID
+      title: String
+      createdAt: Int
+    }
+
+    type Query {
+      post: Post
+    }
+
+    schema {
+      query: Query
+    }
+  `);
+
+  const docs = [
+    gql`
+      query getPost {
+        post {
+          ...PostInfo
+        }
+      }
+    `,
+    gql`
+      fragment PostInfo on Post {
+        id
+        title
+      }
+    `,
+    gql`
+      fragment PostInfo on Post {
+        id
+        title
+      }
+    `,
+  ];
+
+  const results = validate(schema, docs.map(doc => new Source(print(doc))));
+
+  expect(results.length).toEqual(1);
+  expect(results[0].errors.length).toEqual(1);
+  expect(results[0].deprecated.length).toEqual(0);
+
+  const error = results[0].errors[0];
+
+  expect(error.message).toMatch(`Name of 'PostInfo' fragment is not unique`);
+});