Bug 1884032 [wpt PR 44942] - [css-color] add missing colorscheme-aware tests, a=testonly
[gecko.git] / widget / tests / file_test_ime_state_on_focus_move.js
blobf7760d8a09555a3c227df31f22b77f8b6953b88c
1 /* Any copyright is dedicated to the Public Domain.
2    http://creativecommons.org/publicdomain/zero/1.0/ */
4 "use strict";
6 /* import-globals-from file_ime_state_test_helper.js */
8 class IMEStateWhenNoActiveElementTester {
9   #mDescription;
11   constructor(aDescription) {
12     this.#mDescription = aDescription;
13   }
15   async run(aDocument, aWindow = window) {
16     aWindow.focus();
17     aDocument.activeElement?.blur();
19     await new Promise(resolve =>
20       requestAnimationFrame(() => requestAnimationFrame(resolve))
21     ); // wait for sending IME notifications
23     return { designModeValue: aDocument.designMode };
24   }
26   check(aExpectedData, aWindow = window) {
27     const winUtils = SpecialPowers.wrap(aWindow).windowUtils;
28     if (aExpectedData.designModeValue == "on") {
29       is(
30         winUtils.IMEStatus,
31         SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED,
32         `IMEStateWhenNoActiveElementTester(${
33           this.#mDescription
34         }): When no element has focus, IME should stay enabled in design mode`
35       );
36     } else {
37       is(
38         winUtils.IMEStatus,
39         SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED,
40         `IMEStateWhenNoActiveElementTester(${
41           this.#mDescription
42         }): When no element has focus, IME should be disabled`
43       );
44     }
45   }
48 class IMEStateOnFocusMoveTester {
49   // Common fields
50   #mDescription;
51   #mTest;
52   #mWindow;
53   #mWindowUtils;
55   // Only runner fields
56   #mCreatedElement;
57   #mCreatedElementForPreviousFocusedElement;
58   #mElementToSetFocus;
59   #mContainerIsEditable;
61   // Only checker fields
62   #mTIPWrapper;
64   constructor(aDescription, aIndex, aWindow = window) {
65     this.#mTest = IMEStateOnFocusMoveTester.#sTestList[aIndex];
66     this.#mDescription = `IMEStateOnFocusMoveTester(${aDescription}): ${
67       this.#mTest.description
68     }`;
69     this.#mWindow = aWindow;
70     this.#mWindowUtils = SpecialPowers.wrap(this.#mWindow).windowUtils;
71   }
73   /**
74    * prepareToRun should be called before run only in the process which will run the test.
75    */
76   async prepareToRun(aContainer) {
77     const doc = aContainer.ownerDocument;
78     this.#mTest = this.#resolveTest(this.#mTest, aContainer);
79     this.#mContainerIsEditable = nodeIsEditable(aContainer);
80     this.#mCreatedElement = this.#mTest.createElement(doc);
81     const waitForLoadIfIFrame = new Promise(resolve => {
82       if (this.#mCreatedElement.tagName == "IFRAME") {
83         this.#mCreatedElement.addEventListener("load", resolve, {
84           capture: true,
85           once: true,
86         });
87       } else {
88         resolve();
89       }
90     });
91     aContainer.appendChild(this.#mCreatedElement);
92     await waitForLoadIfIFrame;
93     this.#mElementToSetFocus = this.#mCreatedElement.contentDocument
94       ? this.#mCreatedElement.contentDocument.documentElement
95       : this.#mCreatedElement;
96     if (doc.designMode == "on") {
97       doc.activeElement?.blur();
98     } else if (this.#mContainerIsEditable) {
99       getEditingHost(aContainer).focus(); // FIXME: use editing host instead
100     } else {
101       this.#mCreatedElementForPreviousFocusedElement =
102         doc.createElement("input");
103       this.#mCreatedElementForPreviousFocusedElement.setAttribute(
104         "type",
105         this.#mTest.expectedEnabledValue ==
106           SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED
107           ? "password"
108           : "text"
109       );
110       aContainer.appendChild(this.#mCreatedElementForPreviousFocusedElement);
111       this.#mCreatedElementForPreviousFocusedElement.focus();
112     }
114     await new Promise(resolve =>
115       requestAnimationFrame(() => requestAnimationFrame(resolve))
116     ); // wait for sending IME notifications
118     return {
119       designModeValue: doc.designMode,
120       containerIsEditable: this.#mContainerIsEditable,
121       isFocusable: this.#mTest.isFocusable,
122       focusEventFired: this.#mTest.focusEventIsExpected,
123       enabledValue: this.#mTest.expectedEnabledValue,
124       testedSubDocumentInDesignMode:
125         this.#mCreatedElement.contentDocument?.designMode == "on",
126     };
127   }
129   /**
130    * prepareToCheck should be called before calling run only in the process which will check the result.
131    */
132   prepareToCheck(aExpectedData, aTIPWrapper) {
133     info(`Starting ${this.#mDescription} (enable state check)...`);
134     this.#mTIPWrapper = aTIPWrapper;
135     this.#mTIPWrapper.onIMEFocusBlur = aNotificationType => {
136       switch (aNotificationType) {
137         case "notify-focus":
138           info(aNotificationType);
139           is(
140             this.#mWindowUtils.IMEStatus,
141             aExpectedData.enabledValue,
142             `${
143               this.#mDescription
144             }, IME should receive a focus notification after IME state is updated`
145           );
146           break;
147         case "notify-blur":
148           info(aNotificationType);
149           const changingStatus = !(
150             aExpectedData.containerIsEditable &&
151             aExpectedData.enabledValue ==
152               SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED
153           );
154           if (aExpectedData.designModeValue == "on") {
155             is(
156               // FIXME: This is odd, but #mWindowUtils.IMEStatus sometimes IME_STATUS_PASSWORD
157               SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED,
158               aExpectedData.enabledValue,
159               `${
160                 this.#mDescription
161               }, IME should receive a blur notification after IME state is updated`
162             );
163           } else if (changingStatus) {
164             isnot(
165               this.#mWindowUtils.IMEStatus,
166               aExpectedData.enabledValue,
167               `${
168                 this.#mDescription
169               }, IME should receive a blur notification BEFORE IME state is updated`
170             );
171           } else {
172             is(
173               this.#mWindowUtils.IMEStatus,
174               aExpectedData.enabledValue,
175               `${
176                 this.#mDescription
177               }, IME should receive a blur notification and its context has expected IME state if the state isn't being changed`
178             );
179           }
180           break;
181       }
182     };
184     this.#mTIPWrapper.clearFocusBlurNotifications();
185   }
187   /**
188    * @returns {bool} whether expected element has focus or not after moving focus.
189    */
190   async run() {
191     const previousFocusedElement = getFocusedElementOrUAWidgetHost();
192     if (this.#mTest.setFocusIntoUAWidget) {
193       this.#mTest.setFocusIntoUAWidget(this.#mElementToSetFocus);
194     } else {
195       this.#mElementToSetFocus.focus();
196     }
198     await new Promise(resolve =>
199       requestAnimationFrame(() => requestAnimationFrame(resolve))
200     ); // wait for sending IME notifications
202     const currentFocusedElement = getFocusedElementOrUAWidgetHost();
203     this.#mCreatedElementForPreviousFocusedElement?.remove();
204     if (this.#mTest.isFocusable) {
205       return this.#mElementToSetFocus == currentFocusedElement;
206     }
207     return previousFocusedElement == currentFocusedElement;
208   }
210   check(aExpectedData) {
211     this.#mTIPWrapper.onIMEFocusBlur = null;
213     if (aExpectedData.isFocusable) {
214       if (aExpectedData.focusEventFired) {
215         if (
216           aExpectedData.enabledValue ==
217             SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED ||
218           aExpectedData.enabledValue ==
219             SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_PASSWORD
220         ) {
221           ok(
222             this.#mTIPWrapper.numberOfFocusNotifications > 0,
223             `${this.#mDescription}, IME should receive a focus notification`
224           );
225           if (
226             aExpectedData.designModeValue == "on" &&
227             !aExpectedData.testedSubDocumentInDesignMode
228           ) {
229             is(
230               this.#mTIPWrapper.numberOfBlurNotifications,
231               0,
232               `${
233                 this.#mDescription
234               }, IME shouldn't receive a blur notification in designMode since focus isn't moved from another editor`
235             );
236           } else {
237             ok(
238               this.#mTIPWrapper.numberOfBlurNotifications > 0,
239               `${
240                 this.#mDescription
241               }, IME should receive a blur notification for the previous focused editor`
242             );
243           }
244           ok(
245             this.#mTIPWrapper.IMEHasFocus,
246             `${this.#mDescription}, IME should have focus right now`
247           );
248         } else {
249           is(
250             this.#mTIPWrapper.numberOfFocusNotifications,
251             0,
252             `${this.#mDescription}, IME shouldn't receive a focus notification`
253           );
254           ok(
255             this.#mTIPWrapper.numberOfBlurNotifications > 0,
256             `${this.#mDescription}, IME should receive a blur notification`
257           );
258           ok(
259             !this.#mTIPWrapper.IMEHasFocus,
260             `${this.#mDescription}, IME shouldn't have focus right now`
261           );
262         }
263       } else {
264         ok(true, `${this.#mDescription}, focus event should be fired`);
265       }
266     } else {
267       is(
268         this.#mTIPWrapper.numberOfFocusNotifications,
269         0,
270         `${
271           this.#mDescription
272         }, IME shouldn't receive a focus notification at testing non-focusable element`
273       );
274       is(
275         this.#mTIPWrapper.numberOfBlurNotifications,
276         0,
277         `${
278           this.#mDescription
279         }, IME shouldn't receive a blur notification at testing non-focusable element`
280       );
281     }
283     is(
284       this.#mWindowUtils.IMEStatus,
285       aExpectedData.enabledValue,
286       `${this.#mDescription}, wrong enabled state`
287     );
288     if (
289       this.#mTest.expectedInputElementType &&
290       aExpectedData.designModeValue != "on"
291     ) {
292       is(
293         this.#mWindowUtils.focusedInputType,
294         this.#mTest.expectedInputElementType,
295         `${this.#mDescription}, wrong input type`
296       );
297     } else if (aExpectedData.designModeValue == "on") {
298       is(
299         this.#mWindowUtils.focusedInputType,
300         "",
301         `${this.#mDescription}, wrong input type`
302       );
303     }
304   }
306   destroy() {
307     this.#mCreatedElement?.remove();
308     this.#mCreatedElementForPreviousFocusedElement?.remove();
309     this.#mTIPWrapper?.clearFocusBlurNotifications();
310     this.#mTIPWrapper = null;
311   }
313   /**
314    * Open/Close state test check
315    * Note that these tests are not run now.
316    * If these tests should run between `run` and `cleanUp` call of the above
317    * tests.
318    */
319   canTestOpenCloseState(aExpectedData) {
320     return (
321       IsIMEOpenStateSupported() &&
322       this.#mWindowUtils.IMEStatus ==
323         SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED &&
324       aExpectedData.enabledValue ==
325         SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED
326     );
327   }
328   async prepareToRunOpenCloseTest(aContainer) {
329     const doc = aContainer.ownerDocument;
330     this.#mCreatedElementForPreviousFocusedElement?.remove();
331     this.#mCreatedElementForPreviousFocusedElement = doc.createElement("input");
332     this.#mCreatedElementForPreviousFocusedElement.setAttribute("type", "text");
333     aContainer.appendChild(this.#mCreatedElementForPreviousFocusedElement);
335     this.#mContainerIsEditable = nodeIsEditable(aContainer);
336     this.#mCreatedElement = this.#mTest.createElement(doc);
337     const waitForLoadIfIFrame = new Promise(resolve => {
338       if (this.#mCreatedElement.tagName == "IFRAME") {
339         this.#mCreatedElement.addEventListener("load", resolve, {
340           capture: true,
341           once: true,
342         });
343       } else {
344         resolve();
345       }
346     });
347     aContainer.appendChild(this.#mCreatedElement);
348     await waitForLoadIfIFrame;
349     this.#mElementToSetFocus = this.#mCreatedElement.contentDocument
350       ? this.#mCreatedElement.contentDocument.documentElement
351       : this.#mCreatedElement;
353     this.#mCreatedElementForPreviousFocusedElement.focus();
355     return {};
356   }
357   prepareToCheckOpenCloseTest(aPreviousOpenState, aExpectedData) {
358     info(`Starting ${this.#mDescription} (open/close state check)...`);
359     this.#mWindowUtils.IMEIsOpen = aPreviousOpenState;
360     aExpectedData.defaultOpenState = this.#mWindowUtils.IMEIsOpen;
361   }
362   async runOpenCloseTest() {
363     return this.run();
364   }
365   checkOpenCloseTest(aExpectedData) {
366     const expectedOpenState =
367       this.#mTest.expectedOpenState != undefined
368         ? this.#mTest.expectedOpenState
369         : aExpectedData.defaultOpenState;
370     is(
371       this.#mWindowUtils.IMEIsOpen,
372       expectedOpenState,
373       `${this.#mDescription}, IME should ${
374         expectedOpenState != aExpectedData.defaultOpenState ? "become" : "keep"
375       } ${expectedOpenState ? "open" : "closed"}`
376     );
377   }
379   /**
380    * Utility methods for defining kIMEStateTestList.
381    */
383   /**
384    * @param {Element} aElement
385    */
386   static #elementIsConnectedAndNotInDesignMode(aElement) {
387     return aElement.isConnected && !nodeIsInDesignMode(aElement);
388   }
390   /**
391    * @param {Element} aElementContainer
392    * @param {bool} aElementIsEditingHost
393    */
394   static #elementIsFocusableIfEditingHost(
395     aElementContainer,
396     aElementIsEditingHost
397   ) {
398     return !nodeIsEditable(aElementContainer) && aElementIsEditingHost;
399   }
401   static #IMEStateEnabledAlways() {
402     return SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED;
403   }
405   /**
406    * @param {Element} aElement
407    * @param {bool} aElementIsEditingHost
408    */
409   static #IMEStateEnabledIfEditable(aElement, aElementIsEditingHost) {
410     return nodeIsEditable(aElement) || aElementIsEditingHost
411       ? SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED
412       : SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED;
413   }
415   /**
416    * @param {Element} aElement
417    */
418   static #IMEStateEnabledIfInDesignMode(aElement) {
419     return IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode(
420       aElement
421     )
422       ? SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED
423       : SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED;
424   }
426   /**
427    * @param {Element} aElement
428    */
429   static #IMEStatePasswordIfNotInDesignMode(aElement) {
430     return IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode(
431       aElement
432     )
433       ? SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_PASSWORD
434       : SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED;
435   }
437   /**
438    * @param {Element} aElement
439    */
440   static #elementIsConnectedAndNotEditable(aElement) {
441     return aElement.isConnected && !nodeIsEditable(aElement);
442   }
444   /**
445    * @param {Element} aElementContainer
446    */
447   static #focusEventIsExpectedUnlessEditableChild(aElementContainer) {
448     return !nodeIsEditable(aElementContainer);
449   }
451   // Form controls except text editable elements are "disable" in normal
452   // condition, however, if they are editable, they are "enabled".
453   // XXX Probably there are some bugs: If the form controls editable, they
454   //     shouldn't be focusable.
455   #resolveTest(aTest, aContainer) {
456     const isFocusable = aTest.isFocusable(
457       aContainer,
458       aTest.isNewElementEditingHost
459     );
460     return {
461       // Description of the new element
462       description: aTest.description,
463       // Create element to check IME state
464       createElement: aTest.createElement,
465       // Whether the new element is an editing host if container is not editable
466       isNewElementEditingHost: aTest.isNewElementEditingHost,
467       // If the test wants to move focus into an element in UA widget, define
468       // this and set focus in it.
469       setFocusIntoUAWidget: aTest.setFocusIntoUAWidget,
470       // Whether the element is focusable or not
471       isFocusable,
472       // Whether focus events are fired on the element if it's focusable
473       focusEventIsExpected:
474         isFocusable &&
475         aTest.focusEventIsExpected(aContainer, aTest.isNewElementEditingHost),
476       // Expected IME enabled state when the element has focus
477       expectedEnabledValue: aTest.expectedEnabledValue(
478         aContainer,
479         aTest.isNewElementEditingHost
480       ),
481       // Expected IME open state when the element gets focus
482       // "undefined" means that IME open state should not be changed
483       expectedOpenState: aTest.expectedOpenState,
484       // Expected type of input element if it's an <input>
485       expectedInputElementType: aTest.expectedInputElementType,
486     };
487   }
488   static #sTestList = [
489     {
490       description: "input[type=text]",
491       createElement: aDocument => {
492         const element = aDocument.createElement("input");
493         element.setAttribute("type", "text");
494         return element;
495       },
496       isFocusable:
497         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
498       focusEventIsExpected: () => true,
499       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
500       expectedInputElementType: "text",
501     },
502     {
503       description: "input[type=text][readonly]",
504       createElement: aDocument => {
505         const element = aDocument.createElement("input");
506         element.setAttribute("type", "text");
507         element.setAttribute("readonly", "");
508         return element;
509       },
510       isFocusable:
511         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
512       focusEventIsExpected: () => true,
513       expectedEnabledValue:
514         IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
515     },
516     {
517       description: "input[type=password]",
518       createElement: aDocument => {
519         const element = aDocument.createElement("input");
520         element.setAttribute("type", "password");
521         return element;
522       },
523       isFocusable:
524         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
525       focusEventIsExpected: () => true,
526       expectedEnabledValue:
527         IMEStateOnFocusMoveTester.#IMEStatePasswordIfNotInDesignMode,
528       expectedInputElementType: "password",
529     },
530     {
531       description: "input[type=password][readonly]",
532       createElement: aDocument => {
533         const element = aDocument.createElement("input");
534         element.setAttribute("type", "password");
535         element.setAttribute("readonly", "");
536         return element;
537       },
538       isFocusable:
539         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
540       focusEventIsExpected: () => true,
541       expectedEnabledValue:
542         IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
543     },
544     {
545       description: "input[type=checkbox]",
546       createElement: aDocument => {
547         const element = aDocument.createElement("input");
548         element.setAttribute("type", "checkbox");
549         return element;
550       },
551       isFocusable:
552         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
553       focusEventIsExpected:
554         IMEStateOnFocusMoveTester.#focusEventIsExpectedUnlessEditableChild,
555       expectedEnabledValue:
556         IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
557     },
558     {
559       description: "input[type=radio]",
560       createElement: aDocument => {
561         const element = aDocument.createElement("input");
562         element.setAttribute("type", "radio");
563         return element;
564       },
565       isFocusable:
566         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
567       focusEventIsExpected:
568         IMEStateOnFocusMoveTester.#focusEventIsExpectedUnlessEditableChild,
569       expectedEnabledValue:
570         IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
571     },
572     {
573       description: "input[type=submit]",
574       createElement: aDocument => {
575         const element = aDocument.createElement("input");
576         element.setAttribute("type", "submit");
577         return element;
578       },
579       isFocusable:
580         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
581       focusEventIsExpected: () => true,
582       expectedEnabledValue:
583         IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
584     },
585     {
586       description: "input[type=reset]",
587       createElement: aDocument => {
588         const element = aDocument.createElement("input");
589         element.setAttribute("type", "reset");
590         return element;
591       },
592       isFocusable:
593         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
594       focusEventIsExpected: () => true,
595       expectedEnabledValue:
596         IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
597     },
598     {
599       description: "input[type=file]",
600       createElement: aDocument => {
601         const element = aDocument.createElement("input");
602         element.setAttribute("type", "file");
603         return element;
604       },
605       isFocusable:
606         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
607       focusEventIsExpected:
608         IMEStateOnFocusMoveTester.#focusEventIsExpectedUnlessEditableChild,
609       expectedEnabledValue:
610         IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
611     },
612     {
613       description: "input[type=button]",
614       createElement: aDocument => {
615         const element = aDocument.createElement("input");
616         element.setAttribute("type", "button");
617         return element;
618       },
619       isFocusable:
620         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
621       focusEventIsExpected: () => true,
622       expectedEnabledValue:
623         IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
624     },
625     {
626       description: "input[type=image]",
627       createElement: aDocument => {
628         const element = aDocument.createElement("input");
629         element.setAttribute("type", "image");
630         return element;
631       },
632       isFocusable:
633         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
634       focusEventIsExpected: () => true,
635       expectedEnabledValue:
636         IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
637     },
638     {
639       description: "input[type=url]",
640       createElement: aDocument => {
641         const element = aDocument.createElement("input");
642         element.setAttribute("type", "url");
643         return element;
644       },
645       isFocusable:
646         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
647       focusEventIsExpected: () => true,
648       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
649       expectedInputElementType: "url",
650     },
651     {
652       description: "input[type=email]",
653       createElement: aDocument => {
654         const element = aDocument.createElement("input");
655         element.setAttribute("type", "email");
656         return element;
657       },
658       isFocusable:
659         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
660       focusEventIsExpected: () => true,
661       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
662       expectedInputElementType: "email",
663     },
664     {
665       description: "input[type=search]",
666       createElement: aDocument => {
667         const element = aDocument.createElement("input");
668         element.setAttribute("type", "search");
669         return element;
670       },
671       isFocusable:
672         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
673       focusEventIsExpected: () => true,
674       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
675       expectedInputElementType: "search",
676     },
677     {
678       description: "input[type=tel]",
679       createElement: aDocument => {
680         const element = aDocument.createElement("input");
681         element.setAttribute("type", "tel");
682         return element;
683       },
684       isFocusable:
685         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
686       focusEventIsExpected: () => true,
687       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
688       expectedInputElementType: "tel",
689     },
690     {
691       description: "input[type=number]",
692       createElement: aDocument => {
693         const element = aDocument.createElement("input");
694         element.setAttribute("type", "number");
695         return element;
696       },
697       isFocusable:
698         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
699       focusEventIsExpected: () => true,
700       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
701       expectedInputElementType: "number",
702     },
703     {
704       description: "input[type=date]",
705       createElement: aDocument => {
706         const element = aDocument.createElement("input");
707         element.setAttribute("type", "date");
708         return element;
709       },
710       isFocusable:
711         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
712       focusEventIsExpected: () => true,
713       expectedEnabledValue:
714         IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
715       expectedInputElementType: "date",
716     },
717     {
718       description: "input[type=datetime-local]",
719       createElement: aDocument => {
720         const element = aDocument.createElement("input");
721         element.setAttribute("type", "datetime-local");
722         return element;
723       },
724       isFocusable:
725         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
726       focusEventIsExpected: () => true,
727       expectedEnabledValue:
728         IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
729       expectedInputElementType: "datetime-local",
730     },
731     {
732       description: "input[type=time]",
733       createElement: aDocument => {
734         const element = aDocument.createElement("input");
735         element.setAttribute("type", "time");
736         return element;
737       },
738       isFocusable:
739         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
740       focusEventIsExpected: () => true,
741       expectedEnabledValue:
742         IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
743       expectedInputElementType: "time",
744     },
745     // TODO(bug 1283382, bug 1283382): month and week
747     // form controls
748     {
749       description: "button",
750       createElement: aDocument => aDocument.createElement("button"),
751       isFocusable:
752         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
753       focusEventIsExpected: () => true,
754       expectedEnabledValue:
755         IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
756     },
757     {
758       description: "textarea",
759       createElement: aDocument => aDocument.createElement("textarea"),
760       isFocusable:
761         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
762       focusEventIsExpected: () => true,
763       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
764     },
765     {
766       description: "textarea[readonly]",
767       createElement: aDocument => {
768         const element = aDocument.createElement("textarea");
769         element.setAttribute("readonly", "");
770         return element;
771       },
772       isFocusable:
773         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
774       focusEventIsExpected: () => true,
775       expectedEnabledValue:
776         IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
777     },
778     {
779       description: "select (dropdown list)",
780       createElement: aDocument => {
781         const select = aDocument.createElement("select");
782         const option1 = aDocument.createElement("option");
783         option1.textContent = "abc";
784         const option2 = aDocument.createElement("option");
785         option2.textContent = "def";
786         const option3 = aDocument.createElement("option");
787         option3.textContent = "ghi";
788         select.appendChild(option1);
789         select.appendChild(option2);
790         select.appendChild(option3);
791         return select;
792       },
793       isFocusable:
794         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
795       focusEventIsExpected:
796         IMEStateOnFocusMoveTester.#focusEventIsExpectedUnlessEditableChild,
797       expectedEnabledValue:
798         IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
799     },
800     {
801       description: "select (list box)",
802       createElement: aDocument => {
803         const select = aDocument.createElement("select");
804         select.setAttribute("multiple", "multiple");
805         const option1 = aDocument.createElement("option");
806         option1.textContent = "abc";
807         const option2 = aDocument.createElement("option");
808         option2.textContent = "def";
809         const option3 = aDocument.createElement("option");
810         option3.textContent = "ghi";
811         select.appendChild(option1);
812         select.appendChild(option2);
813         select.appendChild(option3);
814         return select;
815       },
816       isFocusable:
817         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
818       focusEventIsExpected:
819         IMEStateOnFocusMoveTester.#focusEventIsExpectedUnlessEditableChild,
820       expectedEnabledValue:
821         IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
822     },
824     // a element
825     {
826       id: "a_href",
827       description: "a[href]",
828       createElement: aDocument => {
829         const element = aDocument.createElement("a");
830         element.setAttribute("href", "about:blank");
831         return element;
832       },
833       isFocusable: IMEStateOnFocusMoveTester.#elementIsConnectedAndNotEditable,
834       focusEventIsExpected:
835         IMEStateOnFocusMoveTester.#focusEventIsExpectedUnlessEditableChild,
836       expectedEnabledValue:
837         IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
838     },
840     // audio element
841     {
842       description: "audio[controls]",
843       createElement: aDocument => {
844         const element = aDocument.createElement("audio");
845         element.setAttribute("controls", "");
846         return element;
847       },
848       isFocusable:
849         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
850       focusEventIsExpected: () => true,
851       expectedEnabledValue:
852         IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
853     },
854     {
855       description: "playButton in audio",
856       createElement: aDocument => {
857         const element = aDocument.createElement("audio");
858         element.setAttribute("controls", "");
859         return element;
860       },
861       setFocusIntoUAWidget: aElement =>
862         SpecialPowers.wrap(aElement)
863           .openOrClosedShadowRoot.getElementById("playButton")
864           .focus(),
865       isFocusable:
866         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
867       focusEventIsExpected: () => true,
868       expectedEnabledValue:
869         IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
870     },
871     {
872       description: "scrubber in audio",
873       createElement: aDocument => {
874         const element = aDocument.createElement("audio");
875         element.setAttribute("controls", "");
876         return element;
877       },
878       setFocusIntoUAWidget: aElement =>
879         SpecialPowers.wrap(aElement)
880           .openOrClosedShadowRoot.getElementById("scrubber")
881           .focus(),
882       isFocusable:
883         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
884       focusEventIsExpected: () => true,
885       expectedEnabledValue:
886         IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
887     },
888     {
889       description: "muteButton in audio",
890       createElement: aDocument => {
891         const element = aDocument.createElement("audio");
892         element.setAttribute("controls", "");
893         return element;
894       },
895       setFocusIntoUAWidget: aElement =>
896         SpecialPowers.wrap(aElement)
897           .openOrClosedShadowRoot.getElementById("muteButton")
898           .focus(),
899       isFocusable:
900         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
901       focusEventIsExpected: () => true,
902       expectedEnabledValue:
903         IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
904     },
905     {
906       description: "volumeControl in audio",
907       createElement: aDocument => {
908         const element = aDocument.createElement("audio");
909         element.setAttribute("controls", "");
910         return element;
911       },
912       setFocusIntoUAWidget: aElement =>
913         SpecialPowers.wrap(aElement)
914           .openOrClosedShadowRoot.getElementById("volumeControl")
915           .focus(),
916       isFocusable:
917         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
918       focusEventIsExpected: () => true,
919       expectedEnabledValue:
920         IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
921     },
923     // video element
924     {
925       description: "video",
926       createElement: aDocument => {
927         const element = aDocument.createElement("video");
928         element.setAttribute("controls", "");
929         return element;
930       },
931       isFocusable:
932         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
933       focusEventIsExpected: () => true,
934       expectedEnabledValue:
935         IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
936     },
937     {
938       description: "playButton in video",
939       createElement: aDocument => {
940         const element = aDocument.createElement("video");
941         element.setAttribute("controls", "");
942         return element;
943       },
944       setFocusIntoUAWidget: aElement =>
945         SpecialPowers.wrap(aElement)
946           .openOrClosedShadowRoot.getElementById("playButton")
947           .focus(),
948       isFocusable:
949         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
950       focusEventIsExpected: () => true,
951       expectedEnabledValue:
952         IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
953     },
954     {
955       description: "scrubber in video",
956       createElement: aDocument => {
957         const element = aDocument.createElement("video");
958         element.setAttribute("controls", "");
959         return element;
960       },
961       setFocusIntoUAWidget: aElement =>
962         SpecialPowers.wrap(aElement)
963           .openOrClosedShadowRoot.getElementById("scrubber")
964           .focus(),
965       isFocusable:
966         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
967       focusEventIsExpected: () => true,
968       expectedEnabledValue:
969         IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
970     },
971     {
972       description: "muteButton in video",
973       createElement: aDocument => {
974         const element = aDocument.createElement("video");
975         element.setAttribute("controls", "");
976         return element;
977       },
978       setFocusIntoUAWidget: aElement =>
979         SpecialPowers.wrap(aElement)
980           .openOrClosedShadowRoot.getElementById("muteButton")
981           .focus(),
982       isFocusable:
983         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
984       focusEventIsExpected: () => true,
985       expectedEnabledValue:
986         IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
987     },
988     {
989       description: "volumeControl in video",
990       createElement: aDocument => {
991         const element = aDocument.createElement("video");
992         element.setAttribute("controls", "");
993         return element;
994       },
995       setFocusIntoUAWidget: aElement =>
996         SpecialPowers.wrap(aElement)
997           .openOrClosedShadowRoot.getElementById("volumeControl")
998           .focus(),
999       isFocusable:
1000         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1001       focusEventIsExpected: () => true,
1002       expectedEnabledValue:
1003         IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
1004     },
1006     // ime-mode
1007     {
1008       description: 'input[type=text][style="ime-mode: auto;"]',
1009       createElement: aDocument => {
1010         const element = aDocument.createElement("input");
1011         element.setAttribute("type", "text");
1012         element.setAttribute("style", "ime-mode: auto;");
1013         return element;
1014       },
1015       isFocusable:
1016         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1017       focusEventIsExpected: () => true,
1018       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1019     },
1020     {
1021       description: 'input[type=text][style="ime-mode: normal;"]',
1022       createElement: aDocument => {
1023         const element = aDocument.createElement("input");
1024         element.setAttribute("type", "text");
1025         element.setAttribute("style", "ime-mode: normal;");
1026         return element;
1027       },
1028       isFocusable:
1029         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1030       focusEventIsExpected: () => true,
1031       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1032     },
1033     {
1034       description: 'input[type=text][style="ime-mode: active;"]',
1035       createElement: aDocument => {
1036         const element = aDocument.createElement("input");
1037         element.setAttribute("type", "text");
1038         element.setAttribute("style", "ime-mode: active;");
1039         return element;
1040       },
1041       isFocusable:
1042         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1043       focusEventIsExpected: () => true,
1044       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1045       expectedOpenState: true,
1046     },
1047     {
1048       description: 'input[type=text][style="ime-mode: inactive;"]',
1049       createElement: aDocument => {
1050         const element = aDocument.createElement("input");
1051         element.setAttribute("type", "text");
1052         element.setAttribute("style", "ime-mode: inactive;");
1053         return element;
1054       },
1055       isFocusable:
1056         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1057       focusEventIsExpected: () => true,
1058       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1059       expectedOpenState: false,
1060     },
1061     {
1062       description: 'input[type=text][style="ime-mode: disabled;"]',
1063       createElement: aDocument => {
1064         const element = aDocument.createElement("input");
1065         element.setAttribute("type", "text");
1066         element.setAttribute("style", "ime-mode: disabled;");
1067         return element;
1068       },
1069       isFocusable:
1070         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1071       focusEventIsExpected: () => true,
1072       expectedEnabledValue:
1073         IMEStateOnFocusMoveTester.#IMEStatePasswordIfNotInDesignMode,
1074     },
1076     {
1077       description: 'input[type=url][style="ime-mode: auto;"]',
1078       createElement: aDocument => {
1079         const element = aDocument.createElement("input");
1080         element.setAttribute("type", "url");
1081         element.setAttribute("style", "ime-mode: auto;");
1082         return element;
1083       },
1084       isFocusable:
1085         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1086       focusEventIsExpected: () => true,
1087       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1088     },
1089     {
1090       description: 'input[type=url][style="ime-mode: normal;"]',
1091       createElement: aDocument => {
1092         const element = aDocument.createElement("input");
1093         element.setAttribute("type", "url");
1094         element.setAttribute("style", "ime-mode: normal;");
1095         return element;
1096       },
1097       isFocusable:
1098         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1099       focusEventIsExpected: () => true,
1100       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1101     },
1102     {
1103       description: 'input[type=url][style="ime-mode: active;"]',
1104       createElement: aDocument => {
1105         const element = aDocument.createElement("input");
1106         element.setAttribute("type", "url");
1107         element.setAttribute("style", "ime-mode: active;");
1108         return element;
1109       },
1110       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1111       isFocusable:
1112         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1113       focusEventIsExpected: () => true,
1114       expectedOpenState: true,
1115     },
1116     {
1117       description: 'input[type=url][style="ime-mode: inactive;"]',
1118       createElement: aDocument => {
1119         const element = aDocument.createElement("input");
1120         element.setAttribute("type", "url");
1121         element.setAttribute("style", "ime-mode: inactive;");
1122         return element;
1123       },
1124       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1125       isFocusable:
1126         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1127       focusEventIsExpected: () => true,
1128       expectedOpenState: false,
1129     },
1130     {
1131       description: 'input[type=url][style="ime-mode: disabled;"]',
1132       createElement: aDocument => {
1133         const element = aDocument.createElement("input");
1134         element.setAttribute("type", "url");
1135         element.setAttribute("style", "ime-mode: disabled;");
1136         return element;
1137       },
1138       isFocusable:
1139         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1140       focusEventIsExpected: () => true,
1141       expectedEnabledValue:
1142         IMEStateOnFocusMoveTester.#IMEStatePasswordIfNotInDesignMode,
1143     },
1145     {
1146       description: 'input[type=email][style="ime-mode: auto;"]',
1147       createElement: aDocument => {
1148         const element = aDocument.createElement("input");
1149         element.setAttribute("type", "email");
1150         element.setAttribute("style", "ime-mode: auto;");
1151         return element;
1152       },
1153       isFocusable:
1154         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1155       focusEventIsExpected: () => true,
1156       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1157     },
1158     {
1159       description: 'input[type=email][style="ime-mode: normal;"]',
1160       createElement: aDocument => {
1161         const element = aDocument.createElement("input");
1162         element.setAttribute("type", "email");
1163         element.setAttribute("style", "ime-mode: normal;");
1164         return element;
1165       },
1166       isFocusable:
1167         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1168       focusEventIsExpected: () => true,
1169       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1170     },
1171     {
1172       description: 'input[type=email][style="ime-mode: active;"]',
1173       createElement: aDocument => {
1174         const element = aDocument.createElement("input");
1175         element.setAttribute("type", "email");
1176         element.setAttribute("style", "ime-mode: active;");
1177         return element;
1178       },
1179       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1180       isFocusable:
1181         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1182       focusEventIsExpected: () => true,
1183       expectedOpenState: true,
1184     },
1185     {
1186       description: 'input[type=email][style="ime-mode: inactive;"]',
1187       createElement: aDocument => {
1188         const element = aDocument.createElement("input");
1189         element.setAttribute("type", "email");
1190         element.setAttribute("style", "ime-mode: inactive;");
1191         return element;
1192       },
1193       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1194       isFocusable:
1195         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1196       focusEventIsExpected: () => true,
1197       expectedOpenState: false,
1198     },
1199     {
1200       description: 'input[type=email][style="ime-mode: disabled;"]',
1201       createElement: aDocument => {
1202         const element = aDocument.createElement("input");
1203         element.setAttribute("type", "email");
1204         element.setAttribute("style", "ime-mode: disabled;");
1205         return element;
1206       },
1207       isFocusable:
1208         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1209       focusEventIsExpected: () => true,
1210       expectedEnabledValue:
1211         IMEStateOnFocusMoveTester.#IMEStatePasswordIfNotInDesignMode,
1212     },
1214     {
1215       description: 'input[type=search][style="ime-mode: auto;"]',
1216       createElement: aDocument => {
1217         const element = aDocument.createElement("input");
1218         element.setAttribute("type", "search");
1219         element.setAttribute("style", "ime-mode: auto;");
1220         return element;
1221       },
1222       isFocusable:
1223         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1224       focusEventIsExpected: () => true,
1225       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1226     },
1227     {
1228       description: 'input[type=search][style="ime-mode: normal;"]',
1229       createElement: aDocument => {
1230         const element = aDocument.createElement("input");
1231         element.setAttribute("type", "search");
1232         element.setAttribute("style", "ime-mode: normal;");
1233         return element;
1234       },
1235       isFocusable:
1236         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1237       focusEventIsExpected: () => true,
1238       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1239     },
1240     {
1241       description: 'input[type=search][style="ime-mode: active;"]',
1242       createElement: aDocument => {
1243         const element = aDocument.createElement("input");
1244         element.setAttribute("type", "search");
1245         element.setAttribute("style", "ime-mode: active;");
1246         return element;
1247       },
1248       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1249       isFocusable:
1250         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1251       focusEventIsExpected: () => true,
1252       expectedOpenState: true,
1253     },
1254     {
1255       description: 'input[type=search][style="ime-mode: inactive;"]',
1256       createElement: aDocument => {
1257         const element = aDocument.createElement("input");
1258         element.setAttribute("type", "search");
1259         element.setAttribute("style", "ime-mode: inactive;");
1260         return element;
1261       },
1262       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1263       isFocusable:
1264         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1265       focusEventIsExpected: () => true,
1266       expectedOpenState: false,
1267     },
1268     {
1269       description: 'input[type=search][style="ime-mode: disabled;"]',
1270       createElement: aDocument => {
1271         const element = aDocument.createElement("input");
1272         element.setAttribute("type", "search");
1273         element.setAttribute("style", "ime-mode: disabled;");
1274         return element;
1275       },
1276       isFocusable:
1277         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1278       focusEventIsExpected: () => true,
1279       expectedEnabledValue:
1280         IMEStateOnFocusMoveTester.#IMEStatePasswordIfNotInDesignMode,
1281     },
1283     {
1284       description: 'input[type=tel][style="ime-mode: auto;"]',
1285       createElement: aDocument => {
1286         const element = aDocument.createElement("input");
1287         element.setAttribute("type", "tel");
1288         element.setAttribute("style", "ime-mode: auto;");
1289         return element;
1290       },
1291       isFocusable:
1292         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1293       focusEventIsExpected: () => true,
1294       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1295     },
1296     {
1297       description: 'input[type=tel][style="ime-mode: normal;"]',
1298       createElement: aDocument => {
1299         const element = aDocument.createElement("input");
1300         element.setAttribute("type", "tel");
1301         element.setAttribute("style", "ime-mode: normal;");
1302         return element;
1303       },
1304       isFocusable:
1305         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1306       focusEventIsExpected: () => true,
1307       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1308     },
1309     {
1310       description: 'input[type=tel][style="ime-mode: active;"]',
1311       createElement: aDocument => {
1312         const element = aDocument.createElement("input");
1313         element.setAttribute("type", "tel");
1314         element.setAttribute("style", "ime-mode: active;");
1315         return element;
1316       },
1317       isFocusable:
1318         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1319       focusEventIsExpected: () => true,
1320       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1321       expectedOpenState: true,
1322     },
1323     {
1324       description: 'input[type=tel][style="ime-mode: inactive;"]',
1325       createElement: aDocument => {
1326         const element = aDocument.createElement("input");
1327         element.setAttribute("type", "tel");
1328         element.setAttribute("style", "ime-mode: inactive;");
1329         return element;
1330       },
1331       isFocusable:
1332         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1333       focusEventIsExpected: () => true,
1334       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1335       expectedOpenState: false,
1336     },
1337     {
1338       description: 'input[type=tel][style="ime-mode: disabled;"]',
1339       createElement: aDocument => {
1340         const element = aDocument.createElement("input");
1341         element.setAttribute("type", "tel");
1342         element.setAttribute("style", "ime-mode: disabled;");
1343         return element;
1344       },
1345       isFocusable:
1346         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1347       focusEventIsExpected: () => true,
1348       expectedEnabledValue:
1349         IMEStateOnFocusMoveTester.#IMEStatePasswordIfNotInDesignMode,
1350     },
1352     {
1353       description: 'input[type=number][style="ime-mode: auto;"]',
1354       createElement: aDocument => {
1355         const element = aDocument.createElement("input");
1356         element.setAttribute("type", "number");
1357         element.setAttribute("style", "ime-mode: auto;");
1358         return element;
1359       },
1360       isFocusable:
1361         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1362       focusEventIsExpected: () => true,
1363       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1364     },
1365     {
1366       description: 'input[type=number][style="ime-mode: normal;"]',
1367       createElement: aDocument => {
1368         const element = aDocument.createElement("input");
1369         element.setAttribute("type", "number");
1370         element.setAttribute("style", "ime-mode: normal;");
1371         return element;
1372       },
1373       isFocusable:
1374         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1375       focusEventIsExpected: () => true,
1376       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1377     },
1378     {
1379       description: 'input[type=number][style="ime-mode: active;"]',
1380       createElement: aDocument => {
1381         const element = aDocument.createElement("input");
1382         element.setAttribute("type", "number");
1383         element.setAttribute("style", "ime-mode: active;");
1384         return element;
1385       },
1386       isFocusable:
1387         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1388       focusEventIsExpected: () => true,
1389       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1390       expectedOpenState: true,
1391     },
1392     {
1393       description: 'input[type=number][style="ime-mode: inactive;"]',
1394       createElement: aDocument => {
1395         const element = aDocument.createElement("input");
1396         element.setAttribute("type", "number");
1397         element.setAttribute("style", "ime-mode: inactive;");
1398         return element;
1399       },
1400       isFocusable:
1401         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1402       focusEventIsExpected: () => true,
1403       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1404       expectedOpenState: false,
1405     },
1406     {
1407       description: 'input[type=number][style="ime-mode: disabled;"]',
1408       createElement: aDocument => {
1409         const element = aDocument.createElement("input");
1410         element.setAttribute("type", "number");
1411         element.setAttribute("style", "ime-mode: disabled;");
1412         return element;
1413       },
1414       isFocusable:
1415         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1416       focusEventIsExpected: () => true,
1417       expectedEnabledValue:
1418         IMEStateOnFocusMoveTester.#IMEStatePasswordIfNotInDesignMode,
1419     },
1421     {
1422       description: 'input[type=password][style="ime-mode: auto;"]',
1423       createElement: aDocument => {
1424         const element = aDocument.createElement("input");
1425         element.setAttribute("type", "password");
1426         element.setAttribute("style", "ime-mode: auto;");
1427         return element;
1428       },
1429       isFocusable:
1430         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1431       focusEventIsExpected: () => true,
1432       expectedEnabledValue:
1433         IMEStateOnFocusMoveTester.#IMEStatePasswordIfNotInDesignMode,
1434     },
1435     {
1436       description: 'input[type=password][style="ime-mode: normal;"]',
1437       createElement: aDocument => {
1438         const element = aDocument.createElement("input");
1439         element.setAttribute("type", "password");
1440         element.setAttribute("style", "ime-mode: normal;");
1441         return element;
1442       },
1443       isFocusable:
1444         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1445       focusEventIsExpected: () => true,
1446       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1447     },
1448     {
1449       description: 'input[type=password][style="ime-mode: active;"]',
1450       createElement: aDocument => {
1451         const element = aDocument.createElement("input");
1452         element.setAttribute("type", "password");
1453         element.setAttribute("style", "ime-mode: active;");
1454         return element;
1455       },
1456       isFocusable:
1457         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1458       focusEventIsExpected: () => true,
1459       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1460       expectedOpenState: true,
1461     },
1462     {
1463       description: 'input[type=password][style="ime-mode: inactive;"]',
1464       createElement: aDocument => {
1465         const element = aDocument.createElement("input");
1466         element.setAttribute("type", "password");
1467         element.setAttribute("style", "ime-mode: inactive;");
1468         return element;
1469       },
1470       isFocusable:
1471         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1472       focusEventIsExpected: () => true,
1473       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1474       expectedOpenState: false,
1475     },
1476     {
1477       description: 'input[type=password][style="ime-mode: disabled;"]',
1478       createElement: aDocument => {
1479         const element = aDocument.createElement("input");
1480         element.setAttribute("type", "password");
1481         element.setAttribute("style", "ime-mode: disabled;");
1482         return element;
1483       },
1484       isFocusable:
1485         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1486       focusEventIsExpected: () => true,
1487       expectedEnabledValue:
1488         IMEStateOnFocusMoveTester.#IMEStatePasswordIfNotInDesignMode,
1489     },
1490     {
1491       description: 'textarea[style="ime-mode: auto;"]',
1492       createElement: aDocument => {
1493         const element = aDocument.createElement("textarea");
1494         element.setAttribute("style", "ime-mode: auto;");
1495         return element;
1496       },
1497       isFocusable:
1498         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1499       focusEventIsExpected: () => true,
1500       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1501     },
1502     {
1503       description: 'textarea[style="ime-mode: normal;"]',
1504       createElement: aDocument => {
1505         const element = aDocument.createElement("textarea");
1506         element.setAttribute("style", "ime-mode: normal;");
1507         return element;
1508       },
1509       isFocusable:
1510         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1511       focusEventIsExpected: () => true,
1512       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1513     },
1514     {
1515       description: 'textarea[style="ime-mode: active;"]',
1516       createElement: aDocument => {
1517         const element = aDocument.createElement("textarea");
1518         element.setAttribute("style", "ime-mode: active;");
1519         return element;
1520       },
1521       isFocusable:
1522         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1523       focusEventIsExpected: () => true,
1524       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1525       expectedOpenState: true,
1526     },
1527     {
1528       description: 'textarea[style="ime-mode: inactive;"]',
1529       createElement: aDocument => {
1530         const element = aDocument.createElement("textarea");
1531         element.setAttribute("style", "ime-mode: inactive;");
1532         return element;
1533       },
1534       isFocusable:
1535         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1536       focusEventIsExpected: () => true,
1537       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1538       expectedOpenState: false,
1539     },
1540     {
1541       description: 'textarea[style="ime-mode: disabled;"]',
1542       createElement: aDocument => {
1543         const element = aDocument.createElement("textarea");
1544         element.setAttribute("style", "ime-mode: disabled;");
1545         return element;
1546       },
1547       isFocusable:
1548         IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
1549       focusEventIsExpected: () => true,
1550       expectedEnabledValue:
1551         IMEStateOnFocusMoveTester.#IMEStatePasswordIfNotInDesignMode,
1552     },
1554     // HTML editors
1555     {
1556       description: 'div[contenteditable="true"]',
1557       createElement: aDocument => {
1558         const div = aDocument.createElement("div");
1559         div.setAttribute("contenteditable", "");
1560         return div;
1561       },
1562       isNewElementEditingHost: true,
1563       isFocusable: IMEStateOnFocusMoveTester.#elementIsFocusableIfEditingHost,
1564       focusEventIsExpected: () => true,
1565       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1566     },
1567     {
1568       description: "designMode editor",
1569       createElement: aDocument => {
1570         const iframe = aDocument.createElement("iframe");
1571         iframe.srcdoc = "<!doctype html><html><body></body></html>";
1572         iframe.addEventListener(
1573           "load",
1574           () => (iframe.contentDocument.designMode = "on"),
1575           { capture: true, once: true }
1576         );
1577         return iframe;
1578       },
1579       isFocusable: () => true,
1580       focusEventIsExpected: () => true,
1581       expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
1582     },
1583   ];
1585   static get numberOfTests() {
1586     return IMEStateOnFocusMoveTester.#sTestList.length;
1587   }