phantom-pr 0.2.8 → 0.3.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/bin/phantom-pr.cjs +19 -19
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/plan.d.ts +1 -1
- package/dist/commands/plan.js +74 -1
- package/dist/commands/plan.js.map +1 -1
- package/dist/commands/tests.js +16 -0
- package/dist/commands/tests.js.map +1 -1
- package/dist/core/config/types.d.ts +11 -0
- package/dist/core/config/validate.js +21 -0
- package/dist/core/config/validate.js.map +1 -1
- package/dist/core/coverage/index.d.ts +3 -0
- package/dist/core/coverage/index.js +2 -0
- package/dist/core/coverage/index.js.map +1 -0
- package/dist/core/coverage/jestProvider.d.ts +48 -0
- package/dist/core/coverage/jestProvider.js +144 -0
- package/dist/core/coverage/jestProvider.js.map +1 -0
- package/dist/core/coverage/types.d.ts +39 -0
- package/dist/core/coverage/types.js +2 -0
- package/dist/core/coverage/types.js.map +1 -0
- package/dist/core/generator/smokeGenerator.js +8 -1
- package/dist/core/generator/smokeGenerator.js.map +1 -1
- package/dist/core/generator/types.d.ts +2 -0
- package/dist/core/plan/planner.d.ts +24 -2
- package/dist/core/plan/planner.js +62 -4
- package/dist/core/plan/planner.js.map +1 -1
- package/dist/core/testGenerator/conventions.d.ts +10 -0
- package/dist/core/testGenerator/conventions.js +17 -0
- package/dist/core/testGenerator/conventions.js.map +1 -1
- package/dist/core/testGenerator/generate.d.ts +2 -0
- package/dist/core/testGenerator/generate.js +49 -17
- package/dist/core/testGenerator/generate.js.map +1 -1
- package/dist/core/tests/types.d.ts +9 -0
- package/package.json +8 -2
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
function toPosix(p) {
|
|
4
|
+
return p.replace(/\\/g, '/');
|
|
5
|
+
}
|
|
6
|
+
function round2(n) {
|
|
7
|
+
return Math.round(n * 100) / 100;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Map an absolute path from Jest coverage to a repo-relative POSIX path.
|
|
11
|
+
* Returns null if the path is outside the repo or invalid (fail-closed).
|
|
12
|
+
*/
|
|
13
|
+
export function mapCoveragePathToRepoPosix(opts) {
|
|
14
|
+
const absNorm = toPosix(opts.coverageAbsPath);
|
|
15
|
+
const repoNorm = toPosix(opts.repoRootAbs);
|
|
16
|
+
// Must be inside repo root
|
|
17
|
+
if (!absNorm.startsWith(repoNorm + '/') && absNorm !== repoNorm) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
// Compute relative from repo root
|
|
21
|
+
const relFromRepo = path.posix.relative(repoNorm, absNorm);
|
|
22
|
+
// Validate: must not escape (no leading ..)
|
|
23
|
+
if (relFromRepo.startsWith('..') || path.posix.isAbsolute(relFromRepo)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
// Skip node_modules
|
|
27
|
+
if (relFromRepo.includes('node_modules/') || relFromRepo.startsWith('node_modules')) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
// Handle dist/build → src mapping (best-effort, fail-closed)
|
|
31
|
+
const srcMapped = relFromRepo
|
|
32
|
+
.replace(/^dist\//, 'src/')
|
|
33
|
+
.replace(/^build\//, 'src/');
|
|
34
|
+
return srcMapped;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Parse Jest's coverage-summary.json and extract file coverage data.
|
|
38
|
+
* Deterministic output: files sorted by pathPosix, numbers rounded.
|
|
39
|
+
*/
|
|
40
|
+
export function parseJestCoverageSummary(opts) {
|
|
41
|
+
const maxFiles = opts.maxFiles ?? 500;
|
|
42
|
+
const warnings = [];
|
|
43
|
+
let raw;
|
|
44
|
+
try {
|
|
45
|
+
raw = fs.readFileSync(opts.summaryPath, 'utf8');
|
|
46
|
+
}
|
|
47
|
+
catch (e) {
|
|
48
|
+
warnings.push('coverage_file_read_failed');
|
|
49
|
+
return { files: [], warnings };
|
|
50
|
+
}
|
|
51
|
+
let data;
|
|
52
|
+
try {
|
|
53
|
+
data = JSON.parse(raw);
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
warnings.push('coverage_parse_failed');
|
|
57
|
+
return { files: [], warnings };
|
|
58
|
+
}
|
|
59
|
+
if (typeof data !== 'object' || data === null) {
|
|
60
|
+
warnings.push('coverage_parse_failed');
|
|
61
|
+
return { files: [], warnings };
|
|
62
|
+
}
|
|
63
|
+
const files = [];
|
|
64
|
+
const keys = Object.keys(data).sort((a, b) => a.localeCompare(b));
|
|
65
|
+
let mappingFailures = 0;
|
|
66
|
+
for (const absPath of keys) {
|
|
67
|
+
if (absPath === 'total')
|
|
68
|
+
continue; // Skip the total summary
|
|
69
|
+
if (files.length >= maxFiles) {
|
|
70
|
+
warnings.push('coverage_max_files_exceeded');
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
const pathPosix = mapCoveragePathToRepoPosix({
|
|
74
|
+
coverageAbsPath: absPath,
|
|
75
|
+
packageRootAbs: opts.packageRootAbs,
|
|
76
|
+
repoRootAbs: opts.repoRootAbs,
|
|
77
|
+
});
|
|
78
|
+
if (pathPosix === null) {
|
|
79
|
+
mappingFailures++;
|
|
80
|
+
continue; // Skip unmappable paths (fail-closed)
|
|
81
|
+
}
|
|
82
|
+
const entry = data[absPath];
|
|
83
|
+
if (!entry || typeof entry !== 'object')
|
|
84
|
+
continue;
|
|
85
|
+
const lines = entry.lines ?? {};
|
|
86
|
+
const branches = entry.branches ?? {};
|
|
87
|
+
files.push({
|
|
88
|
+
pathPosix,
|
|
89
|
+
linesPct: round2(typeof lines.pct === 'number' ? lines.pct : 0),
|
|
90
|
+
linesTotal: typeof lines.total === 'number' ? lines.total : 0,
|
|
91
|
+
linesCovered: typeof lines.covered === 'number' ? lines.covered : 0,
|
|
92
|
+
branchesPct: round2(typeof branches.pct === 'number' ? branches.pct : 0),
|
|
93
|
+
branchesTotal: typeof branches.total === 'number' ? branches.total : 0,
|
|
94
|
+
branchesCovered: typeof branches.covered === 'number' ? branches.covered : 0,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
if (mappingFailures > 0) {
|
|
98
|
+
warnings.push('coverage_path_mapping_failed');
|
|
99
|
+
}
|
|
100
|
+
// Deterministic: sort by path
|
|
101
|
+
files.sort((a, b) => a.pathPosix.localeCompare(b.pathPosix));
|
|
102
|
+
return { files, warnings: [...new Set(warnings)].sort((a, b) => a.localeCompare(b)) };
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Read pre-existing coverage from coverage/coverage-summary.json.
|
|
106
|
+
* Does NOT run Jest; assumes coverage was collected externally.
|
|
107
|
+
* This is the MVP approach: plan command reads existing coverage.
|
|
108
|
+
*/
|
|
109
|
+
export class JestCoverageProvider {
|
|
110
|
+
async collect(opts) {
|
|
111
|
+
const nowMs = opts.nowMs ?? (() => Date.now());
|
|
112
|
+
const started = nowMs();
|
|
113
|
+
const summaryPath = path.join(opts.packageRootAbs, 'coverage', 'coverage-summary.json');
|
|
114
|
+
if (!fs.existsSync(summaryPath)) {
|
|
115
|
+
return { ok: false, reason: 'coverage_file_not_found', details: summaryPath };
|
|
116
|
+
}
|
|
117
|
+
const parseOpts = {
|
|
118
|
+
summaryPath,
|
|
119
|
+
packageRootAbs: opts.packageRootAbs,
|
|
120
|
+
repoRootAbs: opts.repoRootAbs,
|
|
121
|
+
};
|
|
122
|
+
if (opts.maxFiles !== undefined)
|
|
123
|
+
parseOpts.maxFiles = opts.maxFiles;
|
|
124
|
+
const parsed = parseJestCoverageSummary(parseOpts);
|
|
125
|
+
if (parsed.warnings.includes('coverage_parse_failed')) {
|
|
126
|
+
return { ok: false, reason: 'coverage_parse_failed', details: summaryPath };
|
|
127
|
+
}
|
|
128
|
+
const result = {
|
|
129
|
+
source: 'jest-json-summary',
|
|
130
|
+
collectedAtMs: started,
|
|
131
|
+
durationMs: nowMs() - started,
|
|
132
|
+
files: parsed.files,
|
|
133
|
+
warnings: parsed.warnings,
|
|
134
|
+
};
|
|
135
|
+
return { ok: true, result };
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Factory function for DI.
|
|
140
|
+
*/
|
|
141
|
+
export function createJestCoverageProvider() {
|
|
142
|
+
return new JestCoverageProvider();
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=jestProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jestProvider.js","sourceRoot":"","sources":["../../../src/core/coverage/jestProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coverage data for a single file (repo-relative).
|
|
3
|
+
* All numeric fields are deterministic (rounded to 2 decimal places).
|
|
4
|
+
*/
|
|
5
|
+
export type FileCoverage = {
|
|
6
|
+
pathPosix: string;
|
|
7
|
+
linesPct: number;
|
|
8
|
+
linesTotal: number;
|
|
9
|
+
linesCovered: number;
|
|
10
|
+
branchesPct: number;
|
|
11
|
+
branchesTotal: number;
|
|
12
|
+
branchesCovered: number;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Result of a coverage collection run.
|
|
16
|
+
* Deterministic: files sorted by pathPosix, all numbers rounded.
|
|
17
|
+
*/
|
|
18
|
+
export type CoverageResult = {
|
|
19
|
+
source: 'jest-json-summary';
|
|
20
|
+
collectedAtMs: number;
|
|
21
|
+
durationMs: number;
|
|
22
|
+
files: FileCoverage[];
|
|
23
|
+
warnings: string[];
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Reason codes for coverage collection failure (deterministic).
|
|
27
|
+
*/
|
|
28
|
+
export type CoverageFailureReason = 'coverage_disabled' | 'coverage_runner_not_jest' | 'coverage_timeout' | 'coverage_parse_failed' | 'coverage_file_not_found' | 'coverage_command_failed';
|
|
29
|
+
/**
|
|
30
|
+
* Result wrapper: either success with data or failure with reason.
|
|
31
|
+
*/
|
|
32
|
+
export type CoverageCollectResult = {
|
|
33
|
+
ok: true;
|
|
34
|
+
result: CoverageResult;
|
|
35
|
+
} | {
|
|
36
|
+
ok: false;
|
|
37
|
+
reason: CoverageFailureReason;
|
|
38
|
+
details?: string;
|
|
39
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/coverage/types.ts"],"names":[],"mappings":""}
|
|
@@ -12,7 +12,14 @@ export class SmokeGenerator {
|
|
|
12
12
|
}
|
|
13
13
|
async generate(input) {
|
|
14
14
|
// Behavior: delegate to existing generator (synchronous) with repo-relative path.
|
|
15
|
-
const
|
|
15
|
+
const genOpts = {
|
|
16
|
+
root: input.rootAbs,
|
|
17
|
+
targetPath: input.targetPathPosix,
|
|
18
|
+
indexFiles: this.indexFiles,
|
|
19
|
+
};
|
|
20
|
+
if (input.allowCoverageTest)
|
|
21
|
+
genOpts.allowCoverageTest = true;
|
|
22
|
+
const r = generateJestTest(genOpts);
|
|
16
23
|
const expected = r.testPath ? [r.testPath] : [];
|
|
17
24
|
return {
|
|
18
25
|
generator: 'smoke',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smokeGenerator.js","sourceRoot":"","sources":["../../../src/core/generator/smokeGenerator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhE,SAAS,UAAU,CAAC,EAAY;IAC9B,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,OAAO,cAAc;IACR,UAAU,CAA0B;IAErD,YAAY,IAA6C;QACvD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;IACpC,CAAC;IAED,IAAI;QACF,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAoB;QACjC,kFAAkF;QAClF,MAAM,
|
|
1
|
+
{"version":3,"file":"smokeGenerator.js","sourceRoot":"","sources":["../../../src/core/generator/smokeGenerator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhE,SAAS,UAAU,CAAC,EAAY;IAC9B,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,OAAO,cAAc;IACR,UAAU,CAA0B;IAErD,YAAY,IAA6C;QACvD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;IACpC,CAAC;IAED,IAAI;QACF,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAoB;QACjC,kFAAkF;QAClF,MAAM,OAAO,GAA2C;YACtD,IAAI,EAAE,KAAK,CAAC,OAAO;YACnB,UAAU,EAAE,KAAK,CAAC,eAAe;YACjC,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC;QACF,IAAI,KAAK,CAAC,iBAAiB;YAAE,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAC9D,MAAM,CAAC,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAChD,OAAO;YACL,SAAS,EAAE,OAAO;YAClB,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,uFAAuF;YACvF,cAAc,EAAE,UAAU,CAAC,QAAQ,CAAC;YACpC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC;YAChC,OAAO,EAAE,CAAC,CAAC,MAAM;SAClB,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -27,6 +27,8 @@ export type GenerateInput = {
|
|
|
27
27
|
exitCode: number;
|
|
28
28
|
rawOutput: string;
|
|
29
29
|
} | null;
|
|
30
|
+
/** If true, allow generating a coverage test when main test exists (for under-covered targets). */
|
|
31
|
+
allowCoverageTest?: boolean;
|
|
30
32
|
};
|
|
31
33
|
export type GenerateOutput = {
|
|
32
34
|
generator: 'smoke' | 'llm';
|
|
@@ -1,16 +1,38 @@
|
|
|
1
|
+
import type { FileCoverage } from '../coverage/types.js';
|
|
2
|
+
export type PlanTargetCoverage = {
|
|
3
|
+
available: boolean;
|
|
4
|
+
linesPct: number | null;
|
|
5
|
+
branchesPct: number | null;
|
|
6
|
+
source: 'jest-json-summary' | 'fallback' | null;
|
|
7
|
+
};
|
|
1
8
|
export type PlanTarget = {
|
|
2
9
|
id: string;
|
|
3
10
|
paths: string[];
|
|
4
11
|
reasons: string[];
|
|
5
12
|
estimatedRisk: 'low' | 'med' | 'high';
|
|
13
|
+
coverage: PlanTargetCoverage;
|
|
14
|
+
};
|
|
15
|
+
export type PlanFileCoverageMeta = {
|
|
16
|
+
used: boolean;
|
|
17
|
+
source: 'jest-json-summary' | null;
|
|
18
|
+
reason: string | null;
|
|
19
|
+
filesProcessed: number;
|
|
20
|
+
thresholdPct: number;
|
|
6
21
|
};
|
|
7
22
|
export type PlanFile = {
|
|
8
23
|
schemaVersion: 1;
|
|
9
24
|
source: {
|
|
10
25
|
indexSchemaVersion: number | null;
|
|
11
26
|
};
|
|
27
|
+
coverageMeta: PlanFileCoverageMeta;
|
|
12
28
|
targets: PlanTarget[];
|
|
13
29
|
};
|
|
14
|
-
export
|
|
30
|
+
export type BuildPlanOpts = {
|
|
15
31
|
maxTargets?: number;
|
|
16
|
-
|
|
32
|
+
coverage?: {
|
|
33
|
+
files: FileCoverage[];
|
|
34
|
+
source: 'jest-json-summary';
|
|
35
|
+
thresholdPct: number;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
export declare function buildPlanFromIndex(indexData: unknown, opts?: BuildPlanOpts): PlanFile;
|
|
@@ -47,10 +47,35 @@ function possibleTestPaths(modulePath) {
|
|
|
47
47
|
// Stable ordering
|
|
48
48
|
return [...new Set(candidates)].sort((a, b) => a.localeCompare(b));
|
|
49
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Compute score for a file based on coverage data.
|
|
52
|
+
* Lower coverage = higher priority (higher score).
|
|
53
|
+
*/
|
|
54
|
+
function computeCoverageScore(opts) {
|
|
55
|
+
// Coverage score: 0-100 based on inverse of coverage percentage
|
|
56
|
+
// Lower coverage = higher priority
|
|
57
|
+
const coverageScore = opts.coverageAvailable && opts.linesPct !== null
|
|
58
|
+
? Math.max(0, Math.round(100 - opts.linesPct)) // 0% coverage → 100, 100% coverage → 0
|
|
59
|
+
: opts.hasTests
|
|
60
|
+
? 0
|
|
61
|
+
: 100; // fallback: no tests = high priority
|
|
62
|
+
// Risk bonus: prefer smaller files (0-20)
|
|
63
|
+
const riskBonus = opts.risk === 'low' ? 20 : opts.risk === 'med' ? 10 : 0;
|
|
64
|
+
return coverageScore + riskBonus;
|
|
65
|
+
}
|
|
50
66
|
export function buildPlanFromIndex(indexData, opts) {
|
|
51
67
|
const idx = (indexData ?? {});
|
|
52
68
|
const files = (idx.files ?? []).filter((f) => !!f && typeof f.path === 'string');
|
|
53
69
|
const fileSet = new Set(files.map((f) => f.path));
|
|
70
|
+
// Build coverage lookup map (path -> coverage data)
|
|
71
|
+
const coverageMap = new Map();
|
|
72
|
+
if (opts?.coverage) {
|
|
73
|
+
for (const fc of opts.coverage.files) {
|
|
74
|
+
coverageMap.set(fc.pathPosix, fc);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const coverageAvailable = opts?.coverage != null && opts.coverage.files.length > 0;
|
|
78
|
+
const thresholdPct = opts?.coverage?.thresholdPct ?? 80;
|
|
54
79
|
const candidates = files
|
|
55
80
|
.filter((f) => f.path.startsWith('src/'))
|
|
56
81
|
.filter((f) => isCodeExt(f.ext))
|
|
@@ -66,11 +91,36 @@ export function buildPlanFromIndex(indexData, opts) {
|
|
|
66
91
|
reasons.push(`has matching test file(s): ${tests.join(', ')}`);
|
|
67
92
|
const risk = estimateRisk(f.size);
|
|
68
93
|
const id = stableIdForPaths([f.path]);
|
|
69
|
-
//
|
|
70
|
-
const
|
|
71
|
-
|
|
94
|
+
// Look up coverage for this file
|
|
95
|
+
const fileCoverage = coverageMap.get(f.path);
|
|
96
|
+
const linesPct = fileCoverage?.linesPct ?? null;
|
|
97
|
+
const branchesPct = fileCoverage?.branchesPct ?? null;
|
|
98
|
+
const hasCoverageData = fileCoverage != null;
|
|
99
|
+
// Add coverage reason
|
|
100
|
+
if (coverageAvailable) {
|
|
101
|
+
if (hasCoverageData) {
|
|
102
|
+
const isUnderCovered = linesPct !== null && linesPct < thresholdPct;
|
|
103
|
+
reasons.push(`coverage: ${linesPct}% lines${isUnderCovered ? ` (below ${thresholdPct}% threshold)` : ''}`);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
reasons.push('coverage: no data (treated as uncovered)');
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// Compute score using coverage-aware algorithm
|
|
110
|
+
const score = computeCoverageScore({
|
|
111
|
+
hasTests,
|
|
112
|
+
coverageAvailable: hasCoverageData,
|
|
113
|
+
linesPct,
|
|
114
|
+
risk,
|
|
115
|
+
});
|
|
116
|
+
const targetCoverage = {
|
|
117
|
+
available: hasCoverageData,
|
|
118
|
+
linesPct,
|
|
119
|
+
branchesPct,
|
|
120
|
+
source: hasCoverageData ? (opts?.coverage?.source ?? null) : null,
|
|
121
|
+
};
|
|
72
122
|
targets.push({
|
|
73
|
-
target: { id, paths: [f.path], reasons, estimatedRisk: risk },
|
|
123
|
+
target: { id, paths: [f.path], reasons, estimatedRisk: risk, coverage: targetCoverage },
|
|
74
124
|
score,
|
|
75
125
|
sortKey: f.path,
|
|
76
126
|
});
|
|
@@ -82,9 +132,17 @@ export function buildPlanFromIndex(indexData, opts) {
|
|
|
82
132
|
});
|
|
83
133
|
const max = opts?.maxTargets ?? 50;
|
|
84
134
|
const sliced = targets.slice(0, Math.max(0, max)).map((t) => t.target);
|
|
135
|
+
const coverageMeta = {
|
|
136
|
+
used: coverageAvailable,
|
|
137
|
+
source: opts?.coverage?.source ?? null,
|
|
138
|
+
reason: coverageAvailable ? null : 'coverage_not_provided',
|
|
139
|
+
filesProcessed: coverageMap.size,
|
|
140
|
+
thresholdPct,
|
|
141
|
+
};
|
|
85
142
|
return {
|
|
86
143
|
schemaVersion: 1,
|
|
87
144
|
source: { indexSchemaVersion: typeof idx.schemaVersion === 'number' ? idx.schemaVersion : null },
|
|
145
|
+
coverageMeta,
|
|
88
146
|
targets: sliced,
|
|
89
147
|
};
|
|
90
148
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planner.js","sourceRoot":"","sources":["../../../src/core/plan/planner.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"planner.js","sourceRoot":"","sources":["../../../src/core/plan/planner.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,3 +5,13 @@ export declare function computeTestPath(opts: {
|
|
|
5
5
|
targetPath: string;
|
|
6
6
|
testExt: 'ts' | 'js';
|
|
7
7
|
}): string;
|
|
8
|
+
/**
|
|
9
|
+
* Compute a path for an additional coverage-focused test file.
|
|
10
|
+
* Uses a different naming convention to avoid conflict with main test file.
|
|
11
|
+
* Pattern: {base}.coverage.test.{ext}
|
|
12
|
+
*/
|
|
13
|
+
export declare function computeCoverageTestPath(opts: {
|
|
14
|
+
convention: TestConvention;
|
|
15
|
+
targetPath: string;
|
|
16
|
+
testExt: 'ts' | 'js';
|
|
17
|
+
}): string;
|
|
@@ -26,4 +26,21 @@ export function computeTestPath(opts) {
|
|
|
26
26
|
}
|
|
27
27
|
return `${base}.test.${opts.testExt}`;
|
|
28
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Compute a path for an additional coverage-focused test file.
|
|
31
|
+
* Uses a different naming convention to avoid conflict with main test file.
|
|
32
|
+
* Pattern: {base}.coverage.test.{ext}
|
|
33
|
+
*/
|
|
34
|
+
export function computeCoverageTestPath(opts) {
|
|
35
|
+
const target = opts.targetPath;
|
|
36
|
+
const dot = target.lastIndexOf('.');
|
|
37
|
+
const base = dot === -1 ? target : target.slice(0, dot);
|
|
38
|
+
const fileName = base.split('/').pop() ?? base;
|
|
39
|
+
const dir = base.includes('/') ? base.split('/').slice(0, -1).join('/') : '';
|
|
40
|
+
if (opts.convention === 'dir_tests') {
|
|
41
|
+
const testsDir = dir ? `${dir}/__tests__` : '__tests__';
|
|
42
|
+
return `${testsDir}/${fileName}.coverage.test.${opts.testExt}`;
|
|
43
|
+
}
|
|
44
|
+
return `${base}.coverage.test.${opts.testExt}`;
|
|
45
|
+
}
|
|
29
46
|
//# sourceMappingURL=conventions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conventions.js","sourceRoot":"","sources":["../../../src/core/testGenerator/conventions.ts"],"names":[],"mappings":"AAEA,SAAS,MAAM,CAAC,KAAwB,EAAE,IAA4B;IACpE,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,IAAI,IAAI,CAAC,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;IAChD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,UAA6B;IAChE,4FAA4F;IAC5F,MAAM,WAAW,GAAG,MAAM,CACxB,UAAU,EACV,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CACvF,CAAC;IACF,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC;IAEpC,MAAM,YAAY,GAAG,MAAM,CACzB,UAAU,EACV,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAClF,CAAC;IACF,IAAI,YAAY;QAAE,OAAO,mBAAmB,CAAC;IAE7C,OAAO,mBAAmB,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAI/B;IACC,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC;IAC/B,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC;IAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAE7E,IAAI,IAAI,CAAC,UAAU,KAAK,WAAW,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC;QACxD,OAAO,GAAG,QAAQ,IAAI,QAAQ,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC;IACxD,CAAC;IAED,OAAO,GAAG,IAAI,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC;AACxC,CAAC"}
|
|
1
|
+
{"version":3,"file":"conventions.js","sourceRoot":"","sources":["../../../src/core/testGenerator/conventions.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,5 +31,7 @@ export declare function generateJestTest(opts: {
|
|
|
31
31
|
root: string;
|
|
32
32
|
targetPath: string;
|
|
33
33
|
indexFiles: IndexFile[];
|
|
34
|
+
/** If true, try generating a coverage test file when main test exists. */
|
|
35
|
+
allowCoverageTest?: boolean;
|
|
34
36
|
}): GenerateTestResult;
|
|
35
37
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import crypto from 'node:crypto';
|
|
4
|
-
import { computeTestPath, detectTestConvention } from './conventions.js';
|
|
4
|
+
import { computeTestPath, computeCoverageTestPath, detectTestConvention } from './conventions.js';
|
|
5
5
|
import { extractNamedExportsFromJsLike } from '../code/exports.js';
|
|
6
6
|
function toPosix(p) {
|
|
7
7
|
return p.split(path.sep).join('/');
|
|
@@ -85,22 +85,54 @@ export function generateJestTest(opts) {
|
|
|
85
85
|
const targetExt = path.posix.extname(targetPosix).toLowerCase();
|
|
86
86
|
const testExt = isJsLike(targetPosix) ? 'js' : 'ts';
|
|
87
87
|
assumptionsUsed.push(`testExt=${testExt}`);
|
|
88
|
-
const
|
|
89
|
-
//
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
88
|
+
const mainTestPath = computeTestPath({ convention, targetPath: targetPosix, testExt });
|
|
89
|
+
// Check if main test already exists
|
|
90
|
+
const mainTestExists = indexPaths.includes(mainTestPath) || fs.existsSync(path.join(rootAbs, ...mainTestPath.split('/')));
|
|
91
|
+
// Determine which test path to use
|
|
92
|
+
let testPath = mainTestPath;
|
|
93
|
+
let isCoverageTest = false;
|
|
94
|
+
if (mainTestExists) {
|
|
95
|
+
// If coverage mode enabled, try coverage test path
|
|
96
|
+
if (opts.allowCoverageTest) {
|
|
97
|
+
const coverageTestPath = computeCoverageTestPath({ convention, targetPath: targetPosix, testExt });
|
|
98
|
+
const coverageTestExists = indexPaths.includes(coverageTestPath) || fs.existsSync(path.join(rootAbs, ...coverageTestPath.split('/')));
|
|
99
|
+
if (!coverageTestExists) {
|
|
100
|
+
testPath = coverageTestPath;
|
|
101
|
+
isCoverageTest = true;
|
|
102
|
+
assumptionsUsed.push('testMode=coverage');
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
// Both main and coverage test exist
|
|
106
|
+
return {
|
|
107
|
+
created: false,
|
|
108
|
+
testPath: mainTestPath,
|
|
109
|
+
reason: 'Test file already exists (main and coverage); skipping',
|
|
110
|
+
generatedFiles: [],
|
|
111
|
+
targetId,
|
|
112
|
+
targetPath: targetPosix,
|
|
113
|
+
assumptionsUsed,
|
|
114
|
+
warnings,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
// Coverage mode disabled, skip
|
|
120
|
+
return {
|
|
121
|
+
created: false,
|
|
122
|
+
testPath: mainTestPath,
|
|
123
|
+
reason: 'Test file already exists; skipping',
|
|
124
|
+
generatedFiles: [],
|
|
125
|
+
targetId,
|
|
126
|
+
targetPath: targetPosix,
|
|
127
|
+
assumptionsUsed,
|
|
128
|
+
warnings,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
103
131
|
}
|
|
132
|
+
else {
|
|
133
|
+
assumptionsUsed.push('testMode=main');
|
|
134
|
+
}
|
|
135
|
+
const testAbs = path.join(rootAbs, ...testPath.split('/'));
|
|
104
136
|
const targetAbs = path.join(rootAbs, ...targetPosix.split('/'));
|
|
105
137
|
const source = fs.readFileSync(targetAbs, 'utf8');
|
|
106
138
|
const exp = extractNamedExportsFromJsLike(source);
|
|
@@ -116,7 +148,7 @@ export function generateJestTest(opts) {
|
|
|
116
148
|
return {
|
|
117
149
|
created: true,
|
|
118
150
|
testPath,
|
|
119
|
-
reason: 'Generated smoke test',
|
|
151
|
+
reason: isCoverageTest ? 'Generated coverage test (main test exists)' : 'Generated smoke test',
|
|
120
152
|
generatedFiles: [testPath],
|
|
121
153
|
targetId,
|
|
122
154
|
targetPath: targetPosix,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../src/core/testGenerator/generate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../src/core/testGenerator/generate.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,6 +31,13 @@ export type DecisionSummary = {
|
|
|
31
31
|
generatorWarnings: string[];
|
|
32
32
|
};
|
|
33
33
|
};
|
|
34
|
+
/** Coverage metadata for the target being tested (from plan.json). */
|
|
35
|
+
export type TargetCoverageReport = {
|
|
36
|
+
available: boolean;
|
|
37
|
+
linesPct: number | null;
|
|
38
|
+
branchesPct: number | null;
|
|
39
|
+
source: 'jest-json-summary' | 'fallback' | null;
|
|
40
|
+
};
|
|
34
41
|
export type TestsReport = {
|
|
35
42
|
schemaVersion: 1;
|
|
36
43
|
command: 'tests';
|
|
@@ -56,6 +63,8 @@ export type TestsReport = {
|
|
|
56
63
|
hitMaxFiles: boolean;
|
|
57
64
|
hitMaxChars: boolean;
|
|
58
65
|
} | null;
|
|
66
|
+
/** Coverage metadata for the target (from plan.json, deterministic). */
|
|
67
|
+
targetCoverage: TargetCoverageReport;
|
|
59
68
|
runner: 'jest' | 'vitest' | 'pytest' | 'unknown';
|
|
60
69
|
runnerInferred: 'jest' | 'vitest' | 'pytest' | 'unknown';
|
|
61
70
|
runnerObserved: 'jest' | 'vitest' | 'pytest' | 'unknown';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "phantom-pr",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "CI-friendly CLI that opens PRs with passing Jest unit tests.",
|
|
6
6
|
"keywords": [
|
|
@@ -27,7 +27,13 @@
|
|
|
27
27
|
"doc": "docs",
|
|
28
28
|
"test": "tests"
|
|
29
29
|
},
|
|
30
|
-
"files": [
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"bin",
|
|
33
|
+
"README.md",
|
|
34
|
+
"LICENSE",
|
|
35
|
+
"LICENSE.md"
|
|
36
|
+
],
|
|
31
37
|
"scripts": {
|
|
32
38
|
"build": "tsc -p tsconfig.json",
|
|
33
39
|
"test": "npm run build && node --test tests",
|