test_ext_normandyAddonStudy.js (6724B)
1 "use strict"; 2 3 ChromeUtils.defineESModuleGetters(this, { 4 AddonManager: "resource://gre/modules/AddonManager.sys.mjs", 5 }); 6 7 const { AddonStudies } = ChromeUtils.importESModule( 8 "resource://normandy/lib/AddonStudies.sys.mjs" 9 ); 10 const { NormandyTestUtils } = ChromeUtils.importESModule( 11 "resource://testing-common/NormandyTestUtils.sys.mjs" 12 ); 13 const { TestUtils } = ChromeUtils.importESModule( 14 "resource://testing-common/TestUtils.sys.mjs" 15 ); 16 var { AddonTestUtils } = ChromeUtils.importESModule( 17 "resource://testing-common/AddonTestUtils.sys.mjs" 18 ); 19 20 const { addonStudyFactory } = NormandyTestUtils.factories; 21 22 AddonTestUtils.init(this); 23 24 // All tests run privileged unless otherwise specified not to. 25 function createExtension(backgroundScript, permissions, isPrivileged = true) { 26 let extensionData = { 27 background: backgroundScript, 28 manifest: { 29 browser_specific_settings: { 30 gecko: { 31 id: "test@shield.mozilla.com", 32 }, 33 }, 34 permissions, 35 }, 36 isPrivileged, 37 }; 38 return ExtensionTestUtils.loadExtension(extensionData); 39 } 40 41 async function run(test) { 42 let extension = createExtension( 43 test.backgroundScript, 44 test.permissions || ["normandyAddonStudy"], 45 test.isPrivileged 46 ); 47 const promiseValidation = test.validationScript 48 ? test.validationScript(extension) 49 : Promise.resolve(); 50 51 await extension.startup(); 52 53 await promiseValidation; 54 55 if (test.doneSignal) { 56 await extension.awaitFinish(test.doneSignal); 57 } 58 59 await extension.unload(); 60 } 61 62 add_task(async function setup() { 63 await ExtensionTestUtils.startAddonManager(); 64 }); 65 66 add_task( 67 async function test_normandyAddonStudy_without_normandyAddonStudy_permission_privileged() { 68 await run({ 69 backgroundScript: () => { 70 browser.test.assertTrue( 71 !browser.normandyAddonStudy, 72 "'normandyAddonStudy' permission is required" 73 ); 74 browser.test.notifyPass("normandyAddonStudy_permission"); 75 }, 76 permissions: [], 77 doneSignal: "normandyAddonStudy_permission", 78 }); 79 } 80 ); 81 82 add_task(async function test_normandyAddonStudy_without_privilege() { 83 await run({ 84 backgroundScript: () => { 85 browser.test.assertTrue( 86 !browser.normandyAddonStudy, 87 "Extension must be privileged" 88 ); 89 browser.test.notifyPass("normandyAddonStudy_permission"); 90 }, 91 isPrivileged: false, 92 doneSignal: "normandyAddonStudy_permission", 93 }); 94 }); 95 96 add_task(async function test_normandyAddonStudy_temporary_without_privilege() { 97 let extension = ExtensionTestUtils.loadExtension({ 98 temporarilyInstalled: true, 99 isPrivileged: false, 100 manifest: { 101 permissions: ["normandyAddonStudy"], 102 }, 103 }); 104 ExtensionTestUtils.failOnSchemaWarnings(false); 105 let { messages } = await promiseConsoleOutput(async () => { 106 await Assert.rejects( 107 extension.startup(), 108 /Using the privileged permission/, 109 "Startup failed with privileged permission" 110 ); 111 }); 112 ExtensionTestUtils.failOnSchemaWarnings(true); 113 AddonTestUtils.checkMessages( 114 messages, 115 { 116 expected: [ 117 { 118 message: 119 /Using the privileged permission 'normandyAddonStudy' requires a privileged add-on/, 120 }, 121 ], 122 }, 123 true 124 ); 125 }); 126 127 add_task(async function test_getStudy_works() { 128 const study = addonStudyFactory({ 129 addonId: "test@shield.mozilla.com", 130 }); 131 132 const testWrapper = AddonStudies.withStudies([study]); 133 const test = testWrapper(async () => { 134 await run({ 135 backgroundScript: async () => { 136 const result = await browser.normandyAddonStudy.getStudy(); 137 browser.test.sendMessage("study", result); 138 }, 139 validationScript: async extension => { 140 let studyResult = await extension.awaitMessage("study"); 141 deepEqual( 142 studyResult, 143 study, 144 "normandyAddonStudy.getStudy returns the correct study" 145 ); 146 }, 147 }); 148 }); 149 150 await test(); 151 }); 152 153 add_task(async function test_endStudy_works() { 154 const study = addonStudyFactory({ 155 addonId: "test@shield.mozilla.com", 156 }); 157 158 const testWrapper = AddonStudies.withStudies([study]); 159 const test = testWrapper(async () => { 160 await run({ 161 backgroundScript: async () => { 162 await browser.normandyAddonStudy.endStudy("test"); 163 }, 164 validationScript: async () => { 165 // Check that `AddonStudies.markAsEnded` was called 166 await TestUtils.topicObserved( 167 "shield-study-ended", 168 (subject, message) => { 169 return message === `${study.recipeId}`; 170 } 171 ); 172 173 const addon = await AddonManager.getAddonByID(study.addonId); 174 equal(addon, undefined, "Addon should be uninstalled."); 175 }, 176 }); 177 }); 178 179 await test(); 180 }); 181 182 add_task(async function test_getClientMetadata_works() { 183 const study = addonStudyFactory({ 184 addonId: "test@shield.mozilla.com", 185 slug: "test-slug", 186 branch: "test-branch", 187 }); 188 189 const testWrapper = AddonStudies.withStudies([study]); 190 const test = testWrapper(async () => { 191 await run({ 192 backgroundScript: async () => { 193 const metadata = await browser.normandyAddonStudy.getClientMetadata(); 194 browser.test.sendMessage("clientMetadata", metadata); 195 }, 196 validationScript: async extension => { 197 let clientMetadata = await extension.awaitMessage("clientMetadata"); 198 199 Assert.strictEqual( 200 clientMetadata.updateChannel, 201 Services.appinfo.defaultUpdateChannel, 202 "clientMetadata contains correct updateChannel" 203 ); 204 205 Assert.strictEqual( 206 clientMetadata.fxVersion, 207 Services.appinfo.version, 208 "clientMetadata contains correct fxVersion" 209 ); 210 211 ok("clientID" in clientMetadata, "clientMetadata contains a clientID"); 212 }, 213 }); 214 }); 215 216 await test(); 217 }); 218 219 add_task(async function test_onUnenroll_works() { 220 const study = addonStudyFactory({ 221 addonId: "test@shield.mozilla.com", 222 }); 223 224 const testWrapper = AddonStudies.withStudies([study]); 225 const test = testWrapper(async () => { 226 await run({ 227 backgroundScript: () => { 228 browser.normandyAddonStudy.onUnenroll.addListener(reason => { 229 browser.test.sendMessage("unenrollReason", reason); 230 }); 231 browser.test.sendMessage("bgpageReady"); 232 }, 233 validationScript: async extension => { 234 await extension.awaitMessage("bgpageReady"); 235 await AddonStudies.markAsEnded(study, "test"); 236 const unenrollReason = await extension.awaitMessage("unenrollReason"); 237 equal(unenrollReason, "test", "Unenroll listener should be called."); 238 }, 239 }); 240 }); 241 242 await test(); 243 });