@estruyf/github-actions-reporter
Advanced tools
Comparing version
@@ -5,2 +5,7 @@ # Changelog | ||
## [1.6.0] | ||
- [#10](https://github.com/estruyf/playwright-github-actions-reporter/issues/10): Added support for test annotations, tags, and describe titles per test | ||
- [#11](https://github.com/estruyf/playwright-github-actions-reporter/issues/11): Added the ability to hide the header | ||
## [1.5.1] | ||
@@ -7,0 +12,0 @@ |
@@ -36,13 +36,21 @@ "use strict"; | ||
const core = __importStar(require("@actions/core")); | ||
const path_1 = require("path"); | ||
const getHtmlTable_1 = require("./utils/getHtmlTable"); | ||
const getTableRows_1 = require("./utils/getTableRows"); | ||
const getTestStatusIcon_1 = require("./utils/getTestStatusIcon"); | ||
const summary_1 = require("@actions/core/lib/summary"); | ||
const fs_1 = require("fs"); | ||
const getTotalStatus_1 = require("./utils/getTotalStatus"); | ||
const processResults_1 = require("./utils/processResults"); | ||
class GitHubAction { | ||
constructor(options = {}) { | ||
constructor(options = { | ||
showAnnotations: true, | ||
showTags: true, | ||
}) { | ||
this.options = options; | ||
console.log(`Using GitHub Actions reporter`); | ||
// Set default options | ||
if (typeof options.showAnnotations === "undefined") { | ||
this.options.showAnnotations = true; | ||
} | ||
if (typeof options.showTags === "undefined") { | ||
this.options.showTags = true; | ||
} | ||
if (process.env.NODE_ENV === "development") { | ||
console.log(`Using development mode`); | ||
console.log(`Options: ${JSON.stringify(this.options, null, 2)}`); | ||
} | ||
} | ||
@@ -52,75 +60,8 @@ onBegin(_, suite) { | ||
} | ||
onStdOut(chunk, test, result) { | ||
onStdOut(chunk, _, __) { | ||
console.log(chunk.toString()); | ||
} | ||
onEnd(result) { | ||
var _a, _b; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (process.env.NODE_ENV === "development") { | ||
const summaryFile = (0, path_1.join)(__dirname, "../summary.html"); | ||
if ((0, fs_1.existsSync)(summaryFile)) { | ||
(0, fs_1.unlinkSync)(summaryFile); | ||
} | ||
(0, fs_1.writeFileSync)(summaryFile, "", "utf-8"); | ||
process.env[summary_1.SUMMARY_ENV_VAR] = summaryFile; | ||
process.env.GITHUB_ACTIONS = "true"; | ||
} | ||
if (process.env.GITHUB_ACTIONS && this.suite) { | ||
const os = process.platform; | ||
const summary = core.summary; | ||
summary.addHeading(this.options.title || `Test results`, 1); | ||
const totalStatus = (0, getTotalStatus_1.getTotalStatus)((_a = this.suite) === null || _a === void 0 ? void 0 : _a.suites); | ||
const headerText = [`Total tests: ${this.suite.allTests().length}`]; | ||
if (totalStatus.passed > 0) { | ||
headerText.push(`Passed: ${totalStatus.passed}`); | ||
} | ||
if (totalStatus.failed > 0) { | ||
headerText.push(`Failed: ${totalStatus.failed}`); | ||
} | ||
if (totalStatus.skipped > 0) { | ||
headerText.push(`Skipped: ${totalStatus.skipped}`); | ||
} | ||
if (totalStatus.timedOut > 0) { | ||
headerText.push(`Timed Out: ${totalStatus.timedOut}`); | ||
} | ||
summary.addRaw(headerText.join(` - `)); | ||
if (this.options.useDetails) { | ||
summary.addSeparator(); | ||
} | ||
for (const suite of (_b = this.suite) === null || _b === void 0 ? void 0 : _b.suites) { | ||
const project = suite.project(); | ||
// Get all the test files | ||
const files = suite | ||
.allTests() | ||
.map((test) => test.location.file) | ||
.reduce((acc, curr) => { | ||
if (!acc.includes(curr)) { | ||
acc.push(curr); | ||
} | ||
return acc; | ||
}, []); | ||
// Get all the tests per file | ||
const tests = files.reduce((acc, curr) => { | ||
acc[curr] = suite.allTests().filter((test) => { | ||
return test.location.file === curr; | ||
}); | ||
return acc; | ||
}, {}); | ||
for (const filePath of Object.keys(tests)) { | ||
const fileName = (0, path_1.basename)(filePath); | ||
if (this.options.useDetails) { | ||
const content = (0, getHtmlTable_1.getHtmlTable)(tests[filePath], !!this.options.showError); | ||
// Check if there are any failed tests | ||
const testStatusIcon = (0, getTestStatusIcon_1.getTestStatusIcon)(tests[filePath]); | ||
summary.addDetails(`${testStatusIcon} ${fileName} (${os}${project.name ? ` / ${project.name}` : ""})`, content); | ||
} | ||
else { | ||
summary.addHeading(`${fileName} (${os}${project.name ? ` / ${project.name}` : ""})`, 2); | ||
const tableRows = (0, getTableRows_1.getTableRows)(tests[filePath], !!this.options.showError); | ||
summary.addTable(tableRows); | ||
} | ||
} | ||
} | ||
yield summary.write(); | ||
} | ||
yield (0, processResults_1.processResults)(this.suite, this.options); | ||
if ((result === null || result === void 0 ? void 0 : result.status) !== "passed") { | ||
@@ -127,0 +68,0 @@ core.setFailed("Tests failed"); |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -9,3 +18,7 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
const getTestStatus_1 = require("./getTestStatus"); | ||
const getHtmlTable = (tests, showError) => { | ||
const getTestTitle_1 = require("./getTestTitle"); | ||
const getTestTags_1 = require("./getTestTags"); | ||
const getTestAnnotations_1 = require("./getTestAnnotations"); | ||
const getTestDuration_1 = require("./getTestDuration"); | ||
const getHtmlTable = (tests, showAnnotations, showTags, showError) => __awaiter(void 0, void 0, void 0, function* () { | ||
var _a; | ||
@@ -22,2 +35,5 @@ const convert = new ansi_to_html_1.default(); | ||
content.push(`<th>Retries</th>`); | ||
if (showTags) { | ||
content.push(`<th>Tags</th>`); | ||
} | ||
if (showError) { | ||
@@ -32,11 +48,28 @@ content.push(`<th>Error</th>`); | ||
const result = test.results[test.results.length - 1]; | ||
if (showAnnotations && test.annotations) { | ||
let colLength = 4; | ||
if (showTags) { | ||
colLength++; | ||
} | ||
if (showError) { | ||
colLength++; | ||
} | ||
const annotations = yield (0, getTestAnnotations_1.getTestAnnotations)(test); | ||
if (annotations) { | ||
content.push(`<tr>`); | ||
content.push(`<td colspan="${colLength}">${annotations}</td>`); | ||
content.push(`</tr>`); | ||
} | ||
} | ||
content.push(`<tr>`); | ||
content.push(`<td>${test.title}</td>`); | ||
content.push(`<td>${(0, getTestTitle_1.getTestTitle)(test)}</td>`); | ||
content.push(`<td>${(0, getTestStatus_1.getTestStatus)(test, result)}</td>`); | ||
content.push(`<td>${(result === null || result === void 0 ? void 0 : result.duration) ? `${result.duration / 1000}s` : ""}</td>`); | ||
content.push(`<td>${(0, getTestDuration_1.getTestDuration)(result)}</td>`); | ||
content.push(`<td>${(result === null || result === void 0 ? void 0 : result.retry) || ""}</td>`); | ||
if (showTags) { | ||
content.push(`<td>${(0, getTestTags_1.getTestTags)(test)}</td>`); | ||
} | ||
if (showError) { | ||
content.push(`<td>${(result === null || result === void 0 ? void 0 : result.error) && ((_a = result.error) === null || _a === void 0 ? void 0 : _a.message) | ||
? convert.toHtml(result.error.message) | ||
: ""}</td>`); | ||
const error = ((_a = result === null || result === void 0 ? void 0 : result.error) === null || _a === void 0 ? void 0 : _a.message) || ""; | ||
content.push(`<td>${convert.toHtml(error)}</td>`); | ||
} | ||
@@ -48,3 +81,3 @@ content.push(`</tr>`); | ||
return content.join("\n"); | ||
}; | ||
}); | ||
exports.getHtmlTable = getHtmlTable; |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -9,3 +18,7 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
const getTestStatus_1 = require("./getTestStatus"); | ||
const getTableRows = (tests, showError) => { | ||
const getTestTitle_1 = require("./getTestTitle"); | ||
const getTestTags_1 = require("./getTestTags"); | ||
const getTestAnnotations_1 = require("./getTestAnnotations"); | ||
const getTestDuration_1 = require("./getTestDuration"); | ||
const getTableRows = (tests, showAnnotations, showTags, showError) => __awaiter(void 0, void 0, void 0, function* () { | ||
var _a; | ||
@@ -31,2 +44,8 @@ const convert = new ansi_to_html_1.default(); | ||
]; | ||
if (showTags) { | ||
tableHeaders.push({ | ||
data: "Tags", | ||
header: true, | ||
}); | ||
} | ||
if (showError) { | ||
@@ -42,5 +61,24 @@ tableHeaders.push({ | ||
const result = test.results[test.results.length - 1]; | ||
if (showAnnotations && test.annotations) { | ||
let colLength = 4; | ||
if (showTags) { | ||
colLength++; | ||
} | ||
if (showError) { | ||
colLength++; | ||
} | ||
const annotations = yield (0, getTestAnnotations_1.getTestAnnotations)(test); | ||
if (annotations) { | ||
tableRows.push([ | ||
{ | ||
data: annotations, | ||
header: false, | ||
colspan: `${colLength}`, | ||
}, | ||
]); | ||
} | ||
} | ||
const tableRow = [ | ||
{ | ||
data: test.title, | ||
data: (0, getTestTitle_1.getTestTitle)(test), | ||
header: false, | ||
@@ -53,3 +91,3 @@ }, | ||
{ | ||
data: (result === null || result === void 0 ? void 0 : result.duration) ? `${result.duration / 1000}s` : "", | ||
data: (0, getTestDuration_1.getTestDuration)(result), | ||
header: false, | ||
@@ -62,7 +100,12 @@ }, | ||
]; | ||
if (showTags) { | ||
tableRow.push({ | ||
data: (0, getTestTags_1.getTestTags)(test), | ||
header: false, | ||
}); | ||
} | ||
if (showError) { | ||
const error = ((_a = result === null || result === void 0 ? void 0 : result.error) === null || _a === void 0 ? void 0 : _a.message) || ""; | ||
tableRow.push({ | ||
data: (result === null || result === void 0 ? void 0 : result.error) && ((_a = result.error) === null || _a === void 0 ? void 0 : _a.message) | ||
? convert.toHtml(result.error.message) | ||
: "", | ||
data: convert.toHtml(error), | ||
header: false, | ||
@@ -74,3 +117,3 @@ }); | ||
return tableRows; | ||
}; | ||
}); | ||
exports.getTableRows = getTableRows; |
{ | ||
"name": "@estruyf/github-actions-reporter", | ||
"version": "1.5.1", | ||
"version": "1.6.0-beta.8230051", | ||
"description": "GitHub Actions reporter for Playwright", | ||
@@ -11,3 +11,3 @@ "main": "dist/index.js", | ||
"test:local": "act -j testing -P ubuntu-latest=catthehacker/ubuntu:act-latest --container-architecture linux/amd64 --env GITHUB_STEP_SUMMARY='/dev/stdout'", | ||
"test:jest": "jest" | ||
"test:jest": "jest --coverage --coverageDirectory=../coverage" | ||
}, | ||
@@ -35,3 +35,3 @@ "author": "Elio Struyf <elio@struyfconsulting.be>", | ||
"devDependencies": { | ||
"@playwright/test": "^1.41.2", | ||
"@playwright/test": "^1.42.1", | ||
"@tsconfig/recommended": "^1.0.2", | ||
@@ -46,7 +46,8 @@ "@types/jest": "^29.5.12", | ||
"@actions/core": "^1.10.0", | ||
"ansi-to-html": "^0.7.2" | ||
"ansi-to-html": "^0.7.2", | ||
"marked": "^12.0.1" | ||
}, | ||
"peerDependencies": { | ||
"@playwright/test": "^1.41.2" | ||
"@playwright/test": "^1.42.1" | ||
} | ||
} | ||
} |
@@ -36,4 +36,6 @@ # GitHub Actions Reporter for Playwright | ||
| --- | --- | --- | | ||
| title | Title of the report | `Test results` | | ||
| title | Title of the report. Use an empty string (`""`) to remove the heading. | `Test results` | | ||
| useDetails | Use details in summary which creates expandable content | `false` | | ||
| showAnnotations | Show annotations from tests | `true` | | ||
| showTags | Show tags from tests | `true` | | ||
| showError | Show error message in summary | `false` | | ||
@@ -40,0 +42,0 @@ |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
20
11.11%67
3.08%28388
-12.17%4
33.33%576
-26.9%1
Infinity%6
20%1
Infinity%+ Added
+ Added