Remove UIHelper.activateElementAtHumanSpeed
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 27 Aug 2019 00:18:57 +0000 (00:18 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 27 Aug 2019 00:18:57 +0000 (00:18 +0000)
https://bugs.webkit.org/show_bug.cgi?id=201147

Reviewed by Tim Horton.

Tools:

Add plumbing for a new script controller hook to wait for the double tap delay to pass. On non-iOS, this
resolves immediately; on iOS, we inspect the content view for tap gestures that require more than one tap, and
find the value of the maximum double tap delay. We then delay for this amount of time before resolving.

* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.h:
(WTR::UIScriptController::doAfterDoubleTapDelay):
* WebKitTestRunner/ios/UIScriptControllerIOS.h:
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::UIScriptControllerIOS::doAfterDoubleTapDelay):

LayoutTests:

This was used in layout tests that simulate repeated taps to work around <webkit.org/b/201129>, and should no
longer be needed after <https://trac.webkit.org/changeset/249112/webkit>. Instead, we can just use UIHelper's
activateElement as intended in cases where successive taps in the test does not result in a double-click; for
the cases where we need to avoid triggering double clicks when tapping (e.g. in several payment tests), use a
new script controller hook to wait for the double tap gesture delay before continuing.

* fast/forms/ios/file-upload-panel.html:
* http/tests/adClickAttribution/anchor-tag-attributes-validation-expected.txt:

Rebaseline more line numbers.

* http/tests/adClickAttribution/anchor-tag-attributes-validation.html:

Refactor this test so that the links are laid out in two (or more) columns to avoid firing the double click
gesture recognizer instead of the synthetic click gesture.

* http/tests/resources/payment-request.js:
(activateThen):

Instead of using activateElementAtHumanSpeed, wait for the platform double tap delay first, and then simulate
a click using activateElement.

* resources/ui-helper.js:
(window.UIHelper.waitForDoubleTapDelay):

Add a new UIHelper method to wait for the platform double tap delay. See Tools ChangeLog for more details.

(window.UIHelper):
(window.UIHelper.activateElementAtHumanSpeed.return.new.Promise): Deleted.
(window.UIHelper.activateElementAtHumanSpeed): Deleted.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@249125 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/forms/ios/file-upload-panel.html
LayoutTests/http/tests/adClickAttribution/anchor-tag-attributes-validation-expected.txt
LayoutTests/http/tests/adClickAttribution/anchor-tag-attributes-validation.html
LayoutTests/http/tests/resources/payment-request.js
LayoutTests/resources/ui-helper.js
Tools/ChangeLog
Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl
Tools/TestRunnerShared/UIScriptContext/UIScriptController.h
Tools/WebKitTestRunner/ios/UIScriptControllerIOS.h
Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm

index 25d641f..4970bb8 100644 (file)
@@ -1,3 +1,41 @@
+2019-08-26  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Remove UIHelper.activateElementAtHumanSpeed
+        https://bugs.webkit.org/show_bug.cgi?id=201147
+
+        Reviewed by Tim Horton.
+
+        This was used in layout tests that simulate repeated taps to work around <webkit.org/b/201129>, and should no
+        longer be needed after <https://trac.webkit.org/changeset/249112/webkit>. Instead, we can just use UIHelper's
+        activateElement as intended in cases where successive taps in the test does not result in a double-click; for
+        the cases where we need to avoid triggering double clicks when tapping (e.g. in several payment tests), use a
+        new script controller hook to wait for the double tap gesture delay before continuing.
+
+        * fast/forms/ios/file-upload-panel.html:
+        * http/tests/adClickAttribution/anchor-tag-attributes-validation-expected.txt:
+
+        Rebaseline more line numbers.
+
+        * http/tests/adClickAttribution/anchor-tag-attributes-validation.html:
+
+        Refactor this test so that the links are laid out in two (or more) columns to avoid firing the double click
+        gesture recognizer instead of the synthetic click gesture.
+
+        * http/tests/resources/payment-request.js:
+        (activateThen):
+
+        Instead of using activateElementAtHumanSpeed, wait for the platform double tap delay first, and then simulate
+        a click using activateElement.
+
+        * resources/ui-helper.js:
+        (window.UIHelper.waitForDoubleTapDelay):
+
+        Add a new UIHelper method to wait for the platform double tap delay. See Tools ChangeLog for more details.
+
+        (window.UIHelper):
+        (window.UIHelper.activateElementAtHumanSpeed.return.new.Promise): Deleted.
+        (window.UIHelper.activateElementAtHumanSpeed): Deleted.
+
 2019-08-26  Devin Rousso  <drousso@apple.com>
 
         Unreviewed, fix test failure after r200971
index d3697b8..b22df27 100644 (file)
@@ -52,7 +52,7 @@ function runAcceptTest(accept, expectedMenuItems)
         debug("* accept = " + accept);
         testInput.accept = accept;
 
-        UIHelper.activateElementAtHumanSpeed(testInput).then(() => {
+        UIHelper.activateElement(testInput).then(() => {
             getFileUploadPickerMenuItems().then((_items) => {
                 items = _items;
                 shouldBeTrue("areArraysEqual(items, " + expectedMenuItems + ")");
index bf807e8..c2b1d71 100644 (file)
@@ -1,14 +1,14 @@
-CONSOLE MESSAGE: line 182: adcampaignid must have a non-negative value less than or equal to 63 for Ad Click Attribution.
-CONSOLE MESSAGE: line 182: adcampaignid must have a non-negative value less than or equal to 63 for Ad Click Attribution.
-CONSOLE MESSAGE: line 182: adcampaignid can not be converted to a non-negative integer which is required for Ad Click Attribution.
-CONSOLE MESSAGE: line 182: adcampaignid can not be converted to a non-negative integer which is required for Ad Click Attribution.
-CONSOLE MESSAGE: line 182: adcampaignid can not be converted to a non-negative integer which is required for Ad Click Attribution.
-CONSOLE MESSAGE: line 182: addestination could not be converted to a valid HTTP-family URL.
-CONSOLE MESSAGE: line 182: addestination could not be converted to a valid HTTP-family URL.
-CONSOLE MESSAGE: line 182: addestination could not be converted to a valid HTTP-family URL.
-CONSOLE MESSAGE: line 182: Both adcampaignid and addestination need to be set for Ad Click Attribution to work.
-CONSOLE MESSAGE: line 182: Both adcampaignid and addestination need to be set for Ad Click Attribution to work.
-CONSOLE MESSAGE: line 182: addestination can not be the same site as the current website.
+CONSOLE MESSAGE: line 155: adcampaignid must have a non-negative value less than or equal to 63 for Ad Click Attribution.
+CONSOLE MESSAGE: line 155: adcampaignid must have a non-negative value less than or equal to 63 for Ad Click Attribution.
+CONSOLE MESSAGE: line 155: adcampaignid can not be converted to a non-negative integer which is required for Ad Click Attribution.
+CONSOLE MESSAGE: line 155: adcampaignid can not be converted to a non-negative integer which is required for Ad Click Attribution.
+CONSOLE MESSAGE: line 155: adcampaignid can not be converted to a non-negative integer which is required for Ad Click Attribution.
+CONSOLE MESSAGE: line 155: addestination could not be converted to a valid HTTP-family URL.
+CONSOLE MESSAGE: line 155: addestination could not be converted to a valid HTTP-family URL.
+CONSOLE MESSAGE: line 155: addestination could not be converted to a valid HTTP-family URL.
+CONSOLE MESSAGE: line 155: Both adcampaignid and addestination need to be set for Ad Click Attribution to work.
+CONSOLE MESSAGE: line 155: Both adcampaignid and addestination need to be set for Ad Click Attribution to work.
+CONSOLE MESSAGE: line 155: addestination can not be the same site as the current website.
 Test for validity of ad click attribution attributes on anchor tags.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
index 79b9c49..fe2fd63 100644 (file)
@@ -5,6 +5,12 @@
     <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
     <script src="/js-test-resources/js-test.js"></script>
     <script src="/js-test-resources/ui-helper.js"></script>
+    <style>
+        .wide-link {
+            width: 150px;
+            display: inline-block;
+        }
+    </style>
 </head>
 <body onload="runAllTests()">
 <div id="description"></div>
@@ -17,6 +23,7 @@
     function createAdClickAttributionAnchorElement(elementID, adCampaignID, adDestination) {
         let anchorElement = document.createElement("a");
         anchorElement.id = elementID;
+        anchorElement.classList.add("wide-link");
         anchorElement.adcampaignid = adCampaignID;
         anchorElement.addestination = adDestination;
         anchorElement.href = "#";
@@ -25,7 +32,7 @@
     }
 
     function activateElement(elementID, callback) {
-        UIHelper.activateElementAtHumanSpeed(document.getElementById(elementID)).then(
+        UIHelper.activateElement(document.getElementById(elementID)).then(
             function () {
                 callback();
             },
@@ -41,8 +48,6 @@
         const currentElementID = "test" + currentTest++;
         const anchorElement = createAdClickAttributionAnchorElement(currentElementID, adCampaignID, adDestination);
         output.appendChild(anchorElement);
-        const brElement = document.createElement("br");
-        output.appendChild(brElement);
         activateElement(currentElementID, callback);
     }
 
index c261813..555b8a1 100644 (file)
@@ -1,6 +1,6 @@
 function activateThen(completion)
 {
-    return new Promise(resolve => {
+    return new Promise(async resolve => {
         var button = document.createElement("button");
         button.style["position"] = "absolute";
         button.onclick = () => {
@@ -8,7 +8,8 @@ function activateThen(completion)
             resolve(completion());
         };
         document.body.insertBefore(button, document.body.firstChild);
-        UIHelper.activateElementAtHumanSpeed(button);
+        await UIHelper.waitForDoubleTapDelay();
+        await UIHelper.activateElement(button);
     });
 }
 
index e75c8e8..ad36dbb 100644 (file)
@@ -171,27 +171,6 @@ window.UIHelper = class UIHelper {
         return UIHelper.activateAt(x, y);
     }
 
-    static activateElementAtHumanSpeed(element)
-    {
-        const x = element.offsetLeft + element.offsetWidth / 2;
-        const y = element.offsetTop + element.offsetHeight / 2;
-
-        if (!this.isWebKit2() || !this.isIOSFamily()) {
-            eventSender.mouseMoveTo(x, y);
-            eventSender.mouseDown();
-            eventSender.mouseUp();
-            return Promise.resolve();
-        }
-
-        return new Promise(async (resolve) => {
-            await new Promise(resolveAfterDelay => setTimeout(resolveAfterDelay, 350));
-            testRunner.runUIScript(`
-                uiController.singleTapAtPoint(${x}, ${y}, function() {
-                    uiController.uiScriptComplete();
-                });`, resolve);
-        });
-    }
-
     static async doubleActivateAt(x, y)
     {
         if (this.isIOSFamily())
@@ -1033,4 +1012,10 @@ window.UIHelper = class UIHelper {
             })();`, resolve);
         });
     }
+
+    static waitForDoubleTapDelay()
+    {
+        const uiScript = `uiController.doAfterDoubleTapDelay(() => uiController.uiScriptComplete(""))`;
+        return new Promise(resolve => testRunner.runUIScript(uiScript, resolve));
+    }
 }
index 0edf51e..7f9a2dd 100644 (file)
@@ -1,3 +1,21 @@
+2019-08-26  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Remove UIHelper.activateElementAtHumanSpeed
+        https://bugs.webkit.org/show_bug.cgi?id=201147
+
+        Reviewed by Tim Horton.
+
+        Add plumbing for a new script controller hook to wait for the double tap delay to pass. On non-iOS, this
+        resolves immediately; on iOS, we inspect the content view for tap gestures that require more than one tap, and
+        find the value of the maximum double tap delay. We then delay for this amount of time before resolving.
+
+        * TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
+        * TestRunnerShared/UIScriptContext/UIScriptController.h:
+        (WTR::UIScriptController::doAfterDoubleTapDelay):
+        * WebKitTestRunner/ios/UIScriptControllerIOS.h:
+        * WebKitTestRunner/ios/UIScriptControllerIOS.mm:
+        (WTR::UIScriptControllerIOS::doAfterDoubleTapDelay):
+
 2019-08-26  Zhifei Fang  <zhifei_fang@apple.com>
 
         [results.webkit.org Timline] Add symbols to the timeline dot
index 6d94987..6b90ae5 100644 (file)
@@ -48,6 +48,8 @@ interface UIScriptController {
     void ensurePositionInformationIsUpToDateAt(long x, long y, object callback);
     void doAfterVisibleContentRectUpdate(object callback);
 
+    void doAfterDoubleTapDelay(object callback);
+
     void simulateAccessibilitySettingsChangeNotification(object callback);
 
     // Interaction.
index ffe507f..2a36730 100644 (file)
@@ -73,6 +73,8 @@ public:
     virtual void ensurePositionInformationIsUpToDateAt(long x, long y, JSValueRef callback) { doAsyncTask(callback); }
     virtual void doAfterVisibleContentRectUpdate(JSValueRef callback) { doAsyncTask(callback); }
 
+    virtual void doAfterDoubleTapDelay(JSValueRef callback) { doAsyncTask(callback); }
+
     // Preferences
 
     virtual void overridePreference(JSStringRef preference, JSStringRef value) { notImplemented(); }
index 77dd55c..31272bb 100644 (file)
@@ -43,6 +43,7 @@ public:
     void doAfterNextStablePresentationUpdate(JSValueRef) override;
     void ensurePositionInformationIsUpToDateAt(long x, long y, JSValueRef) override;
     void doAfterVisibleContentRectUpdate(JSValueRef) override;
+    void doAfterDoubleTapDelay(JSValueRef) override;
     void zoomToScale(double scale, JSValueRef) override;
     void retrieveSpeakSelectionContent(JSValueRef) override;
     JSRetainPtr<JSStringRef> accessibilitySpeakSelectionContent() const override;
index e10d9ec..9f3b45f 100644 (file)
@@ -1159,6 +1159,34 @@ void UIScriptControllerIOS::setAllowsViewportShrinkToFit(bool allows)
     webView()._allowsViewportShrinkToFit = allows;
 }
 
+void UIScriptControllerIOS::doAfterDoubleTapDelay(JSValueRef callback)
+{
+    unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
+
+    NSTimeInterval maximumIntervalBetweenSuccessiveTaps = 0;
+    for (UIGestureRecognizer *gesture in [platformContentView() gestureRecognizers]) {
+        if (![gesture isKindOfClass:[UITapGestureRecognizer class]])
+            continue;
+
+        UITapGestureRecognizer *tapGesture = (UITapGestureRecognizer *)gesture;
+        if (tapGesture.numberOfTapsRequired < 2)
+            continue;
+
+        if (tapGesture.maximumIntervalBetweenSuccessiveTaps > maximumIntervalBetweenSuccessiveTaps)
+            maximumIntervalBetweenSuccessiveTaps = tapGesture.maximumIntervalBetweenSuccessiveTaps;
+    }
+
+    if (maximumIntervalBetweenSuccessiveTaps) {
+        const NSTimeInterval additionalDelayBetweenSuccessiveTaps = 0.01;
+        maximumIntervalBetweenSuccessiveTaps += additionalDelayBetweenSuccessiveTaps;
+    }
+
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(maximumIntervalBetweenSuccessiveTaps * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+        if (m_context)
+            m_context->asyncTaskComplete(callbackID);
+    });
+}
+
 }
 
 #endif // PLATFORM(IOS_FAMILY)