diff --git a/src/pytest_html/basereport.py b/src/pytest_html/basereport.py
index dde691b5..300fb6cf 100644
--- a/src/pytest_html/basereport.py
+++ b/src/pytest_html/basereport.py
@@ -149,6 +149,15 @@ def _run_count(self):
return f"{counts}/{self._report.collected_items} {'tests' if plural else 'test'} done."
+ def _hydrate_data(self, data, cells):
+ for index, cell in enumerate(cells):
+ # extract column name and data if column is sortable
+ if "sortable" in self._report.table_header[index]:
+ name_match = re.search(r"col-(\w+)", cell)
+ data_match = re.search(r"
(.*?)", cell)
+ if name_match and data_match:
+ data[name_match.group(1)] = data_match.group(1)
+
@pytest.hookimpl(trylast=True)
def pytest_sessionstart(self, session):
self._report.set_data("environment", self._generate_environment())
@@ -193,35 +202,33 @@ def pytest_runtest_logreport(self, report):
)
outcome = _process_outcome(report)
- data = {
- "result": outcome,
- "duration": _format_duration(report.duration),
- }
+ duration = _format_duration(report.duration)
self._report.total_duration += report.duration
test_id = report.nodeid
if report.when != "call":
test_id += f"::{report.when}"
- data["testId"] = test_id
- data["extras"] = self._process_extras(report, test_id)
+ data = {
+ "extras": self._process_extras(report, test_id),
+ }
links = [
extra
for extra in data["extras"]
if extra["format_type"] in ["json", "text", "url"]
]
cells = [
- f'{data["result"]} | ',
- f'{data["testId"]} | ',
- f'{data["duration"]} | ',
+ f'{outcome} | ',
+ f'{test_id} | ',
+ f'{duration} | ',
f'{_process_links(links)} | ',
]
-
self._config.hook.pytest_html_results_table_row(report=report, cells=cells)
if not cells:
return
cells = _fix_py(cells)
+ self._hydrate_data(data, cells)
data["resultsTableRow"] = cells
# don't count passed setups and teardowns
diff --git a/src/pytest_html/report_data.py b/src/pytest_html/report_data.py
index 2cd01705..b3a70809 100644
--- a/src/pytest_html/report_data.py
+++ b/src/pytest_html/report_data.py
@@ -41,7 +41,6 @@ def __init__(self, config):
self._data = {
"environment": {},
"tests": defaultdict(list),
- "resultsTableRow": None,
}
collapsed = config.getini("render_collapsed")
diff --git a/src/pytest_html/scripts/dom.js b/src/pytest_html/scripts/dom.js
index febcd196..6bcb9d00 100644
--- a/src/pytest_html/scripts/dom.js
+++ b/src/pytest_html/scripts/dom.js
@@ -36,7 +36,7 @@ const dom = {
return envRow
},
- getResultTBody: ({ testId, id, log, duration, extras, resultsTableRow, tableHtml, result, collapsed }) => {
+ getResultTBody: ({ testId, id, log, extras, resultsTableRow, tableHtml, result, collapsed }) => {
const resultBody = templateResult.content.cloneNode(true)
resultBody.querySelector('tbody').classList.add(result.toLowerCase())
resultBody.querySelector('tbody').id = testId
diff --git a/testing/test_e2e.py b/testing/test_e2e.py
index de09990f..dbca2074 100644
--- a/testing/test_e2e.py
+++ b/testing/test_e2e.py
@@ -54,6 +54,23 @@ def _encode_query_params(params):
return urllib.parse.urlencode(params)
+def _parse_result_table(driver):
+ table = driver.find_element(By.ID, "results-table")
+ headers = table.find_elements(By.CSS_SELECTOR, "thead th")
+ rows = table.find_elements(By.CSS_SELECTOR, "tbody tr.collapsible")
+ table_data = []
+ for row in rows:
+ data_dict = {}
+
+ cells = row.find_elements(By.TAG_NAME, "td")
+ for header, cell in zip(headers, cells):
+ data_dict[header.text.lower()] = cell.text
+
+ table_data.append(data_dict)
+
+ return table_data
+
+
def test_visible(pytester, path, driver):
pytester.makepyfile(
"""
@@ -76,3 +93,45 @@ def test_pass_two(): pass
)
result = driver.find_elements(By.CSS_SELECTOR, "tr.collapsible")
assert_that(result).is_length(0)
+
+
+def test_custom_sorting(pytester, path, driver):
+ pytester.makeconftest(
+ """
+ def pytest_html_results_table_header(cells):
+ cells.append(
+ 'Alpha | '
+ )
+
+ def pytest_html_results_table_row(report, cells):
+ data = report.nodeid.split("_")[-1]
+ cells.append(f'{data} | ')
+ """
+ )
+ pytester.makepyfile(
+ """
+ def test_AAA(): pass
+ def test_BBB(): pass
+ """
+ )
+ query_params = _encode_query_params({"sort": "alpha"})
+ driver.get(f"file:///reports{path()}?{query_params}")
+ WebDriverWait(driver, 5).until(
+ ec.visibility_of_all_elements_located((By.CSS_SELECTOR, "#results-table"))
+ )
+
+ rows = _parse_result_table(driver)
+ assert_that(rows).is_length(2)
+ assert_that(rows[0]["test"]).contains("AAA")
+ assert_that(rows[0]["alpha"]).is_equal_to("AAA")
+ assert_that(rows[1]["test"]).contains("BBB")
+ assert_that(rows[1]["alpha"]).is_equal_to("BBB")
+
+ driver.find_element(By.CSS_SELECTOR, "th[data-column-type='alpha']").click()
+ # we might need some wait here to ensure sorting happened
+ rows = _parse_result_table(driver)
+ assert_that(rows).is_length(2)
+ assert_that(rows[0]["test"]).contains("BBB")
+ assert_that(rows[0]["alpha"]).is_equal_to("BBB")
+ assert_that(rows[1]["test"]).contains("AAA")
+ assert_that(rows[1]["alpha"]).is_equal_to("AAA")
diff --git a/testing/test_integration.py b/testing/test_integration.py
index c2e147ae..1bc272bd 100644
--- a/testing/test_integration.py
+++ b/testing/test_integration.py
@@ -358,7 +358,7 @@ def test_function(arg):
page = run(pytester)
assert_results(page, error=1, total_tests=0)
- col_name = get_text(page, "td[class='col-name']")
+ col_name = get_text(page, "td[class='col-testId']")
assert_that(col_name).contains("::setup")
assert_that(get_log(page)).contains("ValueError")