browser_range.js (10075B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 /* import-globals-from ../../mochitest/role.js */ 8 /* import-globals-from ../../mochitest/states.js */ 9 loadScripts( 10 { name: "role.js", dir: MOCHITESTS_DIR }, 11 { name: "states.js", dir: MOCHITESTS_DIR } 12 ); 13 14 add_setup(async function () { 15 await SpecialPowers.pushPrefEnv({ 16 set: [["test.wait300msAfterTabSwitch", true]], 17 }); 18 }); 19 20 /** 21 * Verify that the value of a slider input can be incremented/decremented 22 * Test input[type=range] 23 */ 24 addAccessibleTask( 25 `<input id="range" type="range" min="1" max="100" value="1" step="10">`, 26 async (browser, accDoc) => { 27 let range = getNativeInterface(accDoc, "range"); 28 is(range.getAttributeValue("AXRole"), "AXSlider", "Correct AXSlider role"); 29 is(range.getAttributeValue("AXValue"), 1, "Correct initial value"); 30 31 let actions = range.actionNames; 32 ok(actions.includes("AXDecrement"), "Has decrement action"); 33 ok(actions.includes("AXIncrement"), "Has increment action"); 34 35 let evt = waitForMacEvent("AXValueChanged"); 36 range.performAction("AXIncrement"); 37 await evt; 38 is(range.getAttributeValue("AXValue"), 11, "Correct increment value"); 39 40 evt = waitForMacEvent("AXValueChanged"); 41 range.performAction("AXDecrement"); 42 await evt; 43 is(range.getAttributeValue("AXValue"), 1, "Correct decrement value"); 44 45 evt = waitForMacEvent("AXValueChanged"); 46 // Adjust value via script in content 47 await SpecialPowers.spawn(browser, [], () => { 48 content.document.getElementById("range").value = 41; 49 }); 50 await evt; 51 is( 52 range.getAttributeValue("AXValue"), 53 41, 54 "Correct value from content change" 55 ); 56 } 57 ); 58 59 /** 60 * Verify that the value of a slider input can be set directly 61 * Test input[type=range] 62 */ 63 addAccessibleTask( 64 `<input id="range" type="range" min="1" max="100" value="1" step="10">`, 65 async (browser, accDoc) => { 66 let nextValue = 21; 67 let range = getNativeInterface(accDoc, "range"); 68 is(range.getAttributeValue("AXRole"), "AXSlider", "Correct AXSlider role"); 69 is(range.getAttributeValue("AXValue"), 1, "Correct initial value"); 70 71 ok(range.isAttributeSettable("AXValue"), "Range AXValue is settable."); 72 73 let evt = waitForMacEvent("AXValueChanged"); 74 range.setAttributeValue("AXValue", nextValue); 75 await evt; 76 is(range.getAttributeValue("AXValue"), nextValue, "Correct updated value"); 77 } 78 ); 79 80 /** 81 * Verify that the value of a number input can be incremented/decremented 82 * Test input[type=number] 83 */ 84 addAccessibleTask( 85 `<input type="number" value="11" id="number" step=".05">`, 86 async (browser, accDoc) => { 87 let number = getNativeInterface(accDoc, "number"); 88 is( 89 number.getAttributeValue("AXRole"), 90 "AXIncrementor", 91 "Correct AXIncrementor role" 92 ); 93 is(number.getAttributeValue("AXValue"), 11, "Correct initial value"); 94 95 let actions = number.actionNames; 96 ok(actions.includes("AXDecrement"), "Has decrement action"); 97 ok(actions.includes("AXIncrement"), "Has increment action"); 98 99 let evt = waitForMacEvent("AXValueChanged"); 100 number.performAction("AXIncrement"); 101 await evt; 102 is(number.getAttributeValue("AXValue"), 11.05, "Correct increment value"); 103 104 evt = waitForMacEvent("AXValueChanged"); 105 number.performAction("AXDecrement"); 106 await evt; 107 is(number.getAttributeValue("AXValue"), 11, "Correct decrement value"); 108 109 evt = waitForMacEvent("AXValueChanged"); 110 // Adjust value via script in content 111 await SpecialPowers.spawn(browser, [], () => { 112 content.document.getElementById("number").value = 42; 113 }); 114 await evt; 115 is( 116 number.getAttributeValue("AXValue"), 117 42, 118 "Correct value from content change" 119 ); 120 } 121 ); 122 123 /** 124 * Test Min, Max, Orientation, ValueDescription 125 */ 126 addAccessibleTask( 127 `<input type="number" value="11" id="number">`, 128 async (browser, accDoc) => { 129 let nextValue = 21; 130 let number = getNativeInterface(accDoc, "number"); 131 is( 132 number.getAttributeValue("AXRole"), 133 "AXIncrementor", 134 "Correct AXIncrementor role" 135 ); 136 is(number.getAttributeValue("AXValue"), 11, "Correct initial value"); 137 138 ok(number.isAttributeSettable("AXValue"), "Range AXValue is settable."); 139 140 let evt = waitForMacEvent("AXValueChanged"); 141 number.setAttributeValue("AXValue", nextValue); 142 await evt; 143 is(number.getAttributeValue("AXValue"), nextValue, "Correct updated value"); 144 } 145 ); 146 147 /** 148 * Verify that the value of a number input can be set directly 149 * Test input[type=number] 150 */ 151 addAccessibleTask( 152 `<div aria-valuetext="High" id="slider" aria-orientation="horizontal" role="slider" aria-valuenow="2" aria-valuemin="0" aria-valuemax="3"></div>`, 153 async (browser, accDoc) => { 154 let slider = getNativeInterface(accDoc, "slider"); 155 is( 156 slider.getAttributeValue("AXValueDescription"), 157 "High", 158 "Correct value description" 159 ); 160 is( 161 slider.getAttributeValue("AXOrientation"), 162 "AXHorizontalOrientation", 163 "Correct orientation" 164 ); 165 is(slider.getAttributeValue("AXMinValue"), 0, "Correct min value"); 166 is(slider.getAttributeValue("AXMaxValue"), 3, "Correct max value"); 167 168 let evt = waitForMacEvent("AXValueChanged"); 169 await invokeContentTask(browser, [], () => { 170 const s = content.document.getElementById("slider"); 171 s.setAttribute("aria-valuetext", "Low"); 172 }); 173 await evt; 174 is( 175 slider.getAttributeValue("AXValueDescription"), 176 "Low", 177 "Correct value description" 178 ); 179 180 evt = waitForEvent(EVENT_OBJECT_ATTRIBUTE_CHANGED, "slider"); 181 await invokeContentTask(browser, [], () => { 182 const s = content.document.getElementById("slider"); 183 s.setAttribute("aria-orientation", "vertical"); 184 s.setAttribute("aria-valuemin", "-1"); 185 s.setAttribute("aria-valuemax", "5"); 186 }); 187 await evt; 188 is( 189 slider.getAttributeValue("AXOrientation"), 190 "AXVerticalOrientation", 191 "Correct orientation" 192 ); 193 is(slider.getAttributeValue("AXMinValue"), -1, "Correct min value"); 194 is(slider.getAttributeValue("AXMaxValue"), 5, "Correct max value"); 195 } 196 ); 197 198 /** 199 * Verify progress HTML elements expose their min, max, and value to VO. 200 * Progress elements should not expose a value description, and should not 201 * expose increment/decrement actions. 202 */ 203 addAccessibleTask( 204 `<progress id="progress" value="70" max="100"></progress>`, 205 async (browser, accDoc) => { 206 const progress = getNativeInterface(accDoc, "progress"); 207 is(progress.getAttributeValue("AXValue"), 70, "Correct value"); 208 is(progress.getAttributeValue("AXMaxValue"), 100, "Correct max value"); 209 is(progress.getAttributeValue("AXMinValue"), 0, "Correct min value"); 210 is( 211 progress.getAttributeValue("AXValueDescription"), 212 null, 213 "Progress elements should not expose a value description" 214 ); 215 for (let action of progress.actionNames) { 216 isnot( 217 action, 218 "AXIncrement", 219 "Progress elements should not expose increment action" 220 ); 221 isnot( 222 action, 223 "AXDecrement", 224 "Progress elements should not expose decrement action" 225 ); 226 } 227 } 228 ); 229 230 /** 231 * Verify progress HTML elements expose changes to their value. 232 */ 233 addAccessibleTask( 234 `<progress id="progress" value="70" max="100"></progress>`, 235 async (browser, accDoc) => { 236 const progress = getNativeInterface(accDoc, "progress"); 237 is(progress.getAttributeValue("AXValue"), 70, "Correct value"); 238 is(progress.getAttributeValue("AXMaxValue"), 100, "Correct max value"); 239 is(progress.getAttributeValue("AXMinValue"), 0, "Correct min value"); 240 241 const evt = waitForMacEvent("AXValueChanged"); 242 await invokeContentTask(browser, [], () => { 243 const p = content.document.getElementById("progress"); 244 p.setAttribute("value", "90"); 245 }); 246 await evt; 247 248 is(progress.getAttributeValue("AXValue"), 90, "Correct updated value"); 249 } 250 ); 251 252 /** 253 * Verify meter HTML elements expose the value region as part of their value 254 * description. 255 */ 256 addAccessibleTask( 257 `<label for="fuel">Fuel level:</label><meter id="fuel" min="0" max="100" low="33" high="66" optimum="80" value="50"></meter>`, 258 async (browser, accDoc) => { 259 const meter = getNativeInterface(accDoc, "fuel"); 260 is(meter.getAttributeValue("AXValue"), 50, "Correct value"); 261 is( 262 meter.getAttributeValue("AXValueDescription"), 263 "50, Suboptimal value", 264 "Value description contains appropriate value region" 265 ); 266 267 let evt = waitForMacEvent("AXValueChanged"); 268 await invokeContentTask(browser, [], () => { 269 const f = content.document.getElementById("fuel"); 270 f.setAttribute("value", "90"); 271 }); 272 await evt; 273 274 is( 275 meter.getAttributeValue("AXValueDescription"), 276 "90, Optimal value", 277 "Value description updated to optimal" 278 ); 279 280 await invokeContentTask(browser, [], () => { 281 const f = content.document.getElementById("fuel"); 282 f.setAttribute("optimum", "20"); 283 }); 284 await untilCacheIs( 285 () => meter.getAttributeValue("AXValueDescription"), 286 "90, Critical value", 287 "Value description updated to critical." 288 ); 289 290 await invokeContentTask(browser, [], () => { 291 const f = content.document.getElementById("fuel"); 292 f.textContent = "at 90/100"; 293 }); 294 await untilCacheIs( 295 () => meter.getAttributeValue("AXValueDescription"), 296 "at 90/100, Critical value", 297 "Value description updated to include textContent." 298 ); 299 300 await invokeContentTask(browser, [], () => { 301 const f = content.document.getElementById("fuel"); 302 f.innerText = "currently showing 90/100"; 303 }); 304 await untilCacheIs( 305 () => meter.getAttributeValue("AXValueDescription"), 306 "currently showing 90/100, Critical value", 307 "Value description updated to include innerText." 308 ); 309 } 310 );