Feature: Template result filters (#697)

This commit is contained in:
Jim Brännlund 2023-07-25 23:01:18 +02:00 committed by GitHub
parent 62b0eea8a3
commit 2ddef713ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 31 deletions

View File

@ -52,6 +52,7 @@ class BaseReport:
__version__, __version__,
self.css, self.css,
self_contained=self_contained, self_contained=self_contained,
outcomes=self._report.data["outcomes"],
test_data=cleanup_unserializable(self._report.data), test_data=cleanup_unserializable(self._report.data),
table_head=self._report.data["resultsTableHeader"], table_head=self._report.data["resultsTableHeader"],
prefix=self._report.data["additionalSummary"]["prefix"], prefix=self._report.data["additionalSummary"]["prefix"],
@ -123,6 +124,7 @@ class BaseReport:
version, version,
styles, styles,
self_contained, self_contained,
outcomes,
test_data, test_data,
table_head, table_head,
summary, summary,
@ -135,6 +137,7 @@ class BaseReport:
version=version, version=version,
styles=styles, styles=styles,
self_contained=self_contained, self_contained=self_contained,
outcomes=outcomes,
test_data=json.dumps(test_data), test_data=json.dumps(test_data),
table_head=table_head, table_head=table_head,
summary=summary, summary=summary,
@ -189,8 +192,9 @@ class BaseReport:
DeprecationWarning, DeprecationWarning,
) )
outcome = _process_outcome(report)
data = { data = {
"result": _process_outcome(report), "result": outcome,
"duration": _format_duration(report.duration), "duration": _format_duration(report.duration),
} }
@ -223,6 +227,10 @@ class BaseReport:
cells = _fix_py(cells) cells = _fix_py(cells)
data["resultsTableRow"] = 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) processed_logs = _process_logs(report)
self._config.hook.pytest_html_results_table_html( self._config.hook.pytest_html_results_table_html(
report=report, data=processed_logs report=report, data=processed_logs

View File

@ -18,6 +18,16 @@ class ReportData:
"<th>Links</th>", "<th>Links</th>",
] ]
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 = { self._data = {
"title": "", "title": "",
"collectedItems": 0, "collectedItems": 0,
@ -27,6 +37,7 @@ class ReportData:
}, },
"runningState": "not_started", "runningState": "not_started",
"environment": {}, "environment": {},
"outcomes": outcomes,
"tests": defaultdict(list), "tests": defaultdict(list),
"additionalSummary": defaultdict(list), "additionalSummary": defaultdict(list),
"resultsTableHeader": default_headers, "resultsTableHeader": default_headers,

View File

@ -3,13 +3,13 @@
<head> <head>
<meta charset="utf-8"/> <meta charset="utf-8"/>
<title id="head-title"></title> <title id="head-title"></title>
{% if self_contained %} {%- if self_contained %}
<style type="text/css"> <style type="text/css">
{{- styles|safe }} {{- styles|safe }}
</style> </style>
{% else %} {% else %}
<link href="{{ styles }}" rel="stylesheet" type="text/css"/> <link href="{{ styles }}" rel="stylesheet" type="text/css"/>
{% endif %} {%- endif %}
</head> </head>
<body> <body>
<h1 id="title"></h1> <h1 id="title"></h1>
@ -55,9 +55,9 @@
<template id="template_results-table__head"> <template id="template_results-table__head">
<thead id="results-table-head"> <thead id="results-table-head">
<tr> <tr>
{% for th in table_head %} {%- for th in table_head %}
{{ th|safe }} {{ th|safe }}
{% endfor %} {%- endfor %}
</tr> </tr>
</thead> </thead>
</template> </template>
@ -78,9 +78,9 @@
<div class="summary"> <div class="summary">
<div class="summary__data"> <div class="summary__data">
<h2>Summary</h2> <h2>Summary</h2>
{% for p in prefix %} {%- for p in prefix %}
{{ p|safe }} {{ p|safe }}
{% endfor %} {%- endfor %}
<p class="run-count"></p> <p class="run-count"></p>
<p class="filter">(Un)check the boxes to filter the results.</p> <p class="filter">(Un)check the boxes to filter the results.</p>
<div class="summary__reload"> <div class="summary__reload">
@ -91,13 +91,10 @@
<div class="summary__spacer"></div> <div class="summary__spacer"></div>
<div class="controls"> <div class="controls">
<div class="filters"> <div class="filters">
<input checked="true" class="filter" data-test-result="failed" name="filter_checkbox" type="checkbox"/><span class="failed"></span> {%- for result, values in outcomes.items() %}
<input checked="true" class="filter" data-test-result="passed" name="filter_checkbox" type="checkbox"/><span class="passed"></span> <input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="{{ result }}" {{ "disabled" if values["value"] == 0 }}/>
<input checked="true" class="filter" data-test-result="skipped" name="filter_checkbox" type="checkbox"/><span class="skipped"></span> <span class="{{ result }}">{{ values["value"] }} {{ values["label"] }}{{ "," if result != "rerun" }}</span>
<input checked="true" class="filter" data-test-result="xfailed" name="filter_checkbox" type="checkbox"/><span class="xfailed"></span> {%- endfor %}
<input checked="true" class="filter" data-test-result="xpassed" name="filter_checkbox" type="checkbox"/><span class="xpassed"></span>
<input checked="true" class="filter" data-test-result="error" name="filter_checkbox" type="checkbox"/><span class="error"></span>
<input checked="true" class="filter" data-test-result="rerun" name="filter_checkbox" type="checkbox"/><span class="rerun"></span>
</div> </div>
<div class="collapse"> <div class="collapse">
<button id="show_all_details">Show all details</button>&nbsp;/&nbsp;<button id="hide_all_details">Hide all details</button> <button id="show_all_details">Show all details</button>&nbsp;/&nbsp;<button id="hide_all_details">Hide all details</button>
@ -105,13 +102,12 @@
</div> </div>
</div> </div>
</div> </div>
{% for s in summary %} {%- for s in summary %}
{{ s|safe }} {{ s|safe }}
{% endfor %} {%- endfor %}
{% for p in postfix %} {%- for p in postfix %}
{{ p|safe }} {{ p|safe }}
{% endfor %} {%- endfor %}
<table id="results-table"></table> <table id="results-table"></table>
</body> </body>
<footer> <footer>

View File

@ -2,7 +2,7 @@ const { dom, findAll } = require('./dom.js')
const { manager } = require('./datamanager.js') const { manager } = require('./datamanager.js')
const { doSort } = require('./sort.js') const { doSort } = require('./sort.js')
const { doFilter } = require('./filter.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) => { const removeChildren = (node) => {
while (node.firstChild) { while (node.firstChild) {
@ -68,17 +68,8 @@ const renderContent = (tests) => {
const renderDerived = (tests, collectedItems, isFinished, formattedDuration) => { const renderDerived = (tests, collectedItems, isFinished, formattedDuration) => {
const currentFilter = getVisible() const currentFilter = getVisible()
possibleResults.forEach(({ result, label }) => { possibleFilters.forEach((result) => {
const count = tests.filter((test) => test.result.toLowerCase() === result).length
const input = document.querySelector(`input[data-test-result="${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) input.checked = currentFilter.includes(result)
}) })