1 /* Any copyright is dedicated to the Public Domain.
2 http://creativecommons.org/publicdomain/zero/1.0/ */
6 /* import-globals-from file_ime_state_test_helper.js */
8 // Bug 580388 and bug 808287
9 class IMEStateInTextControlOnReframeTester {
10 static #sTextControls = [
24 static get numberOfTextControlTypes() {
25 return IMEStateInTextControlOnReframeTester.#sTextControls.length;
29 const textControl = this.#mDocument.createElement(this.#mTextControl.tag);
30 if (this.#mTextControl.type !== undefined) {
31 textControl.setAttribute("type", this.#mTextControl.type);
37 return `<${this.#mTextControl.tag}${
38 this.#mTextControl.type !== undefined
39 ? ` type=${this.#mTextControl.type}`
44 #getExpectedIMEState() {
45 return this.#mTextControl.type == "password"
46 ? SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_PASSWORD
47 : SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED;
50 #flushPendingIMENotifications() {
51 return new Promise(resolve =>
52 this.#mWindow.requestAnimationFrame(() =>
53 this.#mWindow.requestAnimationFrame(resolve)
58 // Runner only fields.
64 // Checker only fields.
69 this.#mTIPWrapper?.clearFocusBlurNotifications();
70 this.#mTIPWrapper = null;
74 * @param {number} aIndex Index of the test.
75 * @param {Element} aDocument The document to run the test.
76 * @param {Window} aWindow [optional] The DOM window for aDocument.
77 * @returns {object} Expected result of initial state.
79 async prepareToRun(aIndex, aDocument, aWindow = window) {
80 this.#mWindow = aWindow;
81 this.#mDocument = aDocument;
82 this.#mDocument.activeElement?.blur();
83 this.#mTextControlElement?.remove();
84 await this.#flushPendingIMENotifications();
86 IMEStateInTextControlOnReframeTester.#sTextControls[aIndex];
87 this.#mTextControlElement = this.#createElement();
88 this.#mDocument.body.appendChild(this.#mTextControlElement);
89 this.#mTextControlElement.focus();
90 this.#mTextControlElement.style.overflow = "visible";
91 this.#mTextControlElement.addEventListener(
94 aEvent.target.style.overflow = "hidden";
100 await this.#flushPendingIMENotifications();
101 const expectedIMEState = this.#getExpectedIMEState();
103 description: `when ${this.#getDescription()} has focus`,
107 SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED,
108 expectedNumberOfFocusNotifications: 1,
112 #checkResult(aExpectedResult) {
113 const description = "IMEStateInTextControlOnReframeTester";
115 this.#mWindowUtils.IMEStatus,
116 aExpectedResult.expectedIMEState,
117 `${description}: IME state should be proper one for the text control ${aExpectedResult.description}`
120 this.#mTIPWrapper.IMEHasFocus,
121 aExpectedResult.expectedIMEFocus,
122 `${description}: IME should ${
123 aExpectedResult.expectedIMEFocus ? "" : "not "
124 }have focus ${aExpectedResult.description}`
126 if (aExpectedResult.numberOfFocusNotifications !== undefined) {
128 this.#mTIPWrapper.numberOfFocusNotifications,
129 aExpectedResult.numberOfFocusNotifications,
130 `${description}: focus notifications should've been received ${
131 this.#mTIPWrapper.numberOfFocusNotifications
132 } times ${aExpectedResult.description}`
135 if (aExpectedResult.numberOfBlurNotifications !== undefined) {
137 this.#mTIPWrapper.numberOfBlurNotifications,
138 aExpectedResult.numberOfBlurNotifications,
139 `${description}: blur notifications should've been received ${
140 this.#mTIPWrapper.numberOfBlurNotifications
141 } times ${aExpectedResult.description}`
147 * @param {object} aExpectedResult The expected result returned by prepareToRun().
148 * @param {Window} aWindow The window whose IME state should be checked.
149 * @param {TIPWrapper} aTIPWrapper The TIP wrapper of aWindow.
151 checkResultAfterTypingA(aExpectedResult, aWindow, aTIPWrapper) {
152 this.#mWindowUtils = SpecialPowers.wrap(aWindow).windowUtils;
153 this.#mTIPWrapper = aTIPWrapper;
154 this.#checkResult(aExpectedResult);
156 this.#mTIPWrapper.clearFocusBlurNotifications();
159 async prepareToRun2() {
160 this.#mTextControlElement.addEventListener("focus", aEvent => {
161 // Perform a style change and flush it to trigger reframing.
162 aEvent.target.style.overflow = "visible";
163 aEvent.target.getBoundingClientRect();
165 this.#mTextControlElement.blur();
166 this.#mTextControlElement.focus();
168 await this.#flushPendingIMENotifications();
170 const expectedIMEState = this.#getExpectedIMEState();
172 description: `when ${this.#getDescription()} is reframed by focus event listener`,
176 SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED,
177 expectedNumberOfFocusNotifications: 1,
178 expectedNumberOfBlurNotifications: 1,
183 * @param {object} aExpectedResult The expected result returned by prepareToRun().
185 checkResultAfterTypingA2(aExpectedResult) {
186 this.#checkResult(aExpectedResult);
188 this.#mTIPWrapper.clearFocusBlurNotifications();