diff --git a/.changeset/eighty-dingos-end.md b/.changeset/eighty-dingos-end.md new file mode 100644 index 0000000000..482cb0b3c9 --- /dev/null +++ b/.changeset/eighty-dingos-end.md @@ -0,0 +1,6 @@ +--- +'@graphql-inspector/coverage-command': minor +'@graphql-inspector/core': minor +--- + +Fix: coverage calculation improvements: Covered Queries & Covered Mutations & Covered Subscriptions diff --git a/packages/commands/coverage/src/index.ts b/packages/commands/coverage/src/index.ts index 59bcb5589c..fef400cbfa 100644 --- a/packages/commands/coverage/src/index.ts +++ b/packages/commands/coverage/src/index.ts @@ -192,14 +192,30 @@ function renderCoverage(coverage: SchemaCoverage) { method: 'Total Queries', result: String(coverage.stats.numQueries > 0 ? coverage.stats.numQueries : '0'), }, + { + method: 'Covered Queries', + result: String(coverage.stats.numCoveredQueries > 0 ? coverage.stats.numCoveredQueries : '0'), + }, { method: 'Total Mutations', result: String(coverage.stats.numMutations > 0 ? coverage.stats.numMutations : '0'), }, + { + method: 'Covered Mutations', + result: String( + coverage.stats.numCoveredMutations > 0 ? coverage.stats.numCoveredMutations : '0', + ), + }, { method: 'Total Subscriptions', result: String(coverage.stats.numSubscriptions > 0 ? coverage.stats.numSubscriptions : '0'), }, + { + method: 'Covered Subscriptions', + result: String( + coverage.stats.numCoveredSubscriptions > 0 ? coverage.stats.numCoveredSubscriptions : '0', + ), + }, ]; Logger.table(logStatsResult); Logger.log(``); diff --git a/packages/core/__tests__/coverage/coverage.test.ts b/packages/core/__tests__/coverage/coverage.test.ts index 9e6c558cd2..481d01d4ef 100644 --- a/packages/core/__tests__/coverage/coverage.test.ts +++ b/packages/core/__tests__/coverage/coverage.test.ts @@ -23,6 +23,7 @@ describe('coverage', () => { type Mutation { submitPost(title: String!, author: String!): Post! + removePost(id: Int!): Post! } schema { @@ -56,6 +57,10 @@ describe('coverage', () => { id } } + + mutation removePost { + removePost(id: 1) + } `); const results = coverage(schema, [new Source(print(doc))]); @@ -78,7 +83,7 @@ describe('coverage', () => { expect(results.types.Identifiable.children.id.hits).toEqual(1); expect(results.types.Identifiable.children.createdAt.hits).toEqual(0); // Mutation - expect(results.types.Mutation.hits).toEqual(1); + expect(results.types.Mutation.hits).toEqual(2); expect(results.types.Mutation.children.submitPost.hits).toEqual(1); expect(results.types.Mutation.children.submitPost.children.title.hits).toEqual(1); expect(results.types.Mutation.children.submitPost.children.author.hits).toEqual(1); @@ -87,8 +92,12 @@ describe('coverage', () => { expect(results.stats.numTypes).toEqual(4); expect(results.stats.numTypesCovered).toEqual(4); expect(results.stats.numTypesCoveredFully).toEqual(1); - expect(results.stats.numFields).toEqual(14); - expect(results.stats.numFiledsCovered).toEqual(10); + expect(results.stats.numFields).toEqual(16); + expect(results.stats.numFiledsCovered).toEqual(12); + expect(results.stats.numQueries).toEqual(3); + expect(results.stats.numCoveredQueries).toEqual(2); + expect(results.stats.numMutations).toEqual(2); + expect(results.stats.numCoveredMutations).toEqual(2); }); test('no coverage', () => { @@ -121,11 +130,14 @@ describe('coverage', () => { expect(results.stats.numTypes).toEqual(4); expect(results.stats.numTypesCovered).toEqual(0); expect(results.stats.numTypesCoveredFully).toEqual(0); - expect(results.stats.numFields).toEqual(14); + expect(results.stats.numFields).toEqual(16); expect(results.stats.numFiledsCovered).toEqual(0); - expect(results.stats.numQueries).toEqual(1); + expect(results.stats.numQueries).toEqual(3); + expect(results.stats.numCoveredQueries).toEqual(0); expect(results.stats.numSubscriptions).toEqual(0); - expect(results.stats.numMutations).toEqual(1); + expect(results.stats.numCoveredSubscriptions).toEqual(0); + expect(results.stats.numMutations).toEqual(2); + expect(results.stats.numCoveredMutations).toEqual(0); }); test('introspection', () => { diff --git a/packages/core/src/coverage/index.ts b/packages/core/src/coverage/index.ts index 60d32ee863..0c703ff498 100644 --- a/packages/core/src/coverage/index.ts +++ b/packages/core/src/coverage/index.ts @@ -61,8 +61,11 @@ export interface SchemaCoverage { numTypesCovered: number; numFields: number; numQueries: number; + numCoveredQueries: number; numMutations: number; + numCoveredMutations: number; numSubscriptions: number; + numCoveredSubscriptions: number; numFieldsCovered: number; numFiledsCovered: number; // @deprecated will be removed in next major version }; @@ -85,8 +88,11 @@ export function coverage(schema: GraphQLSchema, sources: Source[]): SchemaCovera numFieldsCovered: 0, numFiledsCovered: 0, numQueries: 0, + numCoveredQueries: 0, numMutations: 0, + numCoveredMutations: 0, numSubscriptions: 0, + numCoveredSubscriptions: 0, }, }; const typeMap = schema.getTypeMap(); @@ -108,6 +114,18 @@ export function coverage(schema: GraphQLSchema, sources: Source[]): SchemaCovera const fieldCoverage = typeCoverage.children[fieldDef.name]; const locations = fieldCoverage.locations[sourceName]; + switch (typeCoverage.type.name) { + case 'Query': + coverage.stats.numCoveredQueries++; + break; + case 'Mutation': + coverage.stats.numCoveredMutations++; + break; + case 'Subscription': + coverage.stats.numCoveredSubscriptions++; + break; + } + typeCoverage.hits++; fieldCoverage.hits++; @@ -146,23 +164,23 @@ export function coverage(schema: GraphQLSchema, sources: Source[]): SchemaCovera children: {}, }; - if (isObjectType(type) || isInterfaceType(type)) { - switch (type.name) { - case 'Query': - coverage.stats.numQueries++; - break; - case 'Mutation': - coverage.stats.numMutations++; - break; - case 'Subscription': - coverage.stats.numSubscriptions++; - break; - } - } - const fieldMap = type.getFields(); for (const fieldname in fieldMap) { + if (isObjectType(type) || isInterfaceType(type)) { + switch (type.name) { + case 'Query': + coverage.stats.numQueries++; + break; + case 'Mutation': + coverage.stats.numMutations++; + break; + case 'Subscription': + coverage.stats.numSubscriptions++; + break; + } + } + const field = fieldMap[fieldname]; typeCoverage.children[field.name] = {