diff --git a/src/tests/codeCoverage.ts b/src/tests/codeCoverage.ts index 2411bb47..9221ee5c 100644 --- a/src/tests/codeCoverage.ts +++ b/src/tests/codeCoverage.ts @@ -9,6 +9,7 @@ import { Connection } from '@salesforce/core'; import { ApexCodeCoverage, ApexCodeCoverageAggregate, + ApexCodeCoverageAggregateRecord, ApexOrgWideCoverage, CodeCoverageResult, PerClassCoverage @@ -104,10 +105,6 @@ export class CodeCoverage { totalLines: number; coveredLines: number; }> { - if (apexClassIdSet.size === 0) { - return { codeCoverageResults: [], totalLines: 0, coveredLines: 0 }; - } - const codeCoverageAggregates = await this.queryAggregateCodeCov(apexClassIdSet); @@ -165,9 +162,26 @@ export class CodeCoverage { private async queryAggregateCodeCov( apexClassIdSet: Set ): Promise { - const codeCoverageQuery = - 'SELECT ApexClassOrTrigger.Id, ApexClassOrTrigger.Name, NumLinesCovered, NumLinesUncovered, Coverage FROM ApexCodeCoverageAggregate WHERE ApexClassorTriggerId IN (%s)'; - return this.fetchResults(apexClassIdSet, codeCoverageQuery); + let codeCoverageQuery; + + // If the "Store Only Aggregate Code Coverage" setting is checked, then apexClassIdSet is empty and we should query all the Apex classes and triggers in the ApexCodeCoverageAggregate table. + if (apexClassIdSet.size === 0) { + codeCoverageQuery = + 'SELECT ApexClassOrTrigger.Id, ApexClassOrTrigger.Name, NumLinesCovered, NumLinesUncovered, Coverage FROM ApexCodeCoverageAggregate'; + + const result = await queryAll( + this.connection, + codeCoverageQuery, + true + ); + return [result]; + } + // If the "Store Only Aggregate Code Coverage" setting is unchecked, we continue to query only the Apex classes and triggers in apexClassIdSet from the ApexCodeCoverageAggregate table, as those are the Apex classes and triggers touched by the Apex tests in the current run. + else { + codeCoverageQuery = + 'SELECT ApexClassOrTrigger.Id, ApexClassOrTrigger.Name, NumLinesCovered, NumLinesUncovered, Coverage FROM ApexCodeCoverageAggregate WHERE ApexClassorTriggerId IN (%s)'; + return this.fetchResults(apexClassIdSet, codeCoverageQuery); + } } @elapsedTime() diff --git a/src/tests/utils.ts b/src/tests/utils.ts index c1f138eb..ac86a16b 100644 --- a/src/tests/utils.ts +++ b/src/tests/utils.ts @@ -41,17 +41,17 @@ export async function queryNamespaces( return [...orgNamespaces, ...installedNamespaces]; } -export const queryAll = async ( +export const queryAll = async ( connection: Connection, query: string, tooling = false -): Promise> => { +): Promise> => { const conn = tooling ? connection.tooling : connection; - const allRecords: T[] = []; - let result = await conn.query(query); + const allRecords: R[] = []; + let result = await conn.query(query); allRecords.push(...result.records); while (!result.done) { - result = (await conn.queryMore(result.nextRecordsUrl)) as QueryResult; + result = (await conn.queryMore(result.nextRecordsUrl)) as QueryResult; allRecords.push(...result.records); } @@ -59,5 +59,5 @@ export const queryAll = async ( done: true, totalSize: allRecords.length, records: allRecords - } as QueryResult; + }; }; diff --git a/test/tests/codeCoverage.test.ts b/test/tests/codeCoverage.test.ts index 33915b1c..72a6767c 100644 --- a/test/tests/codeCoverage.test.ts +++ b/test/tests/codeCoverage.test.ts @@ -147,15 +147,75 @@ describe('Get code coverage results', () => { expect(codeCoverageResults).to.eql(expectedResult); }); - it('should return aggregate code coverage result with 0 records', async () => { - toolingQueryStub.throws('Error at Row:1;Column:1'); + it('should return aggregate code coverage result with all records from AggregateCodeCoverage table', async () => { + const codeCoverageQueryResult = [ + { + ApexClassOrTrigger: { Id: '0001x05958', Name: 'ApexTrigger1' }, + NumLinesCovered: 5, + NumLinesUncovered: 1, + Coverage: { coveredLines: [1, 2, 3, 4, 5], uncoveredLines: [6] } + }, + { + ApexClassOrTrigger: { Id: '0001x05959', Name: 'ApexTrigger2' }, + NumLinesCovered: 6, + NumLinesUncovered: 2, + Coverage: { coveredLines: [1, 2, 3, 4, 5, 6], uncoveredLines: [7, 8] } + }, + { + ApexClassOrTrigger: { Id: '0001x05951', Name: 'ApexTrigger3' }, + NumLinesCovered: 7, + NumLinesUncovered: 3, + Coverage: { + coveredLines: [1, 2, 3, 4, 5, 6, 7], + uncoveredLines: [8, 9, 10] + } + } + ]; + const expectedResult = [ + { + apexId: '0001x05958', + coveredLines: [1, 2, 3, 4, 5], + name: 'ApexTrigger1', + numLinesCovered: 5, + numLinesUncovered: 1, + percentage: '83%', + type: 'ApexTrigger', + uncoveredLines: [6] + }, + { + apexId: '0001x05959', + coveredLines: [1, 2, 3, 4, 5, 6], + name: 'ApexTrigger2', + numLinesCovered: 6, + numLinesUncovered: 2, + percentage: '75%', + type: 'ApexTrigger', + uncoveredLines: [7, 8] + }, + { + apexId: '0001x05951', + coveredLines: [1, 2, 3, 4, 5, 6, 7], + name: 'ApexTrigger3', + numLinesCovered: 7, + numLinesUncovered: 3, + percentage: '70%', + type: 'ApexTrigger', + uncoveredLines: [8, 9, 10] + } + ]; + toolingQueryStub.resolves({ + done: true, + totalSize: 3, + records: codeCoverageQueryResult + } as ApexCodeCoverageAggregate); const codeCov = new CodeCoverage(mockConnection); const { codeCoverageResults, totalLines, coveredLines } = - await codeCov.getAggregateCodeCoverage(new Set([])); - expect(codeCoverageResults.length).to.equal(0); - expect(totalLines).to.equal(0); - expect(coveredLines).to.equal(0); + await codeCov.getAggregateCodeCoverage(new Set()); + + expect(totalLines).to.equal(24); + expect(coveredLines).to.equal(18); + expect(codeCoverageResults).to.eql(expectedResult); }); it('should return per class code coverage for multiple test classes', async () => {