Skip to content

Commit 84d0148

Browse files
committed
fix(actions/parse-ci-reports-path): auto-pattern detection and parser accepted paths conflict
Signed-off-by: Emilien Escalle <emilien.escalle@escemi.com>
1 parent 2264147 commit 84d0148

4 files changed

Lines changed: 200 additions & 0 deletions

File tree

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { describe, it } from "node:test";
2+
import assert from "node:assert/strict";
3+
import { CheckStyleParser } from "./CheckStyleParser.js";
4+
5+
const EMPTY_CHECKSTYLE_XML = `<?xml version="1.0" encoding="UTF-8"?>
6+
<checkstyle version="10.0"></checkstyle>`;
7+
8+
const CHECKSTYLE_WITH_ISSUES_XML = `<?xml version="1.0" encoding="UTF-8"?>
9+
<checkstyle version="10.0">
10+
<file name="src/index.js">
11+
<error line="5" column="1" severity="warning" message="Unexpected console statement" source="no-console"/>
12+
</file>
13+
</checkstyle>`;
14+
15+
describe("CheckStyleParser", () => {
16+
it("keeps auto-pattern path detection synchronized", () => {
17+
const parser = new CheckStyleParser();
18+
const filePath = "application/humanize-checkstyle-result.xml";
19+
20+
assert.ok(parser.matchesAutoPatterns(filePath));
21+
assert.ok(parser.canParse(filePath, EMPTY_CHECKSTYLE_XML));
22+
});
23+
24+
it("identifies valid checkstyle XML reports without file entries", () => {
25+
const parser = new CheckStyleParser();
26+
27+
assert.ok(
28+
parser.canParse(
29+
"application/humanize-report-checkstyle.xml",
30+
EMPTY_CHECKSTYLE_XML,
31+
),
32+
);
33+
});
34+
35+
it("parses empty checkstyle reports as zero lint issues", () => {
36+
const parser = new CheckStyleParser();
37+
38+
const reportData = parser.parse(
39+
EMPTY_CHECKSTYLE_XML,
40+
"application/humanize-report-checkstyle.xml",
41+
);
42+
assert.strictEqual(reportData.lintIssues.length, 0);
43+
});
44+
45+
it("parses checkstyle issues from file entries", () => {
46+
const parser = new CheckStyleParser();
47+
48+
const reportData = parser.parse(
49+
CHECKSTYLE_WITH_ISSUES_XML,
50+
"checkstyle-result.xml",
51+
);
52+
53+
assert.strictEqual(reportData.lintIssues.length, 1);
54+
assert.strictEqual(reportData.lintIssues[0].file, "src/index.js");
55+
assert.strictEqual(reportData.lintIssues[0].line, 5);
56+
assert.strictEqual(reportData.lintIssues[0].column, 1);
57+
assert.strictEqual(reportData.lintIssues[0].severity, "warning");
58+
assert.strictEqual(reportData.lintIssues[0].rule, "no-console");
59+
});
60+
});
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { describe, it } from "node:test";
2+
import assert from "node:assert/strict";
3+
import { CoberturaParser } from "./CoberturaParser.js";
4+
5+
const SAMPLE_COBERTURA_XML = `<?xml version="1.0"?>
6+
<coverage line-rate="0.75" branch-rate="0.5">
7+
<packages>
8+
<package name="app">
9+
<classes>
10+
<class name="App" filename="src/app.js">
11+
<lines>
12+
<line number="1" hits="1"/>
13+
<line number="2" hits="0"/>
14+
</lines>
15+
</class>
16+
</classes>
17+
</package>
18+
</packages>
19+
</coverage>`;
20+
21+
describe("CoberturaParser", () => {
22+
it("keeps auto-pattern path detection synchronized", () => {
23+
const parser = new CoberturaParser();
24+
const filePath = "coverage/humanize-coverage.xml";
25+
26+
assert.ok(parser.matchesAutoPatterns(filePath));
27+
assert.ok(parser.canParse(filePath, SAMPLE_COBERTURA_XML));
28+
});
29+
30+
it("identifies Cobertura XML reports", () => {
31+
const parser = new CoberturaParser();
32+
33+
assert.ok(parser.canParse("coverage/coverage.xml", SAMPLE_COBERTURA_XML));
34+
assert.ok(!parser.canParse("reports/report.txt", SAMPLE_COBERTURA_XML));
35+
});
36+
37+
it("parses coverage totals", () => {
38+
const parser = new CoberturaParser();
39+
const reportData = parser.parse(SAMPLE_COBERTURA_XML, "coverage.xml");
40+
41+
assert.ok(reportData.coverage);
42+
assert.strictEqual(reportData.coverage.lines.total, 2);
43+
assert.strictEqual(reportData.coverage.lines.covered, 1);
44+
assert.strictEqual(reportData.coverage.lines.percentage, 50);
45+
});
46+
});
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { describe, it } from "node:test";
2+
import assert from "node:assert/strict";
3+
import { ESLintParser } from "./ESLintParser.js";
4+
5+
const SAMPLE_ESLINT_JSON = JSON.stringify([
6+
{
7+
filePath: "src/app.js",
8+
messages: [
9+
{
10+
ruleId: "no-console",
11+
severity: 2,
12+
message: "Unexpected console statement.",
13+
line: 3,
14+
column: 1,
15+
},
16+
],
17+
},
18+
]);
19+
20+
describe("ESLintParser", () => {
21+
it("keeps auto-pattern path detection synchronized", () => {
22+
const parser = new ESLintParser();
23+
const filePath = "reports/humanize-eslint-report.json";
24+
25+
assert.ok(parser.matchesAutoPatterns(filePath));
26+
assert.ok(parser.canParse(filePath, SAMPLE_ESLINT_JSON));
27+
});
28+
29+
it("identifies ESLint report format", () => {
30+
const parser = new ESLintParser();
31+
32+
assert.ok(parser.canParse("eslint-report.json", SAMPLE_ESLINT_JSON));
33+
assert.ok(!parser.canParse("eslint-report.txt", SAMPLE_ESLINT_JSON));
34+
assert.ok(!parser.canParse("eslint-report.json", "{}"));
35+
});
36+
37+
it("parses lint issues from ESLint JSON", () => {
38+
const parser = new ESLintParser();
39+
const reportData = parser.parse(SAMPLE_ESLINT_JSON, "eslint-report.json");
40+
41+
assert.strictEqual(reportData.lintIssues.length, 1);
42+
const [issue] = reportData.lintIssues;
43+
44+
assert.strictEqual(issue.file, "src/app.js");
45+
assert.strictEqual(issue.line, 3);
46+
assert.strictEqual(issue.column, 1);
47+
assert.strictEqual(issue.severity, "error");
48+
assert.strictEqual(issue.rule, "no-console");
49+
assert.strictEqual(issue.message, "Unexpected console statement.");
50+
});
51+
});
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { describe, it } from "node:test";
2+
import assert from "node:assert/strict";
3+
import { LCOVParser } from "./LCOVParser.js";
4+
5+
const SAMPLE_LCOV = `TN:
6+
SF:src/app.js
7+
DA:1,1
8+
DA:2,0
9+
FNDA:1,handler
10+
BRDA:2,0,0,1
11+
BRDA:2,0,1,0
12+
end_of_record
13+
`;
14+
15+
describe("LCOVParser", () => {
16+
it("keeps auto-pattern path detection synchronized", () => {
17+
const parser = new LCOVParser();
18+
const filePath = "coverage/humanize-lcov.info";
19+
20+
assert.ok(parser.matchesAutoPatterns(filePath));
21+
assert.ok(parser.canParse(filePath, SAMPLE_LCOV));
22+
});
23+
24+
it("identifies LCOV reports", () => {
25+
const parser = new LCOVParser();
26+
27+
assert.ok(parser.canParse("coverage/lcov.info", SAMPLE_LCOV));
28+
assert.ok(!parser.canParse("coverage/report.txt", SAMPLE_LCOV));
29+
});
30+
31+
it("parses line, function, and branch coverage", () => {
32+
const parser = new LCOVParser();
33+
const reportData = parser.parse(SAMPLE_LCOV, "lcov.info");
34+
35+
assert.ok(reportData.coverage);
36+
assert.strictEqual(reportData.coverage.lines.total, 2);
37+
assert.strictEqual(reportData.coverage.lines.covered, 1);
38+
assert.strictEqual(reportData.coverage.functions.total, 1);
39+
assert.strictEqual(reportData.coverage.functions.covered, 1);
40+
assert.strictEqual(reportData.coverage.branches.total, 2);
41+
assert.strictEqual(reportData.coverage.branches.covered, 1);
42+
});
43+
});

0 commit comments

Comments
 (0)