Skip to content

Commit

Permalink
fix: All Apex classes/triggers in the ApexCodeCoverageAggregate table…
Browse files Browse the repository at this point in the history
… are displayed when the "Show Only Aggregated Code Coverage" setting is checked (forcedotcom#370)

* fix: set apexClassIdSet to all Apex classes/triggers in ApexCodeCoverageAggregate if it is empty

* refactor: query ApexCodeCoverageAggregate table only once and use queryAll instead of fetchResults()

* test: update codeCoverage.test.ts to reflect new behavior

* fix: use ApexCodeCoverageAggregateRecord in queryAll + add comments

* refactor: use R instead of T in generics for queryAll()

* test: remove assertion in test file
  • Loading branch information
daphne-sfdc authored and gilgourevitch committed Jun 6, 2024
1 parent 2dd8835 commit d377b3f
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 19 deletions.
28 changes: 21 additions & 7 deletions src/tests/codeCoverage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Connection } from '@salesforce/core';
import {
ApexCodeCoverage,
ApexCodeCoverageAggregate,
ApexCodeCoverageAggregateRecord,
ApexOrgWideCoverage,
CodeCoverageResult,
PerClassCoverage
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -165,9 +162,26 @@ export class CodeCoverage {
private async queryAggregateCodeCov(
apexClassIdSet: Set<string>
): Promise<ApexCodeCoverageAggregate[]> {
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<ApexCodeCoverageAggregateRecord>(
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()
Expand Down
12 changes: 6 additions & 6 deletions src/tests/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,23 @@ export async function queryNamespaces(
return [...orgNamespaces, ...installedNamespaces];
}

export const queryAll = async <T>(
export const queryAll = async <R>(
connection: Connection,
query: string,
tooling = false
): Promise<QueryResult<T>> => {
): Promise<QueryResult<R>> => {
const conn = tooling ? connection.tooling : connection;
const allRecords: T[] = [];
let result = await conn.query<T>(query);
const allRecords: R[] = [];
let result = await conn.query<R>(query);
allRecords.push(...result.records);
while (!result.done) {
result = (await conn.queryMore(result.nextRecordsUrl)) as QueryResult<T>;
result = (await conn.queryMore(result.nextRecordsUrl)) as QueryResult<R>;
allRecords.push(...result.records);
}

return {
done: true,
totalSize: allRecords.length,
records: allRecords
} as QueryResult<T>;
};
};
72 changes: 66 additions & 6 deletions test/tests/codeCoverage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string>());

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 () => {
Expand Down

0 comments on commit d377b3f

Please sign in to comment.