Bug 806996 part.6 Test if nsIWidget::OnIMEFocusChange() is called by nsTextStateManager properly r=smaug

This commit is contained in:
Masayuki Nakano 2012-11-09 17:40:40 +09:00
parent d7ca87539e
commit a33c1f5ebe
3 changed files with 199 additions and 9 deletions

View File

@ -36,6 +36,8 @@
#include "mozilla/Attributes.h"
#include "nsEventDispatcher.h"
#include "TextComposition.h"
#include "mozilla/Preferences.h"
#include "nsAsyncDOMEvent.h"
using namespace mozilla;
using namespace mozilla::widget;
@ -83,6 +85,7 @@ nsIContent* nsIMEStateManager::sContent = nullptr;
nsPresContext* nsIMEStateManager::sPresContext = nullptr;
bool nsIMEStateManager::sInstalledMenuKeyboardListener = false;
bool nsIMEStateManager::sInSecureInputMode = false;
bool nsIMEStateManager::sIsTestingIME = false;
nsTextStateManager* nsIMEStateManager::sTextStateObserver = nullptr;
TextCompositionArray* nsIMEStateManager::sTextCompositions = nullptr;
@ -730,6 +733,12 @@ nsTextStateManager::nsTextStateManager(nsIWidget* aWidget,
}
NS_ENSURE_TRUE_VOID(mRootContent);
if (nsIMEStateManager::sIsTestingIME) {
nsIDocument* doc = aPresContext->Document();
(new nsAsyncDOMEvent(doc, NS_LITERAL_STRING("MozIMEFocusIn"),
false, false))->RunDOMEventWhenSafe();
}
nsresult rv = mWidget->OnIMEFocusChange(true);
if (rv == NS_ERROR_NOT_IMPLEMENTED) {
return;
@ -762,6 +771,11 @@ nsTextStateManager::ObserveEditableNode()
void
nsTextStateManager::Destroy(void)
{
if (nsIMEStateManager::sIsTestingIME && mEditableNode) {
nsIDocument* doc = mEditableNode->OwnerDoc();
(new nsAsyncDOMEvent(doc, NS_LITERAL_STRING("MozIMEFocusOut"),
false, false))->RunDOMEventWhenSafe();
}
mWidget->OnIMEFocusChange(false);
if (mObserving && mSel) {
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(mSel));
@ -1028,6 +1042,12 @@ nsIMEStateManager::CreateTextStateManager()
return;
}
static bool sInitializeIsTestingIME = true;
if (sInitializeIsTestingIME) {
Preferences::AddBoolVarCache(&sIsTestingIME, "test.IME", false);
sInitializeIsTestingIME = false;
}
sTextStateObserver = new nsTextStateManager(widget, sPresContext, sContent);
NS_ADDREF(sTextStateObserver);
}

View File

@ -129,6 +129,7 @@ protected:
static nsPresContext* sPresContext;
static bool sInstalledMenuKeyboardListener;
static bool sInSecureInputMode;
static bool sIsTestingIME;
static nsTextStateManager* sTextStateObserver;

View File

@ -115,6 +115,17 @@
SimpleTest.waitForExplicitFinish();
function hitEventLoop(aFunc, aTimes)
{
SpecialPowers.getDOMWindowUtils(window).advanceTimeAndRefresh(100);
if (--aTimes) {
setTimeout(hitEventLoop, 0, aFunc, aTimes);
} else {
setTimeout(aFunc, 20);
}
}
var gUtils = window.
QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
@ -134,7 +145,7 @@ function runBasicTest(aIsEditable, aInDesignMode, aDescription)
{
function test(aTest)
{
function moveFocus(aTest)
function moveFocus(aTest, aFocusEventHandler)
{
if (aInDesignMode) {
if (document.activeElement) {
@ -149,10 +160,28 @@ function runBasicTest(aIsEditable, aInDesignMode, aDescription)
}
var previousFocusedElement = gFM.focusedElement;
var element = document.getElementById(aTest.id);
var subDocument = null;
if (element.contentDocument) {
subDocument = element.contentDocument;
element = element.contentDocument.documentElement;
}
document.addEventListener("MozIMEFocusIn", aFocusEventHandler, true);
document.addEventListener("MozIMEFocusOut", aFocusEventHandler, true);
if (subDocument) {
subDocument.addEventListener("MozIMEFocusIn", aFocusEventHandler, true);
subDocument.addEventListener("MozIMEFocusOut", aFocusEventHandler, true);
}
element.focus();
document.removeEventListener("MozIMEFocusIn", aFocusEventHandler, true);
document.removeEventListener("MozIMEFocusOut", aFocusEventHandler, true);
if (element.contentDocument) {
subDocument.removeEventListener("MozIMEFocusIn", aFocusEventHandler, true);
subDocument.removeEventListener("MozIMEFocusOut", aFocusEventHandler, true);
}
var focusedElement = gFM.focusedElement;
if (focusedElement) {
var bindingParent = document.getBindingParent(focusedElement);
@ -186,9 +215,90 @@ function runBasicTest(aIsEditable, aInDesignMode, aDescription)
// IME Enabled state testing
var enabled = gUtils.IME_STATUS_ENABLED;
if (kIMEEnabledSupported) {
if (!moveFocus(aTest)) {
var mozIMEFocusInCount = 0;
var mozIMEFocusOutCount = 0;
var IMEHasFocus = false;
function onFocus(aEvent)
{
switch (aEvent.type) {
case "MozIMEFocusIn":
mozIMEFocusInCount++;
IMEHasFocus = true;
is(gUtils.IMEStatus, aTest.expectedEnabled,
aDescription + ": " + aTest.description +
", MozIMEFocusIn event must be fired after IME state is updated");
break;
case "MozIMEFocusOut":
mozIMEFocusOutCount++;
IMEHasFocus = false;
is_not(gUtils.IMEStatus, aTest.expectedEnabled,
aDescription + ": " + aTest.description +
", MozIMEFocusOut event must be fired before IME state is updated");
break;
}
}
if (!moveFocus(aTest, onFocus)) {
return;
}
if (aTest.focusable) {
if (!aTest.focusEventNotFired) {
if (aTest.expectedEnabled == gUtils.IME_STATUS_ENABLED || aTest.expectedEnabled == gUtils.IME_STATUS_PASSWORD) {
var toDesignModeEditor = (document.activeElement.contentDocument &&
(document.activeElement.contentDocument.designMode == "on"));
if (aInDesignMode && toDesignModeEditor) {
is(mozIMEFocusOutCount, 0,
aDescription + ": " + aTest.description +
", MozIMEFocusOut event shouldn't be fired in designMode since focus isn't moved from another editor");
todo(mozIMEFocusInCount > 0,
aDescription + ": " + aTest.description + ", MozIMEFocusIn event should be fired"); // bug 805766
} else {
ok(mozIMEFocusOutCount > 0,
aDescription + ": " + aTest.description +
", MozIMEFocusOut event should be fired for the previous focused editor");
if (toDesignModeEditor) {
todo(mozIMEFocusInCount > 0,
aDescription + ": " + aTest.description + ", MozIMEFocusIn event should be fired"); // bug 805766
} else {
ok(mozIMEFocusInCount > 0,
aDescription + ": " + aTest.description + ", MozIMEFocusIn event should be fired");
}
}
if (aInDesignMode || toDesignModeEditor) { // bug 805766
todo(IMEHasFocus,
aDescription + ": " + aTest.description +
", The latest MozIMEFocus* event must be MozIMEFocusIn");
} else {
ok(IMEHasFocus,
aDescription + ": " + aTest.description +
", The latest MozIMEFocus* event must be MozIMEFocusIn");
}
} else {
is(mozIMEFocusInCount, 0,
aDescription + ": " + aTest.description +
", MozIMEFocusIn event shouldn't be fired");
ok(mozIMEFocusOutCount > 0,
aDescription + ": " + aTest.description +
", MozIMEFocusOut event should be fired");
ok(!IMEHasFocus,
aDescription + ": " + aTest.description +
", The latest MozIMEFocus* event must be MozIMEFocusOut");
}
} else {
todo(false, aDescription + ": " + aTest.description +
", In this case, focus event isn't fired, it's a bug, so, couldn't test it");
}
} else {
is(mozIMEFocusInCount, 0,
aDescription + ": " + aTest.description +
", MozIMEFocusIn event shouldn't be fired at testing non-focusable element");
is(mozIMEFocusOutCount, 0,
aDescription + ": " + aTest.description +
", MozIMEFocusOut event shouldn't be fired at testing non-focusable element");
}
enabled = gUtils.IMEStatus;
inputtype = gUtils.focusedInputType;
is(enabled, aTest.expectedEnabled,
@ -254,10 +364,12 @@ function runBasicTest(aIsEditable, aInDesignMode, aDescription)
{ id: "checkbox",
description: "input[type=checkbox]",
focusable: !aInDesignMode,
focusEventNotFired: aIsEditable && !aInDesignMode,
expectedEnabled: kEnabledStateOnNonEditableElement },
{ id: "radio",
description: "input[type=radio]",
focusable: !aInDesignMode,
focusEventNotFired: aIsEditable && !aInDesignMode,
expectedEnabled: kEnabledStateOnNonEditableElement },
{ id: "submit",
description: "input[type=submit]",
@ -270,6 +382,7 @@ function runBasicTest(aIsEditable, aInDesignMode, aDescription)
{ id: "file",
description: "input[type=file]",
focusable: !aInDesignMode,
focusEventNotFired: aIsEditable && !aInDesignMode,
expectedEnabled: kEnabledStateOnNonEditableElement },
{ id: "button",
description: "input[type=button]",
@ -321,10 +434,12 @@ function runBasicTest(aIsEditable, aInDesignMode, aDescription)
{ id: "select",
description: "select (dropdown list)",
focusable: !aInDesignMode,
focusEventNotFired: aIsEditable && !aInDesignMode,
expectedEnabled: kEnabledStateOnNonEditableElement },
{ id: "select_multiple",
description: "select (list box)",
focusable: !aInDesignMode,
focusEventNotFired: aIsEditable && !aInDesignMode,
expectedEnabled: kEnabledStateOnNonEditableElement },
// a element
@ -1242,11 +1357,66 @@ function runTestPasswordFieldOnDialog()
}
}
function runBug580388Tests(aCallback)
{
if (document.activeElement) {
document.activeElement.blur();
}
var input = document.getElementById("text");
input.focus();
input.style.overflow = "visible";
var mozIMEFocusIn = 0;
var mozIMEFocusOut = 0;
var IMEHasFocus = false;
var handler = function (aEvent) {
switch (aEvent.type) {
case "MozIMEFocusIn":
mozIMEFocusIn++;
IMEHasFocus = true;
break;
case "MozIMEFocusOut":
mozIMEFocusOut++;
IMEHasFocus = false;
break;
}
};
var onInput = function (aEvent) {
aEvent.target.style.overflow = "hidden";
}
document.addEventListener("MozIMEFocusIn", handler, true);
document.addEventListener("MozIMEFocusOut", handler, true);
input.addEventListener("input", onInput, true);
sendChar("a");
hitEventLoop(function () {
ok(mozIMEFocusOut > 0, "runBug580388Tests(): IME focus must be lost at reframing");
ok(mozIMEFocusIn > 0, "runBug580388Tests(): IME focus must be restored after reframing");
ok(IMEHasFocus, "runBug580388Tests(): IME must have focus after reframing");
document.removeEventListener("MozIMEFocusIn", handler, true);
document.removeEventListener("MozIMEFocusOut", handler, true);
input.removeEventListener("input", onInput, true);
input.style.overflow = "visible";
input.value = "";
hitEventLoop(aCallback, 20);
}, 20);
}
function runTests()
{
if (!kIMEEnabledSupported && !kIMEOpenSupported)
return;
SpecialPowers.setBoolPref("test.IME", true);
// test for normal contents.
runBasicTest(false, false, "Testing of normal contents");
@ -1291,17 +1461,16 @@ function runTests()
// XXX temporary disable against failure
//runTestPasswordFieldOnDialog();
runASyncTests();
}
function runASyncTests()
{
// The tests must call onFinish() method.
runEditableSubframeTests();
// Asynchronous tests
runBug580388Tests(function () {
// This will call onFinish(), so, this test must be the last.
runEditableSubframeTests();
});
}
function onFinish()
{
SpecialPowers.clearUserPref("test.IME");
SimpleTest.finish();
}