test_setting_group.html (15439B)
1 <!doctype html> 2 <html> 3 <head> 4 <meta charset="utf-8" /> 5 <title>setting-group Tests</title> 6 <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> 7 <link 8 rel="stylesheet" 9 href="chrome://mochikit/content/tests/SimpleTest/test.css" 10 /> 11 <link rel="stylesheet" href="chrome://global/skin/global.css" /> 12 <link 13 rel="stylesheet" 14 href="chrome://browser/content/preferences/widgets/setting-group.css" 15 /> 16 <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> 17 <script src="../../../../../toolkit/content/tests/widgets/lit-test-helpers.js"></script> 18 <script src="./head.js"></script> 19 <script 20 type="module" 21 src="chrome://browser/content/preferences/widgets/setting-group.mjs" 22 ></script> 23 <script 24 type="module" 25 src="chrome://browser/content/preferences/widgets/setting-control.mjs" 26 ></script> 27 <script 28 type="module" 29 src="chrome://global/content/elements/moz-support-link.mjs" 30 ></script> 31 <script 32 type="application/javascript" 33 src="chrome://global/content/preferencesBindings.js" 34 ></script> 35 <script> 36 /* import-globals-from /toolkit/content/preferencesBindings.js */ 37 let html, nothing, testHelpers; 38 39 const LABEL_L10N_ID = "browsing-use-autoscroll"; 40 const GROUP_L10N_ID = "pane-experimental-reset"; 41 const PREF_ONE = "test.settings-group.itemone"; 42 const PREF_TWO = "test.settings-group.itemtwo"; 43 44 function settingGroupTemplate(config) { 45 return html` 46 <setting-group 47 .config=${config} 48 .getSetting=${(...args) => Preferences.getSetting(...args)} 49 ></setting-group> 50 `; 51 } 52 53 function renderTemplate(config) { 54 return testHelpers.renderTemplate(settingGroupTemplate(config)); 55 } 56 57 add_setup(async function setup() { 58 const mockL10nSource = L10nFileSource.createMock( 59 "test", 60 "app", 61 ["en-US"], 62 "/localization/{locale}/", 63 [ 64 { 65 path: "/localization/en-US/mock.ftl", 66 source: "l10n-test-id =\n .label = Test label", 67 }, 68 ] 69 ); 70 L10nRegistry.getInstance().registerSources([mockL10nSource]); 71 MozXULElement.insertFTLIfNeeded("mock.ftl"); 72 SimpleTest.registerCleanupFunction(() => { 73 L10nRegistry.getInstance().removeSources([mockL10nSource.name]); 74 }); 75 testHelpers = new InputTestHelpers(); 76 ({ html, nothing } = await testHelpers.setupLit()); 77 testHelpers.setupTests({ 78 templateFn: () => html`<setting-group></setting-group>`, 79 }); 80 MozXULElement.insertFTLIfNeeded("branding/brand.ftl"); 81 MozXULElement.insertFTLIfNeeded("browser/preferences/preferences.ftl"); 82 Preferences.addAll([ 83 { id: PREF_ONE, type: "bool" }, 84 { id: PREF_TWO, type: "bool" }, 85 ]); 86 }); 87 88 add_task(async function testSettingGroupSimple() { 89 const SETTING_ONE = "setting-item-one"; 90 const SETTING_TWO = "setting-item-two"; 91 await SpecialPowers.pushPrefEnv({ 92 set: [ 93 [PREF_ONE, true], 94 [PREF_TWO, false], 95 ], 96 }); 97 Preferences.addSetting({ 98 id: SETTING_ONE, 99 pref: PREF_ONE, 100 }); 101 Preferences.addSetting({ 102 id: SETTING_TWO, 103 pref: PREF_TWO, 104 }); 105 let config = { 106 l10nId: GROUP_L10N_ID, 107 items: [ 108 { l10nId: LABEL_L10N_ID, id: SETTING_ONE }, 109 { l10nId: LABEL_L10N_ID, id: SETTING_TWO }, 110 ], 111 }; 112 113 let result = await renderTemplate(config); 114 let group = result.querySelector("setting-group"); 115 ok(group, "setting-group is created"); 116 ok(group.config, "it got a config"); 117 let fieldset = group.children[0]; 118 is(fieldset.localName, "moz-fieldset", "First child is a fieldset"); 119 is( 120 fieldset.dataset.l10nId, 121 GROUP_L10N_ID, 122 "Fieldset has the group label" 123 ); 124 let [item1, item2] = fieldset.children; 125 is(item1.localName, "setting-control", "First setting-control"); 126 is(item1.config.id, SETTING_ONE, "First setting-control id is correct"); 127 is(item2.localName, "setting-control", "Second setting-control"); 128 is( 129 item2.config.id, 130 SETTING_TWO, 131 "Second setting-control id is correct" 132 ); 133 await SpecialPowers.popPrefEnv(); 134 }); 135 136 add_task(async function testSettingGroupVisibility() { 137 /** 138 * Wait for a requestAnimationFrame so lit renders have completed. 139 */ 140 function waitForRenderUpdate() { 141 return new Promise(r => requestAnimationFrame(r)); 142 } 143 144 /** 145 * Render the common template into a groupbox that may be hidden from search. 146 */ 147 async function renderTemplateInGroupbox( 148 config, 149 hiddenFromSearch = false 150 ) { 151 return testHelpers.renderTemplate(html` 152 <groupbox 153 data-hidden-from-search=${hiddenFromSearch ? "true" : nothing} 154 ?hidden=${hiddenFromSearch} 155 > 156 ${settingGroupTemplate(config)} 157 </groupbox> 158 `); 159 } 160 161 async function assertVisibilityChanges( 162 group, 163 staysHidden = false, 164 hiddenElsewhere = false 165 ) { 166 await waitForRenderUpdate(); 167 ok(group, "setting-group is created"); 168 let [control1, control2] = group.querySelectorAll("setting-control"); 169 ok( 170 BrowserTestUtils.isHidden(control1), 171 "First setting-control should be hidden" 172 ); 173 ok( 174 BrowserTestUtils.isHidden(control2), 175 "Second setting-control should be hidden" 176 ); 177 ok( 178 BrowserTestUtils.isHidden(group), 179 "setting-group should be hidden since its controls are hidden" 180 ); 181 let initialHiddenValue = group.hidden; 182 183 if (hiddenElsewhere) { 184 ok( 185 !group.hasAttribute("data-hidden-from-search"), 186 "setting-group is not hidden from search when hidden elsewhere" 187 ); 188 } else { 189 is( 190 group.getAttribute("data-hidden-from-search"), 191 "true", 192 "setting-group is hidden from search when hidden" 193 ); 194 } 195 is( 196 group.hidden, 197 initialHiddenValue, 198 "setting-group should not change hidden attribute" 199 ); 200 201 Services.prefs.setBoolPref(PREF_ONE, true); 202 await waitForRenderUpdate(); 203 is( 204 group.hidden, 205 initialHiddenValue, 206 "setting-group should not change hidden attribute" 207 ); 208 if (staysHidden) { 209 ok(BrowserTestUtils.isHidden(group), "Group should stay hidden"); 210 if (hiddenElsewhere) { 211 ok( 212 !group.hasAttribute("data-hidden-from-search"), 213 "setting-group is not hidden from search when hidden elsewhere" 214 ); 215 } else { 216 is( 217 group.getAttribute("data-hidden-from-search"), 218 "true", 219 "setting-group is hidden from search when hidden" 220 ); 221 } 222 } else { 223 ok( 224 !control1.hidden, 225 "Control 1 should be visible after changing pref value" 226 ); 227 ok( 228 BrowserTestUtils.isVisible(group), 229 "Group should be visible since one of the controls is visible" 230 ); 231 ok( 232 !group.hasAttribute("data-hidden-from-search"), 233 "setting-group is not hidden from search when visible" 234 ); 235 is( 236 control2.hidden, 237 true, 238 "The second setting-control should still be hidden" 239 ); 240 } 241 Services.prefs.setBoolPref(PREF_TWO, true); 242 await waitForRenderUpdate(); 243 is( 244 group.hidden, 245 initialHiddenValue, 246 "setting-group should not change hidden attribute" 247 ); 248 if (staysHidden) { 249 ok( 250 BrowserTestUtils.isHidden(group), 251 "Group should still stay hidden" 252 ); 253 if (hiddenElsewhere) { 254 ok( 255 !group.hasAttribute("data-hidden-from-search"), 256 "setting-group is not hidden from search when hidden elsewhere" 257 ); 258 } else { 259 is( 260 group.getAttribute("data-hidden-from-search"), 261 "true", 262 "setting-group is hidden from search when hidden" 263 ); 264 } 265 } else { 266 ok( 267 !control2.hidden, 268 "Control 2 should be visible after changing pref value" 269 ); 270 ok(!control1.hidden, "Control 1 should still be visible"); 271 ok( 272 BrowserTestUtils.isVisible(group), 273 "Group should still be visible" 274 ); 275 ok( 276 !group.hasAttribute("data-hidden-from-search"), 277 "setting-group is not hidden from search when visible" 278 ); 279 } 280 281 Services.prefs.setBoolPref(PREF_ONE, false); 282 Services.prefs.setBoolPref(PREF_TWO, false); 283 284 await waitForRenderUpdate(); 285 is( 286 group.hidden, 287 initialHiddenValue, 288 "setting-group should not change hidden attribute" 289 ); 290 ok( 291 control1.hidden, 292 "Control 1 should be hidden after changing pref value" 293 ); 294 ok( 295 control2.hidden, 296 "Control 2 should be hidden after changing pref value" 297 ); 298 ok( 299 BrowserTestUtils.isHidden(group), 300 "Group should be hidden now that the controls are hidden" 301 ); 302 is( 303 group.getAttribute("data-hidden-from-search"), 304 "true", 305 "setting-group is hidden from search when hidden" 306 ); 307 } 308 309 const SETTING_ONE = "setting-item-one"; 310 const SETTING_TWO = "setting-item-two"; 311 await SpecialPowers.pushPrefEnv({ 312 set: [ 313 [PREF_ONE, false], 314 [PREF_TWO, false], 315 ], 316 }); 317 Preferences.addSetting({ 318 id: SETTING_ONE, 319 pref: PREF_ONE, 320 visible: (_, setting) => setting.value, 321 }); 322 Preferences.addSetting({ 323 id: SETTING_TWO, 324 pref: PREF_TWO, 325 visible: (_, setting) => setting.value, 326 }); 327 let config = { 328 l10nId: GROUP_L10N_ID, 329 items: [ 330 { l10nId: LABEL_L10N_ID, id: SETTING_ONE }, 331 { l10nId: LABEL_L10N_ID, id: SETTING_TWO }, 332 ], 333 }; 334 335 // Check without a groupbox 336 let result = await renderTemplate(config); 337 let group = result.querySelector("setting-group"); 338 info("-- assertVisibilityChanges setting-group --"); 339 await assertVisibilityChanges(group); 340 341 // Without a groupbox, initially hidden, settings visible 342 result = await renderTemplate(config); 343 group = result.querySelector("setting-group"); 344 // Make a setting visible so the group would be visible 345 Services.prefs.setBoolPref(PREF_TWO, true); 346 await waitForRenderUpdate(); 347 // Hide the group, as if it's on a hidden setting pane 348 group.hidden = true; 349 info("-- assertVisibilityChanges setting-group hidden --"); 350 await assertVisibilityChanges(group, true, true); 351 352 // Check with an initially visible groupbox 353 result = await renderTemplateInGroupbox(config); 354 group = result.querySelector("groupbox"); 355 info("-- assertVisibilityChanges groupbox --"); 356 await assertVisibilityChanges(group); 357 358 // Check with a groupbox that should stay hidden 359 result = await renderTemplateInGroupbox(config, true); 360 group = result.querySelector("groupbox"); 361 info("-- assertVisibilityChanges groupbox[data-hidden-from-search] --"); 362 await assertVisibilityChanges(group, true); 363 }); 364 365 add_task(async function testCommonControlProperties() { 366 const SETTING = "setting-control-support-link"; 367 Preferences.addSetting({ 368 id: SETTING, 369 get: () => true, 370 }); 371 372 await testCommonSettingControlProperties(async commonConfig => { 373 const control = await renderTemplate({ 374 ...commonConfig, 375 id: SETTING, 376 items: [], 377 }); 378 return control.querySelector("moz-fieldset"); 379 }); 380 }); 381 382 add_task(async function testSettingGroupCallbacks() { 383 const SETTING_ONE = "setting-first"; 384 const SETTING_TWO = "setting-second"; 385 386 let clickCallbacks = []; 387 let changeCallbacks = []; 388 389 await SpecialPowers.pushPrefEnv({ 390 set: [[PREF_ONE, true]], 391 }); 392 Preferences.addSetting({ 393 id: SETTING_ONE, 394 pref: PREF_ONE, 395 onUserClick(_, __, setting) { 396 clickCallbacks.push(setting.id); 397 }, 398 onUserChange(_, __, setting) { 399 changeCallbacks.push(setting.id); 400 }, 401 }); 402 Preferences.addSetting({ 403 id: SETTING_TWO, 404 onUserClick(_, __, setting) { 405 clickCallbacks.push(setting.id); 406 }, 407 }); 408 let config = { 409 l10nId: GROUP_L10N_ID, 410 items: [ 411 { 412 l10nId: LABEL_L10N_ID, 413 id: SETTING_ONE, 414 }, 415 { 416 l10nId: LABEL_L10N_ID, 417 id: SETTING_TWO, 418 control: "moz-box-button", 419 }, 420 ], 421 }; 422 423 let result = await renderTemplate(config); 424 let group = result.querySelector("setting-group"); 425 let fieldset = group.children[0]; 426 let [item1, item2] = fieldset.children; 427 428 is( 429 item1.controlEl.localName, 430 "moz-checkbox", 431 "First setting control renders a moz-checkbox." 432 ); 433 is( 434 item2.controlEl.localName, 435 "moz-box-button", 436 "First setting control renders a moz-box-button." 437 ); 438 439 let settingOne = Preferences.getSetting(SETTING_ONE); 440 let settingChanged = waitForSettingChange(settingOne); 441 synthesizeMouseAtCenter(item1.controlEl, {}); 442 await settingChanged; 443 444 is( 445 clickCallbacks.length, 446 0, 447 "onUserClick is not called when clicking on moz-checkbox." 448 ); 449 is( 450 changeCallbacks.length, 451 1, 452 "onUserChange called when clicking on moz-checkbox." 453 ); 454 455 synthesizeMouseAtCenter(item2.controlEl, {}); 456 is( 457 clickCallbacks.length, 458 1, 459 "onUserClick is called when clicking on moz-box-button." 460 ); 461 }); 462 </script> 463 </head> 464 <body> 465 <p id="display"></p> 466 <div id="content" style="display: none"></div> 467 <pre id="test"></pre> 468 </body> 469 </html>