render: add html report generation
This commit is contained in:
110
render/index.js
Normal file
110
render/index.js
Normal 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));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user