You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
4.5 KiB
130 lines
4.5 KiB
4 months ago
|
const REPORT_URL = 'http://localhost:8081/report_gold_data'
|
||
|
// Set this to enforce that the gold server must be up.
|
||
|
// Typically used for debugging.
|
||
|
const fail_on_no_gold = false;
|
||
|
|
||
|
function reportCanvas(canvas, testname, outputType='canvas') {
|
||
|
let b64 = canvas.toDataURL('image/png');
|
||
|
return _report(b64, outputType, testname);
|
||
|
}
|
||
|
|
||
|
function reportSVG(svg, testname) {
|
||
|
// This converts an SVG to a base64 encoded PNG. It basically creates an
|
||
|
// <img> element that takes the inlined SVG and draws it on a canvas.
|
||
|
// The trick is we have to wait until the image is loaded, thus the Promise
|
||
|
// wrapping below.
|
||
|
let svgStr = svg.outerHTML;
|
||
|
let tempImg = document.createElement('img');
|
||
|
|
||
|
let tempCanvas = document.createElement('canvas');
|
||
|
let canvasCtx = tempCanvas.getContext('2d');
|
||
|
setCanvasSize(canvasCtx, svg.getAttribute('width'), svg.getAttribute('height'));
|
||
|
|
||
|
return new Promise(function(resolve, reject) {
|
||
|
tempImg.onload = () => {
|
||
|
canvasCtx.drawImage(tempImg, 0, 0);
|
||
|
let b64 = tempCanvas.toDataURL('image/png');
|
||
|
_report(b64, 'svg', testname).then(() => {
|
||
|
resolve();
|
||
|
}).catch((e) => reject(e));
|
||
|
};
|
||
|
tempImg.setAttribute('src', 'data:image/svg+xml;,' + svgStr);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// For tests that just do a simple path and return it as a string, wrap it in
|
||
|
// a proper svg and send it off. Supports fill (nofill means just stroke it).
|
||
|
// This uses the "standard" size of 600x600.
|
||
|
function reportSVGString(svgstr, testname, fillRule='nofill') {
|
||
|
let newPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
||
|
newPath.setAttribute('stroke', 'black');
|
||
|
if (fillRule !== 'nofill') {
|
||
|
newPath.setAttribute('fill', 'orange');
|
||
|
newPath.setAttribute('fill-rule', fillRule);
|
||
|
} else {
|
||
|
newPath.setAttribute('fill', 'rgba(255,255,255,0.0)');
|
||
|
}
|
||
|
newPath.setAttribute('d', svgstr);
|
||
|
let newSVG = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
||
|
newSVG.appendChild(newPath);
|
||
|
// helps with the conversion to PNG.
|
||
|
newSVG.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
||
|
newSVG.setAttribute('width', 600);
|
||
|
newSVG.setAttribute('height', 600);
|
||
|
return reportSVG(newSVG, testname);
|
||
|
}
|
||
|
|
||
|
// Reports a canvas and then an SVG of this path. Puts it on a standard size canvas.
|
||
|
function reportPath(path, testname, done) {
|
||
|
let canvas = document.createElement('canvas');
|
||
|
let canvasCtx = canvas.getContext('2d');
|
||
|
// Set canvas size and make it a bit bigger to zoom in on the lines
|
||
|
standardizedCanvasSize(canvasCtx);
|
||
|
canvasCtx.stroke(path.toPath2D());
|
||
|
|
||
|
let svgStr = path.toSVGString();
|
||
|
|
||
|
return reportCanvas(canvas, testname).then(() => {
|
||
|
reportSVGString(svgStr, testname).then(() => {
|
||
|
done();
|
||
|
}).catch(reportError(done));
|
||
|
}).catch(reportError(done));
|
||
|
}
|
||
|
|
||
|
// data is a base64 encoded png, outputType is the value that goes with the
|
||
|
// key 'config' when reporting.
|
||
|
function _report(data, outputType, testname) {
|
||
|
return fetch(REPORT_URL, {
|
||
|
method: 'POST',
|
||
|
mode: 'no-cors',
|
||
|
headers: {
|
||
|
'Content-Type': 'application/json',
|
||
|
},
|
||
|
body: JSON.stringify({
|
||
|
'output_type': outputType,
|
||
|
'data': data,
|
||
|
'test_name': testname,
|
||
|
})
|
||
|
}).then(() => console.log(`Successfully reported ${testname} to gold aggregator`));
|
||
|
}
|
||
|
|
||
|
function reportError(done) {
|
||
|
return (e) => {
|
||
|
console.log("Error with fetching. Likely could not connect to aggregator server", e.message);
|
||
|
if (fail_on_no_gold) {
|
||
|
expect(e).toBeUndefined();
|
||
|
}
|
||
|
done();
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function setCanvasSize(ctx, width, height) {
|
||
|
ctx.canvas.width = width;
|
||
|
ctx.canvas.height = height;
|
||
|
}
|
||
|
|
||
|
function standardizedCanvasSize(ctx) {
|
||
|
setCanvasSize(ctx, 600, 600);
|
||
|
}
|
||
|
|
||
|
// A wrapper to catch and print a stacktrace to the logs.
|
||
|
// Exceptions normally shows up in the browser console,
|
||
|
// but not in the logs that appear on the bots AND a thrown
|
||
|
// exception will normally cause a test to time out.
|
||
|
// This wrapper mitigates both those pain points.
|
||
|
function catchException(done, fn) {
|
||
|
return () => {
|
||
|
try {
|
||
|
fn()
|
||
|
} catch (e) {
|
||
|
console.log('Failed with the following error', e);
|
||
|
expect(e).toBeFalsy();
|
||
|
debugger;
|
||
|
done();
|
||
|
}
|
||
|
// We don't call done with finally because
|
||
|
// that would make the break the asynchronous nature
|
||
|
// of fn().
|
||
|
}
|
||
|
}
|