Skip to content

Commit 2ddef71

Browse files
authored
Feature: Template result filters (#697)
1 parent 62b0eea commit 2ddef71

File tree

4 files changed

+37
-31
lines changed

4 files changed

+37
-31
lines changed

src/pytest_html/basereport.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def _generate_report(self, self_contained=False):
5252
__version__,
5353
self.css,
5454
self_contained=self_contained,
55+
outcomes=self._report.data["outcomes"],
5556
test_data=cleanup_unserializable(self._report.data),
5657
table_head=self._report.data["resultsTableHeader"],
5758
prefix=self._report.data["additionalSummary"]["prefix"],
@@ -123,6 +124,7 @@ def _render_html(
123124
version,
124125
styles,
125126
self_contained,
127+
outcomes,
126128
test_data,
127129
table_head,
128130
summary,
@@ -135,6 +137,7 @@ def _render_html(
135137
version=version,
136138
styles=styles,
137139
self_contained=self_contained,
140+
outcomes=outcomes,
138141
test_data=json.dumps(test_data),
139142
table_head=table_head,
140143
summary=summary,
@@ -189,8 +192,9 @@ def pytest_runtest_logreport(self, report):
189192
DeprecationWarning,
190193
)
191194

195+
outcome = _process_outcome(report)
192196
data = {
193-
"result": _process_outcome(report),
197+
"result": outcome,
194198
"duration": _format_duration(report.duration),
195199
}
196200

@@ -223,6 +227,10 @@ def pytest_runtest_logreport(self, report):
223227
cells = _fix_py(cells)
224228
data["resultsTableRow"] = cells
225229

230+
# don't count passed setups and teardowns
231+
if not (report.when in ["setup", "teardown"] and report.outcome == "passed"):
232+
self._report.data["outcomes"][outcome.lower()]["value"] += 1
233+
226234
processed_logs = _process_logs(report)
227235
self._config.hook.pytest_html_results_table_html(
228236
report=report, data=processed_logs

src/pytest_html/report_data.py

+11
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ def __init__(self, config):
1818
"<th>Links</th>",
1919
]
2020

21+
outcomes = {
22+
"failed": {"label": "Failed", "value": 0},
23+
"passed": {"label": "Passed", "value": 0},
24+
"skipped": {"label": "Skipped", "value": 0},
25+
"xfailed": {"label": "Unexpected failures", "value": 0},
26+
"xpassed": {"label": "Unexpected passes", "value": 0},
27+
"error": {"label": "Errors", "value": 0},
28+
"rerun": {"label": "Reruns", "value": 0},
29+
}
30+
2131
self._data = {
2232
"title": "",
2333
"collectedItems": 0,
@@ -27,6 +37,7 @@ def __init__(self, config):
2737
},
2838
"runningState": "not_started",
2939
"environment": {},
40+
"outcomes": outcomes,
3041
"tests": defaultdict(list),
3142
"additionalSummary": defaultdict(list),
3243
"resultsTableHeader": default_headers,

src/pytest_html/resources/index.jinja2

+15-19
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
<head>
44
<meta charset="utf-8"/>
55
<title id="head-title"></title>
6-
{% if self_contained %}
6+
{%- if self_contained %}
77
<style type="text/css">
88
{{- styles|safe }}
99
</style>
1010
{% else %}
1111
<link href="{{ styles }}" rel="stylesheet" type="text/css"/>
12-
{% endif %}
12+
{%- endif %}
1313
</head>
1414
<body>
1515
<h1 id="title"></h1>
@@ -55,9 +55,9 @@
5555
<template id="template_results-table__head">
5656
<thead id="results-table-head">
5757
<tr>
58-
{% for th in table_head %}
59-
{{ th|safe }}
60-
{% endfor %}
58+
{%- for th in table_head %}
59+
{{ th|safe }}
60+
{%- endfor %}
6161
</tr>
6262
</thead>
6363
</template>
@@ -78,9 +78,9 @@
7878
<div class="summary">
7979
<div class="summary__data">
8080
<h2>Summary</h2>
81-
{% for p in prefix %}
81+
{%- for p in prefix %}
8282
{{ p|safe }}
83-
{% endfor %}
83+
{%- endfor %}
8484
<p class="run-count"></p>
8585
<p class="filter">(Un)check the boxes to filter the results.</p>
8686
<div class="summary__reload">
@@ -91,27 +91,23 @@
9191
<div class="summary__spacer"></div>
9292
<div class="controls">
9393
<div class="filters">
94-
<input checked="true" class="filter" data-test-result="failed" name="filter_checkbox" type="checkbox"/><span class="failed"></span>
95-
<input checked="true" class="filter" data-test-result="passed" name="filter_checkbox" type="checkbox"/><span class="passed"></span>
96-
<input checked="true" class="filter" data-test-result="skipped" name="filter_checkbox" type="checkbox"/><span class="skipped"></span>
97-
<input checked="true" class="filter" data-test-result="xfailed" name="filter_checkbox" type="checkbox"/><span class="xfailed"></span>
98-
<input checked="true" class="filter" data-test-result="xpassed" name="filter_checkbox" type="checkbox"/><span class="xpassed"></span>
99-
<input checked="true" class="filter" data-test-result="error" name="filter_checkbox" type="checkbox"/><span class="error"></span>
100-
<input checked="true" class="filter" data-test-result="rerun" name="filter_checkbox" type="checkbox"/><span class="rerun"></span>
94+
{%- for result, values in outcomes.items() %}
95+
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="{{ result }}" {{ "disabled" if values["value"] == 0 }}/>
96+
<span class="{{ result }}">{{ values["value"] }} {{ values["label"] }}{{ "," if result != "rerun" }}</span>
97+
{%- endfor %}
10198
</div>
10299
<div class="collapse">
103100
<button id="show_all_details">Show all details</button>&nbsp;/&nbsp;<button id="hide_all_details">Hide all details</button>
104101
<div>
105102
</div>
106103
</div>
107104
</div>
108-
{% for s in summary %}
105+
{%- for s in summary %}
109106
{{ s|safe }}
110-
{% endfor %}
111-
{% for p in postfix %}
107+
{%- endfor %}
108+
{%- for p in postfix %}
112109
{{ p|safe }}
113-
{% endfor %}
114-
110+
{%- endfor %}
115111
<table id="results-table"></table>
116112
</body>
117113
<footer>

src/pytest_html/scripts/main.js

+2-11
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ const { dom, findAll } = require('./dom.js')
22
const { manager } = require('./datamanager.js')
33
const { doSort } = require('./sort.js')
44
const { doFilter } = require('./filter.js')
5-
const { getVisible, getSort, getSortDirection, possibleResults } = require('./storage.js')
5+
const { getVisible, getSort, getSortDirection, possibleFilters } = require('./storage.js')
66

77
const removeChildren = (node) => {
88
while (node.firstChild) {
@@ -68,17 +68,8 @@ const renderContent = (tests) => {
6868

6969
const renderDerived = (tests, collectedItems, isFinished, formattedDuration) => {
7070
const currentFilter = getVisible()
71-
possibleResults.forEach(({ result, label }) => {
72-
const count = tests.filter((test) => test.result.toLowerCase() === result).length
71+
possibleFilters.forEach((result) => {
7372
const input = document.querySelector(`input[data-test-result="${result}"]`)
74-
const lastInput = document.querySelector(`input[data-test-result="${result}"]:last-of-type`)
75-
document.querySelector(`.${result}`).innerText = `${count} ${label}`
76-
// add a comma and whitespace between the results
77-
if (input !== lastInput) {
78-
document.querySelector(`.${result}`).innerText += ', '
79-
}
80-
81-
input.disabled = !count
8273
input.checked = currentFilter.includes(result)
8374
})
8475

0 commit comments

Comments
 (0)