test_setting_control_options.html (15013B)
1 <!doctype html> 2 <html> 3 <head> 4 <meta charset="utf-8" /> 5 <title>setting-control select 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 <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> 13 <script src="../../../../../toolkit/content/tests/widgets/lit-test-helpers.js"></script> 14 <script src="./head.js"></script> 15 <script 16 type="module" 17 src="chrome://browser/content/preferences/widgets/setting-group.mjs" 18 ></script> 19 <script 20 type="module" 21 src="chrome://browser/content/preferences/widgets/setting-control.mjs" 22 ></script> 23 <script 24 type="module" 25 src="chrome://global/content/elements/moz-support-link.mjs" 26 ></script> 27 <script 28 type="application/javascript" 29 src="chrome://global/content/preferencesBindings.js" 30 ></script> 31 <script> 32 const { Assert } = ChromeUtils.importESModule( 33 "resource://testing-common/Assert.sys.mjs" 34 ); 35 /* import-globals-from /toolkit/content/preferencesBindings.js */ 36 let html, testHelpers; 37 38 const LABEL_L10N_ID = "browsing-use-autoscroll"; 39 const GROUP_L10N_ID = "pane-experimental-reset"; 40 41 async function renderTemplate(itemConfig) { 42 let config = { 43 items: [itemConfig], 44 }; 45 let result = await testHelpers.renderTemplate(html` 46 <setting-group 47 .config=${config} 48 .getSetting=${(...args) => Preferences.getSetting(...args)} 49 ></setting-group> 50 `); 51 await result.firstElementChild.updateComplete; 52 if (document.hasPendingL10nMutations) { 53 await BrowserTestUtils.waitForEvent( 54 document, 55 "L10nMutationsFinished" 56 ); 57 } 58 return result.querySelector("setting-control"); 59 } 60 61 add_setup(async function setup() { 62 testHelpers = new InputTestHelpers(); 63 ({ html } = await testHelpers.setupLit()); 64 testHelpers.setupTests({ 65 templateFn: () => html`<setting-group></setting-group>`, 66 }); 67 MozXULElement.insertFTLIfNeeded("branding/brand.ftl"); 68 MozXULElement.insertFTLIfNeeded("browser/preferences/preferences.ftl"); 69 }); 70 71 add_task(async function testConfigBasedSelect() { 72 const PREF = "test.setting-control-select.one"; 73 const SETTING = "setting-control-select-one"; 74 await SpecialPowers.pushPrefEnv({ 75 set: [[PREF, 1]], 76 }); 77 Preferences.addAll([{ id: PREF, type: "int" }]); 78 Preferences.addSetting({ 79 id: SETTING, 80 pref: PREF, 81 }); 82 let itemConfig = { 83 control: "moz-select", 84 l10nId: LABEL_L10N_ID, 85 id: SETTING, 86 options: [ 87 { 88 l10nId: LABEL_L10N_ID, 89 value: 0, 90 }, 91 { 92 l10nId: LABEL_L10N_ID, 93 value: 1, 94 }, 95 { 96 l10nId: LABEL_L10N_ID, 97 value: 2, 98 }, 99 ], 100 }; 101 let setting = Preferences.getSetting(SETTING); 102 let control = await renderTemplate(itemConfig); 103 104 is( 105 control.controlEl.localName, 106 "moz-select", 107 "The control rendered a select" 108 ); 109 is(control.controlEl.dataset.l10nId, LABEL_L10N_ID, "Label is set"); 110 is(control.controlEl.value, "1", "select value is correct"); 111 is(control.controlEl.disabled, false, "select is enabled"); 112 is(setting.value, 1, "setting is 1"); 113 is(Services.prefs.getIntPref(PREF), 1, "pref is 1"); 114 115 let inputEl = control.controlEl.inputEl; 116 is(inputEl.localName, "select", "it's a select under the hood"); 117 let options = [...inputEl.children]; 118 is(options.length, 3, "There are 3 options"); 119 ok( 120 options.every(opt => opt.localName == "option"), 121 "All children are options" 122 ); 123 options.forEach((option, i) => { 124 is(option.value, i.toString(), `Option ${i} value is correct`); 125 is(option.selected, i == 1, `Option ${i} selected is correct`); 126 }); 127 128 let settingChanged = waitForSettingChange(setting); 129 let topWindow = window.docShell.chromeEventHandler.ownerGlobal; 130 let pickerOpened = BrowserTestUtils.waitForSelectPopupShown(topWindow); 131 control.controlEl.focus(); 132 synthesizeKey(" "); 133 await pickerOpened; 134 synthesizeKey("KEY_ArrowDown"); 135 synthesizeKey("KEY_Enter"); 136 await settingChanged; 137 138 is(Services.prefs.getIntPref(PREF), 2, "pref is 2"); 139 is(setting.value, 2, "setting is 2"); 140 }); 141 142 add_task(async function testConfigBasedRadio() { 143 const PREF = "test.setting-control-radio.one"; 144 const SETTING = "setting-control-radio-one"; 145 await SpecialPowers.pushPrefEnv({ 146 set: [[PREF, 1]], 147 }); 148 Preferences.addAll([{ id: PREF, type: "int" }]); 149 Preferences.addSetting({ 150 id: SETTING, 151 pref: PREF, 152 }); 153 let itemConfig = { 154 control: "moz-radio-group", 155 l10nId: LABEL_L10N_ID, 156 id: SETTING, 157 options: [ 158 { 159 l10nId: LABEL_L10N_ID, 160 value: 0, 161 }, 162 { 163 l10nId: LABEL_L10N_ID, 164 value: 1, 165 }, 166 { 167 l10nId: LABEL_L10N_ID, 168 value: 2, 169 }, 170 ], 171 }; 172 let setting = Preferences.getSetting(SETTING); 173 let control = await renderTemplate(itemConfig); 174 175 is( 176 control.controlEl.localName, 177 "moz-radio-group", 178 "The control rendered a moz-radio-group" 179 ); 180 is(control.controlEl.dataset.l10nId, LABEL_L10N_ID, "Label is set"); 181 is(control.controlEl.value, 1, "select value is correct"); 182 is(control.controlEl.disabled, false, "select is enabled"); 183 is(setting.value, 1, "setting is 1"); 184 is(Services.prefs.getIntPref(PREF), 1, "pref is 1"); 185 186 let radios = [...control.controlEl.children]; 187 is(radios.length, 3, "There are 3 radios"); 188 ok( 189 radios.every(opt => opt.localName == "moz-radio"), 190 "All children are radios" 191 ); 192 radios.forEach((option, i) => { 193 is(option.value, i, `Radio ${i} value is correct`); 194 is(option.checked, i == 1, `Radio ${i} checked is correct`); 195 }); 196 197 let settingChanged = waitForSettingChange(setting); 198 let radioZero = control.querySelector("moz-radio"); 199 is(radioZero.value, 0, "0 radio is first"); 200 control.querySelector("moz-radio[checked]").focus(); 201 synthesizeKey("KEY_ArrowUp"); 202 await settingChanged; 203 204 is(Services.prefs.getIntPref(PREF), 0, "pref is 0"); 205 is(setting.value, 0, "setting is 0"); 206 }); 207 208 add_task(async function testConfigBasedCustomOptions() { 209 const PREF = "test.setting-control-custom.one"; 210 const SETTING = "setting-control-custom-one"; 211 await SpecialPowers.pushPrefEnv({ 212 set: [[PREF, 1]], 213 }); 214 Preferences.addAll([{ id: PREF, type: "int" }]); 215 Preferences.addSetting({ 216 id: SETTING, 217 pref: PREF, 218 }); 219 220 const CUSTOM_LABEL = "Custom label"; 221 let itemConfig = { 222 control: "moz-button-group", 223 id: SETTING, 224 options: [ 225 { 226 l10nId: LABEL_L10N_ID, 227 control: "moz-button", 228 controlAttrs: { 229 type: "primary", 230 }, 231 }, 232 { 233 control: "moz-button", 234 controlAttrs: { 235 label: CUSTOM_LABEL, 236 }, 237 }, 238 ], 239 }; 240 let control = await renderTemplate(itemConfig); 241 242 is( 243 control.controlEl.localName, 244 "moz-button-group", 245 "The control rendered a moz-button-group" 246 ); 247 let buttons = [...control.controlEl.children]; 248 is(buttons.length, 2, "There are two buttons"); 249 ok( 250 buttons.every(btn => btn.localName == "moz-button"), 251 "The buttons are moz-buttons" 252 ); 253 let primaryButton = buttons.find(btn => btn.slot == "primary"); 254 let secondaryButton = buttons.find(btn => !btn.slot); 255 ok(primaryButton, "There is a primary button"); 256 ok(secondaryButton, "There is a secondary button"); 257 is(primaryButton.type, "primary", "Type was set from controlAttrs"); 258 is( 259 secondaryButton.label, 260 CUSTOM_LABEL, 261 "Label was set from controlAttrs" 262 ); 263 }); 264 265 add_task(async function testNestedControlOptions() { 266 const PREF = "test.setting-control-custom-nested.one"; 267 const SETTING = "setting-control-custom-nested-one"; 268 await SpecialPowers.pushPrefEnv({ 269 set: [[PREF, 1]], 270 }); 271 Preferences.addAll([{ id: PREF, type: "int" }]); 272 Preferences.addSetting({ 273 id: SETTING, 274 pref: PREF, 275 }); 276 277 let itemConfig = { 278 control: "moz-button-group", 279 id: SETTING, 280 options: [ 281 { 282 control: "div", 283 options: [ 284 { 285 control: "moz-checkbox", 286 }, 287 ], 288 }, 289 ], 290 }; 291 let control = await renderTemplate(itemConfig); 292 293 is( 294 control.controlEl.localName, 295 "moz-button-group", 296 "The control rendered a moz-button-group as parent control" 297 ); 298 const nestedControl = control.controlEl.children[0]; 299 300 is( 301 nestedControl.localName, 302 "div", 303 "Rendered the nested div element control under the parent control" 304 ); 305 306 const nestedControlOption = nestedControl.children[0]; 307 308 is( 309 nestedControlOption.localName, 310 "moz-checkbox", 311 "Rendered the moz-checkbox option under the div element control" 312 ); 313 }); 314 315 add_task(async function testNestedControlOptionItems() { 316 const PREF = "test.setting-control-custom-nested-items.one"; 317 const SETTING = "setting-control-custom-nested-items-one"; 318 319 const FIRST_NESTED_ITEM_PREF = "test.settings-group.itemone"; 320 const FIRST_NESTED_ITEM_SETTING = "setting-item-one"; 321 322 const SECOND_NESTED_ITEM_PREF = "test.settings-group.itemtwo"; 323 const SECOND_NESTED_ITEM_SETTING = "setting-item-two"; 324 325 await SpecialPowers.pushPrefEnv({ 326 set: [ 327 [PREF, 1], 328 [FIRST_NESTED_ITEM_PREF, true], 329 [SECOND_NESTED_ITEM_PREF, false], 330 ], 331 }); 332 Preferences.addAll([ 333 { id: PREF, type: "int" }, 334 { id: FIRST_NESTED_ITEM_PREF, type: "bool" }, 335 { id: SECOND_NESTED_ITEM_PREF, type: "bool" }, 336 ]); 337 Preferences.addSetting({ 338 id: SETTING, 339 pref: PREF, 340 }); 341 342 Preferences.addSetting({ 343 id: FIRST_NESTED_ITEM_SETTING, 344 pref: FIRST_NESTED_ITEM_PREF, 345 }); 346 Preferences.addSetting({ 347 id: SECOND_NESTED_ITEM_SETTING, 348 pref: SECOND_NESTED_ITEM_PREF, 349 }); 350 351 let itemConfig = { 352 control: "moz-radio-group", 353 l10nId: LABEL_L10N_ID, 354 id: SETTING, 355 options: [ 356 { 357 control: "moz-radio", 358 l10nId: LABEL_L10N_ID, 359 items: [ 360 { 361 l10nId: LABEL_L10N_ID, 362 id: FIRST_NESTED_ITEM_SETTING, 363 control: "moz-box-button", 364 }, 365 ], 366 }, 367 ], 368 }; 369 let control = await renderTemplate(itemConfig); 370 371 is( 372 control.controlEl.localName, 373 "moz-radio-group", 374 "The control rendered a moz-radio-group as parent control" 375 ); 376 const nestedOptionControl = control.controlEl.children[0]; 377 378 is( 379 nestedOptionControl.localName, 380 "moz-radio", 381 "Rendered moz-radio as the nested control option" 382 ); 383 384 const nestedControlItems = nestedOptionControl.children; 385 is(nestedControlItems.length, 1, "Rendered nested control item"); 386 const [firstNestedControlItem] = nestedControlItems; 387 is( 388 firstNestedControlItem.localName, 389 "setting-control", 390 "Rendered the first nested setting-control item" 391 ); 392 is( 393 firstNestedControlItem.controlEl.id, 394 FIRST_NESTED_ITEM_SETTING, 395 "Rendered the first nested setting ID" 396 ); 397 is( 398 firstNestedControlItem.controlEl.localName, 399 "moz-box-button", 400 "Rendered moz-box-button as the first nested control item" 401 ); 402 }); 403 404 add_task(async function testMozSupportLink() { 405 await SpecialPowers.pushPrefEnv({ 406 set: [["app.support.baseURL", "https://support.example.com/"]], 407 }); 408 Preferences.addSetting({ 409 id: "testMozSupportLink", 410 get: () => true, 411 }); 412 let itemConfig = { 413 id: "testMozSupportLink", 414 options: [ 415 { 416 control: "a", 417 slot: "support-link", 418 controlAttrs: { 419 href: "https://example.com/", 420 ".textContent": "Link text", 421 }, 422 }, 423 { 424 control: "a", 425 slot: "support-link", 426 controlAttrs: { 427 is: "moz-support-link", 428 "support-page": "get-help", 429 }, 430 }, 431 ], 432 }; 433 let control = await renderTemplate(itemConfig); 434 let [anchor, mozSupportLink] = control.controlEl.shadowRoot 435 .querySelector('slot[name="support-link"]') 436 .assignedNodes(); 437 438 function assertLinkProperties(el, { href, text }) { 439 ok(el, "Got a link element"); 440 is(el.href, href, "href is correct"); 441 is(el.innerText, text, "text is correct"); 442 } 443 444 assertLinkProperties(anchor, { 445 href: "https://example.com/", 446 text: "Link text", 447 }); 448 assertLinkProperties(mozSupportLink, { 449 href: "https://support.example.com/get-help", 450 text: "Learn more", 451 }); 452 ok( 453 mozSupportLink instanceof customElements.get("moz-support-link"), 454 "moz-support-link is a MozSupportLink" 455 ); 456 }); 457 </script> 458 </head> 459 <body> 460 <p id="display"></p> 461 <div id="content" style="display: none"></div> 462 <pre id="test"></pre> 463 </body> 464 </html>