Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/user_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,9 @@ Note that the values are case *sensitive*.
If tests are run in parallel (with `pytest-xdist`_ for example), then the order may not be
in the correct order.

Columns containing numbers, such as a custom sortable column (see :ref:`modifying-results-table`),
are sorted numerically rather than alphabetically.

Formatting the Duration Column
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
20 changes: 19 additions & 1 deletion src/pytest_html/scripts/sort.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
const { manager } = require('./datamanager.js')
const storageModule = require('./storage.js')

const toNumber = (value) => typeof value === 'string' && value.trim() !== '' ? Number(value) : NaN

const compareValues = (a, b) => {
const aNumber = toNumber(a)
const bNumber = toNumber(b)
const aIsNumber = Number.isFinite(aNumber)
const bIsNumber = Number.isFinite(bNumber)

if (aIsNumber && bIsNumber) {
return aNumber - bNumber
}
if (aIsNumber !== bIsNumber) {
// Numeric values are sorted before non-numeric ones
return aIsNumber ? -1 : 1
}
return a === b ? 0 : a > b ? 1 : -1
}

const genericSort = (list, key, ascending, customOrder) => {
let sorted
if (customOrder) {
Expand All @@ -15,7 +33,7 @@ const genericSort = (list, key, ascending, customOrder) => {
return aIndex - bIndex
})
} else {
sorted = list.sort((a, b) => a[key] === b[key] ? 0 : a[key] > b[key] ? 1 : -1)
sorted = list.sort((a, b) => compareValues(a[key], b[key]))
}

if (ascending) {
Expand Down
35 changes: 35 additions & 0 deletions testing/test_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,38 @@ def test_BBB(): pass
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")


def test_custom_numeric_sorting(pytester, path, driver):
pytester.makeconftest(
"""
def pytest_html_results_table_header(cells):
cells.append(
'<th class="sortable speedup" data-column-type="speedup">Speedup</th>'
)

def pytest_html_results_table_row(report, cells):
data = report.nodeid.split("[")[-1].rstrip("]")
cells.append(f'<td class="col-speedup">{data}</td>')
"""
)
pytester.makepyfile(
"""
import pytest

@pytest.mark.parametrize("speedup", ["10.5", "9.25", "100"])
def test_speedup(speedup): pass
"""
)
query_params = _encode_query_params({"sort": "speedup"})
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([row["speedup"] for row in rows]).is_equal_to(["9.25", "10.5", "100"])

driver.find_element(By.CSS_SELECTOR, "th[data-column-type='speedup']").click()
rows = _parse_result_table(driver)
assert_that([row["speedup"] for row in rows]).is_equal_to(["100", "10.5", "9.25"])
16 changes: 16 additions & 0 deletions testing/unittest.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,22 @@ describe('Sort tests', () => {
'failed', 'passed', 'passed', 'passed', 'passed', 'passed',
])
})
it('sort on numeric column', () => {
dataModule.manager.setManager({
tests: ['10.5', 'n/a', '9.25', '100', '-1', '0'].map((speedup) => ({ result: 'passed', speedup })),
})
getSortMock = sinon.stub(storageModule, 'getSort').returns(null)
setSortMock = sinon.stub(storageModule, 'setSort')
getSortDirectionMock = sinon.stub(storageModule, 'getSortDirection').returns(null)
setSortDirection = sinon.stub(storageModule, 'setSortDirection')
managerSpy = sinon.spy(dataModule.manager, 'setRender')

doSort('speedup')
expect(managerSpy.callCount).to.eql(1)
expect(dataModule.manager.testSubset.map(({ speedup }) => speedup)).to.eql([
'-1', '0', '9.25', '10.5', '100', 'n/a',
])
})
})
})

Expand Down