diff --git a/src/pytest_html/scripts/datamanager.js b/src/pytest_html/scripts/datamanager.js index 7d6e7cef..58344972 100644 --- a/src/pytest_html/scripts/datamanager.js +++ b/src/pytest_html/scripts/datamanager.js @@ -1,13 +1,17 @@ +const { getCollapsedCategory } = require('./storage.js') + class DataManager { setManager(data) { + const collapsedCategories = getCollapsedCategory() const dataBlob = { ...data, tests: data.tests.map((test, index) => ({ ...test, id: `test_${index}`, - collapsed: false, + collapsed: collapsedCategories.includes(test.outcome.toLowerCase()), })) } this.data = { ...dataBlob } this.renderData = { ...dataBlob } } + get allData() { return { ...this.data } } diff --git a/src/pytest_html/scripts/filter.js b/src/pytest_html/scripts/filter.js index bfb994eb..4c2ccac7 100644 --- a/src/pytest_html/scripts/filter.js +++ b/src/pytest_html/scripts/filter.js @@ -2,26 +2,23 @@ const { manager } = require('./datamanager.js') const storageModule = require('./storage.js') const getFilteredSubSet = (filter) => - manager.allData.tests.filter(({ outcome }) => !filter.includes(outcome.toLowerCase())) + manager.allData.tests.filter(({ outcome }) => filter.includes(outcome.toLowerCase())) const doInitFilter = () => { - const currentFilter = storageModule.getFilter() + const currentFilter = storageModule.getVisible() const filteredSubset = getFilteredSubSet(currentFilter) manager.setRender(filteredSubset) } -const doFilter = (type, apply) => { - const currentFilter = storageModule.getFilter() - if (!apply) { - currentFilter.push(type) +const doFilter = (type, show) => { + if (show) { + storageModule.showCategory(type) } else { - const index = currentFilter.indexOf(type) - if (index > -1) { - currentFilter.splice(index, 1) - } + storageModule.hideCategory(type) } - storageModule.setFilter(currentFilter) + const currentFilter = storageModule.getVisible() + if (currentFilter.length) { const filteredSubset = getFilteredSubSet(currentFilter) manager.setRender(filteredSubset) diff --git a/src/pytest_html/scripts/main.js b/src/pytest_html/scripts/main.js index 23898611..c4d1787c 100644 --- a/src/pytest_html/scripts/main.js +++ b/src/pytest_html/scripts/main.js @@ -3,7 +3,7 @@ const { dom, findAll } = require('./dom.js') const { manager } = require('./datamanager.js') const { doSort } = require('./sort.js') const { doFilter } = require('./filter.js') -const { getFilter } = require('./storage.js') +const { getVisible } = require('./storage.js') const removeChildren = (node) => { while (node.firstChild) { @@ -74,14 +74,14 @@ const renderDerived = (tests, collectedItems, isFinished) => { { outcome: 'rerun', label: 'Reruns' }, ] - const currentFilter = getFilter() + const currentFilter = getVisible() possibleOutcomes.forEach(({ outcome, label }) => { const count = renderSet.filter((test) => test.outcome.toLowerCase() === outcome).length const input = document.querySelector(`input[data-test-result="${outcome}"]`) document.querySelector(`.${outcome}`).innerText = `${count} ${label}` input.disabled = !count - input.checked = !currentFilter.includes(outcome) + input.checked = currentFilter.includes(outcome) }) const numberOfTests = renderSet.filter(({ outcome }) => diff --git a/src/pytest_html/scripts/storage.js b/src/pytest_html/scripts/storage.js index 794806e3..c7f5fff1 100644 --- a/src/pytest_html/scripts/storage.js +++ b/src/pytest_html/scripts/storage.js @@ -1,22 +1,71 @@ -const getFilter = () => [...new Set(JSON.parse(sessionStorage.getItem('filter')))] +const possibleFiltes = ['passed', 'skipped', 'failed', 'error', 'xfailed', 'xpassed', 'rerun'] + +const getVisible = () => { + const url = new URL(window.location.href) + const settings = new URLSearchParams(url.search).get('visible') || '' + const toret = settings ? + [...new Set(settings.split(',').filter((filter) => possibleFiltes.includes(filter)))] : possibleFiltes + + return toret +} +const hideCategory = (categoryToHide) => { + const url = new URL(window.location.href) + const visibleParams = new URLSearchParams(url.search).get('visible') + const currentVisible = visibleParams ? visibleParams.split(',') : [...possibleFiltes] + const settings = [...new Set(currentVisible)].filter((f) => f !== categoryToHide).join(',') + + url.searchParams.set('visible', settings) + history.pushState({}, null, unescape(url.href)) +} + +const showCategory = (categoryToShow) => { + const url = new URL(window.location.href) + const currentVisible = new URLSearchParams(url.search).get('visible')?.split(',') || [...possibleFiltes] + const settings = [...new Set([categoryToShow, ...currentVisible])] + const noFilter = possibleFiltes.length === settings.length || !settings.length + + noFilter ? url.searchParams.delete('visible') : url.searchParams.set('visible', settings.join(',')) + history.pushState({}, null, unescape(url.href)) +} const setFilter = (currentFilter) => { - sessionStorage.setItem('filter', JSON.stringify(currentFilter)) + if (!possibleFiltes.includes(currentFilter)) { + return + } + const url = new URL(window.location.href) + const settings = [currentFilter, ...new Set(new URLSearchParams(url.search).get('filter').split(','))] + + url.searchParams.set('filter', settings) + history.pushState({}, null, unescape(url.href)) } -const getSort = () => sessionStorage.getItem('sort') -const setSort = (type) => sessionStorage.setItem('sort', type) +const getSort = () => { + const url = new URL(window.location.href) + return new URLSearchParams(url.search).get('sort') || 'outcome' +} +const setSort = (type) => { + const url = new URL(window.location.href) + url.searchParams.set('sort', type) + history.pushState({}, null, unescape(url.href)) +} + +const getCollapsedCategory = () => { + const url = new URL(window.location.href) + const collapsedItems = new URLSearchParams(url.search).get('collapsed') + return collapsedItems?.split(',') || [] +} const getSortDirection = () => JSON.parse(sessionStorage.getItem('sortAsc')) -const setSortDirection = (ascending) => { - sessionStorage.setItem('sortAsc', ascending) -} +const setSortDirection = (ascending) => sessionStorage.setItem('sortAsc', ascending) module.exports = { - getFilter, + getVisible, setFilter, + hideCategory, + showCategory, getSort, getSortDirection, setSort, setSortDirection, + getCollapsedCategory, } diff --git a/testing/unittest.js b/testing/unittest.js index 0429fdb8..67f19b35 100644 --- a/testing/unittest.js +++ b/testing/unittest.js @@ -45,7 +45,7 @@ describe('Filter tests', () => { after(() => dataModule.manager.setManager({ tests: [] })) describe('doInitFilter', () => { it('has no stored filters', () => { - getFilterMock = sinon.stub(storageModule, 'getFilter').returns([]) + getFilterMock = sinon.stub(storageModule, 'getVisible').returns([]) managerSpy = sinon.spy(dataModule.manager, 'setRender') doInitFilter() @@ -55,7 +55,7 @@ describe('Filter tests', () => { ]) }) it('exclude passed', () => { - getFilterMock = sinon.stub(storageModule, 'getFilter').returns(['passed']) + getFilterMock = sinon.stub(storageModule, 'getVisible').returns(['passed']) managerSpy = sinon.spy(dataModule.manager, 'setRender') doInitFilter() @@ -67,7 +67,7 @@ describe('Filter tests', () => { let setFilterMock afterEach(() => setFilterMock.restore()) it('removes a filter', () => { - getFilterMock = sinon.stub(storageModule, 'getFilter').returns(['passed']) + getFilterMock = sinon.stub(storageModule, 'getVisible').returns(['passed']) setFilterMock = sinon.stub(storageModule, 'setFilter') managerSpy = sinon.spy(dataModule.manager, 'setRender') @@ -78,7 +78,7 @@ describe('Filter tests', () => { ]) }) it('applies a filter', () => { - getFilterMock = sinon.stub(storageModule, 'getFilter').returns([]) + getFilterMock = sinon.stub(storageModule, 'getVisible').returns([]) setFilterMock = sinon.stub(storageModule, 'setFilter') managerSpy = sinon.spy(dataModule.manager, 'setRender')