Fix: Handle appends on table hooks (#630)

This commit is contained in:
Jim Brännlund 2023-04-08 18:16:33 +02:00 committed by GitHub
parent e4ad806b7b
commit 8350dda5eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 104 additions and 13 deletions

View File

@ -1,5 +1,5 @@
const storageModule = require('./storage.js')
const { formatDuration } = require('./utils.js')
const { formatDuration, transformTableObj } = require('./utils.js')
const mediaViewer = require('./mediaviewer.js')
const templateEnvRow = document.querySelector('#template_environment_row')
const templateCollGroup = document.querySelector('#template_table-colgroup')
@ -28,9 +28,9 @@ const findAll = (selector, elem) => {
return [...elem.querySelectorAll(selector)]
}
const insertAdditionalHTML = (html, element, selector) => {
const insertAdditionalHTML = (html, element, selector, position = 'beforebegin') => {
Object.keys(html).map((key) => {
element.querySelectorAll(selector).item(key).insertAdjacentHTML('beforebegin', html[key])
element.querySelectorAll(selector).item(key).insertAdjacentHTML(position, html[key])
})
}
@ -66,7 +66,9 @@ const dom = {
const sortables = ['result', 'testId', 'duration', ...cols]
// Add custom html from the pytest_html_results_table_header hook
insertAdditionalHTML(resultsTableHeader, header, 'th')
const headers = transformTableObj(resultsTableHeader)
insertAdditionalHTML(headers.inserts, header, 'th')
insertAdditionalHTML(headers.appends, header, 'tr', 'beforeend')
sortables.forEach((sortCol) => {
if (sortCol === sortAttr) {
@ -92,7 +94,6 @@ const dom = {
resultBody.querySelector('.col-duration').innerText = duration < 1 ? formatDuration(duration).ms : formatDuration(duration).formatted
if (log) {
resultBody.querySelector('.log').innerHTML = log
} else {
@ -126,7 +127,9 @@ const dom = {
mediaViewer.setUp(resultBody, media)
// Add custom html from the pytest_html_results_table_row hook
resultsTableRow && insertAdditionalHTML(resultsTableRow, resultBody, 'td')
const rows = transformTableObj(resultsTableRow)
resultsTableRow && insertAdditionalHTML(rows.inserts, resultBody, 'td')
resultsTableRow && insertAdditionalHTML(rows.appends, resultBody, 'tr', 'beforeend')
// Add custom html from the pytest_html_results_table_html hook
tableHtml?.forEach((item) => {

View File

@ -21,4 +21,19 @@ const formatDuration = ( totalSeconds ) => {
}
}
module.exports = { formatDuration }
const transformTableObj = (obj) => {
const appends = {}
const inserts = {}
for (const key in obj) {
key.startsWith("Z") ? appends[key] = obj[key] : inserts[key] = obj[key]
}
return {
appends,
inserts,
}
}
module.exports = {
formatDuration,
transformTableObj,
}

View File

@ -29,6 +29,10 @@ class Html(Table):
class Cell(Table):
def __init__(self):
super().__init__()
self._append_counter = 0
def __setitem__(self, key, value):
warnings.warn(
"list-type assignment is deprecated and support "
@ -38,6 +42,12 @@ class Cell(Table):
)
self.insert(key, value)
def append(self, item):
# We need a way of separating inserts from appends in JS,
# hence the "Z" prefix
self.insert(f"Z{self._append_counter}", item)
self._append_counter += 1
def insert(self, index, html):
# backwards-compat
if not isinstance(html, str):

View File

@ -516,6 +516,44 @@ class TestHTML:
page = run(pytester, cmd_flags=["-n1"])
assert_results(page, passed=1)
def test_results_table_hook_append(self, pytester):
header_selector = (
".summary #results-table-head tr:nth-child(1) th:nth-child({})"
)
row_selector = ".summary #results-table tr:nth-child(1) td:nth-child({})"
pytester.makeconftest(
"""
def pytest_html_results_table_header(cells):
cells.append("<th>Description</th>")
cells.append(
'<th class="sortable time" data-column-type="time">Time</th>'
)
def pytest_html_results_table_row(report, cells):
cells.append("<td>A description</td>")
cells.append('<td class="col-time">A time</td>')
"""
)
pytester.makepyfile("def test_pass(): pass")
page = run(pytester)
description_index = 5
time_index = 6
assert_that(get_text(page, header_selector.format(time_index))).is_equal_to(
"Time"
)
assert_that(
get_text(page, header_selector.format(description_index))
).is_equal_to("Description")
assert_that(get_text(page, row_selector.format(time_index))).is_equal_to(
"A time"
)
assert_that(get_text(page, row_selector.format(description_index))).is_equal_to(
"A description"
)
def test_results_table_hook_insert(self, pytester):
header_selector = (
".summary #results-table-head tr:nth-child(1) th:nth-child({})"
@ -539,13 +577,21 @@ class TestHTML:
pytester.makepyfile("def test_pass(): pass")
page = run(pytester)
assert_that(get_text(page, header_selector.format(2))).is_equal_to("Time")
assert_that(get_text(page, header_selector.format(3))).is_equal_to(
"Description"
description_index = 3
time_index = 2
assert_that(get_text(page, header_selector.format(time_index))).is_equal_to(
"Time"
)
assert_that(
get_text(page, header_selector.format(description_index))
).is_equal_to("Description")
assert_that(get_text(page, row_selector.format(2))).is_equal_to("A time")
assert_that(get_text(page, row_selector.format(3))).is_equal_to("A description")
assert_that(get_text(page, row_selector.format(time_index))).is_equal_to(
"A time"
)
assert_that(get_text(page, row_selector.format(description_index))).is_equal_to(
"A description"
)
def test_results_table_hook_delete(self, pytester):
pytester.makeconftest(

View File

@ -2,7 +2,7 @@ const { expect } = require('chai')
const sinon = require('sinon')
const { doInitFilter, doFilter } = require('../src/pytest_html/scripts/filter.js')
const { doInitSort, doSort } = require('../src/pytest_html/scripts/sort.js')
const { formatDuration } = require('../src/pytest_html/scripts/utils.js')
const { formatDuration, transformTableObj } = require('../src/pytest_html/scripts/utils.js')
const dataModule = require('../src/pytest_html/scripts/datamanager.js')
const storageModule = require('../src/pytest_html/scripts/storage.js')
@ -155,6 +155,23 @@ describe('utils tests', () => {
expect(formatDuration(12345.678).formatted).to.eql('03:25:46')
})
})
describe('transformTableObj', () => {
it('handles empty object', () => {
expect(transformTableObj({})).to.eql({appends: {}, inserts: {}})
})
it('handles no appends', () => {
const expected = {1: "hello", 2: "goodbye"}
expect(transformTableObj(expected)).to.eql({appends: {}, inserts: expected})
})
it('handles no inserts', () => {
const expected = {"Z1": "hello", "Z2": "goodbye"}
expect(transformTableObj(expected)).to.eql({appends: expected, inserts: {}})
})
it('handles both', () => {
const expected = {appends: {"Z1": "hello", "Z2": "goodbye"}, inserts: {1: "mee", 2: "moo"}}
expect(transformTableObj({...expected.appends, ...expected.inserts})).to.eql(expected)
})
})
})
describe('Storage tests', () => {