Skip to content
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

Enable testdriver to return results to tests. #18431

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions docs/writing-tests/testdriver-tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ This happens here in the same file:
```javascript
let pending_resolve = null;
let pending_reject = null;
let result = null;
window.addEventListener("message", function(event) {
const data = event.data;

Expand All @@ -112,7 +113,8 @@ This happens here in the same file:
}

if (data.status === "success") {
pending_resolve();
result = JSON.parse(data.message).result
pending_resolve(result);
} else {
pending_reject();
}
Expand Down Expand Up @@ -315,5 +317,35 @@ run instead of testdriver-extra.js in browser-specific test environments. For ex

### What if I need to return a value from my testdriver API?

We currently don't have this capability, but it is coming soon and will be documented. The bug is [here](https://github.com/web-platform-tests/wpt/issues/10716)
You can return values from testdriver by just making your Action and Protocol classes use return statements. The data being returned will be serialized into JSON and passed
back to the test on the resolving promise. The test can then deserialize the JSON to access the return values. Here is an example of a theoretical GetWindowRect API:

```python
class GetWindowRectAction(object):
def __call__(self, payload):
return self.protocol.get_window_rect.get_window_rect()
```

The WebDriver command will return a [WindowRect object](https://www.w3.org/TR/webdriver1/#dfn-window-rect), which is a dictionary with keys `x`, `y`, `width`, and `height`.
```python
class WebDriverGetWindowRectProtocolPart(GetWindowRectProtocolPart):
def get_window_rect(self):
return self.webdriver.get_window_rect()
```

Then a test can access the return value as follows:
```html
<script>
async_test(t => {
test_driver.get_window_rect()
.then((result) => {
assert_equals(result.x, 0)
assert_equals(result.y, 10)
assert_equals(result.width, 800)
assert_equals(result.height, 600)
t.done();
})
});
</script>
```

8 changes: 5 additions & 3 deletions tools/wptrunner/wptrunner/executors/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import hashlib
from six.moves.http_client import HTTPConnection
import io
import json
import os
import threading
import traceback
Expand Down Expand Up @@ -615,15 +616,16 @@ def process_action(self, url, payload):
except KeyError:
raise ValueError("Unknown action %s" % action)
try:
action_handler(payload)
result = action_handler(payload)
except Exception:
self.logger.warning("Action %s failed" % action)
self.logger.warning(traceback.format_exc())
self._send_message("complete", "error")
raise
else:
self.logger.debug("Action %s completed" % action)
self._send_message("complete", "success")
self.logger.debug("Action %s completed with result %s" % (action, result))
return_message = {"result": result}
self._send_message("complete", "success", json.dumps(return_message))

return False, None

Expand Down
4 changes: 3 additions & 1 deletion tools/wptrunner/wptrunner/testdriver-extra.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
(function(){
let pending_resolve = null;
let pending_reject = null;
let result = null;
window.addEventListener("message", function(event) {
const data = event.data;

Expand All @@ -15,7 +16,8 @@
}

if (data.status === "success") {
pending_resolve();
result = JSON.parse(data.message).result
pending_resolve(result);
} else {
pending_reject();
}
Expand Down