Bug 1374057 - Catch more preceding position-change notifications and prevent post-test position change notifications. r?jmaher draft
authorGreg Mierzwinski <gmierz2@outlook.com>
Sun, 18 Jun 2017 10:03:04 -0400
changeset 596159 bfaa91aa76de5501049e055859c62d070bb83e59
parent 596083 316014448e427486cce211217e2aee2f18ee3d69
child 596160 99a9d3ff3cc8fbc5ec4ade03a156c9de35c82374
push id64527
push userbmo:gmierz2@outlook.com
push dateSun, 18 Jun 2017 16:11:20 +0000
reviewersjmaher
bugs1374057
milestone56.0a1
Bug 1374057 - Catch more preceding position-change notifications and prevent post-test position change notifications. r?jmaher This patch fixes failures for widget/tests/test_composition_text_querycontent.xul when it is run on ubuntu 16.04. It adds some missing handling for pre-test position change notifications and also adds some handling for after-test position change notifications. MozReview-Commit-ID: 1t8NuxJqkOo
widget/tests/window_composition_text_querycontent.xul
--- 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();