Skip to content

Commit d568e95

Browse files
Vedu1996Jwaegebaert
authored andcommittedFeb 21, 2024
Adds tests and coverage summary to workflow. Closes #3288
Reorganize scripts
1 parent 0ae7da4 commit d568e95

6 files changed

+200
-9
lines changed
 

‎.c8rc.json

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
{
2-
"exclude": ["**/*.spec.js", "**/*.mock.js", "**/clientsidepages.js", "docs"],
2+
"exclude": [
3+
"**/*.spec.js",
4+
"**/*.mock.js",
5+
"**/clientsidepages.js",
6+
"docs",
7+
"**/ci-test-summary.cjs"
8+
],
39
"reporter": ["lcov", "text", "text-summary"],
410
"check-coverage": true,
511
"branches": 100,
612
"functions": 100,
713
"lines": 100,
814
"statements": 100,
915
"skip-full": true
10-
}
16+
}

‎.eslintrc.cjs

+2-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,8 @@ module.exports = {
142142
"**/package-generate/assets/**",
143143
"**/test-projects/**",
144144
"clientsidepages.ts",
145-
"*.js"
145+
"*.js",
146+
"*.cjs"
146147
],
147148
"rules": {
148149
"cli-microsoft365/correct-command-class-name": ["error", sortedDictionary, capitalized],

‎.mocharc.json

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
{
2-
"extension": [
3-
"ts"
4-
],
2+
"extension": ["ts"],
53
"spec": "dist/**/*.spec.js",
6-
"reporter": "min",
4+
"reporter": "scripts/ci-test-summary.cjs",
75
"require": "source-map-support/register",
86
"watch": "dist/**/*.js",
97
"timeout": 10000,
108
"logpanel": true
11-
}
9+
}

‎npm-shrinkwrap.json

+60
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@
163163
"Kornet, Michał <kornetmichal@gmail.com>",
164164
"Kumar, Shantha <34408892+ktskumar@users.noreply.github.com>",
165165
"Kurian, Cyril C <cyril.kurian2@gmail.com>",
166-
"Lakshminarayanan, Vedant <vlakshminarayanan@seekasia.com>",
166+
"Lakshminarayanan, Vedant <28388096+Vedu1996@users.noreply.github.com>",
167167
"Lamber, Patrick <patrick@nubo.eu>",
168168
"Laskewitz, Daniel <daniel@laskewitz.nl>",
169169
"Lengelle, Veronique <25181757+veronicageek@users.noreply.github.com>",
@@ -277,6 +277,7 @@
277277
"yaml": "^2.3.4"
278278
},
279279
"devDependencies": {
280+
"@actions/core": "^1.10.1",
280281
"@microsoft/microsoft-graph-types": "^2.40.0",
281282
"@types/adm-zip": "^0.5.5",
282283
"@types/jmespath": "^0.15.2",

‎scripts/ci-test-summary.cjs

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
const mocha = require('mocha');
2+
const core = require('@actions/core');
3+
4+
const { EVENT_RUN_END, EVENT_TEST_FAIL, EVENT_RUN_BEGIN } =
5+
mocha.Runner.constants;
6+
7+
class TestSummaryReporter {
8+
summary = core.summary;
9+
testResult = { failedTests: {}, stats: {} };
10+
suiteIndenter = '&emsp; ';
11+
destination;
12+
13+
constructor(runner, options) {
14+
new mocha.reporters.Min(runner, options);
15+
16+
if (!process.env.GITHUB_STEP_SUMMARY) {
17+
return;
18+
}
19+
20+
const stats = runner.stats;
21+
runner
22+
.on(EVENT_RUN_BEGIN, () => {
23+
// Capturing the value of GITHUB_STEP_SUMMARY to use later
24+
this.destination = process.env.GITHUB_STEP_SUMMARY;
25+
})
26+
.on(EVENT_TEST_FAIL, (test, _) => {
27+
const testPath = test.titlePath();
28+
const testName = testPath.pop();
29+
let resultPath = this.testResult.failedTests;
30+
testPath.forEach((item, index) => {
31+
if (index === testPath.length - 1) {
32+
if (!resultPath.hasOwnProperty(item)) {
33+
resultPath[item] = [];
34+
}
35+
resultPath[item].push(testName);
36+
}
37+
if (!resultPath.hasOwnProperty(item)) {
38+
resultPath[item] = {};
39+
}
40+
resultPath = resultPath[item];
41+
});
42+
})
43+
.once(EVENT_RUN_END, () => {
44+
this.testResult.stats = {
45+
passed: stats.passes,
46+
failed: stats.failures,
47+
total: stats.passes + stats.failures,
48+
};
49+
this.writeSummary();
50+
});
51+
}
52+
53+
async writeSummary() {
54+
try {
55+
if (this.testResult.stats.failed > 0) {
56+
this.summary = this.summary.addHeading('Failed tests', 3);
57+
this.summary = this.summary
58+
.addRaw(this.generateAccordion('', null, this.testResult.failedTests))
59+
.addSeparator();
60+
}
61+
this.writeStatsTable();
62+
this.writeResultsBar();
63+
// Resettig GITHUB_STEP_SUMMARY, since unit tests might overwrite it
64+
process.env.GITHUB_STEP_SUMMARY = this.destination;
65+
await this.summary.write();
66+
} catch (e) {
67+
console.error(e);
68+
}
69+
}
70+
71+
generateAccordion(suitePrefix, suiteName, suiteObject) {
72+
if (typeof suiteObject !== 'object') {
73+
// Item is a test, not a suite
74+
return `${suitePrefix}${suiteObject}<br />`;
75+
}
76+
let detailsContent = '';
77+
78+
// Generate accordion for each item in suite
79+
Object.keys(suiteObject).forEach(
80+
(item) =>
81+
(detailsContent =
82+
detailsContent +
83+
this.generateAccordion(
84+
`${suitePrefix}${this.suiteIndenter}`,
85+
item,
86+
suiteObject[item]
87+
))
88+
);
89+
90+
// First level does not require accordion
91+
if (suiteName === null) {
92+
return detailsContent;
93+
}
94+
95+
// Return an accordion for the suite
96+
return `
97+
<details>
98+
<summary>${suitePrefix}${suiteName}</summary>
99+
${detailsContent}
100+
</details>
101+
`;
102+
}
103+
104+
writeStatsTable() {
105+
this.summary.addHeading('Stats', 3);
106+
this.summary = this.summary.addTable([
107+
['Total number of tests', '' + this.testResult.stats.total],
108+
['Passed ✅', '' + this.testResult.stats.passed],
109+
['Failed ❌', '' + this.testResult.stats.failed],
110+
]);
111+
}
112+
113+
writeResultsBar() {
114+
let percentagePassed = Math.floor(
115+
(this.testResult.stats.passed / this.testResult.stats.total) * 100
116+
);
117+
this.summary = this.summary.addRaw(
118+
'<div style="width: 50%; background-color: red; text-align: center; color: white;"><div style="width:' +
119+
percentagePassed +
120+
'%; height: 18px; background-color: green;"></div></div>'
121+
);
122+
}
123+
}
124+
125+
module.exports = TestSummaryReporter;

0 commit comments

Comments
 (0)
Please sign in to comment.