apex-code-coverage-transformer 1.6.0-beta.1 → 1.6.1-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,7 +16,7 @@ This will create a coverage JSON in this relative path - `coverage/coverage/cove
16
16
 
17
17
  This JSON isn't accepted by SonarQube automatically and needs to be converted using this plugin.
18
18
 
19
- **Note**: This has been tested and confirmed on code which meets 100% coverage.
19
+ **Disclaimer**: Due to existing bugs with how the Salesforce CLI reports `covered` lines (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, 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). Once Salesforce updates the API to correctly return `covered` lines in the deploy command, this function will be removed.
20
20
 
21
21
  ## Install
22
22
 
@@ -65,18 +65,99 @@ This [code coverage JSON file](https://raw.githubusercontent.com/mcarvin8/apex-c
65
65
  <lineToCover lineNumber="53" covered="false"/>
66
66
  <lineToCover lineNumber="59" covered="false"/>
67
67
  <lineToCover lineNumber="60" covered="false"/>
68
+ <lineToCover lineNumber="1" covered="true"/>
69
+ <lineToCover lineNumber="2" covered="true"/>
70
+ <lineToCover lineNumber="3" covered="true"/>
71
+ <lineToCover lineNumber="4" covered="true"/>
72
+ <lineToCover lineNumber="5" covered="true"/>
73
+ <lineToCover lineNumber="6" covered="true"/>
74
+ <lineToCover lineNumber="7" covered="true"/>
75
+ <lineToCover lineNumber="8" covered="true"/>
76
+ <lineToCover lineNumber="9" covered="true"/>
77
+ <lineToCover lineNumber="10" covered="true"/>
78
+ <lineToCover lineNumber="11" covered="true"/>
79
+ <lineToCover lineNumber="12" covered="true"/>
80
+ <lineToCover lineNumber="13" covered="true"/>
81
+ <lineToCover lineNumber="14" covered="true"/>
82
+ <lineToCover lineNumber="15" covered="true"/>
83
+ <lineToCover lineNumber="16" covered="true"/>
84
+ <lineToCover lineNumber="17" covered="true"/>
85
+ <lineToCover lineNumber="18" covered="true"/>
86
+ <lineToCover lineNumber="19" covered="true"/>
87
+ <lineToCover lineNumber="20" covered="true"/>
88
+ <lineToCover lineNumber="21" covered="true"/>
89
+ <lineToCover lineNumber="22" covered="true"/>
90
+ <lineToCover lineNumber="23" covered="true"/>
91
+ <lineToCover lineNumber="24" covered="true"/>
92
+ <lineToCover lineNumber="25" covered="true"/>
93
+ <lineToCover lineNumber="26" covered="true"/>
94
+ <lineToCover lineNumber="27" covered="true"/>
68
95
  </file>
69
96
  <file path="force-app\main\default\classes\AccountProfile.cls">
70
97
  <lineToCover lineNumber="52" covered="false"/>
71
98
  <lineToCover lineNumber="53" covered="false"/>
72
99
  <lineToCover lineNumber="59" covered="false"/>
73
100
  <lineToCover lineNumber="60" covered="false"/>
101
+ <lineToCover lineNumber="54" covered="true"/>
102
+ <lineToCover lineNumber="55" covered="true"/>
103
+ <lineToCover lineNumber="56" covered="true"/>
104
+ <lineToCover lineNumber="57" covered="true"/>
105
+ <lineToCover lineNumber="58" covered="true"/>
106
+ <lineToCover lineNumber="61" covered="true"/>
107
+ <lineToCover lineNumber="62" covered="true"/>
108
+ <lineToCover lineNumber="63" covered="true"/>
109
+ <lineToCover lineNumber="64" covered="true"/>
110
+ <lineToCover lineNumber="65" covered="true"/>
111
+ <lineToCover lineNumber="66" covered="true"/>
112
+ <lineToCover lineNumber="67" covered="true"/>
113
+ <lineToCover lineNumber="68" covered="true"/>
114
+ <lineToCover lineNumber="69" covered="true"/>
115
+ <lineToCover lineNumber="70" covered="true"/>
116
+ <lineToCover lineNumber="71" covered="true"/>
117
+ <lineToCover lineNumber="72" covered="true"/>
118
+ <lineToCover lineNumber="1" covered="true"/>
119
+ <lineToCover lineNumber="2" covered="true"/>
120
+ <lineToCover lineNumber="3" covered="true"/>
121
+ <lineToCover lineNumber="4" covered="true"/>
122
+ <lineToCover lineNumber="5" covered="true"/>
123
+ <lineToCover lineNumber="6" covered="true"/>
124
+ <lineToCover lineNumber="7" covered="true"/>
125
+ <lineToCover lineNumber="8" covered="true"/>
126
+ <lineToCover lineNumber="9" covered="true"/>
127
+ <lineToCover lineNumber="10" covered="true"/>
74
128
  </file>
75
- <file path="force-app\main\default\flows\Get_Info.flow-meta.xml">
129
+ <file path="packaged\flows\Get_Info.flow-meta.xml">
76
130
  <lineToCover lineNumber="52" covered="false"/>
77
131
  <lineToCover lineNumber="53" covered="false"/>
78
132
  <lineToCover lineNumber="59" covered="false"/>
79
133
  <lineToCover lineNumber="60" covered="false"/>
134
+ <lineToCover lineNumber="54" covered="true"/>
135
+ <lineToCover lineNumber="55" covered="true"/>
136
+ <lineToCover lineNumber="56" covered="true"/>
137
+ <lineToCover lineNumber="57" covered="true"/>
138
+ <lineToCover lineNumber="58" covered="true"/>
139
+ <lineToCover lineNumber="61" covered="true"/>
140
+ <lineToCover lineNumber="62" covered="true"/>
141
+ <lineToCover lineNumber="63" covered="true"/>
142
+ <lineToCover lineNumber="64" covered="true"/>
143
+ <lineToCover lineNumber="65" covered="true"/>
144
+ <lineToCover lineNumber="66" covered="true"/>
145
+ <lineToCover lineNumber="67" covered="true"/>
146
+ <lineToCover lineNumber="68" covered="true"/>
147
+ <lineToCover lineNumber="69" covered="true"/>
148
+ <lineToCover lineNumber="70" covered="true"/>
149
+ <lineToCover lineNumber="71" covered="true"/>
150
+ <lineToCover lineNumber="72" covered="true"/>
151
+ <lineToCover lineNumber="73" covered="true"/>
152
+ <lineToCover lineNumber="74" covered="true"/>
153
+ <lineToCover lineNumber="75" covered="true"/>
154
+ <lineToCover lineNumber="76" covered="true"/>
155
+ <lineToCover lineNumber="77" covered="true"/>
156
+ <lineToCover lineNumber="78" covered="true"/>
157
+ <lineToCover lineNumber="79" covered="true"/>
158
+ <lineToCover lineNumber="80" covered="true"/>
159
+ <lineToCover lineNumber="81" covered="true"/>
160
+ <lineToCover lineNumber="82" covered="true"/>
80
161
  </file>
81
162
  </coverage>
82
163
  ```
@@ -2,7 +2,6 @@
2
2
  /* eslint-disable no-await-in-loop */
3
3
  import * as fs from 'node:fs';
4
4
  import * as path from 'node:path';
5
- import { findSubFolder } from './findSubFolder.js';
6
5
  import { getPackageDirectories } from './getPackageDirectories.js';
7
6
  export async function findFilePath(fileName, dxConfigFile) {
8
7
  const packageDirectories = await getPackageDirectories(dxConfigFile);
@@ -15,49 +14,40 @@ export async function findFilePath(fileName, dxConfigFile) {
15
14
  }
16
15
  return filePath;
17
16
  }
18
- async function findFilePathinDirectory(fileName, dxDirectory) {
19
- const fileExtension = fileName.split('.').slice(1).join('.');
20
- let relativeClassPath = await findSubFolder(dxDirectory, 'classes');
21
- let relativeTriggerPath = await findSubFolder(dxDirectory, 'triggers');
22
- let relativeFlowPath = await findSubFolder(dxDirectory, 'flows');
23
- let absoluteClassPath = '';
24
- let absoluteTriggerPath = '';
25
- let absoluteFlowPath = '';
26
- // if file extension is found, use that to determine paths
27
- if (fileExtension === 'cls' && relativeClassPath !== undefined) {
28
- absoluteClassPath = path.resolve(relativeClassPath, fileName);
29
- if (fs.existsSync(absoluteClassPath)) {
30
- return path.join(relativeClassPath, fileName);
31
- }
32
- }
33
- else if (fileExtension === 'trigger' && relativeTriggerPath !== undefined) {
34
- absoluteTriggerPath = path.resolve(relativeTriggerPath, fileName);
35
- if (fs.existsSync(absoluteTriggerPath)) {
36
- return path.join(relativeTriggerPath, fileName);
17
+ async function searchRecursively(fileName, dxDirectory) {
18
+ const files = await fs.promises.readdir(dxDirectory);
19
+ for (const file of files) {
20
+ const filePath = path.join(dxDirectory, file);
21
+ const stats = await fs.promises.stat(filePath);
22
+ if (stats.isDirectory()) {
23
+ const result = await searchRecursively(fileName, filePath);
24
+ if (result) {
25
+ return result;
26
+ }
37
27
  }
38
- }
39
- else if (fileExtension === 'flow-meta.xml' && relativeFlowPath !== undefined) {
40
- absoluteFlowPath = path.resolve(relativeFlowPath, fileName);
41
- if (fs.existsSync(absoluteFlowPath)) {
42
- return path.join(relativeFlowPath, fileName);
28
+ else if (file === fileName) {
29
+ return filePath;
43
30
  }
44
31
  }
45
- // if file extension is not found, add file extensions manually and test paths
46
- relativeClassPath = path.join(relativeClassPath, `${fileName}.cls`);
47
- relativeTriggerPath = path.join(relativeTriggerPath, `${fileName}.trigger`);
48
- relativeFlowPath = path.join(relativeFlowPath, `${fileName}.flow-meta.xml`);
49
- absoluteClassPath = path.resolve(relativeClassPath);
50
- absoluteTriggerPath = path.resolve(relativeTriggerPath);
51
- absoluteFlowPath = path.resolve(relativeFlowPath);
52
- if (fs.existsSync(absoluteClassPath)) {
53
- return relativeClassPath;
54
- }
55
- else if (fs.existsSync(absoluteTriggerPath)) {
56
- return relativeTriggerPath;
32
+ return undefined;
33
+ }
34
+ async function findFilePathinDirectory(fileName, dxDirectory) {
35
+ const fileExtension = fileName.split('.').slice(1).join('.');
36
+ let relativeFilePath;
37
+ if (fileExtension) {
38
+ // If file extension is defined, search recursively with that extension
39
+ relativeFilePath = await searchRecursively(fileName, dxDirectory);
57
40
  }
58
- else if (fs.existsSync(absoluteFlowPath)) {
59
- return relativeFlowPath;
41
+ else {
42
+ // If file extension is not defined, test each extension option
43
+ const fileExts = ['cls', 'trigger', 'flow-meta.xml'];
44
+ for (const ext of fileExts) {
45
+ relativeFilePath = await searchRecursively(`${fileName}.${ext}`, dxDirectory);
46
+ if (relativeFilePath !== undefined) {
47
+ break;
48
+ }
49
+ }
60
50
  }
61
- return undefined;
51
+ return relativeFilePath;
62
52
  }
63
53
  //# sourceMappingURL=findFilePath.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"findFilePath.js","sourceRoot":"","sources":["../../src/helpers/findFilePath.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"findFilePath.js","sourceRoot":"","sources":["../../src/helpers/findFilePath.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,qCAAqC;AAErC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB,EAAE,YAAoB;IACvE,MAAM,kBAAkB,GAAG,MAAM,qBAAqB,CAAC,YAAY,CAAC,CAAC;IAErE,IAAI,QAA4B,CAAC;IACjC,KAAK,MAAM,SAAS,IAAI,kBAAkB,EAAE,CAAC;QAC3C,QAAQ,GAAG,MAAM,uBAAuB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAC9D,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,MAAM;QACR,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,QAAgB,EAAE,WAAmB;IACpE,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACrD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAC3D,IAAI,MAAM,EAAE,CAAC;gBACX,OAAO,MAAM,CAAC;YAChB,CAAC;QACH,CAAC;aAAM,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,OAAO,QAAQ,CAAC;QAClB,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,KAAK,UAAU,uBAAuB,CAAC,QAAgB,EAAE,WAAmB;IAC1E,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7D,IAAI,gBAAoC,CAAC;IAEzC,IAAI,aAAa,EAAE,CAAC;QAClB,uEAAuE;QACvE,gBAAgB,GAAG,MAAM,iBAAiB,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IACpE,CAAC;SAAM,CAAC;QACN,+DAA+D;QAC/D,MAAM,QAAQ,GAAa,CAAC,KAAK,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;QAC/D,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC3B,gBAAgB,GAAG,MAAM,iBAAiB,CAAC,GAAG,QAAQ,IAAI,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;YAC9E,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;gBACnC,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,gBAAgB,CAAC;AAC1B,CAAC"}
@@ -73,5 +73,5 @@
73
73
  ]
74
74
  }
75
75
  },
76
- "version": "1.6.0-beta.1"
76
+ "version": "1.6.1-beta.1"
77
77
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "apex-code-coverage-transformer",
3
3
  "description": "Transforms the Apex Code Coverage JSON into the Generic Test Data Report.",
4
- "version": "1.6.0-beta.1",
4
+ "version": "1.6.1-beta.1",
5
5
  "dependencies": {
6
6
  "@oclif/core": "^3.18.1",
7
7
  "@salesforce/core": "^6.4.7",
@@ -1 +0,0 @@
1
- export declare function findSubFolder(parentDirectory: string, subFolderName: string): Promise<string>;
@@ -1,25 +0,0 @@
1
- 'use strict';
2
- /* eslint-disable no-await-in-loop */
3
- import * as path from 'node:path';
4
- import * as promises from 'node:fs/promises';
5
- export async function findSubFolder(parentDirectory, subFolderName) {
6
- const files = await promises.readdir(parentDirectory);
7
- // Check if current directory contains the sub-folder
8
- if (files.includes(subFolderName)) {
9
- return path.join(parentDirectory, subFolderName);
10
- }
11
- // Recursively search sub-directories
12
- for (const file of files) {
13
- const filePath = path.join(parentDirectory, file);
14
- const stats = await promises.stat(filePath);
15
- if (stats.isDirectory()) {
16
- const subFolderPath = await findSubFolder(filePath, subFolderName);
17
- if (subFolderPath) {
18
- return subFolderPath;
19
- }
20
- }
21
- }
22
- // must be a string for the file-path check
23
- return 'undefined';
24
- }
25
- //# sourceMappingURL=findSubFolder.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"findSubFolder.js","sourceRoot":"","sources":["../../src/helpers/findSubFolder.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,qCAAqC;AAErC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,eAAuB,EAAE,aAAqB;IAChF,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAEtD,qDAAqD;IACrD,IAAI,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;IACnD,CAAC;IAED,qCAAqC;IACrC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;QAClD,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,aAAa,GAAG,MAAM,aAAa,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;YACnE,IAAI,aAAa,EAAE,CAAC;gBAClB,OAAO,aAAa,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IAED,2CAA2C;IAC3C,OAAO,WAAW,CAAC;AACrB,CAAC"}