Skip to content

Commit

Permalink
fix: remove covered line adjustment
Browse files Browse the repository at this point in the history
  • Loading branch information
mcarvin8 committed Oct 28, 2024
1 parent a9f7114 commit 9859d23
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 231 deletions.
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ sf apex get test --test-run-id <test run id> --code-coverage --result-format jso

The code coverage JSONs created by the Salesforce CLI aren't accepted by SonarQube automatically for Salesforce DX repositories and needs to be converted using this plugin.

**Disclaimer**: Due to existing bugs with how the Salesforce CLI reports covered lines during deployments (see [5511](https://github.com/forcedotcom/salesforcedx-vscode/issues/5511) and [1568](https://github.com/forcedotcom/cli/issues/1568)), to add support for covered lines in this plugin for deployment coverage files, I had to add a function to re-number out-of-range covered lines the CLI may report (ex: line 100 in a 98-line Apex Class is reported back as covered by the Salesforce CLI deploy command). Salesforce's coverage result may also include extra lines as covered (ex: 120 lines are included in the coverage report for a 100 line file), so the coverage percentage may vary based on how many lines the API returns in the coverage report. Once Salesforce fixes the API to correctly return covered lines in the deploy command, this function will be removed.

## Install

```bash
Expand Down
8 changes: 0 additions & 8 deletions src/helpers/getTotalLines.ts

This file was deleted.

40 changes: 0 additions & 40 deletions src/helpers/setCoveredLines.ts

This file was deleted.

23 changes: 10 additions & 13 deletions src/helpers/transformDeployCoverageReport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { create } from 'xmlbuilder2';
import { DeployCoverageData, CoverageObject, FileObject } from './types.js';
import { getPackageDirectories } from './getPackageDirectories.js';
import { findFilePath } from './findFilePath.js';
import { setCoveredLines } from './setCoveredLines.js';
import { normalizePathToUnix } from './normalizePathToUnix.js';

export async function transformDeployCoverageReport(
Expand All @@ -26,23 +25,21 @@ export async function transformDeployCoverageReport(
warnings.push(`The file name ${formattedFileName} was not found in any package directory.`);
continue;
}
const uncoveredLines = Object.keys(fileInfo.s)
.filter((lineNumber) => fileInfo.s[lineNumber] === 0)
.map(Number);
const coveredLines = Object.keys(fileInfo.s)
.filter((lineNumber) => fileInfo.s[lineNumber] === 1)
.map(Number);

const fileObj: FileObject = {
'@path': normalizePathToUnix(relativeFilePath),
lineToCover: uncoveredLines.map((lineNumber: number) => ({
'@lineNumber': lineNumber,
'@covered': 'false',
})),
lineToCover: [],
};

// this function is only needed until Salesforce fixes the API to correctly return covered lines
await setCoveredLines(coveredLines, uncoveredLines, repoRoot, relativeFilePath, fileObj);
for (const lineNumberString in fileInfo.s) {
if (!Object.hasOwn(fileInfo.s, lineNumberString)) continue;
const covered = fileInfo.s[lineNumberString] === 1 ? 'true' : 'false';
fileObj.lineToCover.push({
'@lineNumber': Number(lineNumberString),
'@covered': covered,
});
}

filesProcessed++;
coverageObj.coverage.file.push(fileObj);
}
Expand Down
72 changes: 0 additions & 72 deletions test/baselines/classes/AccountProfile.cls

This file was deleted.

40 changes: 0 additions & 40 deletions test/baselines/triggers/AccountTrigger.trigger

This file was deleted.

17 changes: 9 additions & 8 deletions test/commands/acc-transformer/transform.nut.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

import { copyFile, writeFile, readFile, rm, mkdir } from 'node:fs/promises';
import { writeFile, readFile, rm, mkdir } from 'node:fs/promises';
import { strictEqual } from 'node:assert';
import { resolve } from 'node:path';

Expand All @@ -9,8 +9,10 @@ import { expect } from 'chai';

describe('acc-transformer transform NUTs', () => {
let session: TestSession;
const baselineClassPath = resolve('test/baselines/classes/AccountProfile.cls');
const baselineTriggerPath = resolve('test/baselines/triggers/AccountTrigger.trigger');
const mockClassContent = '// Test Apex Class';
const mockTriggerContent = '// Test Apex Trigger';
const baselineClassPath = resolve('force-app/main/default/classes/AccountProfile.cls');
const baselineTriggerPath = resolve('packaged/triggers/AccountTrigger.trigger');
const deployCoverageNoExts = resolve('test/deploy_coverage_no_file_exts.json');
const deployCoverageWithExts = resolve('test/deploy_coverage_with_file_exts.json');
const testCoverage = resolve('test/test_coverage.json');
Expand All @@ -26,7 +28,6 @@ describe('acc-transformer transform NUTs', () => {
packageDirectories: [{ path: 'force-app', default: true }, { path: 'packaged' }],
namespace: '',
sfdcLoginUrl: 'https://login.salesforce.com',
sourceApiVersion: '58.0',
};
const configJsonString = JSON.stringify(configFile, null, 2);

Expand All @@ -35,15 +36,15 @@ describe('acc-transformer transform NUTs', () => {
await writeFile(sfdxConfigFile, configJsonString);
await mkdir('force-app/main/default/classes', { recursive: true });
await mkdir('packaged/triggers', { recursive: true });
await copyFile(baselineClassPath, 'force-app/main/default/classes/AccountProfile.cls');
await copyFile(baselineTriggerPath, 'packaged/triggers/AccountTrigger.trigger');
await writeFile(baselineClassPath, mockClassContent);
await writeFile(baselineTriggerPath, mockTriggerContent);
});

after(async () => {
await session?.clean();
await rm(sfdxConfigFile);
await rm('force-app/main/default/classes/AccountProfile.cls');
await rm('packaged/triggers/AccountTrigger.trigger');
await rm(baselineClassPath);
await rm(baselineTriggerPath);
await rm('force-app', { recursive: true });
await rm('packaged', { recursive: true });
await rm(coverageXmlPath1);
Expand Down
19 changes: 10 additions & 9 deletions test/commands/acc-transformer/transform.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

import { copyFile, readFile, writeFile, rm, mkdir } from 'node:fs/promises';
import { readFile, writeFile, rm, mkdir } from 'node:fs/promises';
import { strictEqual } from 'node:assert';
import { resolve } from 'node:path';

Expand All @@ -12,8 +12,10 @@ import TransformerTransform from '../../../src/commands/acc-transformer/transfor
describe('main', () => {
const $$ = new TestContext();
let sfCommandStubs: ReturnType<typeof stubSfCommandUx>;
const baselineClassPath = resolve('test/baselines/classes/AccountProfile.cls');
const baselineTriggerPath = resolve('test/baselines/triggers/AccountTrigger.trigger');
const mockClassContent = '// Test Apex Class';
const mockTriggerContent = '// Test Apex Trigger';
const baselineClassPath = resolve('force-app/main/default/classes/AccountProfile.cls');
const baselineTriggerPath = resolve('packaged/triggers/AccountTrigger.trigger');
const deployCoverageNoExts = resolve('test/deploy_coverage_no_file_exts.json');
const deployCoverageWithExts = resolve('test/deploy_coverage_with_file_exts.json');
const testCoverage = resolve('test/test_coverage.json');
Expand All @@ -29,16 +31,15 @@ describe('main', () => {
packageDirectories: [{ path: 'force-app', default: true }, { path: 'packaged' }],
namespace: '',
sfdcLoginUrl: 'https://login.salesforce.com',
sourceApiVersion: '58.0',
};
const configJsonString = JSON.stringify(configFile, null, 2);

before(async () => {
await writeFile(sfdxConfigFile, configJsonString);
await mkdir('force-app/main/default/classes', { recursive: true });
await mkdir('packaged/triggers', { recursive: true });
await copyFile(baselineClassPath, 'force-app/main/default/classes/AccountProfile.cls');
await copyFile(baselineTriggerPath, 'packaged/triggers/AccountTrigger.trigger');
await writeFile(sfdxConfigFile, configJsonString);
await writeFile(baselineClassPath, mockClassContent);
await writeFile(baselineTriggerPath, mockTriggerContent);
});

beforeEach(() => {
Expand All @@ -51,8 +52,8 @@ describe('main', () => {

after(async () => {
await rm(sfdxConfigFile);
await rm('force-app/main/default/classes/AccountProfile.cls');
await rm('packaged/triggers/AccountTrigger.trigger');
await rm(baselineClassPath);
await rm(baselineTriggerPath);
await rm('force-app', { recursive: true });
await rm('packaged', { recursive: true });
await rm(coverageXmlPath1);
Expand Down
Loading

0 comments on commit 9859d23

Please sign in to comment.