@starci/jest-preset 2.3.1 → 2.3.2
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 +3 -0
- package/index.cjs +11 -5
- package/merge.cjs +45 -0
- package/package.json +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.3.2 - 2026-10-18
|
|
4
|
+
- Added: shard mode `STARCI_COVERAGE_SHARD=1` (only the loaded files are measured, no per-file threshold, istanbul JSON) and `@starci/jest-preset/merge` (istanbul-lib-coverage merge by source location, lcov through the preset reporter): the coverage job of the sharded managed CI.
|
|
5
|
+
|
|
3
6
|
## 2.3.1 - 2026-10-18
|
|
4
7
|
|
|
5
8
|
- Fixed: coverage excludes only compiler-emitted constructor `design:paramtypes` metadata guards injected by the preset transform; application source is never excluded, and the generated anchor is omitted from LCOV.
|
package/index.cjs
CHANGED
|
@@ -223,15 +223,21 @@ function starciJestConfig(options) {
|
|
|
223
223
|
if (hasCoverageSubjects(root, `src/tests/${name}/**/*.${suffix}.ts`)) testProjects.push(suite(name, suffix))
|
|
224
224
|
}
|
|
225
225
|
}
|
|
226
|
+
// A shard of the managed CI (STARCI_COVERAGE_SHARD=1, one of npm test -- --shard=i/N) measures only the files its tests load, without the per-file threshold, and
|
|
227
|
+
// writes istanbul JSON: the coverage job merges the shards by source location (merge.cjs) and the coverage proof enforces 100 per file on the merged report. The
|
|
228
|
+
// all-files instrumentation of collectCoverageFrom is off there: it instruments an unloaded file with another transform (other functions and branches).
|
|
229
|
+
const shard = process.env.STARCI_COVERAGE_SHARD === "1"
|
|
226
230
|
return {
|
|
227
231
|
testTimeout: 120_000,
|
|
228
232
|
coverageProvider: "v8",
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
233
|
+
...(shard ? {} : {
|
|
234
|
+
collectCoverageFrom: collectCoverageFrom(coverage),
|
|
235
|
+
// A glob key is applied to every matching file on its own: each measured file must reach 100, not the average.
|
|
236
|
+
coverageThreshold: Object.fromEntries(coverage.roots.map((root) => rootGlob(root, coverage.roles)).filter((glob) => hasCoverageSubjects(process.cwd(), glob)).map((glob) => [`./${glob}`, { ...COVERAGE_THRESHOLD }])),
|
|
237
|
+
}),
|
|
232
238
|
coverageDirectory: "coverage",
|
|
233
|
-
// lcov is what Sonar imports (coverage/lcov.info); text-summary and text are what the developer reads.
|
|
234
|
-
coverageReporters: ["text-summary", "text", [require.resolve("./lcov.cjs"), {}]],
|
|
239
|
+
// lcov is what Sonar imports (coverage/lcov.info); text-summary and text are what the developer reads; a shard writes the json the merge reads.
|
|
240
|
+
coverageReporters: shard ? ["text-summary", "json"] : ["text-summary", "text", [require.resolve("./lcov.cjs"), {}]],
|
|
235
241
|
projects: [
|
|
236
242
|
{
|
|
237
243
|
...shared,
|
package/merge.cjs
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
|
|
3
|
+
// merge.cjs - the coverage of a sharded unit run merged into the one report the coverage proof, Codecov and Sonar read (`starci app coverage merge`).
|
|
4
|
+
// Each shard runs with STARCI_COVERAGE_SHARD=1 (starciJestConfig): it measures ONLY the files its tests load (no collectCoverageFrom all-files
|
|
5
|
+
// instrumentation, whose fallback transform gives an unloaded file another function and branch set) and writes istanbul JSON (coverage-final.json).
|
|
6
|
+
// The maps of one file come from the same v8 transform in every shard; istanbul-lib-coverage merges them by source location (FileCoverage.merge), and the
|
|
7
|
+
// merged map is written as lcov through this preset's own lcov reporter (lcov.cjs: stable function ids, the generated metadata source left out), exactly
|
|
8
|
+
// as an unsharded run writes it. A measured file no shard loaded is absent from the merged map: the coverage proof refuses it (no lcov record, 0%).
|
|
9
|
+
const fs = require("node:fs")
|
|
10
|
+
const path = require("node:path")
|
|
11
|
+
const { createRequire } = require("node:module")
|
|
12
|
+
|
|
13
|
+
const fromJest = createRequire(require.resolve("jest"))
|
|
14
|
+
const fromCore = createRequire(fromJest.resolve("@jest/core"))
|
|
15
|
+
const fromReporters = createRequire(fromCore.resolve("@jest/reporters"))
|
|
16
|
+
const libCoverage = fromReporters("istanbul-lib-coverage")
|
|
17
|
+
const libReport = fromReporters("istanbul-lib-report")
|
|
18
|
+
const StarciLcovReport = require("./lcov.cjs")
|
|
19
|
+
|
|
20
|
+
/** Every coverage-final.json at or below `target` (a file or a directory), sorted. */
|
|
21
|
+
function coverageFilesUnder(target) {
|
|
22
|
+
if (!fs.statSync(target).isDirectory()) return [target]
|
|
23
|
+
return fs.readdirSync(target, { recursive: true, withFileTypes: true })
|
|
24
|
+
.filter((entry) => entry.isFile() && entry.name === "coverage-final.json")
|
|
25
|
+
.map((entry) => path.join(entry.parentPath ?? entry.path, entry.name))
|
|
26
|
+
.sort()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Merge the shard reports `inputs` (coverage-final.json files or directories holding them) and write `<outDir>/lcov.info` and `<outDir>/coverage-final.json`.
|
|
31
|
+
* Returns { reports, files }; throws when no report is found (an empty merge would read as "nothing to measure").
|
|
32
|
+
*/
|
|
33
|
+
function mergeCoverage({ inputs, outDir }) {
|
|
34
|
+
const reports = inputs.flatMap((input) => coverageFilesUnder(input))
|
|
35
|
+
if (!reports.length) throw new Error(`no coverage-final.json under ${inputs.join(", ")}: the unit shards wrote none (run them with STARCI_COVERAGE_SHARD=1)`)
|
|
36
|
+
const map = libCoverage.createCoverageMap({})
|
|
37
|
+
for (const report of reports) map.merge(JSON.parse(fs.readFileSync(report, "utf8")))
|
|
38
|
+
fs.mkdirSync(outDir, { recursive: true })
|
|
39
|
+
fs.writeFileSync(path.join(outDir, "coverage-final.json"), JSON.stringify(map.toJSON()))
|
|
40
|
+
const context = libReport.createContext({ dir: outDir, coverageMap: map })
|
|
41
|
+
new StarciLcovReport({ file: "lcov.info", projectRoot: process.cwd() }).execute(context)
|
|
42
|
+
return { reports: reports.length, files: map.files().length }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = { mergeCoverage, coverageFilesUnder }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@starci/jest-preset",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.2",
|
|
4
4
|
"description": "The StarCi jest config for Nest repositories (unit, integration, e2e and contract projects, ts-jest with diagnostics off, per-file 100 coverage of *.service.ts only) and the one shared unit-test double kit: typed mock<T>(), mockEntityManager(), fakeTransaction(), fakeCache(), fakeLock(), recordingEventBus(), recordingQueueOutbox(), fakeInbox(), FakeClock, fakeIds(), builder() and the Outcome matchers toBeRefused/toSucceedWith.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
@@ -54,6 +54,9 @@
|
|
|
54
54
|
"./builders": {
|
|
55
55
|
"types": "./builders.d.ts",
|
|
56
56
|
"default": "./builders.cjs"
|
|
57
|
+
},
|
|
58
|
+
"./merge": {
|
|
59
|
+
"default": "./merge.cjs"
|
|
57
60
|
}
|
|
58
61
|
},
|
|
59
62
|
"files": [
|