Fri, 16 Jan 2015 18:13:44 +0100
Integrate suggestion from review to improve consistency with existing code.
1 <html>
3 <head>
4 <title>Accessible state change event testing</title>
6 <link rel="stylesheet" type="text/css"
7 href="chrome://mochikit/content/tests/SimpleTest/test.css" />
9 <script type="application/javascript"
10 src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
12 <script type="application/javascript"
13 src="../common.js"></script>
14 <script type="application/javascript"
15 src="../events.js"></script>
16 <script type="application/javascript"
17 src="../role.js"></script>
18 <script type="application/javascript"
19 src="../states.js"></script>
21 <script type="application/javascript">
22 ////////////////////////////////////////////////////////////////////////////
23 // Invokers
25 function makeEditableDoc(aDocNode, aIsEnabled)
26 {
27 this.DOMNode = aDocNode;
29 this.invoke = function editabledoc_invoke() {
30 // Note: this should fire an EVENT_STATE_CHANGE
31 this.DOMNode.designMode = 'on';
32 };
34 this.check = function editabledoc_check(aEvent) {
36 testStates(aDocNode, 0, EXT_STATE_EDITABLE);
38 var event = null;
39 try {
40 var event = aEvent.QueryInterface(nsIAccessibleStateChangeEvent);
41 } catch (e) {
42 ok(false, "State change event was expected");
43 }
45 if (!event) { return; }
47 ok(event.isExtraState, "Extra state change was expected");
48 is(event.state, EXT_STATE_EDITABLE, "Wrong state of statechange event");
49 ok(event.isEnabled, "Expected editable state to be enabled");
50 }
52 this.getID = function editabledoc_getID() {
53 return prettyName(aDocNode) + " editable state changed";
54 };
55 }
57 function invalidInput(aNodeOrID)
58 {
59 this.DOMNode = getNode(aNodeOrID);
61 this.invoke = function invalidInput_invoke() {
62 // Note: this should fire an EVENT_STATE_CHANGE
63 this.DOMNode.value = "I am not an email";
64 };
66 this.check = function invalidInput_check() {
67 testStates(aNodeOrID, STATE_INVALID);
68 };
70 this.getID = function invalidInput_getID() {
71 return prettyName(aNodeOrID) + " became invalid";
72 };
73 }
75 function changeCheckInput(aID, aIsChecked)
76 {
77 this.DOMNode = getNode(aID);
79 this.eventSeq = [
80 new stateChangeChecker(STATE_CHECKED, false, aIsChecked, this.DOMNode)
81 ];
83 this.invoke = function changeCheckInput_invoke()
84 {
85 this.DOMNode.checked = aIsChecked;
86 }
88 this.getID = function changeCheckInput_getID()
89 {
90 return "change checked state to '" + aIsChecked + "' for " +
91 prettyName(aID);
92 }
93 }
95 function stateChangeOnFileInput(aID, aAttr, aValue,
96 aState, aIsExtraState, aIsEnabled)
97 {
98 this.fileControlNode = getNode(aID);
99 this.fileControl = getAccessible(this.fileControlNode);
100 this.browseButton = this.fileControl.firstChild;
101 // No state change events on the label.
103 this.invoke = function stateChangeOnFileInput_invoke()
104 {
105 this.fileControlNode.setAttribute(aAttr, aValue);
106 }
108 this.eventSeq = [
109 new stateChangeChecker(aState, aIsExtraState, aIsEnabled, this.fileControl),
110 new stateChangeChecker(aState, aIsExtraState, aIsEnabled, this.browseButton)
111 ];
113 this.getID = function stateChangeOnFileInput_getID()
114 {
115 return "inherited state change on file input on attribute '" + aAttr + "' change";
116 }
117 }
119 function dupeStateChange(aID, aAttr, aValue,
120 aState, aIsExtraState, aIsEnabled)
121 {
122 this.eventSeq = [
123 new stateChangeChecker(aState, aIsExtraState, aIsEnabled, getNode(aID))
124 ];
126 this.invoke = function dupeStateChange_invoke()
127 {
128 getNode(aID).setAttribute(aAttr, aValue);
129 getNode(aID).setAttribute(aAttr, aValue);
130 }
132 this.getID = function dupeStateChange_getID()
133 {
134 return "duped state change events";
135 }
136 }
138 function oppositeStateChange(aID, aAttr, aState, aIsExtraState)
139 {
140 this.eventSeq = [ ];
141 this.unexpectedEventSeq = [
142 new stateChangeChecker(aState, aIsExtraState, false, getNode(aID)),
143 new stateChangeChecker(aState, aIsExtraState, true, getNode(aID))
144 ];
146 this.invoke = function oppositeStateChange_invoke()
147 {
148 getNode(aID).setAttribute(aAttr, "false");
149 getNode(aID).setAttribute(aAttr, "true");
150 }
152 this.getID = function oppositeStateChange_getID()
153 {
154 return "opposite state change events";
155 }
156 }
158 /**
159 * Change concomitant ARIA and native attribute at once.
160 */
161 function echoingStateChange(aID, aARIAAttr, aAttr, aValue,
162 aState, aIsExtraState, aIsEnabled)
163 {
164 this.eventSeq = [
165 new stateChangeChecker(aState, aIsExtraState, aIsEnabled, getNode(aID))
166 ];
168 this.invoke = function echoingStateChange_invoke()
169 {
170 if (aValue == null) {
171 getNode(aID).removeAttribute(aARIAAttr);
172 getNode(aID).removeAttribute(aAttr);
174 } else {
175 getNode(aID).setAttribute(aARIAAttr, aValue);
176 getNode(aID).setAttribute(aAttr, aValue);
177 }
178 }
180 this.getID = function echoingStateChange_getID()
181 {
182 return "enchoing ARIA and native attributes change";
183 }
184 }
186 ////////////////////////////////////////////////////////////////////////////
187 // Do tests
189 var gQueue = null;
191 // var gA11yEventDumpID = "eventdump"; // debug stuff
192 //gA11yEventDumpToConsole = true; // debug stuff
194 function doTests()
195 {
196 gQueue = new eventQueue(nsIAccessibleEvent.EVENT_STATE_CHANGE);
198 // Test delayed editable state change
199 var doc = document.getElementById("iframe").contentDocument;
200 gQueue.push(new makeEditableDoc(doc));
202 // invalid state change
203 gQueue.push(new invalidInput("email"));
205 // checked state change
206 gQueue.push(new changeCheckInput("checkbox", true));
207 gQueue.push(new changeCheckInput("checkbox", false));
208 gQueue.push(new changeCheckInput("radio", true));
209 gQueue.push(new changeCheckInput("radio", false));
211 // file input inherited state changes
212 gQueue.push(new stateChangeOnFileInput("file", "aria-busy", "true",
213 STATE_BUSY, false, true));
214 gQueue.push(new stateChangeOnFileInput("file", "aria-required", "true",
215 STATE_REQUIRED, false, true));
216 gQueue.push(new stateChangeOnFileInput("file", "aria-invalid", "true",
217 STATE_INVALID, false, true));
219 gQueue.push(new dupeStateChange("div", "aria-busy", "true",
220 STATE_BUSY, false, true));
221 gQueue.push(new oppositeStateChange("div", "aria-busy",
222 STATE_BUSY, false));
224 gQueue.push(new echoingStateChange("text1", "aria-disabled", "disabled", "true",
225 EXT_STATE_ENABLED, true, false));
226 gQueue.push(new echoingStateChange("text1", "aria-disabled", "disabled", null,
227 EXT_STATE_ENABLED, true, true));
229 gQueue.invoke(); // Will call SimpleTest.finish();
230 }
232 SimpleTest.waitForExplicitFinish();
233 addA11yLoadEvent(doTests);
234 </script>
235 </head>
237 <body>
239 <a target="_blank"
240 href="https://bugzilla.mozilla.org/show_bug.cgi?id=564471"
241 title="Make state change events async">
242 Bug 564471
243 </a>
244 <a target="_blank"
245 href="https://bugzilla.mozilla.org/show_bug.cgi?id=555728"
246 title="Fire a11y event based on HTML5 constraint validation">
247 Bug 555728
248 </a>
249 <a target="_blank"
250 href="https://bugzilla.mozilla.org/show_bug.cgi?id=699017"
251 title="File input control should be propogate states to descendants">
252 Bug 699017
253 </a>
254 <a target="_blank"
255 href="https://bugzilla.mozilla.org/show_bug.cgi?id=788389"
256 title="Fire statechange event whenever checked state is changed not depending on focused state">
257 Bug 788389
258 </a>
259 <a target="_blank"
260 href="https://bugzilla.mozilla.org/show_bug.cgi?id=926812"
261 title="State change event not fired when both disabled and aria-disabled are toggled">
262 Bug 926812
263 </a>
265 <p id="display"></p>
266 <div id="content" style="display: none"></div>
267 <pre id="test">
268 </pre>
270 <div id="testContainer">
271 <iframe id="iframe"></iframe>
272 </div>
274 <input id="email" type='email'>
276 <input id="checkbox" type="checkbox">
277 <input id="radio" type="radio">
279 <input id="file" type="file">
281 <div id="div"></div>
283 <input id="text1">
285 <div id="eventdump"></div>
286 </body>
287 </html>