Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: os == 'android'
- Manifest: widget/tests/chrome.toml
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Test for IME state management at changing editable state</title>
<script src="file_ime_state_test_helper.js"></script>
</head>
<body>
<div></div>
<script>
"use strict";
/* import-globals-from file_ime_state_test_helper.js */
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(async () => {
const tipWrapper = new TIPWrapper(window);
function waitForIMEContentObserverSendingNotifications() {
return new Promise(
resolve => requestAnimationFrame(
() => requestAnimationFrame(resolve)
)
);
}
function resetIMEStateWithFocusMove() {
const input = document.createElement("input");
document.body.appendChild(input);
input.focus();
input.remove();
return waitForIMEContentObserverSendingNotifications();
}
await (async function test_setting_contenteditable_of_focused_div() {
const div = document.querySelector("div");
div.setAttribute("tabindex", "0");
div.focus();
is(
window.windowUtils.IMEStatus,
Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED,
"test_setting_contenteditable_of_focused_div: IME should be disabled when non-editable <div> has focus"
);
div.setAttribute("contenteditable", "");
await waitForIMEContentObserverSendingNotifications();
// Sometimes, it's not enough waiting only 2 animation frames here to wait
// for IME focus, perhaps, it may be related to HTMLEditor initialization.
// Let's wait one more animation frame here.
if (!tipWrapper.IMEHasFocus) {
await new Promise(resolve => requestAnimationFrame(resolve));
}
is(
window.windowUtils.IMEStatus,
Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED,
"test_setting_contenteditable_of_focused_div: IME should be enabled when contenteditable of focused <div> is set"
);
ok(
tipWrapper.IMEHasFocus,
"test_setting_contenteditable_of_focused_div: IME should have focus when contenteditable of focused <div> is set"
)
div.removeAttribute("contenteditable");
await waitForIMEContentObserverSendingNotifications();
is(
window.windowUtils.IMEStatus,
Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED,
"test_setting_contenteditable_of_focused_div: IME should be disabled when contenteditable of focused <div> is removed"
);
ok(
!tipWrapper.IMEHasFocus,
"test_setting_contenteditable_of_focused_div: IME should not have focus when contenteditable of focused <div> is removed"
);
div.removeAttribute("tabindex");
})();
await resetIMEStateWithFocusMove();
await (async function test_removing_contenteditable_of_non_last_editable_div() {
const div = document.querySelector("div");
div.setAttribute("tabindex", "0");
div.setAttribute("contenteditable", "");
const anotherEditableDiv = document.createElement("div");
anotherEditableDiv.setAttribute("contenteditable", "");
div.parentElement.appendChild(anotherEditableDiv);
div.focus();
await waitForIMEContentObserverSendingNotifications();
div.removeAttribute("contenteditable");
await waitForIMEContentObserverSendingNotifications();
is(
window.windowUtils.IMEStatus,
Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED,
"test_removing_contenteditable_of_non_last_editable_div: IME should be disabled when contenteditable of focused <div> is removed"
);
ok(
!tipWrapper.IMEHasFocus,
"test_removing_contenteditable_of_non_last_editable_div: IME should not have focus when contenteditable of focused <div> is removed"
);
anotherEditableDiv.remove();
div.removeAttribute("tabindex");
})();
await resetIMEStateWithFocusMove();
await (async function test_setting_designMode() {
window.focus();
document.designMode = "on";
await waitForIMEContentObserverSendingNotifications();
is(
window.windowUtils.IMEStatus,
Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED,
'test_setting_designMode: IME should be enabled when designMode is set to "on"'
);
ok(
tipWrapper.IMEHasFocus,
'test_setting_designMode: IME should have focus when designMode is set to "on"'
);
document.designMode = "off";
await waitForIMEContentObserverSendingNotifications();
is(
window.windowUtils.IMEStatus,
Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED,
'test_setting_designMode: IME should be disabled when designMode is set to "off"'
);
ok(
!tipWrapper.IMEHasFocus,
'test_setting_designMode: IME should not have focus when designMode is set to "off"'
);
})();
await resetIMEStateWithFocusMove();
async function test_setting_content_editable_of_body_when_shadow_DOM_has_focus(aMode) {
const div = document.querySelector("div");
const shadow = div.attachShadow({mode: aMode});
const divInShadow = document.createElement("div");
divInShadow.setAttribute("tabindex", "0");
shadow.appendChild(divInShadow);
divInShadow.focus();
await waitForIMEContentObserverSendingNotifications();
is(
window.windowUtils.IMEStatus,
Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED,
`test_setting_content_editable_of_body_when_shadow_DOM_has_focus(${
aMode
}): IME should be disabled when non-editable <div> in a shadow DOM has focus`
);
document.body.setAttribute("contenteditable", "");
await waitForIMEContentObserverSendingNotifications();
// element becomes an editable child. Therefore, cannot initialize
// HTMLEditor with the new editing host.
todo_is(
window.windowUtils.IMEStatus,
Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED,
`test_setting_content_editable_of_body_when_shadow_DOM_has_focus(${
aMode
}): IME should be enabled when the <body> becomes editable`
);
todo(
tipWrapper.IMEHasFocus,
`test_setting_content_editable_of_body_when_shadow_DOM_has_focus(${
aMode
}): IME should have focus when the <body> becomes editable`
);
document.body.removeAttribute("contenteditable");
await waitForIMEContentObserverSendingNotifications();
is(
window.windowUtils.IMEStatus,
Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED,
`test_setting_content_editable_of_body_when_shadow_DOM_has_focus)${
aMode
}): IME should be disabled when the <body> becomes not editable`
);
ok(
!tipWrapper.IMEHasFocus,
`test_setting_content_editable_of_body_when_shadow_DOM_has_focus)${
aMode
}): IME should not have focus when the <body> becomes not editable`
);
div.remove();
document.body.appendChild(document.createElement("div"));
};
async function test_setting_designMode_when_shadow_DOM_has_focus(aMode) {
const div = document.querySelector("div");
const shadow = div.attachShadow({mode: aMode});
const divInShadow = document.createElement("div");
divInShadow.setAttribute("tabindex", "0");
shadow.appendChild(divInShadow);
divInShadow.focus();
await waitForIMEContentObserverSendingNotifications();
is(
window.windowUtils.IMEStatus,
Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED,
`test_setting_designMode_when_shadow_DOM_has_focus(${
aMode
}): IME should be disabled when non-editable <div> in a shadow DOM has focus`
);
document.designMode = "on";
await waitForIMEContentObserverSendingNotifications();
is(
window.windowUtils.IMEStatus,
Ci.nsIDOMWindowUtils.IME_STATUS_DISABLED,
`test_setting_designMode_when_shadow_DOM_has_focus(${
aMode
}): IME should stay disabled when designMode is set`
);
ok(
!tipWrapper.IMEHasFocus,
`test_setting_designMode_when_shadow_DOM_has_focus(${
aMode
}): IME should not have focus when designMode is set`
);
divInShadow.setAttribute("contenteditable", "");
await waitForIMEContentObserverSendingNotifications();
is(
window.windowUtils.IMEStatus,
Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED,
`test_setting_designMode_when_shadow_DOM_has_focus(${
aMode
}): IME should be enabled when focused <div> in a shadow DOM becomes editable`
);
ok(
tipWrapper.IMEHasFocus,
`test_setting_designMode_when_shadow_DOM_has_focus(${
aMode
}): IME should have focus when focused <div> in a shadow DOM becomes editable`
);
document.designMode = "off";
await waitForIMEContentObserverSendingNotifications();
is(
window.windowUtils.IMEStatus,
Ci.nsIDOMWindowUtils.IME_STATUS_ENABLED,
`test_setting_designMode_when_shadow_DOM_has_focus(${
aMode
}): IME should keep being enabled when designMode is unset but an editable element in the shadow DOM has focus`
);
ok(
tipWrapper.IMEHasFocus,
`test_setting_designMode_when_shadow_DOM_has_focus(${
aMode
}): IME should keep having focus when designMode is unset but an editable element in the shadow DOM has focus`
);
div.remove();
document.body.appendChild(document.createElement("div"));
}
for (const mode of ["open", "closed"]) {
await test_setting_content_editable_of_body_when_shadow_DOM_has_focus(mode);
await resetIMEStateWithFocusMove();
await test_setting_designMode_when_shadow_DOM_has_focus(mode);
await resetIMEStateWithFocusMove();
}
SimpleTest.finish();
});
</script>
</body>
</html>