Skip to content

[testdriver] Enable manual interaction #11173

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Feb 15, 2019

Conversation

jugglinmike
Copy link
Contributor

@jugglinmike jugglinmike commented May 25, 2018

The testdriver.js utility allows tests which require user input to be
fully automated. It requires that the browser be under the control of a
WebDriver server in order to do this.

In test maintenance contexts, this requirement can slow development
because a new browsing session must be created for each trial, and
debugging tools such as the developer's console cannot be used.

This requirement also limits the tests' value to a larger audience when
published online. Visitors to sites like w3c-test.org are interested in
observing test results experimentally, but although they may be capable
of providing the expected input, the hard requirement on WebDriver will
cause tests to fail unconditionally.

Extend the framework to accept traditional human input if the test is
being run without the WebDriver technology. This allows test authors to
debug tests and other interested parties to verify results in browsers
of their choosing. It does not interfere with fully-automated test
execution.


@gsnedders @kereliuk I'm interested in going even further with this. We could make testdriver.js-powered tests look a lot like today's manual tests by dynamically inserting instructions for human operators. That's less compelling for test authors (since they presumably know exactly what inputs are needed by their own tests), but it could make a big difference for visitors to http://w3c-test.org.

Of course, any change to the document has the potential to invalidate the test, so it would need to be configurable.

For now, I figured this would be a simple and safe way to make test author's lives a little easier.

I'm excited to start extending tests with testdriver.js. Thanks for making it possible!


This change is Reviewable

@gsnedders
Copy link
Member

Given the definition of a user initiated event, we don't actually need to rely on the user carrying out the specific action (at least for what we currently have); we should just be able to throw up a button and tell the user to press that and then dispatch synthetic (but user trusted) events from that for what we need.

Note however: whatwg/html#1903 and https://bugs.chromium.org/p/chromium/issues/detail?id=404161.

@gsnedders
Copy link
Member

(Basically: that doesn't actually quite work currently, but I think it should, and that would be much easier from a UX POV, given we don't need the user to directly trigger the right sequence of events.)

@jugglinmike
Copy link
Contributor Author

Call me a nerd, but that discussion is extremely interesting.

That said, my reading is that the design is heading in a direction that would not support a user interface like "please click this one button, and we'll take care of the rest." It sounds like we're headed towards a consumption-based model, and that would require a 1-to-1 correspondence between user input and protected API call.

@kereliuk
Copy link
Contributor

What use cases are there for manual interaction with testdriver APIs other than debugging (which is an important one).
For debugging at least, I'm leaning towards a 1-to-1 correspondence between user input and protected API call rather than a UI button.
Future testdriver APIs might not have an obvious way to manually interact, but with these I guess we can continue to do what we had before and have it as a not implemented error.

@jugglinmike
Copy link
Contributor Author

What use cases are there for manual interaction with testdriver APIs other than debugging (which is an important one).

Beyond test debugging, this patch allows non-developers to run the tests (e.g. via http://w3c-test.org)

Future testdriver APIs might not have an obvious way to manually interact, but with these I guess we can continue to do what we had before and have it as a not implemented error.

Agreed

@gsnedders
Copy link
Member

@jugglinmike then I misunderstood and we should add something more like this :)

@wpt-pr-bot
Copy link
Collaborator

There are no owners for this pull request. Please reach out on W3C's irc server (irc.w3.org, port 6665) on channel #testing (web client) to get help with this. Thank you!

@gsnedders
Copy link
Member

One thing that would probably good would be draw attention to the element in question, probably by adding a big outline around it.

@jugglinmike
Copy link
Contributor Author

Works for me, @gsnedders. As noted in the comment, I'm recommending we add that decoration even under automation in order to avoid any strange edge cases where the presence of an outline influences the test.

This also needed rebasing to accommodate a recent addition to the testharness.js library. The original version of the branch is available here:

master...bocoup:testdriver-manual-prebase

The testdriver.js utility allows tests which require user input to be
fully automated. It requires that the browser be under the control of a
WebDriver server in order to do this.

In test maintenance contexts, this requirement can slow development
because a new browsing session must be created for each trial, and
debugging tools such as the developer's console cannot be used.

This requirement also limits the tests' value to a larger audience when
published online. Visitors to sites like w3c-test.org are interested in
observing test results experimentally, but although they may be capable
of providing the expected input, the hard requirement on WebDriver will
cause tests to fail unconditionally.

Extend the framework to accept traditional human input if the test is
being run without the WebDriver technology. This allows test authors to
debug tests and other interested parties to verify results in browsers
of their choosing. It does not interfere with fully-automated test
execution.
@jugglinmike
Copy link
Contributor Author

Rebased again to resolve conflicts from gh-11512

@gsnedders
Copy link
Member

On the face of it, this looks good to me.

However, it does mean when we introduce a new testdriver function that the manual codepath will run where previously the Promise rejected, and hence it will run to timeout. And timeouts are going to be a problem with relying on manual interaction with the tests, too.

@jugglinmike
Copy link
Contributor Author

However, it does mean when we introduce a new testdriver function that the
manual codepath will run where previously the Promise rejected, and hence it
will run to timeout.

To support the w3c-test.org/local filesystem use cases, I think that the "fully
manual" implementation has to be the default. We could attempt to detect when
the test is in automation by inspecting the state of the global
test_driver_internal object, and designing all of the "manual"
implementations to throw when any part of that has been modified, e.g.

diff --git a/resources/testdriver.js b/resources/testdriver.js
index 5651bf2..4c3943a 100644
--- a/resources/testdriver.js
+++ b/resources/testdriver.js
@@ -54,6 +54,12 @@
         element.style.outline = 'dashed #0366d6 5px';
     }
 
+    function inAutomation() {
+      return Object.keys(manual).some(function(name) {
+          return window.test_driver_internal[name] !== manual[name];
+      });
+    }
+
     /**
      * @namespace
      */
@@ -154,7 +160,7 @@
         }
     };
 
-    window.test_driver_internal = {
+    var manual = {
         /**
          * Waits for a user-initiated click
          *
@@ -163,7 +169,13 @@
          * @returns {Promise} fulfilled after click occurs
          */
         click: function(element, coords) {
-            return new Promise(function(resolve) {
+            return new Promise(function(resolve, reject) {
+                if (!inAutomation()) {
+                    reject(new Error('Not implemented'));
+
+                    return;
+                }
+
                 element.addEventListener("click", resolve);
             });
         },
@@ -178,6 +190,12 @@
          */
         send_keys: function(element, keys) {
             return new Promise(function(resolve, reject) {
+                if (!inAutomation()) {
+                    reject(new Error('Not implemented'));
+
+                    return;
+                }
+
                 var seen = "";
 
                 function onKeyDown(event) {
@@ -208,4 +226,7 @@
             return Promise.reject(new Error("unimplemented"));
         }
     };
+
+    window.test_driver_internal = Object.create(manual);
+
 })();

This is a little implicit, though. We could also require that implementers
define a property on test_driver_internal to make this more transparent.
That's a different kind of undesirable because it's more to document and prone
to accidental omission.

Do either of those strategies seem like a good idea to you?

And timeouts are going to be a problem with relying on manual interaction
with the tests, too.

That's true, but since that is a case where we know a human operator is
manually executing the test, I think the risk of a timeout is preferable to the
certainty of a failure.

@foolip foolip requested a review from LukeZielinski November 24, 2018 10:31
@foolip
Copy link
Member

foolip commented Nov 24, 2018

@LukeZielinski would be good for you to review these changes too I think.

aarongable pushed a commit to chromium/chromium that referenced this pull request Nov 28, 2018
This is in preparation for supporting manual interactions on testdriver.
By setting this field to true, unimplemented APIs will fail early rather
than waiting for user input (and timing out).

web-platform-tests/wpt#11173

Change-Id: Ie409b683755358fb7978989bf3894e7b45b05239
Reviewed-on: https://chromium-review.googlesource.com/c/1352571
Commit-Queue: Philip Jägenstedt <[email protected]>
Reviewed-by: Philip Jägenstedt <[email protected]>
Cr-Commit-Position: refs/heads/master@{#611690}
Copy link
Contributor

@LukeZielinski LukeZielinski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jugglinmike
Copy link
Contributor Author

I submitted this patch before we integrated Taskcluster into WPT. This means that Taskcluster ignores pushes to the branch, and that's a problem now that the Taskcluster check is required.

I would normally rebase the branch, but since the patch has already been reviewed and approved, I've merged master instead. Please take care to squash when merging this, @LukeZielinski / @gsnedders!

@jugglinmike
Copy link
Contributor Author

It looks like this is blocked on existing flakiness. @gsnedders how would you feel about admin-merging this?

Copy link
Member

@gsnedders gsnedders left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jugglinmike see @foolip's outstanding (non-resolved) comments

@@ -137,27 +137,64 @@
}
};

window.test_driver_internal = {
var manual = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

foolip and others added 2 commits December 17, 2018 20:04
@jugglinmike
Copy link
Contributor Author

@jugglinmike see @foolip's outstanding (non-resolved) comments

Got it!

@foolip
Copy link
Member

foolip commented Dec 20, 2018

This PR is blocked on the required "Travis CI - Pull Request" check after #14499. In order to trigger it, I will close and reopen this PR.

@foolip foolip closed this Dec 20, 2018
@foolip foolip reopened this Dec 20, 2018
@foolip foolip dismissed gsnedders’s stale review February 15, 2019 10:45

I'll fix it separately.

@foolip
Copy link
Member

foolip commented Feb 15, 2019

I'll close and reopen to trigger new CI runs.

@foolip foolip closed this Feb 15, 2019
@foolip foolip reopened this Feb 15, 2019
@foolip
Copy link
Member

foolip commented Feb 15, 2019

Taskcluster failures.

Chrome

Test Subtest Results Messages
/event-timing/event-timing-timingconditions.html OK: 5/10, TIMEOUT: 5/10
/event-timing/event-timing-timingconditions.html Event Timing only times certain types of trusted event. FAIL: 5/10, TIMEOUT: 5/10 assert_equals: Should only observe one entry: []. expected 1 but got 0;Test timed out
/feature-policy/picture-in-picture-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html CRASH: 1/10, OK: 9/10
/feature-policy/picture-in-picture-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html Feature-Policy allow="picture-in-picture" allows same-origin navigation in an iframe. PASS: 9/10, MISSING: 1/10
/feature-policy/picture-in-picture-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html Feature-Policy allow="picture-in-picture" disallows cross-origin navigation in an iframe. PASS: 9/10, MISSING: 1/10
/feature-policy/picture-in-picture-allowed-by-feature-policy.https.sub.html CRASH: 1/10, OK: 9/10
/feature-policy/picture-in-picture-allowed-by-feature-policy.https.sub.html Feature-Policy header: picture-in-picture * allows the top-level document. PASS: 9/10, MISSING: 1/10
/feature-policy/picture-in-picture-allowed-by-feature-policy.https.sub.html Feature-Policy header: picture-in-picture * allows same-origin iframes. PASS: 9/10, MISSING: 1/10
/feature-policy/picture-in-picture-allowed-by-feature-policy.https.sub.html Feature-Policy header: picture-in-picture * allows cross-origin iframes. PASS: 9/10, MISSING: 1/10
/speech-api/SpeechSynthesis-pause-resume.tentative.html OK: 1/10, TIMEOUT: 9/10
/speech-api/SpeechSynthesis-pause-resume.tentative.html speechSynthesis.pause() and resume() state and events FAIL: 1/10, TIMEOUT: 9/10 assert_unreached: error event Reached unreachable code;Test timed out

Firefox

Test Subtest Results Messages
/bluetooth/requestDevice/canonicalizeFilter/max-length-exceeded-name-unicode.https.html ERROR: 1/10, OK: 9/10
/bluetooth/requestDevice/canonicalizeFilter/max-length-exceeded-name-unicode.https.html Unicode string with utf8 representation longer than 248 bytes in 'name' must throw TypeError. FAIL: 9/10, MISSING: 1/10 promise_test: Unhandled rejection with value: object "ReferenceError: Mojo is not defined"
/feature-policy/reporting/camera-report-only.https.html ERROR: 1/10, TIMEOUT: 9/10
/feature-policy/reporting/camera-report-only.https.html Camera report only mode TIMEOUT: 9/10, MISSING: 1/10 Test timed out
/pointerevents/pointerevent_setpointercapture_inactive_button_mouse.html OK: 4/10, TIMEOUT: 6/10
/pointerevents/pointerevent_setpointercapture_inactive_button_mouse.html setPointerCapture + inactive button state FAIL: 4/10, MISSING: 6/10 InvalidPointerId: Invalid pointer id.

@foolip
Copy link
Member

foolip commented Feb 15, 2019

Changing testdriver.js affects tests that were perhaps already flaky, so that isn't very actionable.

Filed web-platform-tests/wpt.fyi#1147 about a problem with the wpt.fyi checks.

There is some regression risk here, but I'll merge and then post a comparison between full runs before/after the change.

@foolip foolip merged commit bfd9504 into web-platform-tests:master Feb 15, 2019
aarongable pushed a commit to chromium/chromium that referenced this pull request Mar 22, 2019
Primarily to support manual interaction of testdriver APIs:
web-platform-tests/wpt#11173

Also roll idlharness.js by the way (webidl2.js hasn't changed).

Change-Id: Ic30677459f9dce2384cffb82b6bf77a141c13495
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1474986
Commit-Queue: Robert Ma <[email protected]>
Reviewed-by: Philip Jägenstedt <[email protected]>
Cr-Commit-Position: refs/heads/master@{#643197}
marcoscaceres pushed a commit that referenced this pull request Jul 23, 2019
The testdriver.js utility allows tests which require user input to be
fully automated. It requires that the browser be under the control of a
WebDriver server in order to do this.

In test maintenance contexts, this requirement can slow development
because a new browsing session must be created for each trial, and
debugging tools such as the developer's console cannot be used.

This requirement also limits the tests' value to a larger audience when
published online. Visitors to sites like w3c-test.org are interested in
observing test results experimentally, but although they may be capable
of providing the expected input, the hard requirement on WebDriver will
cause tests to fail unconditionally.

Extend the framework to accept traditional human input if the test is
being run without the WebDriver technology. This allows test authors to
debug tests and other interested parties to verify results in browsers
of their choosing. It does not interfere with fully-automated test
execution.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
content-security-policy docs infra testdriver.js wptrunner The automated test runner, commonly called through ./wpt run
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants