├── .editorconfig ├── .gitignore ├── .npmignore ├── LICENSE.txt ├── README.md ├── package.json ├── scripts ├── build-core.js └── node-tests.js ├── src ├── copyright-header.txt └── index.js └── tests ├── index.html ├── qunit.config.js └── tests.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = tab 8 | indent_size = 4 9 | 10 | [*.md] 11 | indent_style = space 12 | indent_size = 4 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | coverage/ 3 | dist/ 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .npmignore 2 | .gitignore 3 | node_modules/ 4 | coverage/ 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Kyle Simpson 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mock DOM Resources 2 | 3 | [![npm Module](https://badge.fury.io/js/mock-dom-resources.svg)](https://www.npmjs.org/package/mock-dom-resources) 4 | [![Dependencies](https://david-dm.org/getify/mock-dom-resources.svg)](https://david-dm.org/getify/mock-dom-resources) 5 | [![devDependencies](https://david-dm.org/getify/mock-dom-resources/dev-status.svg)](https://david-dm.org/getify/mock-dom-resources) 6 | 7 | A simple utility for mocking the DOM APIs to simulate browser resource preloading and loading. 8 | 9 | Resources are not actually loaded. This is a simulation. The request for a resource (i.e. adding a ` 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /tests/qunit.config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | QUnit.config.requireExpects = true; 4 | 5 | QUnit.begin(begin); 6 | QUnit.log(testLog); 7 | QUnit.testDone(testDone); 8 | QUnit.done(done); 9 | 10 | var testLogEntries = {}; 11 | 12 | // ****************************** 13 | 14 | function begin(details){ 15 | printEnvNotification(); 16 | 17 | if (details.totalTests > 0) { 18 | console.log(`Mock-DOM-Resources Test Suite (${details.totalTests})`); 19 | console.log(""); 20 | } 21 | else { 22 | console.log(`Mock-DOM-Resources Test Suite: empty!`); 23 | process.exit(1); 24 | } 25 | } 26 | 27 | function testLog(details) { 28 | var testId = details.testId; 29 | 30 | testLogEntries[testId] = testLogEntries[testId] || {}; 31 | testLogEntries[testId][details.message] = details; 32 | } 33 | 34 | function testDone(results){ 35 | var testId = results.testId; 36 | 37 | if (results.failed > 0) { 38 | console.log(`Failed: '${results.name}' (${results.failed}/${results.total})`); 39 | for (let i = 0; i < results.assertions.length; i++) { 40 | if (results.assertions[i].result === false) { 41 | let { message, expected, actual } = testLogEntries[testId][results.assertions[i].message]; 42 | console.log(` ${message}`); 43 | console.log(` expected: ${prettyPrint(expected)}`); 44 | console.log(` actual: ${prettyPrint(actual)}`); 45 | } 46 | } 47 | } 48 | else if (results.passed > 0) { 49 | console.log(`Passed: '${results.name}' (${results.passed}/${results.total})`); 50 | } 51 | else { 52 | console.log(`No assertions run: '${results.name}'`); 53 | } 54 | } 55 | 56 | function done(results){ 57 | console.log(""); 58 | 59 | if (results.failed > 0) { 60 | console.log(`Failed (${results.failed}/${results.total})`); 61 | printEnvNotification(); 62 | process.exit(1); 63 | } 64 | else if (results.passed > 0) { 65 | console.log(`Passed (${results.passed}/${results.total})`); 66 | printEnvNotification(); 67 | process.exit(0); 68 | } 69 | else { 70 | console.log("No tests run!"); 71 | printEnvNotification(); 72 | process.exit(1); 73 | } 74 | } 75 | 76 | function prettyPrint(v) { 77 | if (Array.isArray(v)) { 78 | return `[${ v.map( prettyPrint ).toString() }]`; 79 | } 80 | else if (v && typeof v == "object") { 81 | return JSON.stringify(v,function(k,v){ 82 | if (v === undefined) { 83 | return null; 84 | } 85 | return v; 86 | }); 87 | } 88 | return String(v); 89 | } 90 | 91 | function printEnvNotification() { 92 | return; 93 | 94 | console.log(""); 95 | console.log("**********************************"); 96 | if (process.env.TEST_DIST) { 97 | console.log("********** TESTING DIST **********"); 98 | } 99 | else if (process.env.TEST_PACKAGE) { 100 | console.log("******** TESTING PACKAGE *********"); 101 | } 102 | else { 103 | console.log("********** TESTING SRC ***********"); 104 | } 105 | console.log("**********************************"); 106 | console.log(""); 107 | } 108 | -------------------------------------------------------------------------------- /tests/tests.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const WINDOW_ID = 1; 4 | const DOCUMENT_ID = 2; 5 | const HEAD_ID = 3; 6 | const BODY_ID = 4; 7 | 8 | QUnit.test( "build DOM", function test(assert){ 9 | var win = $DOM( { 10 | sequentialIds: true, 11 | log: function log(){}, 12 | error: function error(){}, 13 | } ); 14 | 15 | var x = win.document.createElement( "p" ); 16 | x.innerHTML = "Hello"; 17 | var y = win.document.createElement( "p" ); 18 | y.innerHTML = "World"; 19 | var z = win.document.createElement( "p" ); 20 | z.innerHTML = "!"; 21 | 22 | var w = win.document.createElement( "div" ); 23 | w.appendChild( x ); 24 | w.appendChild( y ); 25 | w.appendChild( z ); 26 | 27 | var p = win.document.createElement( "p" ); 28 | p.innerHTML = ":)"; 29 | 30 | win.document.body.appendChild( w ); 31 | win.document.body.appendChild( p ); 32 | 33 | var pElems = win.document.body.getElementsByTagName( "p" ); 34 | var aElems = win.document.body.getElementsByTagName( "a" ); 35 | 36 | var rExpected = 4; 37 | var pExpected = 3; 38 | var qExpected = 3; 39 | var tExpected = { 40 | tagName: "DOCUMENT", 41 | childNodes: [ 42 | { tagName: "HEAD", childNodes: [], _internal_id: HEAD_ID, }, 43 | { tagName: "BODY", 44 | childNodes: [ 45 | { tagName: "DIV", 46 | childNodes: [ 47 | { tagName: "P", childNodes: [], innerHTML: "Hello", _internal_id: 5, }, 48 | { tagName: "P", childNodes: [], innerHTML: "!", _internal_id: 7, }, 49 | ], 50 | _internal_id: 8, 51 | }, 52 | { tagName: "P", childNodes: [], innerHTML: ":)", _internal_id: 9, }, 53 | ], 54 | _internal_id: BODY_ID, 55 | }, 56 | ], 57 | _internal_id: DOCUMENT_ID, 58 | }; 59 | var sExpected = ":)"; 60 | var uExpected = 0; 61 | 62 | var rActual = pElems.length; 63 | w.removeChild( y ); 64 | var pActual = pElems.length; 65 | w.removeChild( y ); 66 | var qActual = pElems.length; 67 | var tActual = JSON.parse( JSON.stringify( win.document, ["tagName","childNodes","innerHTML","_internal_id",] ) ); 68 | var sActual = p.getAttribute( "innerHTML" ); 69 | var uActual = aElems.length; 70 | 71 | assert.expect( 6 ); 72 | assert.strictEqual( rActual, rExpected, "p elements" ); 73 | assert.strictEqual( pActual, pExpected, "p elements, after removeChild()" ); 74 | assert.strictEqual( qActual, qExpected, "extraneous removeChild()" ); 75 | assert.deepEqual( tActual, tExpected, "node tree structure" ); 76 | assert.strictEqual( sActual, sExpected, "getAttribute()" ); 77 | assert.strictEqual( uActual, uExpected, "(no) a elements" ); 78 | } ); 79 | 80 | QUnit.test( "check already cached resource", function test(assert){ 81 | assert.expect( 2 ); 82 | 83 | var win = $DOM( { 84 | sequentialIds: true, 85 | log: function log(){}, 86 | error: function error(){}, 87 | resources: [ 88 | { url: "a.js", cached: true, }, 89 | ], 90 | } ); 91 | 92 | var rExpected = ["a.js",]; 93 | var pExpected = []; 94 | 95 | var rActual = win.performance.getEntriesByName( "a.js" ); 96 | var pActual = win.performance.getEntriesByName( "b.js" ); 97 | 98 | assert.deepEqual( rActual, rExpected, "found resource" ); 99 | assert.deepEqual( pActual, pExpected, "resource not found" ); 100 | } ); 101 | 102 | QUnit.test( "relList / supports()", function test(assert){ 103 | var win1 = $DOM( { 104 | relList: false, 105 | log: function log(){}, 106 | error: function error(){}, 107 | } ); 108 | 109 | var win2 = $DOM( { 110 | log: function log(){}, 111 | error: function error(){}, 112 | } ); 113 | 114 | var win3 = $DOM( { 115 | linkPreload: false, 116 | log: function log(){}, 117 | error: function error(){}, 118 | } ); 119 | 120 | var link1 = win2.document.createElement( "link" ); 121 | link1.setAttribute( "rel", "preload" ); 122 | 123 | var link2 = win3.document.createElement( "link" ); 124 | link2.setAttribute( "rel", "preload" ); 125 | 126 | var script = win2.document.createElement( "script" ); 127 | 128 | var rExpected = false; 129 | var pExpected = true; 130 | var qExpected = false; 131 | var tExpected = false; 132 | var sExpected = false; 133 | 134 | var rActual = !!win1.document.relList; 135 | var pActual = link1.relList.supports( "preload" ); 136 | var qActual = link1.relList.supports( "funny" ); 137 | var tActual = link2.relList.supports( "preload" ); 138 | var sActual = script.relList.supports( "preload" ); 139 | 140 | assert.expect( 5 ); 141 | assert.strictEqual( rActual, rExpected, "no relList" ); 142 | assert.strictEqual( pActual, pExpected, "check rel: 'preload'" ); 143 | assert.strictEqual( qActual, qExpected, "check rel: 'funny'" ); 144 | assert.strictEqual( tActual, tExpected, "no preloading" ); 145 | assert.strictEqual( sActual, sExpected, "not " ); 146 | } ); 147 | 148 | QUnit.test( "event listeners", function test(assert){ 149 | var win = $DOM( { 150 | log: function log(){}, 151 | error: function error(){}, 152 | } ); 153 | 154 | var rExpected = 3; 155 | var pExpected = 1; 156 | var qExpected = 2; 157 | 158 | var rActual = 0; 159 | var pActual = 0; 160 | var qActual = 0; 161 | 162 | var x = win.document.createElement( "script" ); 163 | x.addEventListener( "funny", function onfunny(evt){ 164 | evt.preventDefault(); 165 | evt.stopPropagation(); 166 | evt.stopImmediatePropagation(); 167 | rActual++; 168 | } ); 169 | x.addEventListener( "hello", function onhello(){ 170 | x.removeEventListener( "hello", onhello ); 171 | x.removeEventListener( "hello2", onhello ); 172 | pActual++; 173 | } ); 174 | x.addEventListener( "world", function onworld(){ 175 | qActual++; 176 | } ); 177 | 178 | var e1 = win.document.createEvent(); 179 | x.dispatchEvent( e1 ); 180 | e1.initEvent( "funny" ); 181 | 182 | var e2 = new win.Event( "hello" ); 183 | var e3 = new win.Event( "world" ); 184 | var e4 = new win.Event( "!!" ); 185 | 186 | x.dispatchEvent( e1 ); 187 | x.dispatchEvent( e1 ); 188 | x.dispatchEvent( e1 ); 189 | x.dispatchEvent( e2 ); 190 | x.dispatchEvent( e2 ); 191 | x.dispatchEvent( e3 ); 192 | x.dispatchEvent( e3 ); 193 | x.dispatchEvent( e4 ); 194 | 195 | assert.expect( 3 ); 196 | assert.strictEqual( rActual, rExpected, "event prevented" ); 197 | assert.strictEqual( pActual, pExpected, "event removed" ); 198 | assert.strictEqual( qActual, qExpected, "event" ); 199 | } ); 200 | 201 | QUnit.test( "request unknown resources", function test(assert){ 202 | var done = assert.async(); 203 | assert.expect( 1 ); 204 | 205 | var rExpected = [ 206 | { window: WINDOW_ID, }, 207 | { document: DOCUMENT_ID, }, 208 | { head: HEAD_ID, }, 209 | { body: BODY_ID, }, 210 | { createElement: "link", internal_id: 5, }, 211 | { setAttribute: "rel | preload", internal_id: 5, }, 212 | { setAttribute: "href | a.js", internal_id: 5, }, 213 | { createElement: "link", internal_id: 6, }, 214 | { setAttribute: "href | b.js", internal_id: 6, }, 215 | { appendChild: 5, internal_id: HEAD_ID, }, 216 | { message: "appendChild: Preload resource not found (a.js; 5)", }, 217 | { appendChild: 6, internal_id: HEAD_ID, }, 218 | { message: "appendChild: Load resource not found (b.js; 6)", }, 219 | { dispatchEvent: "DOMContentLoaded", internal_id: DOCUMENT_ID, }, 220 | { dispatchEvent: "load", internal_id: WINDOW_ID, }, 221 | ]; 222 | 223 | var { logs: rActual, log, error, } = collectLogs(); 224 | 225 | var wrappedErrorFn = function wrapped(msg) { 226 | if (msg instanceof Error) { 227 | msg = JSON.parse( JSON.stringify( msg, ["message",] ) ); 228 | } 229 | return error( msg ); 230 | }; 231 | 232 | var win = $DOM( { 233 | sequentialIds: true, 234 | log, 235 | error: wrappedErrorFn, 236 | } ); 237 | 238 | var link1 = win.document.createElement( "link" ); 239 | link1.setAttribute( "rel", "preload" ); 240 | link1.setAttribute( "href", "a.js" ); 241 | 242 | var link2 = win.document.createElement( "link" ); 243 | link2.setAttribute( "href", "b.js" ); 244 | 245 | win.document.head.appendChild( link1 ); 246 | win.document.head.appendChild( link2 ); 247 | 248 | win.onload = function onload(){ 249 | assert.deepEqual( rActual, rExpected, "logs" ); 250 | done(); 251 | }; 252 | } ); 253 | 254 | QUnit.test( "load a script", function test(assert){ 255 | var done = assert.async( 2 ); 256 | assert.expect( 1 ); 257 | 258 | var rExpected = [ 259 | { window: WINDOW_ID, }, 260 | { document: DOCUMENT_ID, }, 261 | { head: HEAD_ID, }, 262 | { body: BODY_ID, }, 263 | { createElement: "script", internal_id: 5, }, 264 | { setAttribute: "src | a.js", internal_id: 5, }, 265 | { addEventListener: "load", internal_id: 5, }, 266 | { appendChild: 5, internal_id: HEAD_ID, }, 267 | { dispatchEvent: "DOMContentLoaded", internal_id: DOCUMENT_ID, }, 268 | { dispatchEvent: "load", internal_id: WINDOW_ID, }, 269 | { dispatchEvent: "load", internal_id: 5, }, 270 | ]; 271 | 272 | var { logs: rActual, log, error, } = collectLogs(); 273 | 274 | var win = $DOM( { 275 | sequentialIds: true, 276 | log, 277 | error, 278 | resources: [ 279 | { url: "a.js", load: true, loadDelay: "invalid" }, 280 | ], 281 | } ); 282 | 283 | win.onload = done; 284 | 285 | var script = win.document.createElement( "script" ); 286 | script.setAttribute( "src", "a.js" ); 287 | script.addEventListener( "load", function onload(){ 288 | assert.deepEqual( rActual, rExpected, "logs" ); 289 | done(); 290 | } ); 291 | win.document.head.appendChild( script ); 292 | } ); 293 | 294 | QUnit.test( "load multiple scripts (ordered async)", function test(assert){ 295 | var done = assert.async( 3 ); 296 | assert.expect( 1 ); 297 | 298 | var rExpected = [ 299 | { window: WINDOW_ID, }, 300 | { document: DOCUMENT_ID, }, 301 | { head: HEAD_ID, }, 302 | { body: BODY_ID, }, 303 | { createElement: "script", internal_id: 5, }, 304 | { setAttribute: "src | a.js", internal_id: 5, }, 305 | { addEventListener: "load", internal_id: 5, }, 306 | { createElement: "script", internal_id: 6, }, 307 | { setAttribute: "src | b.js", internal_id: 6, }, 308 | { addEventListener: "load", internal_id: 6, }, 309 | { createElement: "script", internal_id: 7, }, 310 | { setAttribute: "src | c.js", internal_id: 7, }, 311 | { addEventListener: "load", internal_id: 7, }, 312 | { appendChild: 5, internal_id: HEAD_ID, }, 313 | { appendChild: 6, internal_id: HEAD_ID, }, 314 | { appendChild: 7, internal_id: HEAD_ID, }, 315 | { dispatchEvent: "DOMContentLoaded", internal_id: DOCUMENT_ID, }, 316 | { dispatchEvent: "load", internal_id: WINDOW_ID, }, 317 | { updateExecQueue: "b.js", internal_id: 6, }, 318 | { updateExecQueue: "c.js", internal_id: 7, }, 319 | { updateExecQueue: "a.js", internal_id: 5, }, 320 | { dispatchEvent: "load", internal_id: 5, }, 321 | { dispatchEvent: "load", internal_id: 6, }, 322 | { dispatchEvent: "load", internal_id: 7, }, 323 | ]; 324 | 325 | var { logs: rActual, log, error, } = collectLogs(); 326 | 327 | var win = $DOM( { 328 | sequentialIds: true, 329 | log, 330 | error, 331 | resources: [ 332 | { url: "a.js", loadDelay: 40, load: true, }, 333 | { url: "b.js", loadDelay: 10, load: true, }, 334 | { url: "c.js", loadDelay: 25, load: true, }, 335 | ], 336 | } ); 337 | 338 | var script1 = win.document.createElement( "script" ); 339 | script1.setAttribute( "src", "a.js" ); 340 | script1.async = false; 341 | script1.addEventListener( "load", done ); 342 | 343 | var script2 = win.document.createElement( "script" ); 344 | script2.setAttribute( "src", "b.js" ); 345 | script2.async = false; 346 | script2.addEventListener( "load", done ); 347 | 348 | var script3 = win.document.createElement( "script" ); 349 | script3.setAttribute( "src", "c.js" ); 350 | script3.async = false; 351 | script3.addEventListener( "load", function onload(){ 352 | assert.deepEqual( rActual, rExpected, "logs" ); 353 | done(); 354 | } ); 355 | 356 | win.document.head.appendChild( script1 ); 357 | win.document.head.appendChild( script2 ); 358 | win.document.head.appendChild( script3 ); 359 | } ); 360 | 361 | QUnit.test( "load multiple scripts (NO ordered async)", function test(assert){ 362 | var done = assert.async( 3 ); 363 | assert.expect( 1 ); 364 | 365 | var rExpected = [ 366 | { window: WINDOW_ID, }, 367 | { document: DOCUMENT_ID, }, 368 | { head: HEAD_ID, }, 369 | { body: BODY_ID, }, 370 | { createElement: "script", internal_id: 5, }, 371 | { setAttribute: "src | a.js", internal_id: 5, }, 372 | { addEventListener: "load", internal_id: 5, }, 373 | { createElement: "script", internal_id: 6, }, 374 | { setAttribute: "src | b.js", internal_id: 6, }, 375 | { addEventListener: "load", internal_id: 6, }, 376 | { createElement: "script", internal_id: 7, }, 377 | { setAttribute: "src | c.js", internal_id: 7, }, 378 | { addEventListener: "load", internal_id: 7, }, 379 | { appendChild: 5, internal_id: HEAD_ID, }, 380 | { appendChild: 6, internal_id: HEAD_ID, }, 381 | { appendChild: 7, internal_id: HEAD_ID, }, 382 | { dispatchEvent: "DOMContentLoaded", internal_id: DOCUMENT_ID, }, 383 | { dispatchEvent: "load", internal_id: WINDOW_ID, }, 384 | { dispatchEvent: "load", internal_id: 6, }, 385 | { dispatchEvent: "load", internal_id: 7, }, 386 | { dispatchEvent: "load", internal_id: 5, }, 387 | ]; 388 | 389 | var { logs: rActual, log, error, } = collectLogs(); 390 | 391 | var win = $DOM( { 392 | sequentialIds: true, 393 | log, 394 | error, 395 | scriptAsync: false, 396 | resources: [ 397 | { url: "a.js", loadDelay: 40, load: true, }, 398 | { url: "b.js", loadDelay: 10, load: true, }, 399 | { url: "c.js", loadDelay: 25, load: true, }, 400 | ], 401 | } ); 402 | 403 | var script1 = win.document.createElement( "script" ); 404 | script1.setAttribute( "src", "a.js" ); 405 | script1.addEventListener( "load", function onload(){ 406 | assert.deepEqual( rActual, rExpected, "logs" ); 407 | done(); 408 | } ); 409 | 410 | var script2 = win.document.createElement( "script" ); 411 | script2.setAttribute( "src", "b.js" ); 412 | script2.addEventListener( "load", done ); 413 | 414 | var script3 = win.document.createElement( "script" ); 415 | script3.setAttribute( "src", "c.js" ); 416 | script3.addEventListener( "load", done ); 417 | 418 | win.document.head.appendChild( script1 ); 419 | win.document.head.appendChild( script2 ); 420 | win.document.head.appendChild( script3 ); 421 | } ); 422 | 423 | QUnit.test( "preload a script", function test(assert){ 424 | var done = assert.async(); 425 | assert.expect( 1 ); 426 | 427 | var rExpected = [ 428 | { window: WINDOW_ID, }, 429 | { document: DOCUMENT_ID, }, 430 | { head: HEAD_ID, }, 431 | { body: BODY_ID, }, 432 | { createElement: "link", internal_id: 5, }, 433 | { setAttribute: "rel | preload", internal_id: 5, }, 434 | { setAttribute: "as | script", internal_id: 5, }, 435 | { setAttribute: "href | a.js", internal_id: 5, }, 436 | { addEventListener: "load", internal_id: 5, }, 437 | { appendChild: 5, internal_id: HEAD_ID, }, 438 | { dispatchEvent: "DOMContentLoaded", internal_id: DOCUMENT_ID, }, 439 | { dispatchEvent: "load", internal_id: WINDOW_ID, }, 440 | { dispatchEvent: "load", internal_id: 5, }, 441 | ]; 442 | 443 | var { logs: rActual, log, error, } = collectLogs(); 444 | 445 | var win = $DOM( { 446 | sequentialIds: true, 447 | log, 448 | error, 449 | resources: [ 450 | { url: "a.js", preloadDelay: "invalid", preload: true, }, 451 | ], 452 | } ); 453 | 454 | var link = win.document.createElement( "link" ); 455 | link.setAttribute( "rel", "preload" ); 456 | link.setAttribute( "as", "script" ); 457 | link.setAttribute( "href", "a.js" ); 458 | link.addEventListener( "load", function onload(){ 459 | assert.deepEqual( rActual, rExpected, "logs" ); 460 | done(); 461 | } ); 462 | win.document.head.appendChild( link ); 463 | } ); 464 | 465 | QUnit.test( "preload multiple scripts", function test(assert){ 466 | var done = assert.async( 3 ); 467 | assert.expect( 1 ); 468 | 469 | var rExpected = [ 470 | { window: WINDOW_ID, }, 471 | { document: DOCUMENT_ID, }, 472 | { head: HEAD_ID, }, 473 | { body: BODY_ID, }, 474 | { createElement: "link", internal_id: 5, }, 475 | { setAttribute: "rel | preload", internal_id: 5, }, 476 | { setAttribute: "as | script", internal_id: 5, }, 477 | { setAttribute: "href | a.js", internal_id: 5, }, 478 | { addEventListener: "load", internal_id: 5, }, 479 | { createElement: "link", internal_id: 6, }, 480 | { setAttribute: "rel | preload", internal_id: 6, }, 481 | { setAttribute: "as | script", internal_id: 6, }, 482 | { setAttribute: "href | b.js", internal_id: 6, }, 483 | { addEventListener: "load", internal_id: 6, }, 484 | { createElement: "link", internal_id: 7, }, 485 | { setAttribute: "rel | preload", internal_id: 7, }, 486 | { setAttribute: "as | script", internal_id: 7, }, 487 | { setAttribute: "href | c.js", internal_id: 7, }, 488 | { addEventListener: "load", internal_id: 7, }, 489 | { appendChild: 5, internal_id: HEAD_ID, }, 490 | { appendChild: 6, internal_id: HEAD_ID, }, 491 | { appendChild: 7, internal_id: HEAD_ID, }, 492 | { dispatchEvent: "DOMContentLoaded", internal_id: DOCUMENT_ID, }, 493 | { dispatchEvent: "load", internal_id: WINDOW_ID, }, 494 | { dispatchEvent: "load", internal_id: 6, }, 495 | { dispatchEvent: "load", internal_id: 7, }, 496 | { dispatchEvent: "load", internal_id: 5, }, 497 | ]; 498 | 499 | var { logs: rActual, log, error, } = collectLogs(); 500 | 501 | var win = $DOM( { 502 | sequentialIds: true, 503 | log, 504 | error, 505 | resources: [ 506 | { url: "a.js", preloadDelay: 40, preload: true, }, 507 | { url: "b.js", preload: true, }, 508 | { url: "c.js", preloadDelay: 25, preload: true, }, 509 | ], 510 | } ); 511 | 512 | var link1 = win.document.createElement( "link" ); 513 | link1.setAttribute( "rel", "preload" ); 514 | link1.setAttribute( "as", "script" ); 515 | link1.setAttribute( "href", "a.js" ); 516 | link1.addEventListener( "load", function onload(){ 517 | assert.deepEqual( rActual, rExpected, "logs" ); 518 | done(); 519 | } ); 520 | 521 | var link2 = win.document.createElement( "link" ); 522 | link2.setAttribute( "rel", "preload" ); 523 | link2.setAttribute( "as", "script" ); 524 | link2.setAttribute( "href", "b.js" ); 525 | link2.addEventListener( "load", done ); 526 | 527 | var link3 = win.document.createElement( "link" ); 528 | link3.setAttribute( "rel", "preload" ); 529 | link3.setAttribute( "as", "script" ); 530 | link3.setAttribute( "href", "c.js" ); 531 | link3.addEventListener( "load", done ); 532 | 533 | win.document.head.appendChild( link1 ); 534 | win.document.head.appendChild( link2 ); 535 | win.document.head.appendChild( link3 ); 536 | } ); 537 | 538 | QUnit.test( "preload a script, then load it", function test(assert){ 539 | var done = assert.async(); 540 | assert.expect( 1 ); 541 | 542 | var rExpected = [ 543 | { window: WINDOW_ID, }, 544 | { document: DOCUMENT_ID, }, 545 | { head: HEAD_ID, }, 546 | { body: BODY_ID, }, 547 | { createElement: "link", internal_id: 5, }, 548 | { setAttribute: "rel | preload", internal_id: 5, }, 549 | { setAttribute: "as | script", internal_id: 5, }, 550 | { setAttribute: "href | a.js", internal_id: 5, }, 551 | { addEventListener: "load", internal_id: 5, }, 552 | { appendChild: 5, internal_id: HEAD_ID, }, 553 | { dispatchEvent: "DOMContentLoaded", internal_id: DOCUMENT_ID, }, 554 | { dispatchEvent: "load", internal_id: WINDOW_ID, }, 555 | { dispatchEvent: "load", internal_id: 5, }, 556 | { createElement: "script", internal_id: 6, }, 557 | { setAttribute: "src | a.js", internal_id: 6, }, 558 | { addEventListener: "load", internal_id: 6, }, 559 | { appendChild: 6, internal_id: HEAD_ID, }, 560 | { dispatchEvent: "load", internal_id: 6, }, 561 | ]; 562 | 563 | var { logs: rActual, log, error, } = collectLogs(); 564 | 565 | var win = $DOM( { 566 | sequentialIds: true, 567 | log, 568 | error, 569 | resources: [ 570 | { url: "a.js", preloadDelay: 25, preload: true, loadDelay: 50, load: true, }, 571 | ], 572 | } ); 573 | 574 | var link = win.document.createElement( "link" ); 575 | link.setAttribute( "rel", "preload" ); 576 | link.setAttribute( "as", "script" ); 577 | link.setAttribute( "href", "a.js" ); 578 | link.addEventListener( "load", function onload(){ 579 | var script = win.document.createElement( "script" ); 580 | script.setAttribute( "src", "a.js" ); 581 | script.addEventListener( "load", function onload(){ 582 | assert.deepEqual( rActual, rExpected, "logs" ); 583 | done(); 584 | } ); 585 | win.document.head.appendChild( script ); 586 | } ); 587 | win.document.head.appendChild( link ); 588 | } ); 589 | 590 | QUnit.test( "preload multiple scripts, then load them (ordered async)", function test(assert){ 591 | var done = assert.async( 3 ); 592 | assert.expect( 2 ); 593 | 594 | var rExpected = [ 595 | { window: WINDOW_ID, }, 596 | { document: DOCUMENT_ID, }, 597 | { head: HEAD_ID, }, 598 | { body: BODY_ID, }, 599 | { createElement: "link", internal_id: 5, }, 600 | { setAttribute: "rel | preload", internal_id: 5, }, 601 | { setAttribute: "as | script", internal_id: 5, }, 602 | { setAttribute: "href | a.js", internal_id: 5, }, 603 | { addEventListener: "load", internal_id: 5, }, 604 | { createElement: "link", internal_id: 6, }, 605 | { setAttribute: "rel | preload", internal_id: 6, }, 606 | { setAttribute: "as | script", internal_id: 6, }, 607 | { setAttribute: "href | b.js", internal_id: 6, }, 608 | { addEventListener: "load", internal_id: 6, }, 609 | { createElement: "link", internal_id: 7, }, 610 | { setAttribute: "rel | preload", internal_id: 7, }, 611 | { setAttribute: "as | script", internal_id: 7, }, 612 | { setAttribute: "href | c.js", internal_id: 7, }, 613 | { addEventListener: "load", internal_id: 7, }, 614 | { appendChild: 5, internal_id: HEAD_ID, }, 615 | { appendChild: 6, internal_id: HEAD_ID, }, 616 | { appendChild: 7, internal_id: HEAD_ID, }, 617 | { dispatchEvent: "DOMContentLoaded", internal_id: DOCUMENT_ID, }, 618 | { dispatchEvent: "load", internal_id: WINDOW_ID, }, 619 | { dispatchEvent: "load", internal_id: 6, }, 620 | { dispatchEvent: "load", internal_id: 7, }, 621 | { dispatchEvent: "load", internal_id: 5, }, 622 | { createElement: "script", internal_id: 8, }, 623 | { setAttribute: "src | a.js", internal_id: 8, }, 624 | { addEventListener: "load", internal_id: 8, }, 625 | { createElement: "script", internal_id: 9, }, 626 | { setAttribute: "src | b.js", internal_id: 9, }, 627 | { addEventListener: "load", internal_id: 9, }, 628 | { createElement: "script", internal_id: 10, }, 629 | { setAttribute: "src | c.js", internal_id: 10, }, 630 | { addEventListener: "load", internal_id: 10, }, 631 | { appendChild: 8, internal_id: HEAD_ID, }, 632 | { appendChild: 9, internal_id: HEAD_ID, }, 633 | { appendChild: 10, internal_id: HEAD_ID, }, 634 | { updateExecQueue: "c.js", internal_id: 10, }, 635 | { updateExecQueue: "a.js", internal_id: 8, }, 636 | { dispatchEvent: "load", internal_id: 8, }, 637 | { updateExecQueue: "b.js", internal_id: 9, }, 638 | { dispatchEvent: "load", internal_id: 9, }, 639 | { dispatchEvent: "load", internal_id: 10, }, 640 | ]; 641 | var pExpected = ["a.js","b.js","c.js",]; 642 | 643 | var { logs: rActual, log, error, } = collectLogs(); 644 | 645 | var win = $DOM( { 646 | sequentialIds: true, 647 | log, 648 | error, 649 | resources: [ 650 | { url: "a.js", preloadDelay: 40, preload: true, loadDelay: 20, load: true, }, 651 | { url: "b.js", preloadDelay: 10, preload: true, loadDelay: 30, load: true, }, 652 | { url: "c.js", preloadDelay: 25, preload: true, loadDelay: 10, load: true, }, 653 | ], 654 | } ); 655 | 656 | preloadScripts(); 657 | 658 | 659 | // *************************************** 660 | 661 | function preloadScripts() { 662 | var preloadCount = 0; 663 | 664 | var link1 = win.document.createElement( "link" ); 665 | link1.setAttribute( "rel", "preload" ); 666 | link1.setAttribute( "as", "script" ); 667 | link1.setAttribute( "href", "a.js" ); 668 | link1.addEventListener( "load", function onload(){ 669 | preloadCount++; 670 | if (preloadCount == 3) loadScripts(); 671 | } ); 672 | 673 | var link2 = win.document.createElement( "link" ); 674 | link2.setAttribute( "rel", "preload" ); 675 | link2.setAttribute( "as", "script" ); 676 | link2.setAttribute( "href", "b.js" ); 677 | link2.addEventListener( "load", function onload(){ 678 | preloadCount++; 679 | if (preloadCount == 3) loadScripts(); 680 | } ); 681 | 682 | var link3 = win.document.createElement( "link" ); 683 | link3.setAttribute( "rel", "preload" ); 684 | link3.setAttribute( "as", "script" ); 685 | link3.setAttribute( "href", "c.js" ); 686 | link3.addEventListener( "load", function onload(){ 687 | preloadCount++; 688 | if (preloadCount == 3) loadScripts(); 689 | } ); 690 | 691 | win.document.head.appendChild( link1 ); 692 | win.document.head.appendChild( link2 ); 693 | win.document.head.appendChild( link3 ); 694 | } 695 | 696 | function loadScripts() { 697 | var script1 = win.document.createElement( "script" ); 698 | script1.setAttribute( "src", "a.js" ); 699 | script1.async = false; 700 | script1.addEventListener( "load", done ); 701 | 702 | var script2 = win.document.createElement( "script" ); 703 | script2.setAttribute( "src", "b.js" ); 704 | script2.async = false; 705 | script2.addEventListener( "load", done ); 706 | 707 | var script3 = win.document.createElement( "script" ); 708 | script3.setAttribute( "src", "c.js" ); 709 | script3.async = false; 710 | script3.addEventListener( "load", function onload(){ 711 | var pActual = 712 | win.performance.getEntriesByName( "a.js" ) 713 | .concat( 714 | win.performance.getEntriesByName( "b.js" ), 715 | win.performance.getEntriesByName( "c.js" ) 716 | ); 717 | 718 | assert.deepEqual( rActual, rExpected, "logs" ); 719 | assert.deepEqual( pActual, pExpected, "performance entries" ); 720 | done(); 721 | } ); 722 | 723 | win.document.head.appendChild( script1 ); 724 | win.document.head.appendChild( script2 ); 725 | win.document.head.appendChild( script3 ); 726 | } 727 | } ); 728 | 729 | // probably not running in the browser? 730 | if (typeof window == "undefined" || Function("return this")() !== window || !window.document) { 731 | QUnit.test( "location (default); non-browser", function test(assert){ 732 | var rExpected = { 733 | href: "https://some.thing/else", 734 | protocol: "https:", 735 | pathname: "/else", 736 | port: "", 737 | host: "some.thing", 738 | hostname: "some.thing", 739 | hash: "", 740 | search: "", 741 | origin: "https://some.thing", 742 | }; 743 | var pExpected = "https://some.thing/else"; 744 | var qExpected = "https://some.thing/else"; 745 | var tExpected = "https://some.thing/else"; 746 | var sExpected = "https://some.thing/else"; 747 | var uExpected = "https://some.thing/else"; 748 | 749 | var win = $DOM( { 750 | log: function log(){}, 751 | error: function error(){}, 752 | } ); 753 | 754 | var rActual = JSON.parse( JSON.stringify( win.location ) ); 755 | var pActual = win.location.href; 756 | var qActual = win.location.href.toString(); 757 | var tActual = win.location.toString(); 758 | var sActual = "" + win.location; 759 | var uActual = win.document.baseURI; 760 | 761 | assert.expect( 6 ); 762 | assert.deepEqual( rActual, rExpected, "location object" ); 763 | assert.strictEqual( pActual, pExpected, "location.href" ); 764 | assert.strictEqual( qActual, qExpected, "location.href.toString()" ); 765 | assert.strictEqual( tActual, tExpected, "location.toString()" ); 766 | assert.strictEqual( sActual, sExpected, "location + ''" ); 767 | assert.strictEqual( uActual, uExpected, "baseURI default" ); 768 | } ); 769 | 770 | QUnit.test( "location (changed); non-browser", function test(assert){ 771 | var rExpected = { 772 | href: "http://user1:pw1@some.tld:8080/foo/bar?bam=baz#haha", 773 | protocol: "http:", 774 | pathname: "/foo/bar", 775 | port: "8080", 776 | host: "some.tld:8080", 777 | hostname: "some.tld", 778 | hash: "#haha", 779 | search: "?bam=baz", 780 | origin: "http://some.tld:8080", 781 | username: "user1", 782 | password: "pw1", 783 | }; 784 | var pExpected = { 785 | href: "https://some.thing/better", 786 | protocol: "https:", 787 | pathname: "/better", 788 | port: "", 789 | host: "some.thing", 790 | hostname: "some.thing", 791 | hash: "", 792 | search: "", 793 | origin: "https://some.thing", 794 | }; 795 | var qExpected = "http://user1:pw1@some.tld:8080/foo/bar?bam=baz#haha"; 796 | var tExpected = "https://a.tld/funny"; 797 | var sExpected = "http://some.tld/foo/bar"; 798 | var uExpected = "https://other.tld"; 799 | var mExpected = "http://user1:pw1@some.tld:8080/foo/bar?bam=baz#haha"; 800 | 801 | var win = $DOM( { 802 | replaceGlobals: true, 803 | log: function log(){}, 804 | error: function error(){}, 805 | location: "http://user1:pw1@some.tld:8080/foo/bar?bam=baz#haha", 806 | } ); 807 | win.location.reload(); 808 | 809 | var rActual = JSON.parse( JSON.stringify( win.document.location ) ); 810 | 811 | win.location = "https://some.thing/better"; 812 | var pActual = JSON.parse( JSON.stringify( win.location ) ); 813 | 814 | global.location = "http://user1:pw1@some.tld:8080/foo/bar?bam=baz#haha"; 815 | var qActual = win.location.href.toString(); 816 | 817 | document.location = "https://a.tld/funny"; 818 | var tActual = win.location.href.toString(); 819 | 820 | win.location.assign( "http://some.tld/foo/bar" ); 821 | var sActual = win.location.href.toString(); 822 | 823 | win.location.replace( "https://other.tld" ); 824 | var uActual = win.location.href.toString(); 825 | var mActual = win.document.baseURI; 826 | 827 | $DOM.restoreGlobals(); 828 | 829 | assert.expect( 7 ); 830 | assert.deepEqual( rActual, rExpected, "location object" ); 831 | assert.deepEqual( pActual, pExpected, "win.location = .." ); 832 | assert.strictEqual( qActual, qExpected, "global.location = .." ); 833 | assert.strictEqual( tActual, tExpected, "document.location = .." ); 834 | assert.strictEqual( sActual, sExpected, "location.assign()" ); 835 | assert.strictEqual( uActual, uExpected, "location.replace()" ); 836 | assert.strictEqual( mActual, mExpected, "baseURI" ); 837 | } ); 838 | 839 | QUnit.test( "replace and restore globals; non-browser", function test(assert){ 840 | var globalObj = typeof global != "undefined" ? global : Function( "return this" )(); 841 | 842 | var pExpected = [ 843 | globalObj.window, 844 | globalObj.document, 845 | globalObj.performance, 846 | globalObj.Event, 847 | globalObj.location, 848 | ]; 849 | 850 | var win = $DOM( { 851 | replaceGlobals: true, 852 | log: function log(){}, 853 | error: function error(){}, 854 | } ); 855 | 856 | var rExpected = [ 857 | win, 858 | win.document, 859 | win.performance, 860 | win.Event, 861 | win.location, 862 | ]; 863 | 864 | var rActual = [ 865 | globalObj.window, 866 | globalObj.document, 867 | globalObj.performance, 868 | globalObj.Event, 869 | globalObj.location, 870 | ]; 871 | 872 | $DOM.restoreGlobals(); 873 | 874 | var pActual = [ 875 | globalObj.window, 876 | globalObj.document, 877 | globalObj.performance, 878 | globalObj.Event, 879 | globalObj.location, 880 | ]; 881 | 882 | assert.expect( 2 ); 883 | assert.deepEqual( rActual, rExpected, "replaced globals" ); 884 | assert.deepEqual( pActual, pExpected, "restored globals" ); 885 | } ); 886 | } 887 | // otherwise, probably running in the browser 888 | else { 889 | QUnit.test( "replace and restore globals; browser", function test(assert){ 890 | var pExpected = [ 891 | window.document.createElement, 892 | window.document.createEvent, 893 | window.document.appendChild, 894 | window.document.removeChild, 895 | window.document.getElementsByTagName, 896 | window.document.head.appendChild, 897 | window.document.head.removeChild, 898 | window.document.head.getElementsByTagName, 899 | window.document.body.appendChild, 900 | window.document.body.removeChild, 901 | window.document.body.getElementsByTagName, 902 | window.performance.getEntriesByName, 903 | window.Event, 904 | ]; 905 | 906 | var win = $DOM( { 907 | replaceGlobals: true, 908 | log: function log(){}, 909 | error: function error(){}, 910 | } ); 911 | 912 | var rExpected = [ 913 | win.document.createElement, 914 | win.document.createEvent, 915 | win.document.appendChild, 916 | win.document.removeChild, 917 | win.document.getElementsByTagName, 918 | win.document.head.appendChild, 919 | win.document.head.removeChild, 920 | win.document.head.getElementsByTagName, 921 | win.document.body.appendChild, 922 | win.document.body.removeChild, 923 | win.document.body.getElementsByTagName, 924 | win.performance.getEntriesByName, 925 | win.Event, 926 | ]; 927 | 928 | var rActual = [ 929 | window.document.createElement, 930 | window.document.createEvent, 931 | window.document.appendChild, 932 | window.document.removeChild, 933 | window.document.getElementsByTagName, 934 | window.document.head.appendChild, 935 | window.document.head.removeChild, 936 | window.document.head.getElementsByTagName, 937 | window.document.body.appendChild, 938 | window.document.body.removeChild, 939 | window.document.body.getElementsByTagName, 940 | window.performance.getEntriesByName, 941 | window.Event, 942 | ]; 943 | 944 | // restore original globals 945 | $DOM.restoreGlobals(); 946 | 947 | var pActual = [ 948 | window.document.createElement, 949 | window.document.createEvent, 950 | window.document.appendChild, 951 | window.document.removeChild, 952 | window.document.getElementsByTagName, 953 | window.document.head.appendChild, 954 | window.document.head.removeChild, 955 | window.document.head.getElementsByTagName, 956 | window.document.body.appendChild, 957 | window.document.body.removeChild, 958 | window.document.body.getElementsByTagName, 959 | window.performance.getEntriesByName, 960 | window.Event, 961 | ]; 962 | 963 | assert.expect( 2 ); 964 | assert.deepEqual( rActual, rExpected, "replaced globals" ); 965 | assert.deepEqual( pActual, pExpected, "restored globals" ); 966 | } ); 967 | } 968 | 969 | QUnit.test( "document.readyState", function test(assert){ 970 | var done = assert.async( 6 ); 971 | assert.expect( 5 ); 972 | 973 | var rExpected = [ 974 | { window: WINDOW_ID, }, 975 | { document: DOCUMENT_ID, }, 976 | { head: HEAD_ID, }, 977 | { body: BODY_ID, }, 978 | { addEventListener: "DOMContentLoaded", internal_id: DOCUMENT_ID, }, 979 | { addEventListener: "load", internal_id: WINDOW_ID, }, 980 | { dispatchEvent: "DOMContentLoaded", internal_id: DOCUMENT_ID, }, 981 | { dispatchEvent: "load", internal_id: WINDOW_ID, }, 982 | ]; 983 | var pExpected = [ 984 | { window: WINDOW_ID, }, 985 | { document: DOCUMENT_ID, }, 986 | { head: HEAD_ID, }, 987 | { body: BODY_ID, }, 988 | { addEventListener: "DOMContentLoaded", internal_id: WINDOW_ID, }, 989 | { addEventListener: "load", internal_id: WINDOW_ID, }, 990 | { dispatchEvent: "load", internal_id: WINDOW_ID, }, 991 | ]; 992 | var qExpected = [ 993 | { window: WINDOW_ID, }, 994 | { document: DOCUMENT_ID, }, 995 | { head: HEAD_ID, }, 996 | { body: BODY_ID, }, 997 | { addEventListener: "DOMContentLoaded", internal_id: WINDOW_ID, }, 998 | { addEventListener: "load", internal_id: WINDOW_ID, }, 999 | ]; 1000 | var tExpected = [ 1001 | { window: WINDOW_ID, }, 1002 | { document: DOCUMENT_ID, }, 1003 | { head: HEAD_ID, }, 1004 | { body: BODY_ID, }, 1005 | { addEventListener: "DOMContentLoaded", internal_id: DOCUMENT_ID, }, 1006 | { addEventListener: "load", internal_id: WINDOW_ID, }, 1007 | { dispatchEvent: "DOMContentLoaded", internal_id: DOCUMENT_ID, }, 1008 | { dispatchEvent: "load", internal_id: WINDOW_ID, }, 1009 | ]; 1010 | var sExpected = "complete"; 1011 | 1012 | var callDone = function callDone(){ done(); }; 1013 | var reportError = function reportError(err){ throw err; }; 1014 | 1015 | var { logs: rActual, log: log1, error: error1, } = collectLogs(); 1016 | var { logs: pActual, log: log2, error: error2, } = collectLogs(); 1017 | var { logs: qActual, log: log3, error: error3, } = collectLogs(); 1018 | var { logs: tActual, log: log4, error: error4, } = collectLogs(); 1019 | 1020 | var win1 = $DOM( { 1021 | sequentialIds: true, 1022 | log: log1, 1023 | error: error1, 1024 | docReadyDelay: 30, 1025 | } ); 1026 | win1.document.addEventListener( "DOMContentLoaded", callDone ); 1027 | win1.addEventListener( "load", callDone ); 1028 | win1.onload = function onload(){ 1029 | win1.document.readyState = "ignored"; 1030 | var sActual = win1.document.readyState; 1031 | 1032 | assert.deepEqual( rActual, rExpected, "300ms DOMContentLoaded" ); 1033 | assert.deepEqual( pActual, pExpected, "invalid delay" ); 1034 | assert.deepEqual( qActual, qExpected, "document already complete" ); 1035 | assert.deepEqual( tActual, tExpected, "invalid ready-state" ); 1036 | assert.strictEqual( sActual, sExpected, "document.readyState" ); 1037 | 1038 | done(); 1039 | }; 1040 | 1041 | var win2 = $DOM( { 1042 | sequentialIds: true, 1043 | log: log2, 1044 | error: error2, 1045 | docReadyState: "interactive", 1046 | docReadyDelay: "anything but a number like it should be", 1047 | } ); 1048 | win2.addEventListener( "DOMContentLoaded", reportError ); 1049 | win2.addEventListener( "load", callDone ); 1050 | 1051 | var win3 = $DOM( { 1052 | sequentialIds: true, 1053 | log: log3, 1054 | error: error3, 1055 | docReadyState: "complete", 1056 | } ); 1057 | win3.addEventListener( "DOMContentLoaded", reportError ); 1058 | win3.addEventListener( "load", reportError ); 1059 | 1060 | var win4 = $DOM( { 1061 | sequentialIds: true, 1062 | log: log4, 1063 | error: error4, 1064 | docReadyState: "other", 1065 | } ); 1066 | win4.document.addEventListener( "DOMContentLoaded", callDone ); 1067 | win4.addEventListener( "load", callDone ); 1068 | } ); 1069 | 1070 | QUnit.test( "scripts: initial and API", function test(assert){ 1071 | var done = assert.async(); 1072 | assert.expect( 1 ); 1073 | 1074 | var rExpected = [ 1075 | ]; 1076 | 1077 | var { logs: rActual, log, error, } = collectLogs(); 1078 | 1079 | var win = $DOM( { 1080 | sequentialIds: true, 1081 | log, 1082 | error, 1083 | docReadyDelay: 30, 1084 | resources: [ 1085 | { url: "a.js", loadDelay: 50, load: true, }, 1086 | { url: "b.js", loadDelay: 10, load: true, }, 1087 | { url: "c.js", loadDelay: 20, load: true, }, 1088 | ], 1089 | initialDOM: { 1090 | head: [ 1091 | { tagName: "script", src: "a.js", }, 1092 | ], 1093 | body: [ 1094 | { tagName: "script", src: "b.js", }, 1095 | ], 1096 | }, 1097 | } ); 1098 | 1099 | var script = win.document.createElement( "script" ); 1100 | script.setAttribute( "src", "c.js" ); 1101 | win.document.body.appendChild( script ); 1102 | 1103 | win.document.head.childNodes[0].addEventListener( "load", function load(){ 1104 | assert.deepEqual( rActual, rExpected, "all scripts" ); 1105 | done(); 1106 | } ); 1107 | } ); 1108 | 1109 | 1110 | 1111 | 1112 | 1113 | 1114 | // ************************************ 1115 | 1116 | function collectLogs() { 1117 | var logs = []; 1118 | return { 1119 | logs, 1120 | log(msg){ logs.push( msg ); }, 1121 | error(msg) { logs.push( msg ); }, 1122 | }; 1123 | } 1124 | --------------------------------------------------------------------------------