playwright-cucumber-ctrf-generator
Version:
Convert Cucumber JSON reports into CTRF Markdown reports for Playwright
138 lines (137 loc) • 5.64 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertToCTRF = void 0;
const fs = __importStar(require("fs"));
// Helper to format status
const formatStatus = (status) => {
switch (status) {
case "passed": return "✅ Passed";
case "failed": return "❌ Failed";
case "skipped": return "⏭️ Skipped";
case "undefined": return "⚠️ Undefined";
default: return status;
}
};
// Convert time (seconds) to human-readable minutes and seconds
const formatDuration = (duration) => {
if (!duration)
return "0m 0s";
const totalSeconds = Math.floor(duration / 1e9); // Convert nanoseconds to seconds
const minutes = Math.floor(totalSeconds / 60);
const seconds = totalSeconds % 60;
return `${minutes}m ${seconds}s`;
};
// Convert tag to Camel Case and remove '@' symbol
const formatTag = (tag) => {
return tag
.replace(/^@/, "") // Remove '@'
.toLowerCase()
.replace(/(?:^|_|\s)(\w)/g, (_, c) => (c ? c.toUpperCase() : "")); // Convert to Camel Case
};
// Format tags for display
const formatTags = (tags) => {
return tags.map((tag) => formatTag(tag.name)).join(", ");
};
// Calculate the total duration for a scenario
const calculateScenarioDuration = (scenario) => {
return scenario.steps.reduce((sum, step) => sum + (step.result.duration || 0), 0);
};
// Generate CTRF Markdown report
const generateCTRF = (features) => {
let totalFeatures = features.length;
let totalScenarios = 0;
let totalSteps = 0;
let totalPassed = 0;
let totalFailed = 0;
let totalSkipped = 0;
let markdown = ``;
// Summary Calculation
features.forEach((feature) => {
feature.elements.forEach((scenario) => {
totalScenarios++;
totalSteps += scenario.steps.length;
const status = scenario.steps.some((step) => step.result.status === "failed")
? "failed"
: scenario.steps.every((step) => step.result.status === "passed")
? "passed"
: "skipped";
if (status === "passed")
totalPassed++;
else if (status === "failed")
totalFailed++;
else if (status === "skipped")
totalSkipped++;
});
});
// Add the summary as a table at the top
markdown += `## 📊 Test Execution Summary\n\n`;
markdown += `| Total Features | Total Scenarios | Total Steps | ✅ Passed | ❌ Failed | ⏭️ Skipped |\n`;
markdown += `|----------------|-----------------|-------------|----------|----------|-----------|\n`;
markdown += `| ${totalFeatures} | ${totalScenarios} | ${totalSteps} | ${totalPassed} | ${totalFailed} | ${totalSkipped} |\n\n`;
// Add detailed feature sections
features.forEach((feature) => {
markdown += `## Feature: ${feature.name}\n\n`;
markdown += "| Scenario | Status | Duration | Tags |\n";
markdown += "|----------|--------|----------|------|\n";
feature.elements.forEach((scenario) => {
const status = scenario.steps.some((step) => step.result.status === "failed")
? "failed"
: scenario.steps.every((step) => step.result.status === "passed")
? "passed"
: "skipped";
const duration = calculateScenarioDuration(scenario); // Total duration in nanoseconds
const tags = formatTags(scenario.tags); // Format tags
markdown += `| ${scenario.name} | ${formatStatus(status)} | ${formatDuration(duration)} | ${tags} |\n`;
});
markdown += `\n`;
});
markdown += `---\n`;
return markdown;
};
// Main function to convert to CTRF
const convertToCTRF = (inputFilePath, outputFilePath) => {
try {
const data = fs.readFileSync(inputFilePath, "utf-8");
const features = JSON.parse(data);
const markdownReport = generateCTRF(features);
fs.writeFileSync(outputFilePath, markdownReport);
console.log(`✅ CTRF report generated: ${outputFilePath}`);
}
catch (error) {
console.error("❌ Error processing file:", error);
}
};
exports.convertToCTRF = convertToCTRF;