--- a/widget/tests/window_composition_text_querycontent.xul
+++ b/widget/tests/window_composition_text_querycontent.xul
@@ -7151,16 +7151,33 @@ function* runIMEContentObserverTest()
return;
}
// Sometimes, notify-position-change is notified first separately if
// the operation causes scroll or something. Tests can ignore this.
ok(true, "notify-position-change", aDescription + "Unnecessary notify-position-change occurred, ignoring it");
notifications.shift();
}
+ // Bug 1374057 - On ubuntu 16.04 there are notify-position-change events that are
+ // recorded after all the other events so we remove them through this function.
+ function ensureToRemovePostPositionChangeNotification(aDescription, expectedCount)
+ {
+ if (!notifications.length) {
+ return;
+ }
+ if (notifications.length <= expectedCount) {
+ return;
+ }
+ if (notifications[notifications.length-1].type != "notify-position-change") {
+ return;
+ }
+ ok(true, "notify-position-change", aDescription + "Unnecessary notify-position-change occurred, ignoring it");
+ notifications.pop();
+ }
+
function getNativeText(aXPText)
{
if (kLF == "\n") {
return aXPText;
}
return aXPText.replace(/\n/g, kLF);
}
@@ -7223,137 +7240,163 @@ function* runIMEContentObserverTest()
aElement.focus();
yield flushNotifications();
// "a[]"
var description = aDescription + "typing 'a'";
notifications = [];
synthesizeKey("a", { code: "KeyA" }, win, callback);
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkTextChangeNotification(notifications[0], description, { offset: 0, removedLength: 0, addedLength: 1 });
checkSelectionChangeNotification(notifications[1], description, { offset: 1, text: "" });
checkPositionChangeNotification(notifications[2], description);
+ ensureToRemovePostPositionChangeNotification(description, 3);
dumpUnexpectedNotifications(description, 3);
// "ab[]"
description = aDescription + "typing 'b'";
notifications = [];
synthesizeKey("b", { code: "KeyB" }, win, callback);
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkTextChangeNotification(notifications[0], description, { offset: 1, removedLength: 0, addedLength: 1 });
checkSelectionChangeNotification(notifications[1], description, { offset: 2, text: "" });
checkPositionChangeNotification(notifications[2], description);
+ ensureToRemovePostPositionChangeNotification(description, 3);
dumpUnexpectedNotifications(description, 3);
// "abc[]"
description = aDescription + "typing 'c'";
notifications = [];
synthesizeKey("c", { code: "KeyC" }, win, callback);
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkTextChangeNotification(notifications[0], description, { offset: 2, removedLength: 0, addedLength: 1 });
checkSelectionChangeNotification(notifications[1], description, { offset: 3, text: "" });
checkPositionChangeNotification(notifications[2], description);
+ ensureToRemovePostPositionChangeNotification(description, 3);
dumpUnexpectedNotifications(description, 3);
// "ab[c]"
description = aDescription + "selecting 'c' with pressing Shift+ArrowLeft";
notifications = [];
synthesizeKey("KEY_ArrowLeft", { code: "ArrowLeft", shiftKey: true }, win, callback);
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkSelectionChangeNotification(notifications[0], description, { offset: 2, text: "c", reversed: true });
+ ensureToRemovePostPositionChangeNotification(description, 1);
dumpUnexpectedNotifications(description, 1);
// "a[bc]"
description = aDescription + "selecting 'bc' with pressing Shift+ArrowLeft";
notifications = [];
synthesizeKey("KEY_ArrowLeft", { code: "ArrowLeft", shiftKey: true }, win, callback);
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkSelectionChangeNotification(notifications[0], description, { offset: 1, text: "bc", reversed: true });
+ ensureToRemovePostPositionChangeNotification(description, 1);
dumpUnexpectedNotifications(description, 1);
// "[abc]"
description = aDescription + "selecting 'bc' with pressing Shift+ArrowLeft";
notifications = [];
synthesizeKey("KEY_ArrowLeft", { code: "ArrowLeft", shiftKey: true }, win, callback);
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkSelectionChangeNotification(notifications[0], description, { offset: 0, text: "abc", reversed: true });
+ ensureToRemovePostPositionChangeNotification(description, 1);
dumpUnexpectedNotifications(description, 1);
// "[]abc"
description = aDescription + "collapsing selection to the left-most with pressing ArrowLeft";
notifications = [];
synthesizeKey("KEY_ArrowLeft", { code: "ArrowLeft" }, win, callback);
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkSelectionChangeNotification(notifications[0], description, { offset: 0, text: "" });
+ ensureToRemovePostPositionChangeNotification(description, 1);
dumpUnexpectedNotifications(description, 1);
// "[a]bc"
description = aDescription + "selecting 'a' with pressing Shift+ArrowRight";
notifications = [];
synthesizeKey("KEY_ArrowRight", { code: "ArrowRight", shiftKey: true }, win, callback);
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkSelectionChangeNotification(notifications[0], description, { offset: 0, text: "a" });
+ ensureToRemovePostPositionChangeNotification(description, 1);
dumpUnexpectedNotifications(description, 1);
// "[ab]c"
description = aDescription + "selecting 'ab' with pressing Shift+ArrowRight";
notifications = [];
synthesizeKey("KEY_ArrowRight", { code: "ArrowRight", shiftKey: true }, win, callback);
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkSelectionChangeNotification(notifications[0], description, { offset: 0, text: "ab" });
+ ensureToRemovePostPositionChangeNotification(description, 1);
dumpUnexpectedNotifications(description, 1);
// "[]c"
description = aDescription + "deleting 'ab' with pressing Delete";
notifications = [];
synthesizeKey("KEY_Delete", { code: "Delete" }, win, callback);
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkTextChangeNotification(notifications[0], description, { offset: 0, removedLength: 2, addedLength: 0 });
checkSelectionChangeNotification(notifications[1], description, { offset: 0, text: "" });
checkPositionChangeNotification(notifications[2], description);
+ ensureToRemovePostPositionChangeNotification(description, 3);
dumpUnexpectedNotifications(description, 3);
// "[]"
description = aDescription + "deleting following 'c' with pressing Delete";
notifications = [];
synthesizeKey("KEY_Delete", { code: "Delete" }, win, callback);
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkTextChangeNotification(notifications[0], description, { offset: 0, removedLength: 1, addedLength: 0 });
checkPositionChangeNotification(notifications[1], description);
+ ensureToRemovePostPositionChangeNotification(description, 2);
dumpUnexpectedNotifications(description, 2);
// "abc[]"
synthesizeKey("a", { code: "KeyA" }, win, callback);
synthesizeKey("b", { code: "KeyB" }, win, callback);
synthesizeKey("c", { code: "KeyC" }, win, callback);
yield flushNotifications();
// "ab[]"
description = aDescription + "deleting 'c' with pressing Backspace";
notifications = [];
synthesizeKey("KEY_Backspace", { code: "Backspace" }, win, callback);
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkTextChangeNotification(notifications[0], description, { offset: 2, removedLength: 1, addedLength: 0 });
checkSelectionChangeNotification(notifications[1], description, { offset: 2, text: "" });
checkPositionChangeNotification(notifications[2], description);
+ ensureToRemovePostPositionChangeNotification(description, 3);
dumpUnexpectedNotifications(description, 3);
// "[ab]"
synthesizeKey("KEY_ArrowLeft", { code: "ArrowLeft", shiftKey: true }, win, callback);
synthesizeKey("KEY_ArrowLeft", { code: "ArrowLeft", shiftKey: true }, win, callback);
yield flushNotifications();
// "[]"
description = aDescription + "deleting 'ab' with pressing Backspace";
notifications = [];
synthesizeKey("KEY_Backspace", { code: "Backspace" }, win, callback);
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkTextChangeNotification(notifications[0], description, { offset: 0, removedLength: 2, addedLength: 0 });
checkSelectionChangeNotification(notifications[1], description, { offset: 0, text: "" });
checkPositionChangeNotification(notifications[2], description);
+ ensureToRemovePostPositionChangeNotification(description, 3);
dumpUnexpectedNotifications(description, 3);
// "abcd[]"
synthesizeKey("a", { code: "KeyA" }, win, callback);
synthesizeKey("b", { code: "KeyB" }, win, callback);
synthesizeKey("c", { code: "KeyC" }, win, callback);
synthesizeKey("d", { code: "KeyD" }, win, callback);
yield flushNotifications();
@@ -7364,113 +7407,131 @@ function* runIMEContentObserverTest()
synthesizeKey("KEY_ArrowLeft", { code: "ArrowLeft", shiftKey: true }, win, callback);
yield flushNotifications();
// "a[]d"
description = aDescription + "deleting 'bc' with pressing Backspace";
notifications = [];
synthesizeKey("KEY_Backspace", { code: "Backspace" }, win, callback);
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkTextChangeNotification(notifications[0], description, { offset: 1, removedLength: 2, addedLength: 0 });
checkSelectionChangeNotification(notifications[1], description, { offset: 1, text: "" });
checkPositionChangeNotification(notifications[2], description);
+ ensureToRemovePostPositionChangeNotification(description, 3);
dumpUnexpectedNotifications(description, 3);
// "a[bc]d"
synthesizeKey("b", { code: "KeyB" }, win, callback);
synthesizeKey("c", { code: "KeyC" }, win, callback);
synthesizeKey("KEY_ArrowLeft", { code: "ArrowLeft", shiftKey: true }, win, callback);
synthesizeKey("KEY_ArrowLeft", { code: "ArrowLeft", shiftKey: true }, win, callback);
yield flushNotifications();
// "aB[]d"
description = aDescription + "replacing 'bc' with 'B' with pressing Shift+B";
notifications = [];
synthesizeKey("B", { code: "KeyB", shiftKey: true }, win, callback);
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkTextChangeNotification(notifications[0], description, { offset: 1, removedLength: 2, addedLength: 1 });
checkSelectionChangeNotification(notifications[1], description, { offset: 2, text: "" });
checkPositionChangeNotification(notifications[2], description);
+ ensureToRemovePostPositionChangeNotification(description, 3);
dumpUnexpectedNotifications(description, 3);
if (!aTestLineBreaker) {
return;
}
// "aB\n[]d"
description = aDescription + "inserting a line break after 'B' with pressing Enter";
notifications = [];
synthesizeKey("KEY_Enter", { code: "Enter" }, win, callback);
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkTextChangeNotification(notifications[0], description, { offset: 2, removedLength: 0, addedLength: kLFLen });
checkSelectionChangeNotification(notifications[1], description, { offset: getNativeText("aB\n").length, text: "" });
checkPositionChangeNotification(notifications[2], description);
+ ensureToRemovePostPositionChangeNotification(description, 3);
dumpUnexpectedNotifications(description, 3);
// "aB[]d"
description = aDescription + "removing a line break after 'B' with pressing Backspace";
notifications = [];
synthesizeKey("KEY_Backspace", { code: "Backspace" }, win, callback);
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkTextChangeNotification(notifications[0], description, { offset: 2, removedLength: kLFLen, addedLength: 0 });
checkSelectionChangeNotification(notifications[1], description, { offset: 2, text: "" });
checkPositionChangeNotification(notifications[2], description);
+ ensureToRemovePostPositionChangeNotification(description, 3);
dumpUnexpectedNotifications(description, 3);
// "a[B]d"
synthesizeKey("KEY_ArrowLeft", { code: "ArrowLeft", shiftKey: true }, win, callback);
yield flushNotifications();
// "a\n[]d"
description = aDescription + "replacing 'B' with a line break with pressing Enter";
notifications = [];
synthesizeKey("KEY_Enter", { code: "Enter" }, win, callback);
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkTextChangeNotification(notifications[0], description, { offset: 1, removedLength: 1, addedLength: kLFLen });
checkSelectionChangeNotification(notifications[1], description, { offset: getNativeText("a\n").length, text: "" });
checkPositionChangeNotification(notifications[2], description);
+ ensureToRemovePostPositionChangeNotification(description, 3);
dumpUnexpectedNotifications(description, 3);
// "a[\n]d"
description = aDescription + "selecting '\n' with pressing Shift+ArrowLeft";
notifications = [];
synthesizeKey("KEY_ArrowLeft", { code: "ArrowLeft", shiftKey: true }, win, callback);
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkSelectionChangeNotification(notifications[0], description, { offset: 1, text: kLF, reversed: true });
+ ensureToRemovePostPositionChangeNotification(description, 1);
dumpUnexpectedNotifications(description, 1);
// "a[]d"
description = aDescription + "removing selected '\n' with pressing Delete";
notifications = [];
synthesizeKey("KEY_Delete", { code: "Delete", shiftKey: true }, win, callback);
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkTextChangeNotification(notifications[0], description, { offset: 1, removedLength: kLFLen, addedLength: 0 });
checkSelectionChangeNotification(notifications[1], description, { offset: 1, text: "" });
checkPositionChangeNotification(notifications[2], description);
+ ensureToRemovePostPositionChangeNotification(description, 3);
dumpUnexpectedNotifications(description, 3);
// ab\ncd\nef\ngh\n[]
description = aDescription + "setting the value property to 'ab\ncd\nef\ngh\n'";
notifications = [];
aElement.value = "ab\ncd\nef\ngh\n";
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
checkTextChangeNotification(notifications[0], description, { offset: 0, removedLength: 2, addedLength: getNativeText("ab\ncd\nef\ngh\n").length });
checkSelectionChangeNotification(notifications[1], description, { offset: getNativeText("ab\ncd\nef\ngh\n").length, text: "" });
checkPositionChangeNotification(notifications[2], description);
+ ensureToRemovePostPositionChangeNotification(description, 3);
dumpUnexpectedNotifications(description, 3);
// []
description = aDescription + "setting the value property to ''";
notifications = [];
aElement.value = "";
yield waitUntilNotificationsReceived();
+ ensureToRemovePrecedingPositionChangeNotification();
// XXX Removing invisible <br> or something? The removed length is a line breaker length longer.
checkTextChangeNotification(notifications[0], description, { offset: 0, removedLength: getNativeText("ab\ncd\nef\ngh\n").length + kLFLen, addedLength: 0 });
checkSelectionChangeNotification(notifications[1], description, { offset: 0, text: "" });
checkPositionChangeNotification(notifications[2], description);
+ ensureToRemovePostPositionChangeNotification(description, 3);
dumpUnexpectedNotifications(description, 3);
}
function* testWithHTMLEditor(aDescription, aElement, aDefaultParagraphSeparator)
{
var doc = aElement.ownerDocument;
var win = doc.defaultView;
var sel = doc.getSelection();