test.js (12709B)
1 var namespaces = { 2 "html":"http://www.w3.org/1999/xhtml", 3 "math":"http://www.w3.org/1998/Math/MathML", 4 "mathml":"http://www.w3.org/1998/Math/MathML", 5 "svg":"http://www.w3.org/2000/svg", 6 "xlink":"http://www.w3.org/1999/xlink", 7 "xml":"http://www.w3.org/XML/1998/namespace", 8 "xmlns":"http://www.w3.org/2000/xmlns/" 9 }; 10 11 var prefixes = {}; 12 for (var prefix in namespaces) { 13 if (namespaces.hasOwnProperty(prefix)) { 14 prefixes[namespaces[prefix]] = prefix; 15 } 16 } 17 prefixes[namespaces["mathml"]] = "math"; 18 19 function format(format_string) { 20 var insertions = Array.prototype.slice.call(arguments, 1); 21 var regexp = /%s/g; 22 var match_count = 0; 23 var rv = format_string.replace(regexp, function(match) { 24 var rv = insertions[match_count]; 25 match_count++; 26 return rv; 27 }); 28 return rv; 29 } 30 31 function test_serializer(element) { 32 element.normalize(); 33 var lines = []; 34 function serialize_element(element, indent) { 35 var indent_spaces = (new Array(indent)).join(" "); 36 switch(element.nodeType) { 37 case Node.DOCUMENT_TYPE_NODE: 38 if (element.name) { 39 if (element.publicId || element.systemId) { 40 var publicId = element.publicId ? element.publicId : ""; 41 var systemId = element.systemId ? element.systemId : ""; 42 lines.push(format("|%s<!DOCTYPE %s \"%s\" \"%s\">", indent_spaces, 43 element.name, publicId, systemId)); 44 } else { 45 lines.push(format("|%s<!DOCTYPE %s>", indent_spaces, 46 element.name)); 47 } 48 } else { 49 lines.push(format("|%s<!DOCTYPE >", indent_spaces)); 50 } 51 break; 52 case Node.DOCUMENT_NODE: 53 lines.push("#document"); 54 break; 55 case Node.DOCUMENT_FRAGMENT_NODE: 56 lines.push("#document-fragment"); 57 break; 58 case Node.COMMENT_NODE: 59 lines.push(format("|%s<!-- %s -->", indent_spaces, element.nodeValue)); 60 break; 61 case Node.TEXT_NODE: 62 lines.push(format("|%s\"%s\"", indent_spaces, element.nodeValue)); 63 break; 64 case Node.ELEMENT_NODE: 65 if (element.getAttribute("data-skip") !== null) { 66 return; 67 } 68 if (element.namespaceURI !== null && element.namespaceURI !== namespaces.html) { 69 var name = format("%s %s", prefixes[element.namespaceURI], 70 element.localName); 71 } else { 72 var name = element.localName; 73 } 74 lines.push(format("|%s<%s>", indent_spaces, name)); 75 76 var attributes = Array.prototype.map.call( 77 element.attributes, 78 function(attr) { 79 var name = (attr.namespaceURI ? prefixes[attr.namespaceURI] + " " : "") + 80 attr.localName; 81 return [name, attr.value]; 82 }); 83 attributes.sort(function (a, b) { 84 var x = a[0]; 85 var y = b[0]; 86 if (x === y) { 87 return 0; 88 } 89 return x > y ? 1 : -1; 90 }); 91 92 attributes.forEach( 93 function(attr) { 94 var indent_spaces = (new Array(indent + 2)).join(" "); 95 lines.push(format("|%s%s=\"%s\"", indent_spaces, attr[0], attr[1])); 96 } 97 ); 98 if ("HTMLTemplateElement" in window && 99 Object.prototype.toString.call(element) === "[object HTMLTemplateElement]") { 100 indent += 2; 101 indent_spaces = (new Array(indent)).join(" "); 102 lines.push(format("|%scontent", indent_spaces)); 103 indent += 2; 104 Array.prototype.forEach.call(element.content.childNodes, 105 function(node) { 106 serialize_element(node, indent); 107 }); 108 indent -= 4; 109 } 110 break; 111 } 112 indent += 2; 113 Array.prototype.forEach.call(element.childNodes, 114 function(node) { 115 serialize_element(node, indent); 116 }); 117 } 118 serialize_element(element, 0); 119 return lines.join("\n"); 120 } 121 122 function parse_query() { 123 var query = location.search.slice(1); 124 var vars = query.split("&"); 125 var fields = vars.map(function (x) { 126 var split = x.split("="); 127 return [split[0], split.slice(1).join("=")]; 128 }); 129 return fields; 130 } 131 132 function get_type() { 133 var run_type = "uri"; 134 var fields = parse_query(); 135 fields.forEach(function(x) { 136 if(x[0] == "run_type") { 137 run_type = x[1]; 138 } 139 }); 140 return run_type; 141 }; 142 143 var test_in_blob_uri = get_test_func(function (iframe, uri_encoded_input, t) { 144 var b = new Blob([decodeURIComponent(uri_encoded_input)], { type: "text/html" }); 145 var blobURL = URL.createObjectURL(b); 146 iframe.src = blobURL; 147 t.add_cleanup(function() { 148 URL.revokeObjectURL(blobURL); 149 }); 150 }); 151 152 var test_document_write = get_test_func(function(iframe, uri_encoded_input, t) { 153 iframe.contentDocument.open(); 154 var input = decodeURIComponent(uri_encoded_input); 155 iframe.contentDocument.write(input); 156 iframe.contentDocument.close(); 157 }); 158 159 var test_document_write_single = get_test_func(function(iframe, uri_encoded_input, t) { 160 iframe.contentDocument.open(); 161 var input = decodeURIComponent(uri_encoded_input); 162 for (var i=0; i< input.length; i++) { 163 iframe.contentDocument.write(input[i]); 164 } 165 iframe.contentDocument.close(); 166 }); 167 168 function get_test_func(inject_func) { 169 function test_func(iframe, t, test_id, uri_encoded_input, escaped_expected) { 170 var expected = decodeURIComponent(escaped_expected); 171 current_tests[iframe.id] = {test_id:test_id, 172 uri_encoded_input:uri_encoded_input, 173 expected:expected, 174 actual:null 175 }; 176 177 iframe.onload = function() { 178 t.step(function() { 179 iframe.onload = null; 180 var serialized_dom = test_serializer(iframe.contentDocument); 181 current_tests[iframe.id].actual = serialized_dom; 182 assert_equals(serialized_dom, expected); 183 t.done(); 184 } 185 ); 186 }; 187 inject_func(iframe, uri_encoded_input, t); 188 } 189 return test_func; 190 } 191 192 function test_fragment(iframe, t, test_id, uri_encoded_input, escaped_expected, container) { 193 var input_string = decodeURIComponent(uri_encoded_input); 194 var expected = decodeURIComponent(escaped_expected); 195 current_tests[iframe.id] = { 196 test_id:test_id, 197 input:uri_encoded_input, 198 expected:expected, 199 actual:null, 200 container:container 201 }; 202 203 var components = container.split(" "); 204 var container_elem = null; 205 if (components.length > 1) { 206 var namespace = namespaces[components[0]]; 207 container_elem = document.createElementNS(namespace, 208 components[0] + ":" + 209 components[1]); 210 } else { 211 container_elem = document.createElement(container); 212 } 213 container_elem.innerHTML = input_string; 214 var serialized_dom; 215 if (container_elem.namespaceURI === namespaces["html"] && container_elem.localName === "template") { 216 serialized_dom = test_serializer(container_elem.content); 217 } else { 218 serialized_dom = test_serializer(container_elem); 219 } 220 current_tests[iframe.id].actual = serialized_dom; 221 serialized_dom = convert_innerHTML(serialized_dom); 222 assert_equals(serialized_dom, expected); 223 t.done(); 224 } 225 226 function convert_innerHTML(serialized_dom) { 227 var lines = serialized_dom.split("\n"); 228 assert_not_equals(lines[0], "<template>", "template is never the innerHTML context object"); 229 lines[0] = "#document"; 230 return lines.join("\n"); 231 } 232 233 function print_diffs(test_id, uri_encoded_input, expected, actual, container) { 234 container = container ? container : null; 235 if (actual) { 236 var diffs = mark_diffs(expected, actual); 237 var expected_text = diffs[0]; 238 var actual_text = diffs[1]; 239 } else { 240 var expected_text = expected; 241 var actual_text = ""; 242 } 243 244 var tmpl = ["div", {"id":"${test_id}"}, 245 ["h2", {}, "${test_id}"], 246 function(vars) { 247 if (vars.container !== null) { 248 return ["div", {"class":"container"}, 249 ["h3", {}, "innerHTML Container"], 250 ["pre", {}, vars.container]]; 251 } else { 252 return null; 253 } 254 }, 255 ["div", {"id":"input_${test_id}"}, ["h3", {}, "Input"], ["pre", {}, 256 ["code", {}, decodeURIComponent(uri_encoded_input)]]], 257 ["div", {"id":"expected_${test_id}"}, ["h3", {}, "Expected"], 258 ["pre", {}, ["code", {}, expected_text]]], 259 ["div", {"id":"actual_${test_id}"}, ["h3", {}, "Actual"], 260 ["pre", {}, ["code", {}, actual_text]]] 261 ]; 262 263 var diff_dom = template.render(tmpl, {test_id:test_id, container:container}); 264 document.body.appendChild(diff_dom); 265 } 266 267 var current_tests = {}; 268 var iframe_map = {}; 269 270 function init_tests(test_type) { 271 var test_func = null; 272 var test_funcs = { 273 "write":test_document_write, 274 "write_single":test_document_write_single, 275 "uri":test_in_blob_uri, 276 "innerHTML":test_fragment 277 }; 278 var tests_started = 0; 279 var tests_complete = 0; 280 281 setup(function() { 282 test_func = test_funcs[test_type]; 283 284 var fails = []; 285 286 add_result_callback(function(test) { 287 tests_complete++; 288 var iframe = document.getElementById(iframe_map[test.name]); 289 if (test.status !== test.PASS) { 290 fails.push(current_tests[iframe.id]); 291 var new_iframe = document.createElement("iframe"); 292 new_iframe.style.display = "none"; 293 new_iframe.id = iframe.id; 294 document.body.replaceChild(new_iframe, iframe); 295 iframe = new_iframe; 296 } 297 if (tests_complete === order.length) { 298 done(); 299 } else if (tests_started < order.length) { 300 test_next(iframe); 301 } 302 }); 303 304 add_completion_callback(function() { 305 fails.forEach(function(t) { 306 print_diffs(t.test_id, t.uri_encoded_input, 307 t.expected, t.actual); 308 }); 309 }); 310 311 //Create the iframes we will use to test 312 //in the innerHTML case these are not actually used 313 //but it is convenient to reuse the same code 314 for (var i=0; i<num_iframes; i++) { 315 var iframe = document.createElement("iframe"); 316 iframe.id = "iframe_" + i; 317 iframe.style.display = "none"; 318 document.body.appendChild(iframe); 319 } 320 }, 321 {explicit_done:true}); 322 323 function test_next(iframe) { 324 var test_id = order[tests_started]; 325 tests_started++; 326 var x = tests[test_id]; 327 var t = x[0]; 328 iframe_map[t.name] = iframe.id; 329 step_timeout(function() { 330 t.step(function() { 331 var string_uri_encoded_input = x[1]; 332 var string_escaped_expected = x[2]; 333 if (test_type === "innerHTML") { 334 var container = x[3]; 335 } 336 test_func(iframe, t, test_id, string_uri_encoded_input, string_escaped_expected, 337 container); 338 }); 339 }, 0); 340 } 341 342 onload = function() { 343 Array.prototype.forEach.call(document.getElementsByTagName("iframe"), 344 function(iframe) { 345 if (tests_started<order.length) { 346 test_next(iframe); 347 } 348 }); 349 }; 350 }