test_devtools_shim.js (5948B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 const { DevToolsShim } = ChromeUtils.importESModule( 7 "chrome://devtools-startup/content/DevToolsShim.sys.mjs" 8 ); 9 10 // Test the DevToolsShim 11 12 /** 13 * Create a mocked version of DevTools that records all calls made to methods expected 14 * to be called by DevToolsShim. 15 */ 16 function createMockDevTools() { 17 const methods = [ 18 "on", 19 "off", 20 "emit", 21 "saveDevToolsSession", 22 "restoreDevToolsSession", 23 ]; 24 25 const mock = { 26 callLog: {}, 27 }; 28 29 for (const method of methods) { 30 // Create a stub for method, that only pushes its arguments in the inner callLog 31 mock[method] = function (...args) { 32 mock.callLog[method].push(args); 33 }; 34 mock.callLog[method] = []; 35 } 36 37 return mock; 38 } 39 40 /** 41 * Check if a given method was called an expected number of times, and finally check the 42 * arguments provided to the last call, if appropriate. 43 * 44 * @param {object} mock 45 * @param {string} method 46 * @param {number} length 47 * @param {Array} lastArgs 48 */ 49 function checkCalls(mock, method, length, lastArgs) { 50 Assert.strictEqual( 51 mock.callLog[method].length, 52 length, 53 "Devtools.on was called the expected number of times" 54 ); 55 56 // If we don't want to check the last call or if the method was never called, bail out. 57 if (!lastArgs || length === 0) { 58 return; 59 } 60 61 for (let i = 0; i < lastArgs.length; i++) { 62 const expectedArg = lastArgs[i]; 63 Assert.strictEqual( 64 mock.callLog[method][length - 1][i], 65 expectedArg, 66 `Devtools.${method} was called with the expected argument (index ${i})` 67 ); 68 } 69 } 70 71 function test_register_unregister() { 72 ok(!DevToolsShim.isInitialized(), "DevTools are not initialized"); 73 74 DevToolsShim.register(createMockDevTools()); 75 ok(DevToolsShim.isInitialized(), "DevTools are initialized"); 76 77 DevToolsShim.unregister(); 78 ok(!DevToolsShim.isInitialized(), "DevTools are not initialized"); 79 } 80 81 function test_on_is_forwarded_to_devtools() { 82 ok(!DevToolsShim.isInitialized(), "DevTools are not initialized"); 83 84 function cb1() {} 85 function cb2() {} 86 const mock = createMockDevTools(); 87 88 DevToolsShim.on("test_event", cb1); 89 DevToolsShim.register(mock); 90 checkCalls(mock, "on", 1, ["test_event", cb1]); 91 92 DevToolsShim.on("other_event", cb2); 93 checkCalls(mock, "on", 2, ["other_event", cb2]); 94 } 95 96 function test_off_called_before_registering_devtools() { 97 ok(!DevToolsShim.isInitialized(), "DevTools are not initialized"); 98 99 function cb1() {} 100 const mock = createMockDevTools(); 101 102 DevToolsShim.on("test_event", cb1); 103 DevToolsShim.off("test_event", cb1); 104 105 DevToolsShim.register(mock); 106 checkCalls(mock, "on", 0); 107 } 108 109 function test_off_called_before_with_bad_callback() { 110 ok(!DevToolsShim.isInitialized(), "DevTools are not initialized"); 111 112 function cb1() {} 113 function cb2() {} 114 const mock = createMockDevTools(); 115 116 DevToolsShim.on("test_event", cb1); 117 DevToolsShim.off("test_event", cb2); 118 119 DevToolsShim.register(mock); 120 // on should still be called 121 checkCalls(mock, "on", 1, ["test_event", cb1]); 122 // Calls to off should not be held and forwarded. 123 checkCalls(mock, "off", 0); 124 } 125 126 function test_events() { 127 ok(!DevToolsShim.isInitialized(), "DevTools are not initialized"); 128 129 const mock = createMockDevTools(); 130 // Check emit was not called. 131 checkCalls(mock, "emit", 0); 132 133 // Check emit is called once with the devtools-registered event. 134 DevToolsShim.register(mock); 135 checkCalls(mock, "emit", 1, ["devtools-registered"]); 136 137 // Check emit is called once with the devtools-unregistered event. 138 DevToolsShim.unregister(); 139 checkCalls(mock, "emit", 2, ["devtools-unregistered"]); 140 } 141 142 function test_restore_session_apis() { 143 // Backup method that will be updated for the test. 144 const initDevToolsBackup = DevToolsShim.initDevTools; 145 146 // Create fake session objects to restore. 147 const sessionWithoutDevTools = {}; 148 const sessionWithDevTools = { 149 browserConsole: true, 150 }; 151 152 Services.prefs.setBoolPref("devtools.policy.disabled", true); 153 ok(!DevToolsShim.isInitialized(), "DevTools are not initialized"); 154 ok(!DevToolsShim.isEnabled(), "DevTools are not enabled"); 155 156 // Check that save & restore DevToolsSession don't initialize the tools and don't 157 // crash. 158 DevToolsShim.saveDevToolsSession({}); 159 DevToolsShim.restoreDevToolsSession(sessionWithDevTools); 160 ok(!DevToolsShim.isInitialized(), "DevTools are still not initialized"); 161 162 Services.prefs.setBoolPref("devtools.policy.disabled", false); 163 ok(DevToolsShim.isEnabled(), "DevTools are enabled"); 164 ok(!DevToolsShim.isInitialized(), "DevTools are not initialized"); 165 166 // Check that DevTools are not initialized when calling restoreDevToolsSession without 167 // DevTools related data. 168 DevToolsShim.restoreDevToolsSession(sessionWithoutDevTools); 169 ok(!DevToolsShim.isInitialized(), "DevTools are still not initialized"); 170 171 const mock = createMockDevTools(); 172 DevToolsShim.initDevTools = () => { 173 // Next call to restoreDevToolsSession is expected to initialize DevTools, which we 174 // simulate here by registering our mock. 175 DevToolsShim.register(mock); 176 }; 177 178 DevToolsShim.restoreDevToolsSession(sessionWithDevTools); 179 checkCalls(mock, "restoreDevToolsSession", 1, [sessionWithDevTools]); 180 181 ok(DevToolsShim.isInitialized(), "DevTools are initialized"); 182 183 DevToolsShim.saveDevToolsSession({}); 184 checkCalls(mock, "saveDevToolsSession", 1, []); 185 186 // Restore initDevTools backup. 187 DevToolsShim.initDevTools = initDevToolsBackup; 188 } 189 190 function run_test() { 191 test_register_unregister(); 192 DevToolsShim.unregister(); 193 194 test_on_is_forwarded_to_devtools(); 195 DevToolsShim.unregister(); 196 197 test_off_called_before_registering_devtools(); 198 DevToolsShim.unregister(); 199 200 test_off_called_before_with_bad_callback(); 201 DevToolsShim.unregister(); 202 203 test_restore_session_apis(); 204 DevToolsShim.unregister(); 205 206 test_events(); 207 }