Backed out changeset 2450366cf7ca (bug 1891629) for causing win msix mochitest failures
[gecko.git] / widget / tests / file_test_ime_state_on_readonly_change.js
blobaf21f538ba0bb4046f36b3513752d15050b7d481
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 IMEStateOnReadonlyChangeTester {
9   static #sTextControlTypes = [
10     {
11       description: "<input>",
12       createElement: aDoc => aDoc.createElement("input"),
13       expectedIMEState: SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED,
14     },
15     {
16       description: `<input type="text">`,
17       createElement: aDoc => {
18         const input = aDoc.createElement("input");
19         input.setAttribute("type", "text");
20         return input;
21       },
22       expectedIMEState: SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED,
23     },
24     {
25       description: `<input type="password">`,
26       createElement: aDoc => {
27         const input = aDoc.createElement("input");
28         input.setAttribute("type", "password");
29         return input;
30       },
31       expectedIMEState: SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_PASSWORD,
32     },
33     {
34       description: `<input type="url">`,
35       createElement: aDoc => {
36         const input = aDoc.createElement("input");
37         input.setAttribute("type", "url");
38         return input;
39       },
40       expectedIMEState: SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED,
41     },
42     {
43       description: `<input type="email">`,
44       createElement: aDoc => {
45         const input = aDoc.createElement("input");
46         input.setAttribute("type", "email");
47         return input;
48       },
49       expectedIMEState: SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED,
50     },
51     {
52       description: `<input type="search">`,
53       createElement: aDoc => {
54         const input = aDoc.createElement("input");
55         input.setAttribute("type", "search");
56         return input;
57       },
58       expectedIMEState: SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED,
59     },
60     {
61       description: `<input type="tel">`,
62       createElement: aDoc => {
63         const input = aDoc.createElement("input");
64         input.setAttribute("type", "tel");
65         return input;
66       },
67       expectedIMEState: SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED,
68     },
69     {
70       description: `<input type="number">`,
71       createElement: aDoc => {
72         const input = aDoc.createElement("input");
73         input.setAttribute("type", "number");
74         return input;
75       },
76       expectedIMEState: SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED,
77     },
78     {
79       description: `<textarea></textarea>`,
80       createElement: aDoc => aDoc.createElement("textarea"),
81       expectedIMEState: SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED,
82     },
83   ];
85   static get numberOfTextControlTypes() {
86     return IMEStateOnReadonlyChangeTester.#sTextControlTypes.length;
87   }
89   // Only runner fields
90   #mTextControl;
91   #mTextControlElement;
92   #mWindow;
94   // Only checker fields
95   #mWindowUtils;
96   #mTIPWrapper;
98   clear() {
99     this.#mTextControlElement?.remove();
100     this.#mTIPWrapper?.clearFocusBlurNotifications();
101     this.#mTIPWrapper = null;
102   }
104   #flushPendingIMENotifications() {
105     return new Promise(resolve =>
106       this.#mWindow.requestAnimationFrame(() =>
107         this.#mWindow.requestAnimationFrame(resolve)
108       )
109     );
110   }
112   /**
113    * @param {number} aIndex The index of text control types.
114    * @param {Window} aWindow The window running tests.
115    * @param {Element} aContainer The element which should have new <input> or <textarea>.
116    * @returns {object} Expected data before running tests.
117    */
118   async prepareToRun(aIndex, aWindow, aContainer) {
119     this.#mWindow = aWindow;
120     this.#mTextControl =
121       IMEStateOnReadonlyChangeTester.#sTextControlTypes[aIndex];
123     if (aContainer.ownerDocument.activeElement) {
124       aContainer.ownerDocument.activeElement.blur();
125       await this.#flushPendingIMENotifications();
126     }
127     if (this.#mTextControlElement?.isConnected) {
128       this.#mTextControlElement.remove();
129     }
130     this.#mTextControlElement = this.#mTextControl.createElement(
131       aContainer.ownerDocument
132     );
134     const waitForFocus = new Promise(resolve =>
135       this.#mTextControlElement.addEventListener("focus", resolve, {
136         once: true,
137       })
138     );
139     aContainer.appendChild(this.#mTextControlElement);
140     this.#mTextControlElement.focus();
141     await waitForFocus;
143     await this.#flushPendingIMENotifications();
145     return {
146       description: this.#mTextControl.description,
147       expectedIMEState: this.#mTextControl.expectedIMEState,
148       expectedIMEFocus: true,
149     };
150   }
152   /**
153    * @param {object} aExpectedData The expected data which was returned by prepareToRun().
154    * @param {TIPWrapper} aTIPWrapper TIP wrapper in aWindow.
155    * @param {Window} aWindow [optional] The window object of which you want to check IME state.
156    */
157   checkBeforeRun(aExpectedData, aTIPWrapper, aWindow = window) {
158     this.#mWindowUtils = SpecialPowers.wrap(aWindow).windowUtils;
159     this.#mTIPWrapper = aTIPWrapper;
160     const description = `IMEStateOnReadonlyChangeTester(${aExpectedData.description})`;
161     is(
162       this.#mWindowUtils.IMEStatus,
163       aExpectedData.expectedIMEState,
164       `${description}: IME state should be set to expected value before setting readonly attribute`
165     );
166     is(
167       this.#mTIPWrapper.IMEHasFocus,
168       aExpectedData.expectedIMEFocus,
169       `${description}: IME state should ${
170         aExpectedData.expectedIMEFocus ? "" : "not"
171       } have focus before setting readonly attribute`
172     );
173   }
175   /**
176    * @returns {object} Expected result.
177    */
178   async runToMakeTextControlReadonly() {
179     this.#mTextControlElement.setAttribute("readonly", "");
181     await this.#flushPendingIMENotifications();
183     return {
184       description: this.#mTextControl.description,
185       expectedIMEState: SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED,
186       expectedIMEFocus: false,
187     };
188   }
190   /**
191    * @param {object} aExpectedData Expected result which is returned by runToMakeTextControlReadonly().
192    */
193   checkResultOfMakingTextControlReadonly(aExpectedData) {
194     const description = `IMEStateOnReadonlyChangeTester(${aExpectedData.description})`;
195     is(
196       this.#mWindowUtils.IMEStatus,
197       aExpectedData.expectedIMEState,
198       `${description}: IME state should be set to expected value after setting readonly attribute`
199     );
200     is(
201       this.#mTIPWrapper.IMEHasFocus,
202       aExpectedData.expectedIMEFocus,
203       `${description}: IME state should ${
204         aExpectedData.expectedIMEFocus ? "" : "not"
205       } have focus after setting readonly attribute`
206     );
207   }
209   /**
210    * @returns {object} Expected result.
211    */
212   async runToMakeTextControlEditable() {
213     this.#mTextControlElement.removeAttribute("readonly");
215     await this.#flushPendingIMENotifications();
217     return {
218       description: this.#mTextControl.description,
219       expectedIMEState: this.#mTextControl.expectedIMEState,
220       expectedIMEFocus: true,
221     };
222   }
224   /**
225    * @param {object} aExpectedData Expected result which is returned by runToMakeTextControlEditable().
226    */
227   checkResultOfMakingTextControlEditable(aExpectedData) {
228     const description = `IMEStateOnReadonlyChangeTester(${aExpectedData.description})`;
229     is(
230       this.#mWindowUtils.IMEStatus,
231       aExpectedData.expectedIMEState,
232       `${description}: IME state should be set to expected value after removing readonly attribute`
233     );
234     is(
235       this.#mTIPWrapper.IMEHasFocus,
236       aExpectedData.expectedIMEFocus,
237       `${description}: IME state should ${
238         aExpectedData.expectedIMEFocus ? "" : "not"
239       } have focus after removing readonly attribute`
240     );
241   }