diff --git a/src/pytest_html/basereport.py b/src/pytest_html/basereport.py
index 6d8e1563..9fa47d44 100644
--- a/src/pytest_html/basereport.py
+++ b/src/pytest_html/basereport.py
@@ -52,6 +52,7 @@ def _generate_report(self, self_contained=False):
__version__,
self.css,
self_contained=self_contained,
+ outcomes=self._report.data["outcomes"],
test_data=cleanup_unserializable(self._report.data),
table_head=self._report.data["resultsTableHeader"],
prefix=self._report.data["additionalSummary"]["prefix"],
@@ -123,6 +124,7 @@ def _render_html(
version,
styles,
self_contained,
+ outcomes,
test_data,
table_head,
summary,
@@ -135,6 +137,7 @@ def _render_html(
version=version,
styles=styles,
self_contained=self_contained,
+ outcomes=outcomes,
test_data=json.dumps(test_data),
table_head=table_head,
summary=summary,
@@ -189,8 +192,9 @@ def pytest_runtest_logreport(self, report):
DeprecationWarning,
)
+ outcome = _process_outcome(report)
data = {
- "result": _process_outcome(report),
+ "result": outcome,
"duration": _format_duration(report.duration),
}
@@ -223,6 +227,10 @@ def pytest_runtest_logreport(self, report):
cells = _fix_py(cells)
data["resultsTableRow"] = cells
+ # don't count passed setups and teardowns
+ if not (report.when in ["setup", "teardown"] and report.outcome == "passed"):
+ self._report.data["outcomes"][outcome.lower()]["value"] += 1
+
processed_logs = _process_logs(report)
self._config.hook.pytest_html_results_table_html(
report=report, data=processed_logs
diff --git a/src/pytest_html/report_data.py b/src/pytest_html/report_data.py
index f16ea608..2524df80 100644
--- a/src/pytest_html/report_data.py
+++ b/src/pytest_html/report_data.py
@@ -18,6 +18,16 @@ def __init__(self, config):
"
Links ",
]
+ outcomes = {
+ "failed": {"label": "Failed", "value": 0},
+ "passed": {"label": "Passed", "value": 0},
+ "skipped": {"label": "Skipped", "value": 0},
+ "xfailed": {"label": "Unexpected failures", "value": 0},
+ "xpassed": {"label": "Unexpected passes", "value": 0},
+ "error": {"label": "Errors", "value": 0},
+ "rerun": {"label": "Reruns", "value": 0},
+ }
+
self._data = {
"title": "",
"collectedItems": 0,
@@ -27,6 +37,7 @@ def __init__(self, config):
},
"runningState": "not_started",
"environment": {},
+ "outcomes": outcomes,
"tests": defaultdict(list),
"additionalSummary": defaultdict(list),
"resultsTableHeader": default_headers,
diff --git a/src/pytest_html/resources/index.jinja2 b/src/pytest_html/resources/index.jinja2
index 5e8369a0..5b0b5b8e 100644
--- a/src/pytest_html/resources/index.jinja2
+++ b/src/pytest_html/resources/index.jinja2
@@ -3,13 +3,13 @@
- {% if self_contained %}
+ {%- if self_contained %}
{% else %}
- {% endif %}
+ {%- endif %}
@@ -55,9 +55,9 @@
- {% for th in table_head %}
- {{ th|safe }}
- {% endfor %}
+ {%- for th in table_head %}
+ {{ th|safe }}
+ {%- endfor %}
@@ -78,9 +78,9 @@
Summary
- {% for p in prefix %}
+ {%- for p in prefix %}
{{ p|safe }}
- {% endfor %}
+ {%- endfor %}
(Un)check the boxes to filter the results.
- {% for s in summary %}
+ {%- for s in summary %}
{{ s|safe }}
- {% endfor %}
- {% for p in postfix %}
+ {%- endfor %}
+ {%- for p in postfix %}
{{ p|safe }}
- {% endfor %}
-
+ {%- endfor %}
diff --git a/src/pytest_html/scripts/main.js b/src/pytest_html/scripts/main.js
index 24005dac..46fec6a2 100644
--- a/src/pytest_html/scripts/main.js
+++ b/src/pytest_html/scripts/main.js
@@ -2,7 +2,7 @@ const { dom, findAll } = require('./dom.js')
const { manager } = require('./datamanager.js')
const { doSort } = require('./sort.js')
const { doFilter } = require('./filter.js')
-const { getVisible, getSort, getSortDirection, possibleResults } = require('./storage.js')
+const { getVisible, getSort, getSortDirection, possibleFilters } = require('./storage.js')
const removeChildren = (node) => {
while (node.firstChild) {
@@ -68,17 +68,8 @@ const renderContent = (tests) => {
const renderDerived = (tests, collectedItems, isFinished, formattedDuration) => {
const currentFilter = getVisible()
- possibleResults.forEach(({ result, label }) => {
- const count = tests.filter((test) => test.result.toLowerCase() === result).length
+ possibleFilters.forEach((result) => {
const input = document.querySelector(`input[data-test-result="${result}"]`)
- const lastInput = document.querySelector(`input[data-test-result="${result}"]:last-of-type`)
- document.querySelector(`.${result}`).innerText = `${count} ${label}`
- // add a comma and whitespace between the results
- if (input !== lastInput) {
- document.querySelector(`.${result}`).innerText += ', '
- }
-
- input.disabled = !count
input.checked = currentFilter.includes(result)
})