summaryrefslogtreecommitdiffstats
path: root/widget/tests/file_test_ime_state_on_focus_move.js
diff options
context:
space:
mode:
Diffstat (limited to 'widget/tests/file_test_ime_state_on_focus_move.js')
-rw-r--r--widget/tests/file_test_ime_state_on_focus_move.js1588
1 files changed, 1588 insertions, 0 deletions
diff --git a/widget/tests/file_test_ime_state_on_focus_move.js b/widget/tests/file_test_ime_state_on_focus_move.js
new file mode 100644
index 0000000000..f7760d8a09
--- /dev/null
+++ b/widget/tests/file_test_ime_state_on_focus_move.js
@@ -0,0 +1,1588 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/* import-globals-from file_ime_state_test_helper.js */
+
+class IMEStateWhenNoActiveElementTester {
+ #mDescription;
+
+ constructor(aDescription) {
+ this.#mDescription = aDescription;
+ }
+
+ async run(aDocument, aWindow = window) {
+ aWindow.focus();
+ aDocument.activeElement?.blur();
+
+ await new Promise(resolve =>
+ requestAnimationFrame(() => requestAnimationFrame(resolve))
+ ); // wait for sending IME notifications
+
+ return { designModeValue: aDocument.designMode };
+ }
+
+ check(aExpectedData, aWindow = window) {
+ const winUtils = SpecialPowers.wrap(aWindow).windowUtils;
+ if (aExpectedData.designModeValue == "on") {
+ is(
+ winUtils.IMEStatus,
+ SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED,
+ `IMEStateWhenNoActiveElementTester(${
+ this.#mDescription
+ }): When no element has focus, IME should stay enabled in design mode`
+ );
+ } else {
+ is(
+ winUtils.IMEStatus,
+ SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED,
+ `IMEStateWhenNoActiveElementTester(${
+ this.#mDescription
+ }): When no element has focus, IME should be disabled`
+ );
+ }
+ }
+}
+
+class IMEStateOnFocusMoveTester {
+ // Common fields
+ #mDescription;
+ #mTest;
+ #mWindow;
+ #mWindowUtils;
+
+ // Only runner fields
+ #mCreatedElement;
+ #mCreatedElementForPreviousFocusedElement;
+ #mElementToSetFocus;
+ #mContainerIsEditable;
+
+ // Only checker fields
+ #mTIPWrapper;
+
+ constructor(aDescription, aIndex, aWindow = window) {
+ this.#mTest = IMEStateOnFocusMoveTester.#sTestList[aIndex];
+ this.#mDescription = `IMEStateOnFocusMoveTester(${aDescription}): ${
+ this.#mTest.description
+ }`;
+ this.#mWindow = aWindow;
+ this.#mWindowUtils = SpecialPowers.wrap(this.#mWindow).windowUtils;
+ }
+
+ /**
+ * prepareToRun should be called before run only in the process which will run the test.
+ */
+ async prepareToRun(aContainer) {
+ const doc = aContainer.ownerDocument;
+ this.#mTest = this.#resolveTest(this.#mTest, aContainer);
+ this.#mContainerIsEditable = nodeIsEditable(aContainer);
+ this.#mCreatedElement = this.#mTest.createElement(doc);
+ const waitForLoadIfIFrame = new Promise(resolve => {
+ if (this.#mCreatedElement.tagName == "IFRAME") {
+ this.#mCreatedElement.addEventListener("load", resolve, {
+ capture: true,
+ once: true,
+ });
+ } else {
+ resolve();
+ }
+ });
+ aContainer.appendChild(this.#mCreatedElement);
+ await waitForLoadIfIFrame;
+ this.#mElementToSetFocus = this.#mCreatedElement.contentDocument
+ ? this.#mCreatedElement.contentDocument.documentElement
+ : this.#mCreatedElement;
+ if (doc.designMode == "on") {
+ doc.activeElement?.blur();
+ } else if (this.#mContainerIsEditable) {
+ getEditingHost(aContainer).focus(); // FIXME: use editing host instead
+ } else {
+ this.#mCreatedElementForPreviousFocusedElement =
+ doc.createElement("input");
+ this.#mCreatedElementForPreviousFocusedElement.setAttribute(
+ "type",
+ this.#mTest.expectedEnabledValue ==
+ SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED
+ ? "password"
+ : "text"
+ );
+ aContainer.appendChild(this.#mCreatedElementForPreviousFocusedElement);
+ this.#mCreatedElementForPreviousFocusedElement.focus();
+ }
+
+ await new Promise(resolve =>
+ requestAnimationFrame(() => requestAnimationFrame(resolve))
+ ); // wait for sending IME notifications
+
+ return {
+ designModeValue: doc.designMode,
+ containerIsEditable: this.#mContainerIsEditable,
+ isFocusable: this.#mTest.isFocusable,
+ focusEventFired: this.#mTest.focusEventIsExpected,
+ enabledValue: this.#mTest.expectedEnabledValue,
+ testedSubDocumentInDesignMode:
+ this.#mCreatedElement.contentDocument?.designMode == "on",
+ };
+ }
+
+ /**
+ * prepareToCheck should be called before calling run only in the process which will check the result.
+ */
+ prepareToCheck(aExpectedData, aTIPWrapper) {
+ info(`Starting ${this.#mDescription} (enable state check)...`);
+ this.#mTIPWrapper = aTIPWrapper;
+ this.#mTIPWrapper.onIMEFocusBlur = aNotificationType => {
+ switch (aNotificationType) {
+ case "notify-focus":
+ info(aNotificationType);
+ is(
+ this.#mWindowUtils.IMEStatus,
+ aExpectedData.enabledValue,
+ `${
+ this.#mDescription
+ }, IME should receive a focus notification after IME state is updated`
+ );
+ break;
+ case "notify-blur":
+ info(aNotificationType);
+ const changingStatus = !(
+ aExpectedData.containerIsEditable &&
+ aExpectedData.enabledValue ==
+ SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED
+ );
+ if (aExpectedData.designModeValue == "on") {
+ is(
+ // FIXME: This is odd, but #mWindowUtils.IMEStatus sometimes IME_STATUS_PASSWORD
+ SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED,
+ aExpectedData.enabledValue,
+ `${
+ this.#mDescription
+ }, IME should receive a blur notification after IME state is updated`
+ );
+ } else if (changingStatus) {
+ isnot(
+ this.#mWindowUtils.IMEStatus,
+ aExpectedData.enabledValue,
+ `${
+ this.#mDescription
+ }, IME should receive a blur notification BEFORE IME state is updated`
+ );
+ } else {
+ is(
+ this.#mWindowUtils.IMEStatus,
+ aExpectedData.enabledValue,
+ `${
+ this.#mDescription
+ }, IME should receive a blur notification and its context has expected IME state if the state isn't being changed`
+ );
+ }
+ break;
+ }
+ };
+
+ this.#mTIPWrapper.clearFocusBlurNotifications();
+ }
+
+ /**
+ * @returns {bool} whether expected element has focus or not after moving focus.
+ */
+ async run() {
+ const previousFocusedElement = getFocusedElementOrUAWidgetHost();
+ if (this.#mTest.setFocusIntoUAWidget) {
+ this.#mTest.setFocusIntoUAWidget(this.#mElementToSetFocus);
+ } else {
+ this.#mElementToSetFocus.focus();
+ }
+
+ await new Promise(resolve =>
+ requestAnimationFrame(() => requestAnimationFrame(resolve))
+ ); // wait for sending IME notifications
+
+ const currentFocusedElement = getFocusedElementOrUAWidgetHost();
+ this.#mCreatedElementForPreviousFocusedElement?.remove();
+ if (this.#mTest.isFocusable) {
+ return this.#mElementToSetFocus == currentFocusedElement;
+ }
+ return previousFocusedElement == currentFocusedElement;
+ }
+
+ check(aExpectedData) {
+ this.#mTIPWrapper.onIMEFocusBlur = null;
+
+ if (aExpectedData.isFocusable) {
+ if (aExpectedData.focusEventFired) {
+ if (
+ aExpectedData.enabledValue ==
+ SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED ||
+ aExpectedData.enabledValue ==
+ SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_PASSWORD
+ ) {
+ ok(
+ this.#mTIPWrapper.numberOfFocusNotifications > 0,
+ `${this.#mDescription}, IME should receive a focus notification`
+ );
+ if (
+ aExpectedData.designModeValue == "on" &&
+ !aExpectedData.testedSubDocumentInDesignMode
+ ) {
+ is(
+ this.#mTIPWrapper.numberOfBlurNotifications,
+ 0,
+ `${
+ this.#mDescription
+ }, IME shouldn't receive a blur notification in designMode since focus isn't moved from another editor`
+ );
+ } else {
+ ok(
+ this.#mTIPWrapper.numberOfBlurNotifications > 0,
+ `${
+ this.#mDescription
+ }, IME should receive a blur notification for the previous focused editor`
+ );
+ }
+ ok(
+ this.#mTIPWrapper.IMEHasFocus,
+ `${this.#mDescription}, IME should have focus right now`
+ );
+ } else {
+ is(
+ this.#mTIPWrapper.numberOfFocusNotifications,
+ 0,
+ `${this.#mDescription}, IME shouldn't receive a focus notification`
+ );
+ ok(
+ this.#mTIPWrapper.numberOfBlurNotifications > 0,
+ `${this.#mDescription}, IME should receive a blur notification`
+ );
+ ok(
+ !this.#mTIPWrapper.IMEHasFocus,
+ `${this.#mDescription}, IME shouldn't have focus right now`
+ );
+ }
+ } else {
+ ok(true, `${this.#mDescription}, focus event should be fired`);
+ }
+ } else {
+ is(
+ this.#mTIPWrapper.numberOfFocusNotifications,
+ 0,
+ `${
+ this.#mDescription
+ }, IME shouldn't receive a focus notification at testing non-focusable element`
+ );
+ is(
+ this.#mTIPWrapper.numberOfBlurNotifications,
+ 0,
+ `${
+ this.#mDescription
+ }, IME shouldn't receive a blur notification at testing non-focusable element`
+ );
+ }
+
+ is(
+ this.#mWindowUtils.IMEStatus,
+ aExpectedData.enabledValue,
+ `${this.#mDescription}, wrong enabled state`
+ );
+ if (
+ this.#mTest.expectedInputElementType &&
+ aExpectedData.designModeValue != "on"
+ ) {
+ is(
+ this.#mWindowUtils.focusedInputType,
+ this.#mTest.expectedInputElementType,
+ `${this.#mDescription}, wrong input type`
+ );
+ } else if (aExpectedData.designModeValue == "on") {
+ is(
+ this.#mWindowUtils.focusedInputType,
+ "",
+ `${this.#mDescription}, wrong input type`
+ );
+ }
+ }
+
+ destroy() {
+ this.#mCreatedElement?.remove();
+ this.#mCreatedElementForPreviousFocusedElement?.remove();
+ this.#mTIPWrapper?.clearFocusBlurNotifications();
+ this.#mTIPWrapper = null;
+ }
+
+ /**
+ * Open/Close state test check
+ * Note that these tests are not run now.
+ * If these tests should run between `run` and `cleanUp` call of the above
+ * tests.
+ */
+ canTestOpenCloseState(aExpectedData) {
+ return (
+ IsIMEOpenStateSupported() &&
+ this.#mWindowUtils.IMEStatus ==
+ SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED &&
+ aExpectedData.enabledValue ==
+ SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED
+ );
+ }
+ async prepareToRunOpenCloseTest(aContainer) {
+ const doc = aContainer.ownerDocument;
+ this.#mCreatedElementForPreviousFocusedElement?.remove();
+ this.#mCreatedElementForPreviousFocusedElement = doc.createElement("input");
+ this.#mCreatedElementForPreviousFocusedElement.setAttribute("type", "text");
+ aContainer.appendChild(this.#mCreatedElementForPreviousFocusedElement);
+
+ this.#mContainerIsEditable = nodeIsEditable(aContainer);
+ this.#mCreatedElement = this.#mTest.createElement(doc);
+ const waitForLoadIfIFrame = new Promise(resolve => {
+ if (this.#mCreatedElement.tagName == "IFRAME") {
+ this.#mCreatedElement.addEventListener("load", resolve, {
+ capture: true,
+ once: true,
+ });
+ } else {
+ resolve();
+ }
+ });
+ aContainer.appendChild(this.#mCreatedElement);
+ await waitForLoadIfIFrame;
+ this.#mElementToSetFocus = this.#mCreatedElement.contentDocument
+ ? this.#mCreatedElement.contentDocument.documentElement
+ : this.#mCreatedElement;
+
+ this.#mCreatedElementForPreviousFocusedElement.focus();
+
+ return {};
+ }
+ prepareToCheckOpenCloseTest(aPreviousOpenState, aExpectedData) {
+ info(`Starting ${this.#mDescription} (open/close state check)...`);
+ this.#mWindowUtils.IMEIsOpen = aPreviousOpenState;
+ aExpectedData.defaultOpenState = this.#mWindowUtils.IMEIsOpen;
+ }
+ async runOpenCloseTest() {
+ return this.run();
+ }
+ checkOpenCloseTest(aExpectedData) {
+ const expectedOpenState =
+ this.#mTest.expectedOpenState != undefined
+ ? this.#mTest.expectedOpenState
+ : aExpectedData.defaultOpenState;
+ is(
+ this.#mWindowUtils.IMEIsOpen,
+ expectedOpenState,
+ `${this.#mDescription}, IME should ${
+ expectedOpenState != aExpectedData.defaultOpenState ? "become" : "keep"
+ } ${expectedOpenState ? "open" : "closed"}`
+ );
+ }
+
+ /**
+ * Utility methods for defining kIMEStateTestList.
+ */
+
+ /**
+ * @param {Element} aElement
+ */
+ static #elementIsConnectedAndNotInDesignMode(aElement) {
+ return aElement.isConnected && !nodeIsInDesignMode(aElement);
+ }
+
+ /**
+ * @param {Element} aElementContainer
+ * @param {bool} aElementIsEditingHost
+ */
+ static #elementIsFocusableIfEditingHost(
+ aElementContainer,
+ aElementIsEditingHost
+ ) {
+ return !nodeIsEditable(aElementContainer) && aElementIsEditingHost;
+ }
+
+ static #IMEStateEnabledAlways() {
+ return SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED;
+ }
+
+ /**
+ * @param {Element} aElement
+ * @param {bool} aElementIsEditingHost
+ */
+ static #IMEStateEnabledIfEditable(aElement, aElementIsEditingHost) {
+ return nodeIsEditable(aElement) || aElementIsEditingHost
+ ? SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED
+ : SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED;
+ }
+
+ /**
+ * @param {Element} aElement
+ */
+ static #IMEStateEnabledIfInDesignMode(aElement) {
+ return IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode(
+ aElement
+ )
+ ? SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED
+ : SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED;
+ }
+
+ /**
+ * @param {Element} aElement
+ */
+ static #IMEStatePasswordIfNotInDesignMode(aElement) {
+ return IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode(
+ aElement
+ )
+ ? SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_PASSWORD
+ : SpecialPowers.Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED;
+ }
+
+ /**
+ * @param {Element} aElement
+ */
+ static #elementIsConnectedAndNotEditable(aElement) {
+ return aElement.isConnected && !nodeIsEditable(aElement);
+ }
+
+ /**
+ * @param {Element} aElementContainer
+ */
+ static #focusEventIsExpectedUnlessEditableChild(aElementContainer) {
+ return !nodeIsEditable(aElementContainer);
+ }
+
+ // Form controls except text editable elements are "disable" in normal
+ // condition, however, if they are editable, they are "enabled".
+ // XXX Probably there are some bugs: If the form controls editable, they
+ // shouldn't be focusable.
+ #resolveTest(aTest, aContainer) {
+ const isFocusable = aTest.isFocusable(
+ aContainer,
+ aTest.isNewElementEditingHost
+ );
+ return {
+ // Description of the new element
+ description: aTest.description,
+ // Create element to check IME state
+ createElement: aTest.createElement,
+ // Whether the new element is an editing host if container is not editable
+ isNewElementEditingHost: aTest.isNewElementEditingHost,
+ // If the test wants to move focus into an element in UA widget, define
+ // this and set focus in it.
+ setFocusIntoUAWidget: aTest.setFocusIntoUAWidget,
+ // Whether the element is focusable or not
+ isFocusable,
+ // Whether focus events are fired on the element if it's focusable
+ focusEventIsExpected:
+ isFocusable &&
+ aTest.focusEventIsExpected(aContainer, aTest.isNewElementEditingHost),
+ // Expected IME enabled state when the element has focus
+ expectedEnabledValue: aTest.expectedEnabledValue(
+ aContainer,
+ aTest.isNewElementEditingHost
+ ),
+ // Expected IME open state when the element gets focus
+ // "undefined" means that IME open state should not be changed
+ expectedOpenState: aTest.expectedOpenState,
+ // Expected type of input element if it's an <input>
+ expectedInputElementType: aTest.expectedInputElementType,
+ };
+ }
+ static #sTestList = [
+ {
+ description: "input[type=text]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "text");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ expectedInputElementType: "text",
+ },
+ {
+ description: "input[type=text][readonly]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "text");
+ element.setAttribute("readonly", "");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
+ },
+ {
+ description: "input[type=password]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "password");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStatePasswordIfNotInDesignMode,
+ expectedInputElementType: "password",
+ },
+ {
+ description: "input[type=password][readonly]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "password");
+ element.setAttribute("readonly", "");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
+ },
+ {
+ description: "input[type=checkbox]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "checkbox");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected:
+ IMEStateOnFocusMoveTester.#focusEventIsExpectedUnlessEditableChild,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
+ },
+ {
+ description: "input[type=radio]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "radio");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected:
+ IMEStateOnFocusMoveTester.#focusEventIsExpectedUnlessEditableChild,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
+ },
+ {
+ description: "input[type=submit]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "submit");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
+ },
+ {
+ description: "input[type=reset]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "reset");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
+ },
+ {
+ description: "input[type=file]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "file");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected:
+ IMEStateOnFocusMoveTester.#focusEventIsExpectedUnlessEditableChild,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
+ },
+ {
+ description: "input[type=button]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "button");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
+ },
+ {
+ description: "input[type=image]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "image");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
+ },
+ {
+ description: "input[type=url]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "url");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ expectedInputElementType: "url",
+ },
+ {
+ description: "input[type=email]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "email");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ expectedInputElementType: "email",
+ },
+ {
+ description: "input[type=search]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "search");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ expectedInputElementType: "search",
+ },
+ {
+ description: "input[type=tel]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "tel");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ expectedInputElementType: "tel",
+ },
+ {
+ description: "input[type=number]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "number");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ expectedInputElementType: "number",
+ },
+ {
+ description: "input[type=date]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "date");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
+ expectedInputElementType: "date",
+ },
+ {
+ description: "input[type=datetime-local]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "datetime-local");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
+ expectedInputElementType: "datetime-local",
+ },
+ {
+ description: "input[type=time]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "time");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
+ expectedInputElementType: "time",
+ },
+ // TODO(bug 1283382, bug 1283382): month and week
+
+ // form controls
+ {
+ description: "button",
+ createElement: aDocument => aDocument.createElement("button"),
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
+ },
+ {
+ description: "textarea",
+ createElement: aDocument => aDocument.createElement("textarea"),
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ },
+ {
+ description: "textarea[readonly]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("textarea");
+ element.setAttribute("readonly", "");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
+ },
+ {
+ description: "select (dropdown list)",
+ createElement: aDocument => {
+ const select = aDocument.createElement("select");
+ const option1 = aDocument.createElement("option");
+ option1.textContent = "abc";
+ const option2 = aDocument.createElement("option");
+ option2.textContent = "def";
+ const option3 = aDocument.createElement("option");
+ option3.textContent = "ghi";
+ select.appendChild(option1);
+ select.appendChild(option2);
+ select.appendChild(option3);
+ return select;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected:
+ IMEStateOnFocusMoveTester.#focusEventIsExpectedUnlessEditableChild,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
+ },
+ {
+ description: "select (list box)",
+ createElement: aDocument => {
+ const select = aDocument.createElement("select");
+ select.setAttribute("multiple", "multiple");
+ const option1 = aDocument.createElement("option");
+ option1.textContent = "abc";
+ const option2 = aDocument.createElement("option");
+ option2.textContent = "def";
+ const option3 = aDocument.createElement("option");
+ option3.textContent = "ghi";
+ select.appendChild(option1);
+ select.appendChild(option2);
+ select.appendChild(option3);
+ return select;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected:
+ IMEStateOnFocusMoveTester.#focusEventIsExpectedUnlessEditableChild,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
+ },
+
+ // a element
+ {
+ id: "a_href",
+ description: "a[href]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("a");
+ element.setAttribute("href", "about:blank");
+ return element;
+ },
+ isFocusable: IMEStateOnFocusMoveTester.#elementIsConnectedAndNotEditable,
+ focusEventIsExpected:
+ IMEStateOnFocusMoveTester.#focusEventIsExpectedUnlessEditableChild,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
+ },
+
+ // audio element
+ {
+ description: "audio[controls]",
+ createElement: aDocument => {
+ const element = aDocument.createElement("audio");
+ element.setAttribute("controls", "");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
+ },
+ {
+ description: "playButton in audio",
+ createElement: aDocument => {
+ const element = aDocument.createElement("audio");
+ element.setAttribute("controls", "");
+ return element;
+ },
+ setFocusIntoUAWidget: aElement =>
+ SpecialPowers.wrap(aElement)
+ .openOrClosedShadowRoot.getElementById("playButton")
+ .focus(),
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
+ },
+ {
+ description: "scrubber in audio",
+ createElement: aDocument => {
+ const element = aDocument.createElement("audio");
+ element.setAttribute("controls", "");
+ return element;
+ },
+ setFocusIntoUAWidget: aElement =>
+ SpecialPowers.wrap(aElement)
+ .openOrClosedShadowRoot.getElementById("scrubber")
+ .focus(),
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
+ },
+ {
+ description: "muteButton in audio",
+ createElement: aDocument => {
+ const element = aDocument.createElement("audio");
+ element.setAttribute("controls", "");
+ return element;
+ },
+ setFocusIntoUAWidget: aElement =>
+ SpecialPowers.wrap(aElement)
+ .openOrClosedShadowRoot.getElementById("muteButton")
+ .focus(),
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
+ },
+ {
+ description: "volumeControl in audio",
+ createElement: aDocument => {
+ const element = aDocument.createElement("audio");
+ element.setAttribute("controls", "");
+ return element;
+ },
+ setFocusIntoUAWidget: aElement =>
+ SpecialPowers.wrap(aElement)
+ .openOrClosedShadowRoot.getElementById("volumeControl")
+ .focus(),
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
+ },
+
+ // video element
+ {
+ description: "video",
+ createElement: aDocument => {
+ const element = aDocument.createElement("video");
+ element.setAttribute("controls", "");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfEditable,
+ },
+ {
+ description: "playButton in video",
+ createElement: aDocument => {
+ const element = aDocument.createElement("video");
+ element.setAttribute("controls", "");
+ return element;
+ },
+ setFocusIntoUAWidget: aElement =>
+ SpecialPowers.wrap(aElement)
+ .openOrClosedShadowRoot.getElementById("playButton")
+ .focus(),
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
+ },
+ {
+ description: "scrubber in video",
+ createElement: aDocument => {
+ const element = aDocument.createElement("video");
+ element.setAttribute("controls", "");
+ return element;
+ },
+ setFocusIntoUAWidget: aElement =>
+ SpecialPowers.wrap(aElement)
+ .openOrClosedShadowRoot.getElementById("scrubber")
+ .focus(),
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
+ },
+ {
+ description: "muteButton in video",
+ createElement: aDocument => {
+ const element = aDocument.createElement("video");
+ element.setAttribute("controls", "");
+ return element;
+ },
+ setFocusIntoUAWidget: aElement =>
+ SpecialPowers.wrap(aElement)
+ .openOrClosedShadowRoot.getElementById("muteButton")
+ .focus(),
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
+ },
+ {
+ description: "volumeControl in video",
+ createElement: aDocument => {
+ const element = aDocument.createElement("video");
+ element.setAttribute("controls", "");
+ return element;
+ },
+ setFocusIntoUAWidget: aElement =>
+ SpecialPowers.wrap(aElement)
+ .openOrClosedShadowRoot.getElementById("volumeControl")
+ .focus(),
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStateEnabledIfInDesignMode,
+ },
+
+ // ime-mode
+ {
+ description: 'input[type=text][style="ime-mode: auto;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "text");
+ element.setAttribute("style", "ime-mode: auto;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ },
+ {
+ description: 'input[type=text][style="ime-mode: normal;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "text");
+ element.setAttribute("style", "ime-mode: normal;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ },
+ {
+ description: 'input[type=text][style="ime-mode: active;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "text");
+ element.setAttribute("style", "ime-mode: active;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ expectedOpenState: true,
+ },
+ {
+ description: 'input[type=text][style="ime-mode: inactive;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "text");
+ element.setAttribute("style", "ime-mode: inactive;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ expectedOpenState: false,
+ },
+ {
+ description: 'input[type=text][style="ime-mode: disabled;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "text");
+ element.setAttribute("style", "ime-mode: disabled;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStatePasswordIfNotInDesignMode,
+ },
+
+ {
+ description: 'input[type=url][style="ime-mode: auto;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "url");
+ element.setAttribute("style", "ime-mode: auto;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ },
+ {
+ description: 'input[type=url][style="ime-mode: normal;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "url");
+ element.setAttribute("style", "ime-mode: normal;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ },
+ {
+ description: 'input[type=url][style="ime-mode: active;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "url");
+ element.setAttribute("style", "ime-mode: active;");
+ return element;
+ },
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedOpenState: true,
+ },
+ {
+ description: 'input[type=url][style="ime-mode: inactive;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "url");
+ element.setAttribute("style", "ime-mode: inactive;");
+ return element;
+ },
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedOpenState: false,
+ },
+ {
+ description: 'input[type=url][style="ime-mode: disabled;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "url");
+ element.setAttribute("style", "ime-mode: disabled;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStatePasswordIfNotInDesignMode,
+ },
+
+ {
+ description: 'input[type=email][style="ime-mode: auto;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "email");
+ element.setAttribute("style", "ime-mode: auto;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ },
+ {
+ description: 'input[type=email][style="ime-mode: normal;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "email");
+ element.setAttribute("style", "ime-mode: normal;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ },
+ {
+ description: 'input[type=email][style="ime-mode: active;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "email");
+ element.setAttribute("style", "ime-mode: active;");
+ return element;
+ },
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedOpenState: true,
+ },
+ {
+ description: 'input[type=email][style="ime-mode: inactive;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "email");
+ element.setAttribute("style", "ime-mode: inactive;");
+ return element;
+ },
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedOpenState: false,
+ },
+ {
+ description: 'input[type=email][style="ime-mode: disabled;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "email");
+ element.setAttribute("style", "ime-mode: disabled;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStatePasswordIfNotInDesignMode,
+ },
+
+ {
+ description: 'input[type=search][style="ime-mode: auto;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "search");
+ element.setAttribute("style", "ime-mode: auto;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ },
+ {
+ description: 'input[type=search][style="ime-mode: normal;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "search");
+ element.setAttribute("style", "ime-mode: normal;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ },
+ {
+ description: 'input[type=search][style="ime-mode: active;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "search");
+ element.setAttribute("style", "ime-mode: active;");
+ return element;
+ },
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedOpenState: true,
+ },
+ {
+ description: 'input[type=search][style="ime-mode: inactive;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "search");
+ element.setAttribute("style", "ime-mode: inactive;");
+ return element;
+ },
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedOpenState: false,
+ },
+ {
+ description: 'input[type=search][style="ime-mode: disabled;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "search");
+ element.setAttribute("style", "ime-mode: disabled;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStatePasswordIfNotInDesignMode,
+ },
+
+ {
+ description: 'input[type=tel][style="ime-mode: auto;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "tel");
+ element.setAttribute("style", "ime-mode: auto;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ },
+ {
+ description: 'input[type=tel][style="ime-mode: normal;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "tel");
+ element.setAttribute("style", "ime-mode: normal;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ },
+ {
+ description: 'input[type=tel][style="ime-mode: active;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "tel");
+ element.setAttribute("style", "ime-mode: active;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ expectedOpenState: true,
+ },
+ {
+ description: 'input[type=tel][style="ime-mode: inactive;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "tel");
+ element.setAttribute("style", "ime-mode: inactive;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ expectedOpenState: false,
+ },
+ {
+ description: 'input[type=tel][style="ime-mode: disabled;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "tel");
+ element.setAttribute("style", "ime-mode: disabled;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStatePasswordIfNotInDesignMode,
+ },
+
+ {
+ description: 'input[type=number][style="ime-mode: auto;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "number");
+ element.setAttribute("style", "ime-mode: auto;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ },
+ {
+ description: 'input[type=number][style="ime-mode: normal;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "number");
+ element.setAttribute("style", "ime-mode: normal;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ },
+ {
+ description: 'input[type=number][style="ime-mode: active;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "number");
+ element.setAttribute("style", "ime-mode: active;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ expectedOpenState: true,
+ },
+ {
+ description: 'input[type=number][style="ime-mode: inactive;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "number");
+ element.setAttribute("style", "ime-mode: inactive;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ expectedOpenState: false,
+ },
+ {
+ description: 'input[type=number][style="ime-mode: disabled;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "number");
+ element.setAttribute("style", "ime-mode: disabled;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStatePasswordIfNotInDesignMode,
+ },
+
+ {
+ description: 'input[type=password][style="ime-mode: auto;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "password");
+ element.setAttribute("style", "ime-mode: auto;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStatePasswordIfNotInDesignMode,
+ },
+ {
+ description: 'input[type=password][style="ime-mode: normal;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "password");
+ element.setAttribute("style", "ime-mode: normal;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ },
+ {
+ description: 'input[type=password][style="ime-mode: active;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "password");
+ element.setAttribute("style", "ime-mode: active;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ expectedOpenState: true,
+ },
+ {
+ description: 'input[type=password][style="ime-mode: inactive;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "password");
+ element.setAttribute("style", "ime-mode: inactive;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ expectedOpenState: false,
+ },
+ {
+ description: 'input[type=password][style="ime-mode: disabled;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("input");
+ element.setAttribute("type", "password");
+ element.setAttribute("style", "ime-mode: disabled;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStatePasswordIfNotInDesignMode,
+ },
+ {
+ description: 'textarea[style="ime-mode: auto;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("textarea");
+ element.setAttribute("style", "ime-mode: auto;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ },
+ {
+ description: 'textarea[style="ime-mode: normal;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("textarea");
+ element.setAttribute("style", "ime-mode: normal;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ },
+ {
+ description: 'textarea[style="ime-mode: active;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("textarea");
+ element.setAttribute("style", "ime-mode: active;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ expectedOpenState: true,
+ },
+ {
+ description: 'textarea[style="ime-mode: inactive;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("textarea");
+ element.setAttribute("style", "ime-mode: inactive;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ expectedOpenState: false,
+ },
+ {
+ description: 'textarea[style="ime-mode: disabled;"]',
+ createElement: aDocument => {
+ const element = aDocument.createElement("textarea");
+ element.setAttribute("style", "ime-mode: disabled;");
+ return element;
+ },
+ isFocusable:
+ IMEStateOnFocusMoveTester.#elementIsConnectedAndNotInDesignMode,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue:
+ IMEStateOnFocusMoveTester.#IMEStatePasswordIfNotInDesignMode,
+ },
+
+ // HTML editors
+ {
+ description: 'div[contenteditable="true"]',
+ createElement: aDocument => {
+ const div = aDocument.createElement("div");
+ div.setAttribute("contenteditable", "");
+ return div;
+ },
+ isNewElementEditingHost: true,
+ isFocusable: IMEStateOnFocusMoveTester.#elementIsFocusableIfEditingHost,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ },
+ {
+ description: "designMode editor",
+ createElement: aDocument => {
+ const iframe = aDocument.createElement("iframe");
+ iframe.srcdoc = "<!doctype html><html><body></body></html>";
+ iframe.addEventListener(
+ "load",
+ () => (iframe.contentDocument.designMode = "on"),
+ { capture: true, once: true }
+ );
+ return iframe;
+ },
+ isFocusable: () => true,
+ focusEventIsExpected: () => true,
+ expectedEnabledValue: IMEStateOnFocusMoveTester.#IMEStateEnabledAlways,
+ },
+ ];
+
+ static get numberOfTests() {
+ return IMEStateOnFocusMoveTester.#sTestList.length;
+ }
+}