Fix: Broken sorting for custom columns (#715)
This commit is contained in:
parent
5e3cca16ee
commit
abde929fc8
|
@ -149,6 +149,15 @@ class BaseReport:
|
||||||
|
|
||||||
return f"{counts}/{self._report.collected_items} {'tests' if plural else 'test'} done."
|
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"<td.*?>(.*?)</td>", cell)
|
||||||
|
if name_match and data_match:
|
||||||
|
data[name_match.group(1)] = data_match.group(1)
|
||||||
|
|
||||||
@pytest.hookimpl(trylast=True)
|
@pytest.hookimpl(trylast=True)
|
||||||
def pytest_sessionstart(self, session):
|
def pytest_sessionstart(self, session):
|
||||||
self._report.set_data("environment", self._generate_environment())
|
self._report.set_data("environment", self._generate_environment())
|
||||||
|
@ -193,35 +202,33 @@ class BaseReport:
|
||||||
)
|
)
|
||||||
|
|
||||||
outcome = _process_outcome(report)
|
outcome = _process_outcome(report)
|
||||||
data = {
|
duration = _format_duration(report.duration)
|
||||||
"result": outcome,
|
|
||||||
"duration": _format_duration(report.duration),
|
|
||||||
}
|
|
||||||
self._report.total_duration += report.duration
|
self._report.total_duration += report.duration
|
||||||
|
|
||||||
test_id = report.nodeid
|
test_id = report.nodeid
|
||||||
if report.when != "call":
|
if report.when != "call":
|
||||||
test_id += f"::{report.when}"
|
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 = [
|
links = [
|
||||||
extra
|
extra
|
||||||
for extra in data["extras"]
|
for extra in data["extras"]
|
||||||
if extra["format_type"] in ["json", "text", "url"]
|
if extra["format_type"] in ["json", "text", "url"]
|
||||||
]
|
]
|
||||||
cells = [
|
cells = [
|
||||||
f'<td class="col-result">{data["result"]}</td>',
|
f'<td class="col-result">{outcome}</td>',
|
||||||
f'<td class="col-name">{data["testId"]}</td>',
|
f'<td class="col-testId">{test_id}</td>',
|
||||||
f'<td class="col-duration">{data["duration"]}</td>',
|
f'<td class="col-duration">{duration}</td>',
|
||||||
f'<td class="col-links">{_process_links(links)}</td>',
|
f'<td class="col-links">{_process_links(links)}</td>',
|
||||||
]
|
]
|
||||||
|
|
||||||
self._config.hook.pytest_html_results_table_row(report=report, cells=cells)
|
self._config.hook.pytest_html_results_table_row(report=report, cells=cells)
|
||||||
if not cells:
|
if not cells:
|
||||||
return
|
return
|
||||||
|
|
||||||
cells = _fix_py(cells)
|
cells = _fix_py(cells)
|
||||||
|
self._hydrate_data(data, cells)
|
||||||
data["resultsTableRow"] = cells
|
data["resultsTableRow"] = cells
|
||||||
|
|
||||||
# don't count passed setups and teardowns
|
# don't count passed setups and teardowns
|
||||||
|
|
|
@ -41,7 +41,6 @@ class ReportData:
|
||||||
self._data = {
|
self._data = {
|
||||||
"environment": {},
|
"environment": {},
|
||||||
"tests": defaultdict(list),
|
"tests": defaultdict(list),
|
||||||
"resultsTableRow": None,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
collapsed = config.getini("render_collapsed")
|
collapsed = config.getini("render_collapsed")
|
||||||
|
|
|
@ -36,7 +36,7 @@ const dom = {
|
||||||
|
|
||||||
return envRow
|
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)
|
const resultBody = templateResult.content.cloneNode(true)
|
||||||
resultBody.querySelector('tbody').classList.add(result.toLowerCase())
|
resultBody.querySelector('tbody').classList.add(result.toLowerCase())
|
||||||
resultBody.querySelector('tbody').id = testId
|
resultBody.querySelector('tbody').id = testId
|
||||||
|
|
|
@ -54,6 +54,23 @@ def _encode_query_params(params):
|
||||||
return urllib.parse.urlencode(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):
|
def test_visible(pytester, path, driver):
|
||||||
pytester.makepyfile(
|
pytester.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -76,3 +93,45 @@ def test_visible(pytester, path, driver):
|
||||||
)
|
)
|
||||||
result = driver.find_elements(By.CSS_SELECTOR, "tr.collapsible")
|
result = driver.find_elements(By.CSS_SELECTOR, "tr.collapsible")
|
||||||
assert_that(result).is_length(0)
|
assert_that(result).is_length(0)
|
||||||
|
|
||||||
|
|
||||||
|
def test_custom_sorting(pytester, path, driver):
|
||||||
|
pytester.makeconftest(
|
||||||
|
"""
|
||||||
|
def pytest_html_results_table_header(cells):
|
||||||
|
cells.append(
|
||||||
|
'<th class="sortable alpha" data-column-type="alpha">Alpha</th>'
|
||||||
|
)
|
||||||
|
|
||||||
|
def pytest_html_results_table_row(report, cells):
|
||||||
|
data = report.nodeid.split("_")[-1]
|
||||||
|
cells.append(f'<td class="col-alpha">{data}</td>')
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
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")
|
||||||
|
|
|
@ -358,7 +358,7 @@ class TestHTML:
|
||||||
page = run(pytester)
|
page = run(pytester)
|
||||||
assert_results(page, error=1, total_tests=0)
|
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(col_name).contains("::setup")
|
||||||
assert_that(get_log(page)).contains("ValueError")
|
assert_that(get_log(page)).contains("ValueError")
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue