apex-code-coverage-transformer 2.13.3 → 2.14.0
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/CHANGELOG.md +14 -0
- package/README.md +276 -9
- package/lib/handlers/BaseHandler.d.ts +51 -0
- package/lib/handlers/BaseHandler.js +63 -0
- package/lib/handlers/BaseHandler.js.map +1 -0
- package/lib/handlers/HandlerRegistry.d.ts +90 -0
- package/lib/handlers/HandlerRegistry.js +103 -0
- package/lib/handlers/HandlerRegistry.js.map +1 -0
- package/lib/handlers/clover.d.ts +16 -2
- package/lib/handlers/clover.js +35 -16
- package/lib/handlers/clover.js.map +1 -1
- package/lib/handlers/cobertura.d.ts +11 -2
- package/lib/handlers/cobertura.js +23 -11
- package/lib/handlers/cobertura.js.map +1 -1
- package/lib/handlers/getHandler.d.ts +24 -0
- package/lib/handlers/getHandler.js +27 -19
- package/lib/handlers/getHandler.js.map +1 -1
- package/lib/handlers/istanbulJson.d.ts +18 -2
- package/lib/handlers/istanbulJson.js +28 -1
- package/lib/handlers/istanbulJson.js.map +1 -1
- package/lib/handlers/jacoco.d.ts +18 -2
- package/lib/handlers/jacoco.js +27 -1
- package/lib/handlers/jacoco.js.map +1 -1
- package/lib/handlers/jsonSummary.d.ts +49 -0
- package/lib/handlers/jsonSummary.js +103 -0
- package/lib/handlers/jsonSummary.js.map +1 -0
- package/lib/handlers/lcov.d.ts +17 -2
- package/lib/handlers/lcov.js +29 -9
- package/lib/handlers/lcov.js.map +1 -1
- package/lib/handlers/opencover.d.ts +71 -0
- package/lib/handlers/opencover.js +165 -0
- package/lib/handlers/opencover.js.map +1 -0
- package/lib/handlers/simplecov.d.ts +50 -0
- package/lib/handlers/simplecov.js +83 -0
- package/lib/handlers/simplecov.js.map +1 -0
- package/lib/handlers/sonar.d.ts +10 -2
- package/lib/handlers/sonar.js +20 -2
- package/lib/handlers/sonar.js.map +1 -1
- package/lib/hooks/finally.d.ts +2 -0
- package/lib/hooks/{postrun.js → finally.js} +5 -4
- package/lib/hooks/finally.js.map +1 -0
- package/lib/transformers/reportGenerator.d.ts +2 -2
- package/lib/transformers/reportGenerator.js +7 -8
- package/lib/transformers/reportGenerator.js.map +1 -1
- package/lib/utils/constants.d.ts +5 -0
- package/lib/utils/constants.js +8 -1
- package/lib/utils/constants.js.map +1 -1
- package/lib/utils/types.d.ts +78 -1
- package/oclif.lock +2697 -3086
- package/oclif.manifest.json +8 -5
- package/package.json +2 -2
- package/lib/hooks/postrun.d.ts +0 -2
- package/lib/hooks/postrun.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,20 @@
|
|
|
5
5
|
|
|
6
6
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
7
7
|
|
|
8
|
+
## [2.14.0](https://github.com/mcarvin8/apex-code-coverage-transformer/compare/v2.13.4...v2.14.0) (2025-10-27)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* add json-summary, simplecov, and opencover coverage formats ([#231](https://github.com/mcarvin8/apex-code-coverage-transformer/issues/231)) ([9da086f](https://github.com/mcarvin8/apex-code-coverage-transformer/commit/9da086f212cbdd98184f8c873792b8da882815db))
|
|
14
|
+
|
|
15
|
+
## [2.13.4](https://github.com/mcarvin8/apex-code-coverage-transformer/compare/v2.13.3...v2.13.4) (2025-10-27)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* change oclif hook from postrun to finally ([#229](https://github.com/mcarvin8/apex-code-coverage-transformer/issues/229)) ([27bb6d6](https://github.com/mcarvin8/apex-code-coverage-transformer/commit/27bb6d62d85b616130e11398fedd7fff614f9fe3))
|
|
21
|
+
|
|
8
22
|
## [2.13.3](https://github.com/mcarvin8/apex-code-coverage-transformer/compare/v2.13.2...v2.13.3) (2025-07-14)
|
|
9
23
|
|
|
10
24
|
|
package/README.md
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
<summary>Table of Contents</summary>
|
|
13
13
|
|
|
14
14
|
- [Install](#install)
|
|
15
|
+
- [Quick Start](#quick-start)
|
|
15
16
|
- [Usage](#usage)
|
|
16
17
|
- [Salesforce CLI](#salesforce-cli)
|
|
17
18
|
- [SFDX Hardis](#sfdx-hardis)
|
|
@@ -19,6 +20,11 @@
|
|
|
19
20
|
- [Command](#command)
|
|
20
21
|
- [`sf acc-transformer transform`](#sf-acc-transformer-transform)
|
|
21
22
|
- [Coverage Report Formats](#coverage-report-formats)
|
|
23
|
+
- [CI/CD Integration Examples](#cicd-integration-examples)
|
|
24
|
+
- [Codecov](#codecov)
|
|
25
|
+
- [SonarQube](#sonarqube)
|
|
26
|
+
- [GitHub Actions](#github-actions)
|
|
27
|
+
- [GitLab CI](#gitlab-ci)
|
|
22
28
|
- [Hook](#hook)
|
|
23
29
|
- [Troubleshooting](#troubleshooting)
|
|
24
30
|
- [Issues](#issues)
|
|
@@ -26,7 +32,7 @@
|
|
|
26
32
|
- [License](#license)
|
|
27
33
|
</details>
|
|
28
34
|
|
|
29
|
-
Transform the Salesforce Apex code coverage JSON files created during deployments and test runs into other [formats](#coverage-report-formats) accepted by SonarQube, GitHub, GitLab, Azure, Bitbucket, etc.
|
|
35
|
+
Transform the Salesforce Apex code coverage JSON files created during deployments and test runs into other [formats](#coverage-report-formats) accepted by SonarQube, Codecov, GitHub, GitLab, Azure, Bitbucket, etc.
|
|
30
36
|
|
|
31
37
|
> If there's a coverage format not yet supported by this plugin, feel free to provide a pull request or issue for the coverage format.
|
|
32
38
|
|
|
@@ -36,6 +42,51 @@ Transform the Salesforce Apex code coverage JSON files created during deployment
|
|
|
36
42
|
sf plugins install apex-code-coverage-transformer@x.y.z
|
|
37
43
|
```
|
|
38
44
|
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
1. **Generate Salesforce code coverage in JSON format**:
|
|
48
|
+
|
|
49
|
+
**Option A - Run Apex tests directly**:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
sf apex run test --code-coverage --output-dir "coverage"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Option B - Deploy/validate with coverage**:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
sf project deploy start --coverage-formatters json --results-dir "coverage"
|
|
59
|
+
# or for validation
|
|
60
|
+
sf project deploy validate --coverage-formatters json --results-dir "coverage"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
2. **Transform the coverage to your desired format**:
|
|
64
|
+
|
|
65
|
+
**For test command** (creates `coverage/test-result-codecoverage.json`):
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# For SonarQube
|
|
69
|
+
sf acc-transformer transform -j "coverage/test-result-codecoverage.json" -r "coverage.xml" -f "sonar"
|
|
70
|
+
|
|
71
|
+
# For Codecov
|
|
72
|
+
sf acc-transformer transform -j "coverage/test-result-codecoverage.json" -r "coverage.xml" -f "cobertura"
|
|
73
|
+
|
|
74
|
+
# For multiple formats at once
|
|
75
|
+
sf acc-transformer transform -j "coverage/test-result-codecoverage.json" -f "sonar" -f "cobertura" -f "jacoco"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**For deploy command** (creates `coverage/coverage/coverage.json`):
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# For SonarQube
|
|
82
|
+
sf acc-transformer transform -j "coverage/coverage/coverage.json" -r "coverage.xml" -f "sonar"
|
|
83
|
+
|
|
84
|
+
# For Codecov
|
|
85
|
+
sf acc-transformer transform -j "coverage/coverage/coverage.json" -r "coverage.xml" -f "cobertura"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
3. **Upload to your coverage tool** (see [CI/CD Integration Examples](#cicd-integration-examples) for platform-specific instructions).
|
|
89
|
+
|
|
39
90
|
## Usage
|
|
40
91
|
|
|
41
92
|
This plugin is designed for users deploying Apex or running Apex tests within Salesforce DX projects (`sfdx-project.json`). It transforms Salesforce CLI JSON coverage reports into formats recognized by external tools.
|
|
@@ -126,6 +177,18 @@ EXAMPLES
|
|
|
126
177
|
|
|
127
178
|
$ sf acc-transformer transform -j "coverage.json" -r "coverage.info" -f "lcovonly"
|
|
128
179
|
|
|
180
|
+
Transform the JSON into JSON Summary format:
|
|
181
|
+
|
|
182
|
+
$ sf acc-transformer transform -j "coverage.json" -r "coverage.json" -f "json-summary"
|
|
183
|
+
|
|
184
|
+
Transform the JSON into SimpleCov format:
|
|
185
|
+
|
|
186
|
+
$ sf acc-transformer transform -j "coverage.json" -r "coverage.json" -f "simplecov"
|
|
187
|
+
|
|
188
|
+
Transform the JSON into OpenCover format:
|
|
189
|
+
|
|
190
|
+
$ sf acc-transformer transform -j "coverage.json" -r "coverage.xml" -f "opencover"
|
|
191
|
+
|
|
129
192
|
Transform the JSON into Sonar format, ignoring Apex in the "force-app" directory:
|
|
130
193
|
|
|
131
194
|
$ sf acc-transformer transform -j "coverage.json" -i "force-app"
|
|
@@ -137,14 +200,218 @@ The `-f`/`--format` flag allows you to specify the format of the transformed cov
|
|
|
137
200
|
|
|
138
201
|
You can provide multiple `--format` flags in a single command to create multiple reports. If multiple `--format` flags are provided, each output report will have the format appended to the name. For example, if `--output-report` is set `coverage.xml` and you supply `--format sonar --format cobertura` to the command, the output reports will be `coverage-sonar.xml` and `coverage-cobertura.xml`.
|
|
139
202
|
|
|
140
|
-
|
|
|
141
|
-
|
|
|
142
|
-
| [sonar](https://raw.githubusercontent.com/mcarvin8/apex-code-coverage-transformer/main/baselines/sonar_baseline.xml)
|
|
143
|
-
| [
|
|
144
|
-
| [
|
|
145
|
-
| [
|
|
146
|
-
| [
|
|
147
|
-
| [json](https://raw.githubusercontent.com/mcarvin8/apex-code-coverage-transformer/main/baselines/json_baseline.json)
|
|
203
|
+
| Format | Description | Compatible Platforms/Tools |
|
|
204
|
+
| ----------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ---------------------------------------------------------- |
|
|
205
|
+
| [sonar](https://raw.githubusercontent.com/mcarvin8/apex-code-coverage-transformer/main/baselines/sonar_baseline.xml) | Generates a SonarQube-compatible coverage report. This is the default option. | SonarQube, SonarCloud |
|
|
206
|
+
| [cobertura](https://raw.githubusercontent.com/mcarvin8/apex-code-coverage-transformer/main/baselines/cobertura_baseline.xml) | Creates a Cobertura XML report, a widely used format for coverage reporting. | **Codecov**, Azure DevOps, Jenkins, GitLab, GitHub Actions |
|
|
207
|
+
| [jacoco](https://raw.githubusercontent.com/mcarvin8/apex-code-coverage-transformer/main/baselines/jacoco_baseline.xml) | Creates a JaCoCo XML report, the standard for Java projects. | **Codecov**, Jenkins, Maven, Gradle |
|
|
208
|
+
| [lcovonly](https://raw.githubusercontent.com/mcarvin8/apex-code-coverage-transformer/main/baselines/lcov_baseline.info) | Outputs coverage data in LCOV format, useful for integrating with LCOV-based tools. | Codecov, Coveralls, GitHub Actions |
|
|
209
|
+
| [clover](https://raw.githubusercontent.com/mcarvin8/apex-code-coverage-transformer/main/baselines/clover_baseline.xml) | Produces a Clover XML report format, commonly used with Atlassian tools. | Bamboo, Bitbucket, Jenkins |
|
|
210
|
+
| [json](https://raw.githubusercontent.com/mcarvin8/apex-code-coverage-transformer/main/baselines/json_baseline.json) | Generates a Istanbul JSON report compatible with Node.js tooling and coverage visualizers. | Istanbul/NYC, Codecov, custom tools |
|
|
211
|
+
| [json-summary](https://raw.githubusercontent.com/mcarvin8/apex-code-coverage-transformer/main/baselines/json-summary_baseline.json) | Generates a concise JSON summary ideal for badges, PR comments, and quick analysis. | GitHub Actions, GitLab CI, Custom Dashboards |
|
|
212
|
+
| [simplecov](https://raw.githubusercontent.com/mcarvin8/apex-code-coverage-transformer/main/baselines/simplecov_baseline.json) | Generates SimpleCov JSON format compatible with Ruby coverage tools. | Codecov, SimpleCov, Ruby Tools |
|
|
213
|
+
| [opencover](https://raw.githubusercontent.com/mcarvin8/apex-code-coverage-transformer/main/baselines/opencover_baseline.xml) | Generates OpenCover XML format for .NET and Azure DevOps integration. | Azure DevOps, Visual Studio, Codecov, JetBrains Tools |
|
|
214
|
+
|
|
215
|
+
## CI/CD Integration Examples
|
|
216
|
+
|
|
217
|
+
### Codecov
|
|
218
|
+
|
|
219
|
+
Codecov accepts multiple formats including Cobertura, JaCoCo, and LCOV. Cobertura is recommended for its wide compatibility.
|
|
220
|
+
|
|
221
|
+
**Using Codecov CLI**:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
# Generate Salesforce coverage
|
|
225
|
+
sf apex run test --code-coverage --output-dir "coverage"
|
|
226
|
+
|
|
227
|
+
# Transform to Cobertura format
|
|
228
|
+
sf acc-transformer transform -j "coverage/test-result-codecoverage.json" -r "coverage.xml" -f "cobertura"
|
|
229
|
+
|
|
230
|
+
# Upload to Codecov
|
|
231
|
+
codecovcli upload-process --file coverage.xml
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
**Using Codecov GitHub Action**:
|
|
235
|
+
|
|
236
|
+
```yaml
|
|
237
|
+
name: Salesforce CI with Codecov
|
|
238
|
+
|
|
239
|
+
on: [push, pull_request]
|
|
240
|
+
|
|
241
|
+
jobs:
|
|
242
|
+
test:
|
|
243
|
+
runs-on: ubuntu-latest
|
|
244
|
+
steps:
|
|
245
|
+
- uses: actions/checkout@v4
|
|
246
|
+
|
|
247
|
+
- name: Install Salesforce CLI
|
|
248
|
+
run: npm install -g @salesforce/cli
|
|
249
|
+
|
|
250
|
+
- name: Install Coverage Transformer Plugin
|
|
251
|
+
run: sf plugins install apex-code-coverage-transformer
|
|
252
|
+
|
|
253
|
+
- name: Authenticate to Salesforce
|
|
254
|
+
run: sf org login sfdx-url --sfdx-url-file ${{ secrets.SFDX_AUTH_URL }} --alias ci-org
|
|
255
|
+
|
|
256
|
+
- name: Run Apex Tests
|
|
257
|
+
run: sf apex run test --code-coverage --output-dir coverage --target-org ci-org
|
|
258
|
+
|
|
259
|
+
- name: Transform Coverage to Cobertura
|
|
260
|
+
run: sf acc-transformer transform -j "coverage/test-result-codecoverage.json" -r "coverage.xml" -f "cobertura"
|
|
261
|
+
|
|
262
|
+
- name: Upload to Codecov
|
|
263
|
+
uses: codecov/codecov-action@v4
|
|
264
|
+
with:
|
|
265
|
+
files: ./coverage.xml
|
|
266
|
+
flags: apex
|
|
267
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### SonarQube
|
|
271
|
+
|
|
272
|
+
SonarQube requires its own Generic Coverage format (Sonar format).
|
|
273
|
+
|
|
274
|
+
**SonarQube Scanner Example**:
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
# Generate and transform coverage
|
|
278
|
+
sf apex run test --code-coverage --output-dir "coverage"
|
|
279
|
+
sf acc-transformer transform -j "coverage/test-result-codecoverage.json" -r "coverage.xml" -f "sonar"
|
|
280
|
+
|
|
281
|
+
# Run SonarQube scanner
|
|
282
|
+
sonar-scanner \
|
|
283
|
+
-Dsonar.projectKey=your-project-key \
|
|
284
|
+
-Dsonar.sources=force-app \
|
|
285
|
+
-Dsonar.tests=force-app \
|
|
286
|
+
-Dsonar.test.inclusions=**/*Test.cls \
|
|
287
|
+
-Dsonar.apex.coverage.reportPath=coverage.xml \
|
|
288
|
+
-Dsonar.host.url=https://sonarqube.example.com \
|
|
289
|
+
-Dsonar.login=$SONAR_TOKEN
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
**SonarCloud GitHub Action**:
|
|
293
|
+
|
|
294
|
+
```yaml
|
|
295
|
+
name: SonarCloud Analysis
|
|
296
|
+
|
|
297
|
+
on: [push, pull_request]
|
|
298
|
+
|
|
299
|
+
jobs:
|
|
300
|
+
sonarcloud:
|
|
301
|
+
runs-on: ubuntu-latest
|
|
302
|
+
steps:
|
|
303
|
+
- uses: actions/checkout@v4
|
|
304
|
+
with:
|
|
305
|
+
fetch-depth: 0
|
|
306
|
+
|
|
307
|
+
- name: Install Salesforce CLI
|
|
308
|
+
run: npm install -g @salesforce/cli
|
|
309
|
+
|
|
310
|
+
- name: Install Coverage Transformer Plugin
|
|
311
|
+
run: sf plugins install apex-code-coverage-transformer
|
|
312
|
+
|
|
313
|
+
- name: Authenticate to Salesforce
|
|
314
|
+
run: sf org login sfdx-url --sfdx-url-file ${{ secrets.SFDX_AUTH_URL }} --alias ci-org
|
|
315
|
+
|
|
316
|
+
- name: Run Apex Tests
|
|
317
|
+
run: sf apex run test --code-coverage --output-dir coverage --target-org ci-org
|
|
318
|
+
|
|
319
|
+
- name: Transform Coverage to Sonar Format
|
|
320
|
+
run: sf acc-transformer transform -j "coverage/test-result-codecoverage.json" -r "coverage.xml" -f "sonar"
|
|
321
|
+
|
|
322
|
+
- name: SonarCloud Scan
|
|
323
|
+
uses: SonarSource/sonarcloud-github-action@master
|
|
324
|
+
env:
|
|
325
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
326
|
+
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
|
327
|
+
with:
|
|
328
|
+
args: >
|
|
329
|
+
-Dsonar.projectKey=your-project-key
|
|
330
|
+
-Dsonar.organization=your-org
|
|
331
|
+
-Dsonar.sources=force-app
|
|
332
|
+
-Dsonar.tests=force-app
|
|
333
|
+
-Dsonar.test.inclusions=**/*Test.cls
|
|
334
|
+
-Dsonar.apex.coverage.reportPath=coverage.xml
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### GitHub Actions
|
|
338
|
+
|
|
339
|
+
GitHub Actions can display coverage using various formats. Use Cobertura or LCOV for best compatibility.
|
|
340
|
+
|
|
341
|
+
**With Coverage Report Action**:
|
|
342
|
+
|
|
343
|
+
```yaml
|
|
344
|
+
name: Salesforce CI with Coverage Report
|
|
345
|
+
|
|
346
|
+
on: [push, pull_request]
|
|
347
|
+
|
|
348
|
+
jobs:
|
|
349
|
+
test:
|
|
350
|
+
runs-on: ubuntu-latest
|
|
351
|
+
steps:
|
|
352
|
+
- uses: actions/checkout@v4
|
|
353
|
+
|
|
354
|
+
- name: Install Salesforce CLI
|
|
355
|
+
run: npm install -g @salesforce/cli
|
|
356
|
+
|
|
357
|
+
- name: Install Coverage Transformer Plugin
|
|
358
|
+
run: sf plugins install apex-code-coverage-transformer
|
|
359
|
+
|
|
360
|
+
- name: Authenticate to Salesforce
|
|
361
|
+
run: sf org login sfdx-url --sfdx-url-file ${{ secrets.SFDX_AUTH_URL }} --alias ci-org
|
|
362
|
+
|
|
363
|
+
- name: Run Apex Tests
|
|
364
|
+
run: sf apex run test --code-coverage --output-dir coverage --target-org ci-org
|
|
365
|
+
|
|
366
|
+
- name: Transform Coverage to Cobertura
|
|
367
|
+
run: sf acc-transformer transform -j "coverage/test-result-codecoverage.json" -r "coverage.xml" -f "cobertura"
|
|
368
|
+
|
|
369
|
+
- name: Code Coverage Report
|
|
370
|
+
uses: irongut/CodeCoverageSummary@v1.3.0
|
|
371
|
+
with:
|
|
372
|
+
filename: coverage.xml
|
|
373
|
+
badge: true
|
|
374
|
+
format: markdown
|
|
375
|
+
output: both
|
|
376
|
+
|
|
377
|
+
- name: Add Coverage PR Comment
|
|
378
|
+
uses: marocchino/sticky-pull-request-comment@v2
|
|
379
|
+
if: github.event_name == 'pull_request'
|
|
380
|
+
with:
|
|
381
|
+
recreate: true
|
|
382
|
+
path: code-coverage-results.md
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### GitLab CI
|
|
386
|
+
|
|
387
|
+
GitLab supports Cobertura format natively for coverage visualization.
|
|
388
|
+
|
|
389
|
+
**`.gitlab-ci.yml` Example**:
|
|
390
|
+
|
|
391
|
+
```yaml
|
|
392
|
+
stages:
|
|
393
|
+
- test
|
|
394
|
+
|
|
395
|
+
apex-tests:
|
|
396
|
+
stage: test
|
|
397
|
+
image: node:20
|
|
398
|
+
before_script:
|
|
399
|
+
- npm install -g @salesforce/cli
|
|
400
|
+
- sf plugins install apex-code-coverage-transformer
|
|
401
|
+
- echo $SFDX_AUTH_URL | sf org login sfdx-url --sfdx-url-stdin --alias ci-org
|
|
402
|
+
script:
|
|
403
|
+
- sf apex run test --code-coverage --output-dir coverage --target-org ci-org
|
|
404
|
+
- sf acc-transformer transform -j "coverage/test-result-codecoverage.json" -r "coverage.xml" -f "cobertura"
|
|
405
|
+
coverage: '/TOTAL.*\s+(\d+%)$/'
|
|
406
|
+
artifacts:
|
|
407
|
+
reports:
|
|
408
|
+
coverage_report:
|
|
409
|
+
coverage_format: cobertura
|
|
410
|
+
path: coverage.xml
|
|
411
|
+
paths:
|
|
412
|
+
- coverage/
|
|
413
|
+
expire_in: 30 days
|
|
414
|
+
```
|
|
148
415
|
|
|
149
416
|
## Hook
|
|
150
417
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { CoverageHandler, SonarCoverageObject, CoberturaCoverageObject, CloverCoverageObject, LcovCoverageObject, JaCoCoCoverageObject, IstanbulCoverageObject, JsonSummaryCoverageObject, SimpleCovCoverageObject, OpenCoverCoverageObject } from '../utils/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Abstract base class for coverage handlers providing common utilities.
|
|
4
|
+
* Reduces code duplication across different format handlers.
|
|
5
|
+
*/
|
|
6
|
+
export declare abstract class BaseHandler implements CoverageHandler {
|
|
7
|
+
/**
|
|
8
|
+
* Calculate line coverage metrics from a lines record.
|
|
9
|
+
*
|
|
10
|
+
* @param lines - Record of line numbers to hit counts
|
|
11
|
+
* @returns Coverage metrics including totals and rates
|
|
12
|
+
*/
|
|
13
|
+
protected calculateCoverage(lines: Record<string, number>): {
|
|
14
|
+
totalLines: number;
|
|
15
|
+
coveredLines: number;
|
|
16
|
+
uncoveredLines: number;
|
|
17
|
+
lineRate: number;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Extract line numbers by coverage status.
|
|
21
|
+
*
|
|
22
|
+
* @param lines - Record of line numbers to hit counts
|
|
23
|
+
* @param covered - True to get covered lines, false for uncovered
|
|
24
|
+
* @returns Sorted array of line numbers
|
|
25
|
+
*/
|
|
26
|
+
protected extractLinesByStatus(lines: Record<string, number>, covered: boolean): number[];
|
|
27
|
+
/**
|
|
28
|
+
* Get covered and uncovered line numbers from a lines record.
|
|
29
|
+
*
|
|
30
|
+
* @param lines - Record of line numbers to hit counts
|
|
31
|
+
* @returns Object with covered and uncovered line arrays
|
|
32
|
+
*/
|
|
33
|
+
protected getCoveredAndUncovered(lines: Record<string, number>): {
|
|
34
|
+
covered: number[];
|
|
35
|
+
uncovered: number[];
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Sort array of objects by their path property.
|
|
39
|
+
* Handles various path property names (@path, @filename, @name).
|
|
40
|
+
*
|
|
41
|
+
* @param items - Array of objects to sort
|
|
42
|
+
* @returns Sorted array
|
|
43
|
+
*/
|
|
44
|
+
protected sortByPath<T extends {
|
|
45
|
+
'@path'?: string;
|
|
46
|
+
'@filename'?: string;
|
|
47
|
+
'@name'?: string;
|
|
48
|
+
}>(items: T[]): T[];
|
|
49
|
+
abstract processFile(filePath: string, fileName: string, lines: Record<string, number>): void;
|
|
50
|
+
abstract finalize(): SonarCoverageObject | CoberturaCoverageObject | CloverCoverageObject | LcovCoverageObject | JaCoCoCoverageObject | IstanbulCoverageObject | JsonSummaryCoverageObject | SimpleCovCoverageObject | OpenCoverCoverageObject;
|
|
51
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* Abstract base class for coverage handlers providing common utilities.
|
|
4
|
+
* Reduces code duplication across different format handlers.
|
|
5
|
+
*/
|
|
6
|
+
export class BaseHandler {
|
|
7
|
+
/**
|
|
8
|
+
* Calculate line coverage metrics from a lines record.
|
|
9
|
+
*
|
|
10
|
+
* @param lines - Record of line numbers to hit counts
|
|
11
|
+
* @returns Coverage metrics including totals and rates
|
|
12
|
+
*/
|
|
13
|
+
// eslint-disable-next-line class-methods-use-this
|
|
14
|
+
calculateCoverage(lines) {
|
|
15
|
+
const uncoveredLines = Object.values(lines).filter((hits) => hits === 0).length;
|
|
16
|
+
const coveredLines = Object.values(lines).filter((hits) => hits > 0).length;
|
|
17
|
+
const totalLines = uncoveredLines + coveredLines;
|
|
18
|
+
const lineRate = totalLines > 0 ? coveredLines / totalLines : 0;
|
|
19
|
+
return { totalLines, coveredLines, uncoveredLines, lineRate };
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Extract line numbers by coverage status.
|
|
23
|
+
*
|
|
24
|
+
* @param lines - Record of line numbers to hit counts
|
|
25
|
+
* @param covered - True to get covered lines, false for uncovered
|
|
26
|
+
* @returns Sorted array of line numbers
|
|
27
|
+
*/
|
|
28
|
+
// eslint-disable-next-line class-methods-use-this
|
|
29
|
+
extractLinesByStatus(lines, covered) {
|
|
30
|
+
return Object.entries(lines)
|
|
31
|
+
.filter(([, hits]) => (covered ? hits > 0 : hits === 0))
|
|
32
|
+
.map(([line]) => Number(line))
|
|
33
|
+
.sort((a, b) => a - b);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get covered and uncovered line numbers from a lines record.
|
|
37
|
+
*
|
|
38
|
+
* @param lines - Record of line numbers to hit counts
|
|
39
|
+
* @returns Object with covered and uncovered line arrays
|
|
40
|
+
*/
|
|
41
|
+
getCoveredAndUncovered(lines) {
|
|
42
|
+
return {
|
|
43
|
+
covered: this.extractLinesByStatus(lines, true),
|
|
44
|
+
uncovered: this.extractLinesByStatus(lines, false),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Sort array of objects by their path property.
|
|
49
|
+
* Handles various path property names (@path, @filename, @name).
|
|
50
|
+
*
|
|
51
|
+
* @param items - Array of objects to sort
|
|
52
|
+
* @returns Sorted array
|
|
53
|
+
*/
|
|
54
|
+
// eslint-disable-next-line class-methods-use-this
|
|
55
|
+
sortByPath(items) {
|
|
56
|
+
return items.sort((a, b) => {
|
|
57
|
+
const pathA = a['@path'] ?? a['@filename'] ?? a['@name'] ?? '';
|
|
58
|
+
const pathB = b['@path'] ?? b['@filename'] ?? b['@name'] ?? '';
|
|
59
|
+
return pathA.localeCompare(pathB);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=BaseHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseHandler.js","sourceRoot":"","sources":["../../src/handlers/BaseHandler.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAeb;;;GAGG;AACH,MAAM,OAAgB,WAAW;IAC/B;;;;;OAKG;IACH,kDAAkD;IACxC,iBAAiB,CAAC,KAA6B;QAMvD,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QAChF,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;QAC5E,MAAM,UAAU,GAAG,cAAc,GAAG,YAAY,CAAC;QACjD,MAAM,QAAQ,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QAEhE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC;IAChE,CAAC;IAED;;;;;;OAMG;IACH,kDAAkD;IACxC,oBAAoB,CAAC,KAA6B,EAAE,OAAgB;QAC5E,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;aACzB,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC;aACvD,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;aAC7B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,CAAC;IAED;;;;;OAKG;IACO,sBAAsB,CAAC,KAA6B;QAI5D,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAC;YAC/C,SAAS,EAAE,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,KAAK,CAAC;SACnD,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,kDAAkD;IACxC,UAAU,CAAyE,KAAU;QACrG,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACzB,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAC/D,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAC/D,OAAO,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;IACL,CAAC;CAcF"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { CoverageHandler } from '../utils/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Registration information for a coverage format handler.
|
|
4
|
+
*/
|
|
5
|
+
export type HandlerRegistration = {
|
|
6
|
+
/** Format identifier (e.g., 'sonar', 'cobertura') */
|
|
7
|
+
name: string;
|
|
8
|
+
/** Human-readable description of the format */
|
|
9
|
+
description: string;
|
|
10
|
+
/** File extension for this format (e.g., '.xml', '.json', '.info') */
|
|
11
|
+
fileExtension: string;
|
|
12
|
+
/** Factory function to create a new handler instance */
|
|
13
|
+
handler: () => CoverageHandler;
|
|
14
|
+
/** List of platforms/tools compatible with this format */
|
|
15
|
+
compatibleWith?: string[];
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Registry for coverage format handlers.
|
|
19
|
+
* Provides a centralized system for registering and retrieving format handlers.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* // Register a handler
|
|
24
|
+
* HandlerRegistry.register({
|
|
25
|
+
* name: 'myformat',
|
|
26
|
+
* description: 'My custom format',
|
|
27
|
+
* fileExtension: '.xml',
|
|
28
|
+
* handler: () => new MyFormatHandler(),
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* // Retrieve a handler
|
|
32
|
+
* const handler = HandlerRegistry.get('myformat');
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare class HandlerRegistry {
|
|
36
|
+
private static handlers;
|
|
37
|
+
/**
|
|
38
|
+
* Register a new format handler.
|
|
39
|
+
*
|
|
40
|
+
* @param registration - Handler registration information
|
|
41
|
+
* @throws Error if a handler with the same name is already registered
|
|
42
|
+
*/
|
|
43
|
+
static register(registration: HandlerRegistration): void;
|
|
44
|
+
/**
|
|
45
|
+
* Get a handler instance for the specified format.
|
|
46
|
+
*
|
|
47
|
+
* @param format - Format identifier
|
|
48
|
+
* @returns New handler instance
|
|
49
|
+
* @throws Error if format is not supported
|
|
50
|
+
*/
|
|
51
|
+
static get(format: string): CoverageHandler;
|
|
52
|
+
/**
|
|
53
|
+
* Get list of all registered format names.
|
|
54
|
+
*
|
|
55
|
+
* @returns Array of format identifiers
|
|
56
|
+
*/
|
|
57
|
+
static getAvailableFormats(): string[];
|
|
58
|
+
/**
|
|
59
|
+
* Get file extension for a format.
|
|
60
|
+
*
|
|
61
|
+
* @param format - Format identifier
|
|
62
|
+
* @returns File extension including the dot (e.g., '.xml')
|
|
63
|
+
*/
|
|
64
|
+
static getExtension(format: string): string;
|
|
65
|
+
/**
|
|
66
|
+
* Get description for a format.
|
|
67
|
+
*
|
|
68
|
+
* @param format - Format identifier
|
|
69
|
+
* @returns Human-readable description
|
|
70
|
+
*/
|
|
71
|
+
static getDescription(format: string): string;
|
|
72
|
+
/**
|
|
73
|
+
* Get compatible platforms for a format.
|
|
74
|
+
*
|
|
75
|
+
* @param format - Format identifier
|
|
76
|
+
* @returns Array of compatible platform names
|
|
77
|
+
*/
|
|
78
|
+
static getCompatiblePlatforms(format: string): string[];
|
|
79
|
+
/**
|
|
80
|
+
* Check if a format is registered.
|
|
81
|
+
*
|
|
82
|
+
* @param format - Format identifier
|
|
83
|
+
* @returns True if format is registered
|
|
84
|
+
*/
|
|
85
|
+
static has(format: string): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Clear all registered handlers (primarily for testing).
|
|
88
|
+
*/
|
|
89
|
+
static clear(): void;
|
|
90
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* Registry for coverage format handlers.
|
|
4
|
+
* Provides a centralized system for registering and retrieving format handlers.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* // Register a handler
|
|
9
|
+
* HandlerRegistry.register({
|
|
10
|
+
* name: 'myformat',
|
|
11
|
+
* description: 'My custom format',
|
|
12
|
+
* fileExtension: '.xml',
|
|
13
|
+
* handler: () => new MyFormatHandler(),
|
|
14
|
+
* });
|
|
15
|
+
*
|
|
16
|
+
* // Retrieve a handler
|
|
17
|
+
* const handler = HandlerRegistry.get('myformat');
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export class HandlerRegistry {
|
|
21
|
+
static handlers = new Map();
|
|
22
|
+
/**
|
|
23
|
+
* Register a new format handler.
|
|
24
|
+
*
|
|
25
|
+
* @param registration - Handler registration information
|
|
26
|
+
* @throws Error if a handler with the same name is already registered
|
|
27
|
+
*/
|
|
28
|
+
static register(registration) {
|
|
29
|
+
if (this.handlers.has(registration.name)) {
|
|
30
|
+
throw new Error(`Handler for format '${registration.name}' is already registered`);
|
|
31
|
+
}
|
|
32
|
+
this.handlers.set(registration.name, registration);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Get a handler instance for the specified format.
|
|
36
|
+
*
|
|
37
|
+
* @param format - Format identifier
|
|
38
|
+
* @returns New handler instance
|
|
39
|
+
* @throws Error if format is not supported
|
|
40
|
+
*/
|
|
41
|
+
static get(format) {
|
|
42
|
+
const registration = this.handlers.get(format);
|
|
43
|
+
if (!registration) {
|
|
44
|
+
const available = this.getAvailableFormats().join(', ');
|
|
45
|
+
throw new Error(`Unsupported format: ${format}. Available formats: ${available}`);
|
|
46
|
+
}
|
|
47
|
+
return registration.handler();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get list of all registered format names.
|
|
51
|
+
*
|
|
52
|
+
* @returns Array of format identifiers
|
|
53
|
+
*/
|
|
54
|
+
static getAvailableFormats() {
|
|
55
|
+
return Array.from(this.handlers.keys()).sort();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get file extension for a format.
|
|
59
|
+
*
|
|
60
|
+
* @param format - Format identifier
|
|
61
|
+
* @returns File extension including the dot (e.g., '.xml')
|
|
62
|
+
*/
|
|
63
|
+
static getExtension(format) {
|
|
64
|
+
const registration = this.handlers.get(format);
|
|
65
|
+
return registration?.fileExtension ?? '.xml';
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get description for a format.
|
|
69
|
+
*
|
|
70
|
+
* @param format - Format identifier
|
|
71
|
+
* @returns Human-readable description
|
|
72
|
+
*/
|
|
73
|
+
static getDescription(format) {
|
|
74
|
+
const registration = this.handlers.get(format);
|
|
75
|
+
return registration?.description ?? '';
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Get compatible platforms for a format.
|
|
79
|
+
*
|
|
80
|
+
* @param format - Format identifier
|
|
81
|
+
* @returns Array of compatible platform names
|
|
82
|
+
*/
|
|
83
|
+
static getCompatiblePlatforms(format) {
|
|
84
|
+
const registration = this.handlers.get(format);
|
|
85
|
+
return registration?.compatibleWith ?? [];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Check if a format is registered.
|
|
89
|
+
*
|
|
90
|
+
* @param format - Format identifier
|
|
91
|
+
* @returns True if format is registered
|
|
92
|
+
*/
|
|
93
|
+
static has(format) {
|
|
94
|
+
return this.handlers.has(format);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Clear all registered handlers (primarily for testing).
|
|
98
|
+
*/
|
|
99
|
+
static clear() {
|
|
100
|
+
this.handlers.clear();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=HandlerRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HandlerRegistry.js","sourceRoot":"","sources":["../../src/handlers/HandlerRegistry.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAoBb;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAO,eAAe;IAClB,MAAM,CAAC,QAAQ,GAAG,IAAI,GAAG,EAA+B,CAAC;IAEjE;;;;;OAKG;IACI,MAAM,CAAC,QAAQ,CAAC,YAAiC;QACtD,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CAAC,uBAAuB,YAAY,CAAC,IAAI,yBAAyB,CAAC,CAAC;QACrF,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACrD,CAAC;IAED;;;;;;OAMG;IACI,MAAM,CAAC,GAAG,CAAC,MAAc;QAC9B,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,SAAS,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxD,MAAM,IAAI,KAAK,CAAC,uBAAuB,MAAM,wBAAwB,SAAS,EAAE,CAAC,CAAC;QACpF,CAAC;QACD,OAAO,YAAY,CAAC,OAAO,EAAE,CAAC;IAChC,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,mBAAmB;QAC/B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACjD,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,YAAY,CAAC,MAAc;QACvC,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/C,OAAO,YAAY,EAAE,aAAa,IAAI,MAAM,CAAC;IAC/C,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,cAAc,CAAC,MAAc;QACzC,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/C,OAAO,YAAY,EAAE,WAAW,IAAI,EAAE,CAAC;IACzC,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,sBAAsB,CAAC,MAAc;QACjD,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/C,OAAO,YAAY,EAAE,cAAc,IAAI,EAAE,CAAC;IAC5C,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,GAAG,CAAC,MAAc;QAC9B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,KAAK;QACjB,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC"}
|