Skip to content

Commit 20399a5

Browse files
committed
Fix: Initial sort and query param
1 parent e4ad806 commit 20399a5

File tree

4 files changed

+87
-18
lines changed

4 files changed

+87
-18
lines changed

docs/user_guide.rst

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,16 +254,16 @@ By setting the query parameter to empty string :code:`?collapsed=""` **none** of
254254

255255
Note that the query parameter is case insensitive, so passing :code:`PASSED` and :code:`passed` has the same effect.
256256

257-
You can also set the collapsed behaviour by setting the :code:`render_collapsed` in a configuration file (pytest.ini, setup.cfg, etc).
257+
You can also set the collapsed behaviour by setting :code:`render_collapsed` in a configuration file (pytest.ini, setup.cfg, etc).
258258
Note that the query parameter takes precedence.
259259

260260
.. code-block:: ini
261261
262262
[pytest]
263263
render_collapsed = failed,error
264264
265-
Controlling Test Result Visibility Via Query Params
266-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
265+
Controlling Test Result Visibility
266+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
267267

268268
By default, all tests are visible, regardless of their results. It is possible to control which tests are visible on
269269
page load by passing the :code:`visible` query parameter. To use this parameter, please pass a comma separated list
@@ -272,7 +272,7 @@ tests in the report that have outcome :code:`passed` or :code:`skipped`.
272272

273273
Note that this match is case insensitive, so passing :code:`PASSED` and :code:`passed` has the same effect.
274274

275-
The following query parameters may be passed:
275+
The following values may be passed:
276276

277277
* :code:`passed`
278278
* :code:`skipped`
@@ -282,9 +282,29 @@ The following query parameters may be passed:
282282
* :code:`xpassed`
283283
* :code:`rerun`
284284

285+
Results Table Sorting
286+
~~~~~~~~~~~~~~~~~~~~~
287+
288+
You can change the sort order of the results table on page load by passing the :code:`sort` query parameter.
289+
290+
The following values may be passed:
291+
292+
* :code:`result`
293+
* :code:`testId`
294+
* :code:`duration`
295+
* :code:`original`
296+
297+
Note that the values are case *sensitive*.
298+
299+
``original`` means that a best effort is made to sort the table in the order of execution.
300+
If tests are run in parallel (with `pytest-xdist`_ for example), then the order may not be
301+
in the correct order.
302+
303+
285304
.. _@pytest.hookimpl(tryfirst=True): https://docs.pytest.org/en/stable/writing_plugins.html#hook-function-ordering-call-example
286305
.. _ansi2html: https://pypi.python.org/pypi/ansi2html/
287306
.. _Content Security Policy (CSP): https://developer.mozilla.org/docs/Web/Security/CSP/
288307
.. _JSON: https://json.org/
289308
.. _pytest-metadata: https://pypi.python.org/pypi/pytest-metadata/
309+
.. _pytest-xdist: https://pypi.python.org/pypi/pytest-xdist/
290310
.. _time.strftime: https://docs.python.org/3/library/time.html#time.strftime

src/pytest_html/scripts/sort.js

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,41 @@
11
const { manager } = require('./datamanager.js')
22
const storageModule = require('./storage.js')
33

4-
const genericSort = (list, key, ascending) => {
5-
const sorted = list.sort((a, b) => a[key] === b[key] ? 0 : a[key] > b[key] ? 1 : -1)
4+
const customSort = (list, key, ascending, customOrder) => {
5+
const sorted = list.sort((a, b) => {
6+
const aValue = a.result.toLowerCase()
7+
const bValue = b.result.toLowerCase()
8+
9+
const aIndex = customOrder.findIndex(item => item.toLowerCase() === aValue)
10+
const bIndex = customOrder.findIndex(item => item.toLowerCase() === bValue)
11+
12+
// Compare the indices to determine the sort order
13+
return aIndex - bIndex
14+
})
15+
16+
if (ascending) {
17+
sorted.reverse()
18+
}
19+
20+
return sorted
21+
}
22+
23+
const genericSort = (list, key, ascending, customOrder) => {
24+
let sorted
25+
if (customOrder) {
26+
sorted = list.sort((a, b) => {
27+
const aValue = a.result.toLowerCase()
28+
const bValue = b.result.toLowerCase()
29+
30+
const aIndex = customOrder.findIndex(item => item.toLowerCase() === aValue)
31+
const bIndex = customOrder.findIndex(item => item.toLowerCase() === bValue)
32+
33+
// Compare the indices to determine the sort order
34+
return aIndex - bIndex
35+
})
36+
} else {
37+
sorted = list.sort((a, b) => a[key] === b[key] ? 0 : a[key] > b[key] ? 1 : -1)
38+
}
639

740
if (ascending) {
841
sorted.reverse()
@@ -14,8 +47,14 @@ const doInitSort = () => {
1447
const type = storageModule.getSort()
1548
const ascending = storageModule.getSortDirection()
1649
const list = manager.testSubset
17-
const sortedList = genericSort(list, type, ascending)
18-
manager.setRender(sortedList)
50+
const initialOrder = ['Error', 'Failed', 'Rerun', 'XFailed', 'XPassed', 'Skipped', 'Passed']
51+
console.log(list)
52+
if (type?.toLowerCase() === 'original') {
53+
manager.setRender(list)
54+
} else {
55+
const sortedList = genericSort(list, type, ascending, initialOrder)
56+
manager.setRender(sortedList)
57+
}
1958
}
2059

2160
const doSort = (type) => {

src/pytest_html/scripts/storage.js

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,18 +65,17 @@ const getCollapsedCategory = (config) => {
6565
const collapsedItems = new URLSearchParams(url.search).get('collapsed')
6666
switch (true) {
6767
case !config && collapsedItems === null:
68-
categories = ['passed'];
69-
break;
68+
categories = ['passed']
69+
break
7070
case collapsedItems?.length === 0 || /^["']{2}$/.test(collapsedItems):
71-
categories = [];
72-
break;
71+
categories = []
72+
break
7373
case /^all$/.test(collapsedItems) || (collapsedItems === null && /^all$/.test(config)):
74-
categories = [...possibleFilters];
75-
break;
74+
categories = [...possibleFilters]
75+
break
7676
default:
77-
categories = collapsedItems?.split(',').map(item => item.toLowerCase()) || config;
78-
break;
79-
}
77+
categories = collapsedItems?.split(',').map(item => item.toLowerCase()) || config
78+
break }
8079
} else {
8180
categories = []
8281
}

testing/unittest.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ describe('Sort tests', () => {
102102
doInitSort()
103103
expect(managerSpy.callCount).to.eql(1)
104104
expect(dataModule.manager.testSubset.map(({ result }) => result)).to.eql([
105-
'passed', 'failed', 'passed', 'passed', 'passed', 'passed',
105+
'failed', 'passed', 'passed', 'passed', 'passed', 'passed',
106106
])
107107
})
108108
it('has stored sort preference', () => {
@@ -116,6 +116,17 @@ describe('Sort tests', () => {
116116
'failed', 'passed', 'passed', 'passed', 'passed', 'passed',
117117
])
118118
})
119+
it('keeps original test execution order', () => {
120+
sortMock = sinon.stub(storageModule, 'getSort').returns('original')
121+
sortDirectionMock = sinon.stub(storageModule, 'getSortDirection').returns(false)
122+
managerSpy = sinon.spy(dataModule.manager, 'setRender')
123+
124+
doInitSort()
125+
expect(managerSpy.callCount).to.eql(1)
126+
expect(dataModule.manager.testSubset.map(({ result }) => result)).to.eql([
127+
'passed', 'failed', 'passed', 'passed', 'passed', 'passed',
128+
])
129+
})
119130
})
120131
describe('doSort', () => {
121132
let getSortMock

0 commit comments

Comments
 (0)