browser_live_regions.js (6636B)
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 /** 8 * Test live region creation and removal. 9 */ 10 addAccessibleTask( 11 ` 12 <div id="polite" aria-relevant="removals">Polite region</div> 13 <div id="assertive" aria-live="assertive">Assertive region</div> 14 `, 15 async (browser, accDoc) => { 16 let politeRegion = getNativeInterface(accDoc, "polite"); 17 ok( 18 !politeRegion.attributeNames.includes("AXARIALive"), 19 "region is not live" 20 ); 21 22 let liveRegionAdded = waitForMacEvent("AXLiveRegionCreated", "polite"); 23 await SpecialPowers.spawn(browser, [], () => { 24 content.document 25 .getElementById("polite") 26 .setAttribute("aria-atomic", "true"); 27 content.document 28 .getElementById("polite") 29 .setAttribute("aria-live", "polite"); 30 }); 31 await liveRegionAdded; 32 is( 33 politeRegion.getAttributeValue("AXARIALive"), 34 "polite", 35 "region is now live" 36 ); 37 ok(politeRegion.getAttributeValue("AXARIAAtomic"), "region is atomic"); 38 is( 39 politeRegion.getAttributeValue("AXARIARelevant"), 40 "removals", 41 "region has defined aria-relevant" 42 ); 43 44 let assertiveRegion = getNativeInterface(accDoc, "assertive"); 45 is( 46 assertiveRegion.getAttributeValue("AXARIALive"), 47 "assertive", 48 "region is assertive" 49 ); 50 ok( 51 !assertiveRegion.getAttributeValue("AXARIAAtomic"), 52 "region is not atomic" 53 ); 54 is( 55 assertiveRegion.getAttributeValue("AXARIARelevant"), 56 "additions text", 57 "region has default aria-relevant" 58 ); 59 60 let liveRegionRemoved = waitForEvent( 61 EVENT_LIVE_REGION_REMOVED, 62 "assertive" 63 ); 64 await SpecialPowers.spawn(browser, [], () => { 65 content.document.getElementById("assertive").removeAttribute("aria-live"); 66 }); 67 await liveRegionRemoved; 68 ok(!assertiveRegion.getAttributeValue("AXARIALive"), "region is not live"); 69 70 liveRegionAdded = waitForMacEvent("AXLiveRegionCreated", "new-region"); 71 await SpecialPowers.spawn(browser, [], () => { 72 let newRegionElm = content.document.createElement("div"); 73 newRegionElm.id = "new-region"; 74 newRegionElm.setAttribute("aria-live", "assertive"); 75 content.document.body.appendChild(newRegionElm); 76 }); 77 await liveRegionAdded; 78 79 let newRegion = getNativeInterface(accDoc, "new-region"); 80 is( 81 newRegion.getAttributeValue("AXARIALive"), 82 "assertive", 83 "region is assertive" 84 ); 85 86 let loadComplete = Promise.all([ 87 waitForMacEvent("AXLoadComplete"), 88 waitForMacEvent("AXLiveRegionCreated", "region-1"), 89 waitForMacEvent("AXLiveRegionCreated", "region-2"), 90 waitForMacEvent("AXLiveRegionCreated", "status"), 91 waitForMacEvent("AXLiveRegionCreated", "output"), 92 ]); 93 94 await SpecialPowers.spawn(browser, [], () => { 95 content.location = `data:text/html;charset=utf-8, 96 <div id="region-1" aria-live="polite"></div> 97 <div id="region-2" aria-live="assertive"></div> 98 <div id="region-3" aria-live="off"></div> 99 <div id="alert" role="alert"></div> 100 <div id="status" role="status"></div> 101 <output id="output"></output>`; 102 }); 103 let webArea = (await loadComplete)[0]; 104 105 is(webArea.getAttributeValue("AXRole"), "AXWebArea", "web area yeah"); 106 const searchPred = { 107 AXSearchKey: "AXLiveRegionSearchKey", 108 AXResultsLimit: -1, 109 AXDirection: "AXDirectionNext", 110 }; 111 const liveRegions = webArea.getParameterizedAttributeValue( 112 "AXUIElementsForSearchPredicate", 113 NSDictionary(searchPred) 114 ); 115 Assert.deepEqual( 116 liveRegions.map(r => r.getAttributeValue("AXDOMIdentifier")), 117 ["region-1", "region-2", "alert", "status", "output"], 118 "SearchPredicate returned all live regions" 119 ); 120 } 121 ); 122 123 /** 124 * Test live region changes 125 */ 126 addAccessibleTask( 127 ` 128 <div id="live" aria-live="polite"> 129 The time is <span id="time">4:55pm</span> 130 <p id="p" style="display: none">Georgia on my mind</p> 131 <button id="button" aria-label="Start"></button> 132 </div> 133 `, 134 async browser => { 135 let liveRegionChanged = waitForMacEvent("AXLiveRegionChanged", "live"); 136 await SpecialPowers.spawn(browser, [], () => { 137 content.document.getElementById("time").textContent = "4:56pm"; 138 }); 139 await liveRegionChanged; 140 ok(true, "changed textContent"); 141 142 liveRegionChanged = waitForMacEvent("AXLiveRegionChanged", "live"); 143 await SpecialPowers.spawn(browser, [], () => { 144 content.document.getElementById("p").style.display = "block"; 145 }); 146 await liveRegionChanged; 147 ok(true, "changed display style to block"); 148 149 liveRegionChanged = waitForMacEvent("AXLiveRegionChanged", "live"); 150 await SpecialPowers.spawn(browser, [], () => { 151 content.document.getElementById("p").style.display = "none"; 152 }); 153 await liveRegionChanged; 154 ok(true, "changed display style to none"); 155 156 liveRegionChanged = waitForMacEvent("AXLiveRegionChanged", "live"); 157 await SpecialPowers.spawn(browser, [], () => { 158 content.document 159 .getElementById("button") 160 .setAttribute("aria-label", "Stop"); 161 }); 162 await liveRegionChanged; 163 ok(true, "changed aria-label"); 164 165 liveRegionChanged = waitForMacEvent("AXLiveRegionChanged", "live"); 166 await SpecialPowers.spawn(browser, [], () => { 167 content.document.getElementById("live").firstChild.data = "The hour is "; 168 }); 169 await liveRegionChanged; 170 ok(true, "changed text leaf contents"); 171 172 liveRegionChanged = waitForMacEvent("AXLiveRegionChanged", "live"); 173 await SpecialPowers.spawn(browser, [], () => { 174 content.document.getElementById("live").firstChild.data = ""; 175 }); 176 await liveRegionChanged; 177 ok(true, "delete text leaf contents"); 178 } 179 ); 180 181 /** 182 * Test live region announcements caused by clicking a button that modifies a region. 183 */ 184 addAccessibleTask( 185 ` 186 <div id="status-container" aria-live="polite" aria-label=""> 187 </div> 188 189 <button id="clickme" onClick="(function(){document.getElementById('status-container').setAttribute('aria-label', 'hello world');})()"> 190 Add something! 191 </button> 192 `, 193 async (browser, accDoc) => { 194 let liveRegionChanged = waitForMacEvent( 195 "AXLiveRegionChanged", 196 "status-container" 197 ); 198 const button = getNativeInterface(accDoc, "clickme"); 199 button.performAction("AXPress"); 200 await liveRegionChanged; 201 ok(true, "aria-label was changed, and event was fired"); 202 } 203 );