130 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
| 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().
 | |
|     }
 | |
| }
 |