yachr
Version:
Yet another cucumber html reporter
495 lines (421 loc) • 13.1 kB
HTML
<html lang="en">
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
body {
font-family: 'Roboto', sans-serif;
}
summary {
background-color: rgb(235, 231, 231);
padding: 10px
}
details>summary {
list-style: none;
}
details summary::-webkit-details-marker {
display: none;
}
details summary::-moz-list-bullet {
display: none;
}
.chart {
margin-bottom: 25px;
width: 620px;
display: inline-block;
}
details {
display: inline-block;
width: 620px;
vertical-align: top;
}
details section {
padding: 10px;
padding-bottom: 0px;
overflow: hidden;
}
table i {
vertical-align: middle;
}
.summary-table {
display: table;
width: 80%;
border-collapse: collapse;
border-spacing: 0;
overflow: auto;
}
.summary-hr-row {
background-color: #fff;
border-top: 1px solid #ccc;
}
.summary-table th {
font-size: 14px;
}
.summary-row {
background-color: #fff;
border-top: 1px solid #ccc;
}
.summary-cell {
padding: 6px 13px;
border: 1px solid #ddd;
}
.scenario section {
padding-left: 10px;
}
.scenario {
margin-bottom: 5px;
}
.feature {
margin-bottom: 5px;
}
.scenario details p:hover {
cursor: hand;
}
.feature-rollup-summary i {
vertical-align: bottom;
}
.passing-feature {
border: 1px solid rgba(75, 192, 192, 1)
}
.passing-feature>summary {
background-color: rgba(75, 192, 192, 0.2)
}
.passing-scenario {
border: 1px solid rgba(75, 192, 192, 1)
}
.passing-scenario>summary {
background-color: rgba(75, 192, 192, 0.2)
}
.step {
border-left: solid 5px;
padding-left: 5px;
padding-right: 5px;
color: black;
}
/* Adds a gray border around the steps data table */
.scenario td {
border: 1px solid gray;
}
/* Removes the cell spacing so the border above looks clean */
.scenario table {
border-collapse: collapse;
}
/* Shade the header row of the table */
.scenario table tr:first-child td {
background-color: #d3d3d385;
}
.passing-step {
border-color: rgba(75, 192, 192, 1);
background-color: rgba(75, 192, 192, 0.2)
}
.failing-feature {
border: 1px solid rgb(255, 99, 132, 1)
}
.failing-feature>summary {
background-color: rgba(255, 99, 132, 0.2)
}
.failing-scenario {
border: 1px solid rgb(255, 99, 132, 1)
}
.failing-scenario>summary {
background-color: rgba(255, 99, 132, 0.2)
}
.failing-step {
border-color: rgba(255, 99, 132, 1);
background-color: rgba(255, 99, 132, 0.2)
}
.ambiguous-feature {
border: 1px solid rgb(255, 140, 0, 1)
}
.ambiguous-feature>summary {
background-color: rgba(255, 140, 0, 0.2)
}
.ambiguous-scenario {
border: 1px solid rgb(255, 140, 0, 1)
}
.ambiguous-scenario>summary {
background-color: rgba(255, 140, 0, 0.2)
}
.ambiguous-step {
border-color: rgba(255, 140, 0, 1);
background-color: rgba(255, 140, 0, 0.2)
}
.undefined-feature {
border: 1px solid rgb(54, 162, 235, 1)
}
.undefined-feature>summary {
background-color: rgba(54, 162, 235, 0.2)
}
.undefined-scenario {
border: 1px solid rgb(54, 162, 235, 1)
}
.undefined-scenario>summary {
background-color: rgba(54, 162, 235, 0.2)
}
.undefined-step {
border-color: rgba(54, 162, 235, 1);
background-color: rgba(54, 162, 235, 0.2)
}
.pending-feature {
border: 1px solid rgba(111, 109, 107, 1);
}
.pending-feature>summary {
background-color: rgba(111, 109, 107, 0.2);
}
.pending-scenario {
border: 1px solid rgba(111, 109, 107, 1);
}
.pending-scenario>summary {
background-color: rgba(111, 109, 107, 0.2);
}
.pending-step {
border-color: rgba(111, 109, 107, 1);
background-color: rgba(111, 109, 107, 0.2)
}
.summary-counts-failing {
color: rgba(255, 99, 132, 1);
}
.summary-counts-undefined {
color: rgb(54, 162, 235, 1)
}
.summary-counts-ambiguous {
color: rgba(255, 140, 0, 1);
}
.summary-counts-passing {
color: rgba(75, 192, 192, 1);
}
/* Thanks to: https://www.w3schools.com/howto/howto_css_modals.asp */
/* The Modal (background) */
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
/* Modal Content/Box */
.modal-content {
background-color: #fefefe;
margin: 15% auto; /* 15% from the top and centered */
padding: 20px;
border: 1px solid #888;
width: 80%; /* Could be more or less, depending on screen size */
}
/* The Close Button */
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
</style>
</head>
<body style="width: 1280px; margin: auto;">
<h1>Specification Execution Results</h1>
<span style="position: absolute;right: 40px;top: 15px; font-size: 12px; color: lightgray;">Generated at:
{{ generateTime }}</span>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<script>
// if the user is looking at the modal, and clicks the background close the modal.
window.onclick = (event) => {
// Don't close if they are trying to open the modal
if (!event.target.classList.contains('screenshot-thumbnail')) {
document.getElementById('myModal').style.display = 'none';
}
}
</script>
<div class="chart">
<canvas id="myChart"></canvas>
</div>
<div class="chart">
<canvas id="myChart2"></canvas>
</div>
<script>
Chart.defaults.global.defaultFontFamily = 'Roboto';
Chart.defaults.global.defaultFontSize = 16;
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Failed', 'Undefined', 'Pending', 'Passed', 'Ambiguous'],
datasets: [{
data: [
{{ countOf cucumberReportSummary.featureSummary 'failed' }},
{{ countOf cucumberReportSummary.featureSummary 'undefined' }},
{{ countOf cucumberReportSummary.featureSummary 'pending' }},
{{ countOf cucumberReportSummary.featureSummary 'passed' }},
{{ countOf cucumberReportSummary.featureSummary 'ambiguous' }},
],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(111, 109, 107, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(255, 140, 0, 0.2)',
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(111, 109, 107, 1)',
'rgba(75, 192, 192, 1)',
'rgba(255, 140, 0, 1)',
],
borderWidth: 1
}]
},
options: {
responsive: true,
legend: {
display: false
},
title: {
display: true,
text: "Feature Summary ({{ countOf cucumberReportSummary.featureSummary 'total'}} Total)",
fontSize: 24
},
scales: {
yAxes: [{
ticks: {
precision: 0,
beginAtZero: true,
suggestedMax: 5
}
}]
}
}
});
var ctx2 = document.getElementById('myChart2').getContext('2d');
var myChart2 = new Chart(ctx2, {
type: 'bar',
responsive: true,
data: {
labels: ['Failed', 'Undefined', 'Pending', 'Passed', 'Ambiguous'],
datasets: [{
data: [
{{ countOf cucumberReportSummary.scenarioSummary 'failed' }},
{{ countOf cucumberReportSummary.scenarioSummary 'undefined' }},
{{ countOf cucumberReportSummary.scenarioSummary 'pending' }},
{{ countOf cucumberReportSummary.scenarioSummary 'passed' }},
{{ countOf cucumberReportSummary.scenarioSummary 'ambiguous' }},
],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(111, 109, 107, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(255, 140, 0, 0.2)',
// 'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(111, 109, 107, 1)',
'rgba(75, 192, 192, 1)',
'rgba(255, 140, 0, 1)',
// 'rgba(153, 102, 255, 1)',
// 'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
responsive: true,
legend: {
display: false
},
title: {
display: true,
text: "Scenario Summary ({{countOf cucumberReportSummary.scenarioSummary 'total' }} Total)",
fontSize: 24
},
scales: {
yAxes: [{
ticks: {
precision: 0,
beginAtZero: true,
suggestedMax: 5
}
}]
}
}
});
</script>
<table class="summary-table" style="margin: auto;">
<header>
<thead>
<tr class="summary-hr-row">
<th class="summary-cell"><i class="material-icons" title="The status of a scenario or feature is based on the worst status of its steps, in order: ambiguous -> failed -> undefined -> pending -> passed">info</i></th>
<th class="summary-cell">Failed</th>
<th class="summary-cell">Undefined</th>
<th class="summary-cell">Pending</th>
<th class="summary-cell">Passed</th>
<th class="summary-cell">Ambiguous</th>
<th class="summary-cell">Total</th>
</tr>
</thead>
</header>
<tr class="summary-row">
<th class="summary-cell" align="center">Features</th>
<td class="summary-cell" align="center">{{ countOf cucumberReportSummary.featureSummary 'failed' }}</td>
<td class="summary-cell" align="center">{{ countOf cucumberReportSummary.featureSummary 'undefined'}}</td>
<td class="summary-cell" align="center">{{ countOf cucumberReportSummary.featureSummary 'pending' }}</td>
<td class="summary-cell" align="center">{{ countOf cucumberReportSummary.featureSummary 'passed' }}</td>
<td class="summary-cell" align="center">{{ countOf cucumberReportSummary.featureSummary 'ambiguous' }}</td>
<td class="summary-cell" align="center">{{ countOf cucumberReportSummary.featureSummary 'total' }}</td>
</tr>
<tr class="summary-row">
<th class="summary-cell" align="center">Scenarios</th>
<td class="summary-cell" align="center">{{ countOf cucumberReportSummary.scenarioSummary 'failed' }} </td>
<td class="summary-cell" align="center">{{ countOf cucumberReportSummary.scenarioSummary 'undefined' }}</td>
<td class="summary-cell" align="center">{{ countOf cucumberReportSummary.scenarioSummary 'pending' }}</td>
<td class="summary-cell" align="center">{{ countOf cucumberReportSummary.scenarioSummary 'passed' }}</td>
<td class="summary-cell" align="center">{{ countOf cucumberReportSummary.scenarioSummary 'ambiguous' }}</td>
<td class="summary-cell" align="center">{{ countOf cucumberReportSummary.scenarioSummary 'total' }}</td>
</tr>
</table>
<hr />
<div>
<h2>Feature Breakdown</h2>
{{#each cucumberReportSummary.featureSummary.failingFeatures}}
{{> feature}}
{{/each}}
{{#each cucumberReportSummary.featureSummary.ambiguousFeatures}}
{{> feature}}
{{/each}}
{{#each cucumberReportSummary.featureSummary.undefinedFeatures}}
{{> feature}}
{{/each}}
{{#each cucumberReportSummary.featureSummary.pendingFeatures}}
{{> feature}}
{{/each}}
{{#each cucumberReportSummary.featureSummary.passingFeatures}}
{{> feature}}
{{/each}}
</body>
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span onclick="document.getElementById('myModal').style.display = 'none';" class="close">×</span>
<img id="modal-image"></img>
</div>
</div>
</html>
<script id="foo-partial" type="text/x-handlebars-template">
<div class="foo">
<h2>{{foo}}</h2>
<div class="foo_bar">{{foo_bar}}</div>
</div>
</script>