1const REPORT_URL = 'http://localhost:8081/report_gold_data'
2// Set this to enforce that the gold server must be up.
3// Typically used for debugging.
4const fail_on_no_gold = false;
5
6function reportCanvas(canvas, testname, outputType='canvas') {
7    let b64 = canvas.toDataURL('image/png');
8    return _report(b64, outputType, testname);
9}
10
11function reportSVG(svg, testname) {
12    // This converts an SVG to a base64 encoded PNG. It basically creates an
13    // <img> element that takes the inlined SVG and draws it on a canvas.
14    // The trick is we have to wait until the image is loaded, thus the Promise
15    // wrapping below.
16    let svgStr = svg.outerHTML;
17    let tempImg = document.createElement('img');
18
19    let tempCanvas = document.createElement('canvas');
20    let canvasCtx = tempCanvas.getContext('2d');
21    setCanvasSize(canvasCtx, svg.getAttribute('width'), svg.getAttribute('height'));
22
23    return new Promise(function(resolve, reject) {
24        tempImg.onload = () => {
25            canvasCtx.drawImage(tempImg, 0, 0);
26            let b64 = tempCanvas.toDataURL('image/png');
27            _report(b64, 'svg', testname).then(() => {
28                resolve();
29            }).catch((e) => reject(e));
30        };
31        tempImg.setAttribute('src', 'data:image/svg+xml;,' + svgStr);
32    });
33}
34
35// For tests that just do a simple path and return it as a string, wrap it in
36// a proper svg and send it off.  Supports fill (nofill means just stroke it).
37// This uses the "standard" size of 600x600.
38function reportSVGString(svgstr, testname, fillRule='nofill') {
39    let newPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
40    newPath.setAttribute('stroke', 'black');
41    if (fillRule !== 'nofill') {
42        newPath.setAttribute('fill', 'orange');
43        newPath.setAttribute('fill-rule', fillRule);
44    } else {
45        newPath.setAttribute('fill', 'rgba(255,255,255,0.0)');
46    }
47    newPath.setAttribute('d', svgstr);
48    let newSVG = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
49    newSVG.appendChild(newPath);
50    // helps with the conversion to PNG.
51    newSVG.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
52    newSVG.setAttribute('width', 600);
53    newSVG.setAttribute('height', 600);
54    return reportSVG(newSVG, testname);
55}
56
57// Reports a canvas and then an SVG of this path. Puts it on a standard size canvas.
58function reportPath(path, testname, done) {
59    let canvas = document.createElement('canvas');
60    let canvasCtx = canvas.getContext('2d');
61    // Set canvas size and make it a bit bigger to zoom in on the lines
62    standardizedCanvasSize(canvasCtx);
63    canvasCtx.stroke(path.toPath2D());
64
65    let svgStr = path.toSVGString();
66
67    return reportCanvas(canvas, testname).then(() => {
68                reportSVGString(svgStr, testname).then(() => {
69                    done();
70                }).catch(reportError(done));
71            }).catch(reportError(done));
72}
73
74// data is a base64 encoded png, outputType is the value that goes with the
75// key 'config' when reporting.
76function _report(data, outputType, testname) {
77    return fetch(REPORT_URL, {
78        method: 'POST',
79        mode: 'no-cors',
80        headers: {
81            'Content-Type': 'application/json',
82        },
83        body: JSON.stringify({
84            'output_type': outputType,
85            'data': data,
86            'test_name': testname,
87        })
88    }).then(() => console.log(`Successfully reported ${testname} to gold aggregator`));
89}
90
91function reportError(done) {
92    return (e) => {
93        console.log("Error with fetching. Likely could not connect to aggregator server", e.message);
94        if (fail_on_no_gold) {
95            expect(e).toBeUndefined();
96        }
97        done();
98    };
99}
100
101function setCanvasSize(ctx, width, height) {
102    ctx.canvas.width = width;
103    ctx.canvas.height = height;
104}
105
106function standardizedCanvasSize(ctx) {
107    setCanvasSize(ctx, 600, 600);
108}
109
110// A wrapper to catch and print a stacktrace to the logs.
111// Exceptions normally shows up in the browser console,
112// but not in the logs that appear on the bots AND a thrown
113// exception will normally cause a test to time out.
114// This wrapper mitigates both those pain points.
115function catchException(done, fn) {
116    return () => {
117        try {
118            fn()
119        } catch (e) {
120            console.log('Failed with the following error', e);
121            expect(e).toBeFalsy();
122            debugger;
123            done();
124        }
125        // We don't call done with finally because
126        // that would make the break the asynchronous nature
127        // of fn().
128    }
129}
130