webchannel-js-sources.html (6606B)
1 <!DOCTYPE html> 2 <!-- This Source Code Form is subject to the terms of the Mozilla Public 3 - License, v. 2.0. If a copy of the MPL was not distributed with this 4 - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> 5 <html> 6 <head> 7 <meta charset="utf-8"/> 8 <title></title> 9 </head> 10 <body> 11 <script> 12 "use strict"; 13 // This file is used to test the retrieval of JS sources from a front-end. 14 // Rather than using some kind of complicated message passing scheme to 15 // talk to the test harness, modify the title of the page. The tests can 16 // easily read the window title to see if things worked as expected. 17 18 // The following are the titles used to communicate the page's state to the tests. 19 // Keep these in sync with any tests that read them. 20 const initialTitle = "Waiting for the JS sources"; 21 const successTitle = "JS sources received"; 22 const errorTitle = "Error" 23 24 document.title = initialTitle; 25 26 // A function which requests the JS sources from the browser using the GET_JS_SOURCES 27 // WebChannel message. 28 function getJSSources(sourceUuids, expectError = false) { 29 return new Promise((resolve, reject) => { 30 const requestId = Date.now(); 31 32 function listener(event) { 33 window.removeEventListener( 34 "WebChannelMessageToContent", 35 listener, 36 true 37 ); 38 39 const { id, message } = event.detail; 40 41 dump(JSON.stringify(message)); 42 dump("\n"); 43 if (id !== "profiler.firefox.com" || 44 !message || 45 typeof message !== "object" 46 ) { 47 console.error(message); 48 reject(new Error("A malformed WebChannel event was received.")); 49 return; 50 } 51 52 if (!message.type) { 53 console.error(message); 54 reject(new Error("The WebChannel event indicates an error.")); 55 return; 56 } 57 58 if (message.requestId === requestId) { 59 if (message.type === "SUCCESS_RESPONSE") { 60 resolve(message.response); 61 } else if (message.type === "ERROR_RESPONSE") { 62 if (expectError) { 63 resolve({ error: message.error }); 64 } else { 65 reject(new Error(message.error)); 66 } 67 } else { 68 reject(new Error("Unknown response type: " + message.type)); 69 } 70 } 71 } 72 73 window.addEventListener("WebChannelMessageToContent", listener, true); 74 75 window.dispatchEvent( 76 new CustomEvent("WebChannelMessageToChrome", { 77 detail: JSON.stringify({ 78 id: "profiler.firefox.com", 79 message: { type: "GET_JS_SOURCES", requestId, sourceUuids }, 80 }), 81 }) 82 ); 83 }) 84 } 85 86 async function runTest() { 87 try { 88 // Get test configuration from URL parameters 89 const params = new URLSearchParams(document.location.search); 90 const testType = params.get("testType") || "basic"; 91 const expectError = params.get("expectError") === "true"; 92 93 let sourcesToRequest; 94 let expectedResponse; 95 96 // Handle invalid-request test case where sourceUuids is intentionally not JSON 97 if (testType === "invalid-request") { 98 sourcesToRequest = params.get("sourceUuids"); // Keep as string for invalid test 99 expectedResponse = null; 100 } else { 101 sourcesToRequest = JSON.parse(params.get("sourceUuids") || "[]"); 102 expectedResponse = JSON.parse(params.get("expectedResponse") || "null"); 103 } 104 105 let response; 106 if (expectError) { 107 response = await getJSSources(sourcesToRequest, true); 108 } else { 109 response = await getJSSources(sourcesToRequest, false); 110 } 111 112 dump("response\n") 113 dump(JSON.stringify(response)); 114 115 let testPassed = false; 116 117 function deepEqual(obj1, obj2) { 118 return JSON.stringify(obj1) === JSON.stringify(obj2); 119 } 120 121 switch (testType) { 122 case "basic": 123 // Test case: Request existing JS sources 124 testPassed = response && 125 Array.isArray(response) && 126 response.length === expectedResponse.length && 127 response.every((item, index) => deepEqual(item, expectedResponse[index])); 128 break; 129 130 case "nonexistent": 131 // Test case: Request non-existent sources (should return error objects) 132 testPassed = response && 133 Array.isArray(response) && 134 response.length === expectedResponse.length && 135 response.every((item, index) => deepEqual(item, expectedResponse[index])); 136 break; 137 138 case "no-data": 139 // Test case: No JS source data registered (should return error) 140 testPassed = response && 141 response.error && 142 response.error.includes("No JS source data found for this tab"); 143 break; 144 145 case "invalid-request": 146 // Test case: Invalid sources parameter (should return error) 147 testPassed = response && 148 response.error && 149 response.error.includes("sourceUuids must be an array"); 150 break; 151 152 default: 153 throw new Error("Unknown test type: " + testType); 154 } 155 156 if (testPassed) { 157 document.title = successTitle; 158 } else { 159 dump('Test failed in webchannel-js-sources.html\n'); 160 dump(`Test type: ${testType}\n`); 161 dump(`Expected: ${JSON.stringify(expectedResponse)}\n`); 162 dump(`Actual: ${JSON.stringify(response)}\n`); 163 164 console.error( 165 "Test failed in webchannel-js-sources.html", 166 { testType, expectedResponse, response } 167 ); 168 169 document.title = errorTitle; 170 } 171 } catch (error) { 172 // Catch any error and notify the test. 173 document.title = errorTitle; 174 dump('An error was caught in webchannel-js-sources.html\n'); 175 dump(`${error}\n`); 176 console.error( 177 "An error was caught in webchannel-js-sources.html", 178 error 179 ); 180 } 181 } 182 183 runTest(); 184 </script> 185 </body> 186 </html>