Skip to content

Commit

Permalink
feat: add support for flows
Browse files Browse the repository at this point in the history
  • Loading branch information
mcarvin8 committed Feb 7, 2024
1 parent 8bbcc9a commit 6bf0da1
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 4 deletions.
85 changes: 83 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

[![NPM](https://img.shields.io/npm/v/apex-code-coverage-transformer.svg?label=apex-code-coverage-transformer)](https://www.npmjs.com/package/apex-code-coverage-transformer) [![Downloads/week](https://img.shields.io/npm/dw/apex-code-coverage-transformer.svg)](https://npmjs.org/package/apex-code-coverage-transformer) [![License](https://img.shields.io/badge/License-MIT-yellow.svg)](https://raw.githubusercontent.com/mcarvin8/apex-code-coverage-transformer/main/LICENSE.md)

The `apex-code-coverage-transformer` is a simple plugin to transform the JSON file for Apex Code Coverage into Generic Test Coverage Format (XML). This format is accepted by static code analysis tools like SonarQube.
The `apex-code-coverage-transformer` is a simple Salesforce CLI plugin to transform the Apex Code Coverage JSON file into Generic Test Coverage Format (XML). This format is accepted by static code analysis tools like SonarQube.

Here is how you can create the JSON file with the Salesforce CLI:
This plugin supports code coverage metrics created for Apex Classes, Apex Triggers, and Flows (if flows are deployed as active in your org).

Here is how you can create the Code Coverage JSON file with the Salesforce CLI:

```
sf project deploy validate -x manifest/package.xml -l RunSpecifiedTests -t {testclasses} --verbose --coverage-formatters json --results-dir coverage
Expand Down Expand Up @@ -200,6 +202,79 @@ A JSON created by the Salesforce CLI :
"81": { "start": { "line": 81, "column": 0 }, "end": { "line": 81, "column": 0 } },
"82": { "start": { "line": 82, "column": 0 }, "end": { "line": 82, "column": 0 } }
}
},
"no-map/Get_Info": {
"fnMap": {},
"branchMap": {},
"path": "no-map/Get_Info",
"f": {},
"b": {},
"s": {
"52": 0,
"53": 0,
"54": 1,
"55": 1,
"56": 1,
"57": 1,
"58": 1,
"59": 0,
"60": 0,
"61": 1,
"62": 1,
"63": 1,
"64": 1,
"65": 1,
"66": 1,
"67": 1,
"68": 1,
"69": 1,
"70": 1,
"71": 1,
"72": 1,
"73": 1,
"74": 1,
"75": 1,
"76": 1,
"77": 1,
"78": 1,
"79": 1,
"80": 1,
"81": 1,
"82": 1
},
"statementMap": {
"52": { "start": { "line": 52, "column": 0 }, "end": { "line": 52, "column": 0 } },
"53": { "start": { "line": 53, "column": 0 }, "end": { "line": 53, "column": 0 } },
"54": { "start": { "line": 54, "column": 0 }, "end": { "line": 54, "column": 0 } },
"55": { "start": { "line": 55, "column": 0 }, "end": { "line": 55, "column": 0 } },
"56": { "start": { "line": 56, "column": 0 }, "end": { "line": 56, "column": 0 } },
"57": { "start": { "line": 57, "column": 0 }, "end": { "line": 57, "column": 0 } },
"58": { "start": { "line": 58, "column": 0 }, "end": { "line": 58, "column": 0 } },
"59": { "start": { "line": 59, "column": 0 }, "end": { "line": 59, "column": 0 } },
"60": { "start": { "line": 60, "column": 0 }, "end": { "line": 60, "column": 0 } },
"61": { "start": { "line": 61, "column": 0 }, "end": { "line": 61, "column": 0 } },
"62": { "start": { "line": 62, "column": 0 }, "end": { "line": 62, "column": 0 } },
"63": { "start": { "line": 63, "column": 0 }, "end": { "line": 63, "column": 0 } },
"64": { "start": { "line": 64, "column": 0 }, "end": { "line": 64, "column": 0 } },
"65": { "start": { "line": 65, "column": 0 }, "end": { "line": 65, "column": 0 } },
"66": { "start": { "line": 66, "column": 0 }, "end": { "line": 66, "column": 0 } },
"67": { "start": { "line": 67, "column": 0 }, "end": { "line": 67, "column": 0 } },
"68": { "start": { "line": 68, "column": 0 }, "end": { "line": 68, "column": 0 } },
"69": { "start": { "line": 69, "column": 0 }, "end": { "line": 69, "column": 0 } },
"70": { "start": { "line": 70, "column": 0 }, "end": { "line": 70, "column": 0 } },
"71": { "start": { "line": 71, "column": 0 }, "end": { "line": 71, "column": 0 } },
"72": { "start": { "line": 72, "column": 0 }, "end": { "line": 72, "column": 0 } },
"73": { "start": { "line": 73, "column": 0 }, "end": { "line": 73, "column": 0 } },
"74": { "start": { "line": 74, "column": 0 }, "end": { "line": 74, "column": 0 } },
"75": { "start": { "line": 75, "column": 0 }, "end": { "line": 75, "column": 0 } },
"76": { "start": { "line": 76, "column": 0 }, "end": { "line": 76, "column": 0 } },
"77": { "start": { "line": 77, "column": 0 }, "end": { "line": 77, "column": 0 } },
"78": { "start": { "line": 78, "column": 0 }, "end": { "line": 78, "column": 0 } },
"79": { "start": { "line": 79, "column": 0 }, "end": { "line": 79, "column": 0 } },
"80": { "start": { "line": 80, "column": 0 }, "end": { "line": 80, "column": 0 } },
"81": { "start": { "line": 81, "column": 0 }, "end": { "line": 81, "column": 0 } },
"82": { "start": { "line": 82, "column": 0 }, "end": { "line": 82, "column": 0 } }
}
}
}
```
Expand All @@ -221,5 +296,11 @@ will be converted to:
<lineToCover lineNumber="59" covered="false"/>
<lineToCover lineNumber="60" covered="false"/>
</file>
<file path="force-app/main/default/flows/Get_Info.flow-meta.xml">
<lineToCover lineNumber="52" covered="false"/>
<lineToCover lineNumber="53" covered="false"/>
<lineToCover lineNumber="59" covered="false"/>
<lineToCover lineNumber="60" covered="false"/>
</file>
</coverage>
```
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
"sfdx",
"sfdx-plugin",
"xml",
"json"
"json",
"sonarqube"
],
"license": "MIT",
"oclif": {
Expand Down
4 changes: 4 additions & 0 deletions src/commands/apex-code-coverage/transformer/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,17 @@ export default class TransformerTransform extends SfCommand<TransformerTransform
function findFilePath(className: string, dxDirectory: string): string | null {
const relativeClassPath = `${dxDirectory}/classes/${className}.cls`;
const relativeTriggerPath = `${dxDirectory}/triggers/${className}.trigger`;
const relativeFlowPath = `${dxDirectory}/flows/${className}.flow-meta.xml`;

const absoluteClassPath = path.resolve(relativeClassPath);
const absoluteTriggerPath = path.resolve(relativeTriggerPath);
const absoluteFlowPath = path.resolve(relativeFlowPath);
if (fs.existsSync(absoluteClassPath)) {
return relativeClassPath;
} else if (fs.existsSync(absoluteTriggerPath)) {
return relativeTriggerPath;
} else if (fs.existsSync(absoluteFlowPath)) {
return relativeFlowPath;
} else {
throw Error(`The file name ${className} was not found in the classes or triggers directory.`);
}
Expand Down
2 changes: 1 addition & 1 deletion test.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"no-map/AccountTrigger": {"fnMap":{},"branchMap":{},"path":"no-map/AccountTrigger","f":{},"b":{},"s":{"52":0,"53":0,"54":1,"55":1,"56":1,"57":1,"58":1,"59":0,"60":0,"61":1,"62":1,"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"73":1,"74":1,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1},"statementMap":{"52":{"start":{"line":52,"column":0},"end":{"line":52,"column":0}},"53":{"start":{"line":53,"column":0},"end":{"line":53,"column":0}},"54":{"start":{"line":54,"column":0},"end":{"line":54,"column":0}},"55":{"start":{"line":55,"column":0},"end":{"line":55,"column":0}},"56":{"start":{"line":56,"column":0},"end":{"line":56,"column":0}},"57":{"start":{"line":57,"column":0},"end":{"line":57,"column":0}},"58":{"start":{"line":58,"column":0},"end":{"line":58,"column":0}},"59":{"start":{"line":59,"column":0},"end":{"line":59,"column":0}},"60":{"start":{"line":60,"column":0},"end":{"line":60,"column":0}},"61":{"start":{"line":61,"column":0},"end":{"line":61,"column":0}},"62":{"start":{"line":62,"column":0},"end":{"line":62,"column":0}},"63":{"start":{"line":63,"column":0},"end":{"line":63,"column":0}},"64":{"start":{"line":64,"column":0},"end":{"line":64,"column":0}},"65":{"start":{"line":65,"column":0},"end":{"line":65,"column":0}},"66":{"start":{"line":66,"column":0},"end":{"line":66,"column":0}},"67":{"start":{"line":67,"column":0},"end":{"line":67,"column":0}},"68":{"start":{"line":68,"column":0},"end":{"line":68,"column":0}},"69":{"start":{"line":69,"column":0},"end":{"line":69,"column":0}},"70":{"start":{"line":70,"column":0},"end":{"line":70,"column":0}},"71":{"start":{"line":71,"column":0},"end":{"line":71,"column":0}},"72":{"start":{"line":72,"column":0},"end":{"line":72,"column":0}},"73":{"start":{"line":73,"column":0},"end":{"line":73,"column":0}},"74":{"start":{"line":74,"column":0},"end":{"line":74,"column":0}},"75":{"start":{"line":75,"column":0},"end":{"line":75,"column":0}},"76":{"start":{"line":76,"column":0},"end":{"line":76,"column":0}},"77":{"start":{"line":77,"column":0},"end":{"line":77,"column":0}},"78":{"start":{"line":78,"column":0},"end":{"line":78,"column":0}},"79":{"start":{"line":79,"column":0},"end":{"line":79,"column":0}},"80":{"start":{"line":80,"column":0},"end":{"line":80,"column":0}},"81":{"start":{"line":81,"column":0},"end":{"line":81,"column":0}},"82":{"start":{"line":82,"column":0},"end":{"line":82,"column":0}}}}, "no-map/AccountProfile": {"fnMap":{},"branchMap":{},"path":"no-map/AccountProfile","f":{},"b":{},"s":{"52":0,"53":0,"54":1,"55":1,"56":1,"57":1,"58":1,"59":0,"60":0,"61":1,"62":1,"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"73":1,"74":1,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1},"statementMap":{"52":{"start":{"line":52,"column":0},"end":{"line":52,"column":0}},"53":{"start":{"line":53,"column":0},"end":{"line":53,"column":0}},"54":{"start":{"line":54,"column":0},"end":{"line":54,"column":0}},"55":{"start":{"line":55,"column":0},"end":{"line":55,"column":0}},"56":{"start":{"line":56,"column":0},"end":{"line":56,"column":0}},"57":{"start":{"line":57,"column":0},"end":{"line":57,"column":0}},"58":{"start":{"line":58,"column":0},"end":{"line":58,"column":0}},"59":{"start":{"line":59,"column":0},"end":{"line":59,"column":0}},"60":{"start":{"line":60,"column":0},"end":{"line":60,"column":0}},"61":{"start":{"line":61,"column":0},"end":{"line":61,"column":0}},"62":{"start":{"line":62,"column":0},"end":{"line":62,"column":0}},"63":{"start":{"line":63,"column":0},"end":{"line":63,"column":0}},"64":{"start":{"line":64,"column":0},"end":{"line":64,"column":0}},"65":{"start":{"line":65,"column":0},"end":{"line":65,"column":0}},"66":{"start":{"line":66,"column":0},"end":{"line":66,"column":0}},"67":{"start":{"line":67,"column":0},"end":{"line":67,"column":0}},"68":{"start":{"line":68,"column":0},"end":{"line":68,"column":0}},"69":{"start":{"line":69,"column":0},"end":{"line":69,"column":0}},"70":{"start":{"line":70,"column":0},"end":{"line":70,"column":0}},"71":{"start":{"line":71,"column":0},"end":{"line":71,"column":0}},"72":{"start":{"line":72,"column":0},"end":{"line":72,"column":0}},"73":{"start":{"line":73,"column":0},"end":{"line":73,"column":0}},"74":{"start":{"line":74,"column":0},"end":{"line":74,"column":0}},"75":{"start":{"line":75,"column":0},"end":{"line":75,"column":0}},"76":{"start":{"line":76,"column":0},"end":{"line":76,"column":0}},"77":{"start":{"line":77,"column":0},"end":{"line":77,"column":0}},"78":{"start":{"line":78,"column":0},"end":{"line":78,"column":0}},"79":{"start":{"line":79,"column":0},"end":{"line":79,"column":0}},"80":{"start":{"line":80,"column":0},"end":{"line":80,"column":0}},"81":{"start":{"line":81,"column":0},"end":{"line":81,"column":0}},"82":{"start":{"line":82,"column":0},"end":{"line":82,"column":0}}}}}
{"no-map/AccountTrigger": {"fnMap":{},"branchMap":{},"path":"no-map/AccountTrigger","f":{},"b":{},"s":{"52":0,"53":0,"54":1,"55":1,"56":1,"57":1,"58":1,"59":0,"60":0,"61":1,"62":1,"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"73":1,"74":1,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1},"statementMap":{"52":{"start":{"line":52,"column":0},"end":{"line":52,"column":0}},"53":{"start":{"line":53,"column":0},"end":{"line":53,"column":0}},"54":{"start":{"line":54,"column":0},"end":{"line":54,"column":0}},"55":{"start":{"line":55,"column":0},"end":{"line":55,"column":0}},"56":{"start":{"line":56,"column":0},"end":{"line":56,"column":0}},"57":{"start":{"line":57,"column":0},"end":{"line":57,"column":0}},"58":{"start":{"line":58,"column":0},"end":{"line":58,"column":0}},"59":{"start":{"line":59,"column":0},"end":{"line":59,"column":0}},"60":{"start":{"line":60,"column":0},"end":{"line":60,"column":0}},"61":{"start":{"line":61,"column":0},"end":{"line":61,"column":0}},"62":{"start":{"line":62,"column":0},"end":{"line":62,"column":0}},"63":{"start":{"line":63,"column":0},"end":{"line":63,"column":0}},"64":{"start":{"line":64,"column":0},"end":{"line":64,"column":0}},"65":{"start":{"line":65,"column":0},"end":{"line":65,"column":0}},"66":{"start":{"line":66,"column":0},"end":{"line":66,"column":0}},"67":{"start":{"line":67,"column":0},"end":{"line":67,"column":0}},"68":{"start":{"line":68,"column":0},"end":{"line":68,"column":0}},"69":{"start":{"line":69,"column":0},"end":{"line":69,"column":0}},"70":{"start":{"line":70,"column":0},"end":{"line":70,"column":0}},"71":{"start":{"line":71,"column":0},"end":{"line":71,"column":0}},"72":{"start":{"line":72,"column":0},"end":{"line":72,"column":0}},"73":{"start":{"line":73,"column":0},"end":{"line":73,"column":0}},"74":{"start":{"line":74,"column":0},"end":{"line":74,"column":0}},"75":{"start":{"line":75,"column":0},"end":{"line":75,"column":0}},"76":{"start":{"line":76,"column":0},"end":{"line":76,"column":0}},"77":{"start":{"line":77,"column":0},"end":{"line":77,"column":0}},"78":{"start":{"line":78,"column":0},"end":{"line":78,"column":0}},"79":{"start":{"line":79,"column":0},"end":{"line":79,"column":0}},"80":{"start":{"line":80,"column":0},"end":{"line":80,"column":0}},"81":{"start":{"line":81,"column":0},"end":{"line":81,"column":0}},"82":{"start":{"line":82,"column":0},"end":{"line":82,"column":0}}}}, "no-map/AccountProfile": {"fnMap":{},"branchMap":{},"path":"no-map/AccountProfile","f":{},"b":{},"s":{"52":0,"53":0,"54":1,"55":1,"56":1,"57":1,"58":1,"59":0,"60":0,"61":1,"62":1,"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"73":1,"74":1,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1},"statementMap":{"52":{"start":{"line":52,"column":0},"end":{"line":52,"column":0}},"53":{"start":{"line":53,"column":0},"end":{"line":53,"column":0}},"54":{"start":{"line":54,"column":0},"end":{"line":54,"column":0}},"55":{"start":{"line":55,"column":0},"end":{"line":55,"column":0}},"56":{"start":{"line":56,"column":0},"end":{"line":56,"column":0}},"57":{"start":{"line":57,"column":0},"end":{"line":57,"column":0}},"58":{"start":{"line":58,"column":0},"end":{"line":58,"column":0}},"59":{"start":{"line":59,"column":0},"end":{"line":59,"column":0}},"60":{"start":{"line":60,"column":0},"end":{"line":60,"column":0}},"61":{"start":{"line":61,"column":0},"end":{"line":61,"column":0}},"62":{"start":{"line":62,"column":0},"end":{"line":62,"column":0}},"63":{"start":{"line":63,"column":0},"end":{"line":63,"column":0}},"64":{"start":{"line":64,"column":0},"end":{"line":64,"column":0}},"65":{"start":{"line":65,"column":0},"end":{"line":65,"column":0}},"66":{"start":{"line":66,"column":0},"end":{"line":66,"column":0}},"67":{"start":{"line":67,"column":0},"end":{"line":67,"column":0}},"68":{"start":{"line":68,"column":0},"end":{"line":68,"column":0}},"69":{"start":{"line":69,"column":0},"end":{"line":69,"column":0}},"70":{"start":{"line":70,"column":0},"end":{"line":70,"column":0}},"71":{"start":{"line":71,"column":0},"end":{"line":71,"column":0}},"72":{"start":{"line":72,"column":0},"end":{"line":72,"column":0}},"73":{"start":{"line":73,"column":0},"end":{"line":73,"column":0}},"74":{"start":{"line":74,"column":0},"end":{"line":74,"column":0}},"75":{"start":{"line":75,"column":0},"end":{"line":75,"column":0}},"76":{"start":{"line":76,"column":0},"end":{"line":76,"column":0}},"77":{"start":{"line":77,"column":0},"end":{"line":77,"column":0}},"78":{"start":{"line":78,"column":0},"end":{"line":78,"column":0}},"79":{"start":{"line":79,"column":0},"end":{"line":79,"column":0}},"80":{"start":{"line":80,"column":0},"end":{"line":80,"column":0}},"81":{"start":{"line":81,"column":0},"end":{"line":81,"column":0}},"82":{"start":{"line":82,"column":0},"end":{"line":82,"column":0}}}},"no-map/Get_Info": {"fnMap":{},"branchMap":{},"path":"no-map/Get_Info","f":{},"b":{},"s":{"52":0,"53":0,"54":1,"55":1,"56":1,"57":1,"58":1,"59":0,"60":0,"61":1,"62":1,"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"73":1,"74":1,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1},"statementMap":{"52":{"start":{"line":52,"column":0},"end":{"line":52,"column":0}},"53":{"start":{"line":53,"column":0},"end":{"line":53,"column":0}},"54":{"start":{"line":54,"column":0},"end":{"line":54,"column":0}},"55":{"start":{"line":55,"column":0},"end":{"line":55,"column":0}},"56":{"start":{"line":56,"column":0},"end":{"line":56,"column":0}},"57":{"start":{"line":57,"column":0},"end":{"line":57,"column":0}},"58":{"start":{"line":58,"column":0},"end":{"line":58,"column":0}},"59":{"start":{"line":59,"column":0},"end":{"line":59,"column":0}},"60":{"start":{"line":60,"column":0},"end":{"line":60,"column":0}},"61":{"start":{"line":61,"column":0},"end":{"line":61,"column":0}},"62":{"start":{"line":62,"column":0},"end":{"line":62,"column":0}},"63":{"start":{"line":63,"column":0},"end":{"line":63,"column":0}},"64":{"start":{"line":64,"column":0},"end":{"line":64,"column":0}},"65":{"start":{"line":65,"column":0},"end":{"line":65,"column":0}},"66":{"start":{"line":66,"column":0},"end":{"line":66,"column":0}},"67":{"start":{"line":67,"column":0},"end":{"line":67,"column":0}},"68":{"start":{"line":68,"column":0},"end":{"line":68,"column":0}},"69":{"start":{"line":69,"column":0},"end":{"line":69,"column":0}},"70":{"start":{"line":70,"column":0},"end":{"line":70,"column":0}},"71":{"start":{"line":71,"column":0},"end":{"line":71,"column":0}},"72":{"start":{"line":72,"column":0},"end":{"line":72,"column":0}},"73":{"start":{"line":73,"column":0},"end":{"line":73,"column":0}},"74":{"start":{"line":74,"column":0},"end":{"line":74,"column":0}},"75":{"start":{"line":75,"column":0},"end":{"line":75,"column":0}},"76":{"start":{"line":76,"column":0},"end":{"line":76,"column":0}},"77":{"start":{"line":77,"column":0},"end":{"line":77,"column":0}},"78":{"start":{"line":78,"column":0},"end":{"line":78,"column":0}},"79":{"start":{"line":79,"column":0},"end":{"line":79,"column":0}},"80":{"start":{"line":80,"column":0},"end":{"line":80,"column":0}},"81":{"start":{"line":81,"column":0},"end":{"line":81,"column":0}},"82":{"start":{"line":82,"column":0},"end":{"line":82,"column":0}}}}}
5 changes: 5 additions & 0 deletions test/commands/transformer/unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ describe('transform the code coverage json', () => {
// Mock file contents
const mockClassContent = '// Test Apex Class';
const mockTriggerContent = '// Test Apex Trigger';
const mockFlowContent = '<!-- Test Flow -->';

// Create mock files
before(() => {
fs.mkdirSync('force-app/main/default/classes', { recursive: true });
fs.mkdirSync('force-app/main/default/triggers', { recursive: true });
fs.mkdirSync('force-app/main/default/flows', { recursive: true });
fs.writeFileSync('force-app/main/default/classes/AccountProfile.cls', mockClassContent);
fs.writeFileSync('force-app/main/default/triggers/AccountTrigger.trigger', mockTriggerContent);
fs.writeFileSync('force-app/main/default/flows/Get_Info.flow-meta.xml', mockFlowContent);
});

beforeEach(() => {
Expand All @@ -38,8 +41,10 @@ describe('transform the code coverage json', () => {
after(() => {
fs.unlinkSync('force-app/main/default/classes/AccountProfile.cls');
fs.unlinkSync('force-app/main/default/triggers/AccountTrigger.trigger');
fs.unlinkSync('force-app/main/default/flows/Get_Info.flow-meta.xml');
fs.rmdirSync('force-app/main/default/classes');
fs.rmdirSync('force-app/main/default/triggers');
fs.rmdirSync('force-app/main/default/flows');
});

it('transform the test JSON file into the generic test coverage format', async () => {
Expand Down

0 comments on commit 6bf0da1

Please sign in to comment.