test-helper.js (4381B)
1 setup({allow_uncaught_exception : true}); 2 3 // Creates a new Document (via <iframe>) and add an inline import map. 4 function createTestIframe(importMap, importMapBaseURL) { 5 return new Promise(resolve => { 6 const iframe = document.createElement('iframe'); 7 8 window.addEventListener('message', event => { 9 // Parsing result is saved here and checked later, rather than 10 // rejecting the promise on errors. 11 iframe.parseImportMapResult = event.data.type; 12 resolve(iframe); 13 }, 14 {once: true}); 15 16 const testHTML = createTestHTML(importMap, importMapBaseURL); 17 18 if (new URL(importMapBaseURL).protocol === 'data:') { 19 iframe.src = 'data:text/html;base64,' + btoa(testHTML); 20 } else { 21 iframe.src = '/common/blank.html'; 22 iframe.addEventListener('load', () => { 23 iframe.contentDocument.write(testHTML); 24 iframe.contentDocument.close(); 25 }, {once: true}); 26 } 27 document.body.appendChild(iframe); 28 }); 29 } 30 31 function createTestHTML(importMap, importMapBaseURL) { 32 return ` 33 <!DOCTYPE html> 34 <script src="${location.origin}/import-maps/data-driven/resources/test-helper-iframe.js"></script> 35 36 <base href="${importMapBaseURL}"> 37 <script type="importmap" onerror="onScriptError(event)"> 38 ${JSON.stringify(importMap)} 39 </script> 40 41 <script type="module"> 42 if (!window.registrationResult) { 43 window.registrationResult = {type: 'Success'}; 44 } 45 window.removeEventListener('error', window.windowErrorHandler); 46 parent.postMessage(window.registrationResult, '*'); 47 </script> 48 `; 49 } 50 51 // Returns a promise that is resolved with the resulting URL, or rejected if 52 // the resolution fails. 53 function resolve(specifier, baseURL, iframe) { 54 return new Promise((resolve, reject) => { 55 window.addEventListener('message', event => { 56 if (event.data.type === 'ResolutionSuccess') { 57 resolve(event.data.result); 58 } else if (event.data.type === 'Failure') { 59 if (event.data.result === 'TypeError') { 60 reject(new TypeError(event.data.message)); 61 } else { 62 reject(new Error(event.data.message)); 63 } 64 } else { 65 assert_unreached('Invalid message: ' + event.data.type); 66 } 67 }, 68 {once: true}); 69 70 iframe.contentWindow.postMessage( 71 {action: 'resolve', specifier, baseURL}, 72 '*' 73 ); 74 }); 75 } 76 77 function assert_no_extra_properties(object, expectedProperties, description) { 78 for (const actualProperty in object) { 79 assert_true(expectedProperties.indexOf(actualProperty) !== -1, 80 description + ': unexpected property ' + actualProperty); 81 } 82 } 83 84 async function runTests(j) { 85 const tests = j.tests; 86 delete j.tests; 87 88 if (j.hasOwnProperty('importMap')) { 89 assert_own_property(j, 'importMap'); 90 assert_own_property(j, 'importMapBaseURL'); 91 j.iframe = await createTestIframe(j.importMap, j.importMapBaseURL); 92 delete j.importMap; 93 delete j.importMapBaseURL; 94 } 95 96 assert_no_extra_properties( 97 j, 98 ['expectedResults', 'expectedParsedImportMap', 99 'baseURL', 'name', 'iframe', 100 'importMap', 'importMapBaseURL', 101 'link', 'details'], 102 j.name); 103 104 if (tests) { 105 // Nested node. 106 for (const testName in tests) { 107 let fullTestName = testName; 108 if (j.name) { 109 fullTestName = j.name + ': ' + testName; 110 } 111 tests[testName].name = fullTestName; 112 const k = Object.assign({}, j, tests[testName]); 113 await runTests(k); 114 } 115 } else { 116 // Leaf node. 117 for (const key of ['iframe', 'name', 'expectedResults']) { 118 assert_own_property(j, key, j.name); 119 } 120 121 assert_equals( 122 j.iframe.parseImportMapResult, 123 'Success', 124 'Import map registration should be successful for resolution tests'); 125 for (const [specifier, expected] of Object.entries(j.expectedResults)) { 126 promise_test(async t => { 127 if (expected === null) { 128 return promise_rejects_js(t, TypeError, resolve(specifier, j.baseURL, j.iframe)); 129 } else { 130 assert_equals(await resolve(specifier, j.baseURL, j.iframe), expected); 131 } 132 }, 133 j.name + ': ' + specifier); 134 } 135 } 136 } 137 138 export async function runTestsFromJSON(jsonURL) { 139 const response = await fetch(jsonURL); 140 const json = await response.json(); 141 await runTests(json); 142 }