render: add html report generation

This commit is contained in:
Ivan Avdeev
2023-11-28 12:32:40 -05:00
parent bb5c04efd8
commit c1bd3d7619
6 changed files with 330 additions and 22 deletions

110
render/index.js Normal file
View File

@@ -0,0 +1,110 @@
"use strict";
const fieldFuncDefault = (value) => {
return [Text(value)];
};
function makeId(d) {
return `${d.test}/${d.channel}`;
}
function rowAttribs(d) {
return d.fail ? {style: `background-color: rgb(128, 0, 0)`} : null;
}
function sectionLink(value, d) {
const id = makeId(d);
const a = Tag('a', {href: '#'+id}, value);
a.addEventListener('click', () => { $(id).setAttribute('open', true); });
return [a];
}
function makeTable(fields, data, attrs_func) {
const table = Tag('table', null, null, [
Tag('tr', null, null, (() => {
let tds = [];
for (const f of fields) {
tds.push(Tag('td', null, null, [Text(f.label)]));
}
return tds;
})()),
]);
for (const di in data) {
let d = data[di];
const attrs = attrs_func ? attrs_func(d) : null;
table.appendChild(Tag('tr', attrs, null, (() => {
let ret = [];
for (const f of fields) {
const value = d[f.field];
if (value === undefined) {
ret.push(Tag('td'));
continue;
}
const field_func = f.tags_func ? f.tags_func : fieldFuncDefault;
const tags = field_func(value, d);
let attrs = null;
// if (f.good && f.bad) {
// const rating = linearStep(value, f.good, f.bad);
// const c = {
// r: 224 + 31 * clamp(2 - rating * 2, 0, 1),
// g: 224 + 31 * clamp(rating * 2, 0, 1),
// b: 224,
// };
// attrs = {style: `background-color: rgb(${c.r}, ${c.g}, ${c.b})`};
// }
ret.push(Tag('td', attrs, null, tags));
}
return ret;
})()));
}
return table;
}
function buildTestResultsTable(data) {
const fields = [
{label: 'Test', field: 'test', tags_func: sectionLink},
{label: 'Channel', field: 'channel', tags_func: sectionLink},
{label: 'Diff, %', field: 'diff_pct'},
{label: 'Failed', field: 'fail'},
];
return [makeTable(fields, data, rowAttribs)];
}
// Filter out all success
function filterData(data) {
return data
.filter((d) => {return d.diff_pct != 0;})
.sort((l, r) => {return l.diff_pct < r.diff_pct;});
}
function buildSummary(data) {
const total = data.length;
const fails = data.filter((d) => {return !!d.fail;}).length;
const fails_pct = fails * 100.0 / total;
return [Text(`Tests failed: ${fails} / ${total} (${fails_pct.toFixed(3)}%)`)];
}
function buildTestResultImages(data) {
return data.flatMap((d) => {
return Tag('details', {id: makeId(d)}, null, [
Tag('summary', null, `${d.test}/${d.channel} diff=${d.diff_pct}`),
Tag('img', {src: d.image_diff}),
Tag('img', {src: d.image_flip}),
]);
});
}
window.onload = () => {
$('summary').replaceChildren(...buildSummary(data));
const filtered_data = filterData(data);
$('fail_table').replaceChildren(...buildTestResultsTable(filtered_data));
$('fail_images').replaceChildren(...buildTestResultImages(filtered_data));
}