Skip to content
Merged
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
22 changes: 15 additions & 7 deletions src/layout/css/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -183,23 +183,31 @@ div.media {
flex: 0 0 25px;
align-items: center;
}

.collapsed {
display: none;
}

.expander::after {
content: ' (show details)';
@mixin rowToggle {
color: #bbb;
font-style: italic;
cursor: pointer;
}

.collapser::after {
content: ' (hide details)';
color: #bbb;
font-style: italic;
.col-result {
cursor: pointer;
&:hover::after {
@include rowToggle;
}
}
.col-result.collapser {
&:hover::after {
content: ' (hide details)';
}
}
.col-result.expander {
&:hover::after {
content: ' (show details)';
}
}

/*------------------
Expand Down
17 changes: 13 additions & 4 deletions src/pytest_html/nextgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,17 @@ def _data_content(self, *args, **kwargs):
def _media_content(self, *args, **kwargs):
pass

def _process_extras(self, report):
test_id = report.nodeid.encode("utf-8").decode("unicode_escape")
def _process_extras(self, report, test_id):
test_index = hasattr(report, "rerun") and report.rerun + 1 or 0
report_extras = getattr(report, "extras", [])
for extra_index, extra in enumerate(report_extras):
content = extra["content"]
asset_name = self._asset_filename(test_id, extra_index, test_index, extra['extension'])
asset_name = self._asset_filename(
test_id.encode("utf-8").decode("unicode_escape"),
extra_index,
test_index,
extra['extension']
)
if extra["format_type"] == extras.FORMAT_JSON:
content = json.dumps(content)
extra["content"] = self._data_content(content, asset_name=asset_name, mime_type=extra["mime_type"])
Expand Down Expand Up @@ -216,6 +220,11 @@ def pytest_runtest_logreport(self, report):
config=self._config, report=report
)

test_id = report.nodeid
if report.when != "call":
test_id += f"::{report.when}"
data["nodeid"] = test_id

if report.longrepr:
data["longreprtext"] = report.longreprtext

Expand All @@ -229,7 +238,7 @@ def pytest_runtest_logreport(self, report):
self._config.hook.pytest_html_results_table_html(report=report, data=table_html)
data.update({"tableHtml": table_html})

data.update({"extras": self._process_extras(report)})
data.update({"extras": self._process_extras(report, test_id)})
self._report.data["tests"].append(data)
self._generate_report()

Expand Down
9 changes: 9 additions & 0 deletions src/pytest_html/resources/index.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@
<th colspan="4">No results found. Try to check the filters</th>
</tr>
</template>
<template id="template_table-colgroup">
<colgroup>
<col span="1" style="width: 25%;">
<col span="1" style="width: 25%;">
<col span="1" style="width: 25%;">
<col span="1" style="width: 25%;">
</colgroup>
</template>
<!-- END TEMPLATES -->
<div class="summary">
<div class="summary__data">
Expand Down Expand Up @@ -113,6 +121,7 @@
{% for p in postfix %}
{{ p|safe }}
{% endfor %}

<table id="results-table"></table>
</body>
<footer>
Expand Down
15 changes: 9 additions & 6 deletions src/pytest_html/resources/style.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 14 additions & 5 deletions src/pytest_html/scripts/datamanager.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
class DataManager {
setManager(data) {
this.data = { ...data }
this.renderData = { ...data }
const dataBlob = { ...data, tests: data.tests.map((test, index) => ({
...test,
id: `test_${index}`,
collapsed: false,
})) }
this.data = { ...dataBlob }
this.renderData = { ...dataBlob }
}
get allData() {
return { ...this.data }
Expand All @@ -10,11 +15,15 @@ class DataManager {
this.renderData = { ...this.data }
}
setRender(data) {
this.renderData.tests = data
this.renderData.tests = [...data]
}
toggleCollapsedItem(id) {
this.renderData.tests = this.renderData.tests.map((test) =>
test.id === id ? { ...test, collapsed: !test.collapsed } : test,
)
}

set allCollapsed(collapsed) {
this.renderData = { ...this.data, tests: [...this.data.tests.map((test) => (
this.renderData = { ...this.renderData, tests: [...this.renderData.tests.map((test) => (
{ ...test, collapsed }
))] }
}
Expand Down
13 changes: 9 additions & 4 deletions src/pytest_html/scripts/dom.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const storageModule = require('./storage.js')
const { formatDuration } = require('./utils.js')
const mediaViewer = require('./mediaViewer.js')
const templateEnvRow = document.querySelector('#template_environment_row')
const templateCollGroup = document.querySelector('#template_table-colgroup')
const templateResult = document.querySelector('#template_results-table__tbody')
const aTag = document.querySelector('#template_a')
const listHeader = document.querySelector('#template_results-table__head')
Expand Down Expand Up @@ -48,8 +50,8 @@ const dom = {
},
getListHeader: ({ resultsTableHeader }) => {
const header = listHeader.content.cloneNode(true)
const sortAttr = localStorage.getItem('sort')
const sortAsc = JSON.parse(localStorage.getItem('sortAsc'))
const sortAttr = storageModule.getSort()
const sortAsc = JSON.parse(storageModule.getSortDirection())
const sortables = ['outcome', 'nodeid', 'duration']

sortables.forEach((sortCol) => {
Expand All @@ -64,11 +66,14 @@ const dom = {
return header
},
getListHeaderEmpty: () => listHeaderEmpty.content.cloneNode(true),
getResultTBody: ({ nodeid, longreprtext, duration, extras, resultsTableRow, tableHtml, outcome, collapsed }) => {
getColGroup: () => templateCollGroup.content.cloneNode(true),
getResultTBody: ({ nodeid, id, longreprtext, duration, extras, resultsTableRow, tableHtml, outcome, collapsed }) => {
const outcomeLower = outcome.toLowerCase()
const resultBody = templateResult.content.cloneNode(true)
resultBody.querySelector('tbody').classList.add(outcomeLower)
resultBody.querySelector('.col-result').innerText = outcome
resultBody.querySelector('.col-result').classList.add(`${collapsed ? 'expander' : 'collapser'}`)
resultBody.querySelector('.col-result').dataset.id = id
resultBody.querySelector('.col-name').innerText = nodeid
resultBody.querySelector('.col-duration').innerText = `${formatDuration(duration)}s`

Expand All @@ -95,7 +100,7 @@ const dom = {
}

if (format_type === 'html') {
resultBody.querySelector('.extraHTML').insertAdjacentHTML('beforeend', `<div>${content}</div>`)
resultBody.querySelector('.extraHTML').insertAdjacentHTML('beforeend', `<div>${content}</div>`)
}
})
mediaViewer.setUp(resultBody, media)
Expand Down
13 changes: 6 additions & 7 deletions src/pytest_html/scripts/filter.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
const { manager } = require('./datamanager.js')
const localStorageModule = require('./localstorage_utils.js')
const storageModule = require('./storage.js')

const getFilteredSubSet = (filter) =>
manager.allData.tests.filter(({ outcome }) => !filter.includes(outcome))
manager.allData.tests.filter(({ outcome }) => !filter.includes(outcome.toLowerCase()))

const doInitFilter = () => {
const currentFilter = localStorageModule.getFilter()
const currentFilter = storageModule.getFilter()
const filteredSubset = getFilteredSubSet(currentFilter)
manager.setRender(filteredSubset)
}

const doFilter = (type, apply) => {
const currentFilter = localStorageModule.getFilter()
const currentFilter = storageModule.getFilter()
if (!apply) {
currentFilter.push(type)
} else {
const index = currentFilter.indexOf(type);
const index = currentFilter.indexOf(type)
if (index > -1) {
currentFilter.splice(index, 1)
}
}

localStorageModule.setFilter(currentFilter)

storageModule.setFilter(currentFilter)
if (currentFilter.length) {
const filteredSubset = getFilteredSubSet(currentFilter)
manager.setRender(filteredSubset)
Expand Down
3 changes: 2 additions & 1 deletion src/pytest_html/scripts/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { redraw } = require('./main.js')
const { redraw, bindEvents } = require('./main.js')
const { doInitFilter } = require('./filter.js')
const { doInitSort } = require('./sort.js')
const { manager } = require('./datamanager.js')
Expand All @@ -9,6 +9,7 @@ function init() {
doInitFilter()
doInitSort()
redraw()
bindEvents()
}

init()
22 changes: 0 additions & 22 deletions src/pytest_html/scripts/localstorage_utils.js

This file was deleted.

51 changes: 26 additions & 25 deletions src/pytest_html/scripts/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -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('./localstorage_utils.js')
const { getFilter } = require('./storage.js')

const removeChildren = (node) => {
while (node.firstChild) {
Expand Down Expand Up @@ -37,14 +37,28 @@ const renderContent = (tests) => {
if (!rows.length) {
tableHeader.appendChild(dom.getListHeaderEmpty())
}

table.appendChild(dom.getColGroup())
table.appendChild(tableHeader)

rows.forEach((row) => !!row && table.appendChild(row))

table.querySelectorAll('.extra').forEach((item) => {
item.colSpan = document.querySelectorAll('th').length
})
findAll('.sortable').forEach((elem) => {
elem.addEventListener('click', (evt) => {
const { target: element } = evt
const { columnType } = element.dataset
doSort(columnType)
redraw()
})
})
findAll('.col-result').forEach((elem) => {
elem.addEventListener('click', ({ target }) => {
manager.toggleCollapsedItem(target.dataset.id)
redraw()
})
})
}

const renderDerived = (tests, collectedItems, isFinished) => {
Expand Down Expand Up @@ -86,23 +100,16 @@ const renderDerived = (tests, collectedItems, isFinished) => {
}

const bindEvents = () => {
findAll('.sortable').forEach((elem) => {
elem.addEventListener('click', (evt) => {
const { target: element } = evt
const { columnType } = element.dataset
const filterColumn = (evt) => {
const { target: element } = evt
const { testResult } = element.dataset

doSort(columnType)
redraw()
})
})
doFilter(testResult, element.checked)
redraw()
}
findAll('input[name="filter_checkbox"]').forEach((elem) => {
elem.addEventListener('click', (evt) => {
const { target: element } = evt
const { testResult } = element.dataset

doFilter(testResult, element.checked)
redraw()
})
elem.removeEventListener('click', filterColumn)
elem.addEventListener('click', filterColumn)
})
document.querySelector('#show_all_details').addEventListener('click', () => {
manager.allCollapsed = false
Expand All @@ -114,19 +121,13 @@ const bindEvents = () => {
})
}

const renderPage = () => {
const redraw = () => {
const { testSubset, allTests, collectedItems, isFinished } = manager

renderStatic()
renderContent(testSubset)
renderDerived(allTests, collectedItems, isFinished)
}

const redraw = () => {
setTimeout(() => {
renderPage()
bindEvents()
}, 0)
}

exports.redraw = redraw
exports.bindEvents = bindEvents
Loading