testharnessreport.js (8527B)
1 /* global add_completion_callback */ 2 /* global setup */ 3 4 /* 5 * This file is intended for vendors to implement code needed to integrate 6 * testharness.js tests with their own test systems. 7 * 8 * Typically test system integration will attach callbacks when each test has 9 * run, using add_result_callback(callback(test)), or when the whole test file 10 * has completed, using 11 * add_completion_callback(callback(tests, harness_status)). 12 * 13 * For more documentation about the callback functions and the 14 * parameters they are called with see testharness.js 15 */ 16 17 /* 18 * If the query parameter token is available means that the test was loaded by 19 * the WAVE test runner and the results need to be reported to the server using 20 * the provided token to identify the session associated this token. 21 */ 22 if (location.search && location.search.indexOf("token=") != -1) { 23 var __WAVE__HOSTNAME = location.hostname; 24 var __WAVE__PORT = location.port; 25 var __WAVE__PROTOCOL = location.protocol.replace(/:/, ""); 26 var __WAVE__QUERY = location.search; 27 var queryParameters = {}; 28 var keysAndValues = location.search.replace("?", "").split("&"); 29 for (var i = 0; i < keysAndValues.length; i++) { 30 var key = keysAndValues[i].split("=")[0]; 31 var value = keysAndValues[i].split("=")[1]; 32 queryParameters[key] = value; 33 } 34 var __HTTPS_PORT = parseInt(queryParameters["https_port"] || 443); 35 var __WAVE__TIMEOUT = parseInt(queryParameters["timeout"] || 65000); 36 var __WAVE__WEB_ROOT = queryParameters["web_root"] || "/_wave/"; 37 var __WAVE__TOKEN = queryParameters["token"] || null; 38 var __WAVE__TEST = location.pathname; 39 var nextUrl = null; 40 var resultSent = false; 41 var screenConsole; 42 43 try { 44 var documentRoot = document.body ? document.body : document.documentElement; 45 documentRoot.style["background-color"] = "#FFF"; 46 window.open = function () { 47 logToConsole( 48 "window.open() is overridden in testharnessreport.js and has not effect" 49 ); 50 var dummyWin = { 51 close: function () { 52 logToConsole( 53 "dummyWindow.close() in testharnessreport.js and has not effect" 54 ); 55 }, 56 }; 57 return dummyWin; 58 }; 59 window.close = function () { 60 logToConsole( 61 "window.close() is overridden in testharnessreport.js and has not effect" 62 ); 63 }; 64 } catch (err) {} 65 66 setTimeout(function () { 67 loadNext(); 68 }, __WAVE__TIMEOUT); 69 70 function logToConsole() { 71 var text = ""; 72 for (var i = 0; i < arguments.length; i++) { 73 text += arguments[i] + " "; 74 } 75 if (console && console.log) { 76 console.log(text); 77 } 78 if (screenConsole) { 79 try { 80 text = text.replace(/ /gm, " "); 81 text = text.replace(/\n/gm, "<br/>"); 82 screenConsole.innerHTML += "<br/>" + text; 83 } catch (error) { 84 screenConsole.innerText += "\n" + text; 85 } 86 } 87 } 88 89 function dump_and_report_test_results(tests, status) { 90 var results_element = document.createElement("script"); 91 results_element.type = "text/json"; 92 results_element.id = "__testharness__results__"; 93 var test_results = tests.map(function (x) { 94 return { 95 name: x.name, 96 status: x.status, 97 message: x.message, 98 stack: x.stack, 99 }; 100 }); 101 var data = { 102 test: window.location.href, 103 tests: test_results, 104 status: status.status, 105 message: status.message, 106 stack: status.stack, 107 }; 108 results_element.textContent = JSON.stringify(data); 109 110 // To avoid a HierarchyRequestError with XML documents, ensure that 'results_element' 111 // is inserted at a location that results in a valid document. 112 var parent = document.body 113 ? document.body // <body> is required in XHTML documents 114 : document.documentElement; // fallback for optional <body> in HTML5, SVG, etc. 115 116 parent.appendChild(results_element); 117 118 screenConsole = document.getElementById("console"); 119 if (!screenConsole) { 120 screenConsole = document.createElement("div"); 121 screenConsole.setAttribute("id", "console"); 122 screenConsole.setAttribute("style", "font-family: monospace; padding: 5px"); 123 parent.appendChild(screenConsole); 124 } 125 window.onerror = logToConsole; 126 127 finishWptTest(data); 128 } 129 130 function finishWptTest(data) { 131 logToConsole("Creating result ..."); 132 data.test = __WAVE__TEST; 133 createResult( 134 __WAVE__TOKEN, 135 data, 136 function () { 137 logToConsole("Result created."); 138 loadNext(); 139 }, 140 function () { 141 logToConsole("Failed to create result."); 142 logToConsole("Trying alternative method ..."); 143 createResultAlt(__WAVE__TOKEN, data); 144 } 145 ); 146 } 147 148 function loadNext() { 149 logToConsole("Loading next test ..."); 150 readNextTest( 151 __WAVE__TOKEN, 152 function (url) { 153 logToConsole("Redirecting to " + url); 154 location.href = url; 155 }, 156 function () { 157 logToConsole("Could not load next test."); 158 logToConsole("Trying alternative method ..."); 159 readNextAlt(__WAVE__TOKEN); 160 } 161 ); 162 } 163 164 function readNextTest(token, onSuccess, onError) { 165 sendRequest( 166 "GET", 167 "api/tests/" + token + "/next", 168 null, 169 null, 170 function (response) { 171 var jsonObject = JSON.parse(response); 172 onSuccess(jsonObject.next_test); 173 }, 174 onError 175 ); 176 } 177 178 function readNextAlt(token) { 179 location.href = 180 location.protocol + 181 "//" + 182 location.host + 183 getWaveUrl("next.html?token=" + token); 184 } 185 186 function createResult(token, result, onSuccess, onError) { 187 sendRequest( 188 "POST", 189 "api/results/" + token, 190 { 191 "Content-Type": "application/json", 192 }, 193 JSON.stringify(result), 194 function () { 195 onSuccess(); 196 }, 197 onError 198 ); 199 } 200 201 function createResultAlt(token, result) { 202 location.href = 203 __WAVE__WEB_ROOT + 204 "submitresult.html" + 205 "?token=" + 206 token + 207 "&result=" + 208 encodeURIComponent(JSON.stringify(result)); 209 } 210 211 function sendRequest(method, uri, headers, data, onSuccess, onError) { 212 var url = getWaveUrl(uri); 213 url = location.protocol + "//" + location.host + url; 214 var xhr = new XMLHttpRequest(); 215 xhr.addEventListener("load", function () { 216 onSuccess(xhr.response); 217 }); 218 xhr.addEventListener("error", function () { 219 if (onError) onError(); 220 }); 221 logToConsole("Sending", method, 'request to "' + url + '"'); 222 xhr.open(method, url, true); 223 if (headers) { 224 for (var header in headers) { 225 xhr.setRequestHeader(header, headers[header]); 226 } 227 } 228 xhr.send(data); 229 } 230 231 function getWaveUrl(uri) { 232 var url = __WAVE__WEB_ROOT + uri; 233 return url; 234 } 235 236 add_completion_callback(dump_and_report_test_results); 237 } else { 238 function dump_test_results(tests, status) { 239 var results_element = document.createElement("script"); 240 results_element.type = "text/json"; 241 results_element.id = "__testharness__results__"; 242 var test_results = tests.map(function (x) { 243 return { 244 name: x.name, 245 status: x.status, 246 message: x.message, 247 stack: x.stack, 248 }; 249 }); 250 var data = { 251 test: window.location.href, 252 tests: test_results, 253 status: status.status, 254 message: status.message, 255 stack: status.stack, 256 }; 257 results_element.textContent = JSON.stringify(data); 258 259 // To avoid a HierarchyRequestError with XML documents, ensure that 'results_element' 260 // is inserted at a location that results in a valid document. 261 var parent = document.body 262 ? document.body // <body> is required in XHTML documents 263 : document.documentElement; // fallback for optional <body> in HTML5, SVG, etc. 264 265 parent.appendChild(results_element); 266 } 267 268 add_completion_callback(dump_test_results); 269 270 /* If the parent window has a testharness_properties object, 271 * we use this to provide the test settings. This is used by the 272 * default in-browser runner to configure the timeout and the 273 * rendering of results 274 */ 275 try { 276 if (window.opener && "testharness_properties" in window.opener) { 277 /* If we pass the testharness_properties object as-is here without 278 * JSON stringifying and reparsing it, IE fails & emits the message 279 * "Could not complete the operation due to error 80700019". 280 */ 281 setup(JSON.parse(JSON.stringify(window.opener.testharness_properties))); 282 } 283 } catch (e) {} 284 }