Commit 373c08b7 authored by Chromium WPT Sync's avatar Chromium WPT Sync Committed by Commit Bot

Import wpt@68c457ca8284cf54237f62174561bdef10ec72c7

Using wpt-import in Chromium 25035574.
With Chromium commits locally applied on WPT:
750bcab0 "[ScrollTimeline] Update compositor timeline from blink timeline"


Note to sheriffs: This CL imports external tests and adds
expectations for those tests; if this CL is large and causes
a few new failures, please fix the failures by adding new
lines to TestExpectations rather than reverting. See:
https://chromium.googlesource.com/chromium/src/+/master/docs/testing/web_platform_tests.md

Directory owners for changes in this CL:
foolip@chromium.org, lpz@chromium.org, robertma@chromium.org:
  external/wpt/tools
foolip@chromium.org, robertma@chromium.org, smcgruer@chromium.org:
  external/wpt/infrastructure
jsbell@chromium.org:
  external/wpt/resources

NOAUTOREVERT=true
TBR=robertma

No-Export: true
Change-Id: I26010ce757548d5e046df79f2cd9941b2cb575df
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2226279Reviewed-by: default avatarWPT Autoroller <wpt-autoroller@chops-service-accounts.iam.gserviceaccount.com>
Commit-Queue: WPT Autoroller <wpt-autoroller@chops-service-accounts.iam.gserviceaccount.com>
Cr-Commit-Position: refs/heads/master@{#774477}
parent c3bc0d24
...@@ -2637,6 +2637,12 @@ crbug.com/1024156 external/wpt/css/css-pseudo/cascade-highlight-004.html [ Failu ...@@ -2637,6 +2637,12 @@ crbug.com/1024156 external/wpt/css/css-pseudo/cascade-highlight-004.html [ Failu
crbug.com/1086855 external/wpt/css/css-pseudo/file-chooser-button-001.tentative.html [ Failure ] crbug.com/1086855 external/wpt/css/css-pseudo/file-chooser-button-001.tentative.html [ Failure ]
# ====== New tests from wpt-importer added here ====== # ====== New tests from wpt-importer added here ======
crbug.com/626703 [ Linux ] external/wpt/infrastructure/reftest/reftest_match-print.html [ Failure ]
crbug.com/626703 [ Mac ] external/wpt/infrastructure/reftest/reftest_match-print.html [ Failure ]
crbug.com/626703 [ Win ] external/wpt/infrastructure/reftest/reftest_match-print.html [ Failure ]
crbug.com/626703 [ Linux ] external/wpt/infrastructure/reftest/reftest_match_fail-print.html [ Failure ]
crbug.com/626703 [ Mac ] external/wpt/infrastructure/reftest/reftest_match_fail-print.html [ Failure ]
crbug.com/626703 [ Win ] external/wpt/infrastructure/reftest/reftest_match_fail-print.html [ Failure ]
crbug.com/626703 [ Linux ] external/wpt/css/CSS2/normal-flow/min-height-applies-to-014.xht [ Failure ] crbug.com/626703 [ Linux ] external/wpt/css/CSS2/normal-flow/min-height-applies-to-014.xht [ Failure ]
crbug.com/626703 [ Mac ] external/wpt/css/CSS2/normal-flow/min-height-applies-to-014.xht [ Failure ] crbug.com/626703 [ Mac ] external/wpt/css/CSS2/normal-flow/min-height-applies-to-014.xht [ Failure ]
crbug.com/626703 [ Win ] external/wpt/css/CSS2/normal-flow/min-height-applies-to-014.xht [ Failure ] crbug.com/626703 [ Win ] external/wpt/css/CSS2/normal-flow/min-height-applies-to-014.xht [ Failure ]
......
...@@ -214,9 +214,7 @@ table.simple { ...@@ -214,9 +214,7 @@ table.simple {
is to ensure that most tests are automatable (i.e. they're either is to ensure that most tests are automatable (i.e. they're either
reftests or use <code>testharness.js</code>). Even where manual tests reftests or use <code>testharness.js</code>). Even where manual tests
are absolutely necessary they should be written so that they can be are absolutely necessary they should be written so that they can be
easily automated – as there are on-going efforts to make easily automated. This means that even if a manual test requires user
WebDriver [<cite><a class="bibref" href="#bib-webdriver">webdriver</a></cite>] automated tests a first class citizen in W3C
testing. This means that even if a manual test requires user
interaction, the validation or PASS/FAIL conditions should still be interaction, the validation or PASS/FAIL conditions should still be
clear enough as to allow automatic validation if said interaction is clear enough as to allow automatic validation if said interaction is
later automated. later automated.
......
<!doctype html>
<script>
parent.postMessage(document.readyState, "*");
let f = document.createElement("iframe");
f.onload = function() {
parent.postMessage("stop", "*");
window.stop();
};
document.documentElement.appendChild(f);
window.addEventListener("load", (event) => {
parent.postMessage("load", "*");
});
window.addEventListener("error", (event) => {
parent.postMessage("error", "*");
});
window.addEventListener("abort", (event) => {
parent.postMessage("abort", "*");
});
window.addEventListener("pageshow", (event) => {
parent.postMessage("pageshow", "*");
});
window.addEventListener("DOMContentLoaded", (event) => {
parent.postMessage("DOMContentLoaded", "*");
});
document.addEventListener("readystatechange", (event) => {
if (document.readyState === "complete") {
parent.postMessage("complete", "*");
}
});
</script>
<!doctype html>
<script>
parent.postMessage(document.readyState, "*");
window.addEventListener("load", (event) => {
parent.postMessage("load", "*");
});
window.addEventListener("error", (event) => {
parent.postMessage("error", "*");
});
window.addEventListener("abort", (event) => {
parent.postMessage("abort", "*");
});
window.addEventListener("pageshow", (event) => {
parent.postMessage("pageshow", "*");
});
window.addEventListener("DOMContentLoaded", (event) => {
parent.postMessage("DOMContentLoaded", "*");
});
document.addEventListener("readystatechange", (event) => {
if (document.readyState === "complete") {
parent.postMessage("complete", "*");
}
});
window.setTimeout(function() {
parent.postMessage("stop", "*");
window.stop();
}, 100);
</script>
<link rel="stylesheet" href="/common/slow.py"></link>
This is a testharness.js-based test.
FAIL Aborting a Document load assert_array_equals: no load event was fired lengths differ, expected array ["loading", "DOMContentLoaded", "stop", "complete"] length 4, got ["loading", "stop"] length 2
Harness: the test ran to completion.
<!doctype html>
<title>Aborting a Document load</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<link rel="help" href="https://html.spec.whatwg.org/multipage/browsing-the-web.html#aborting-a-document-load">
<div id="log"></div>
<script>
var events = [];
onmessage = function(e) {
events.push(e.data);
};
async_test(test => {
test.step_timeout(() => {
const frame = document.querySelector('iframe');
const child = frame.contentWindow;
assert_equals(child.document.readyState, 'complete', 'readyState is complete');
assert_array_equals(events, ["loading", "DOMContentLoaded", "stop", "complete"], 'no load event was fired');
events = [];
frame.src = "abort-document-load-2.html";
test.step_timeout(() => {
const child = frame.contentWindow;
assert_equals(child.document.readyState, 'complete', 'readyState is complete');
assert_array_equals(events, ["loading", "DOMContentLoaded", "stop", "complete"], 'no load event was fired');
test.done();
}, 1000);
}, 1000);
});
</script>
<iframe src="abort-document-load-1.html"></iframe>
<title></title>
<meta name="reftest-pages" content="1-2">
<style>
* {margin: 0; padding:0}
/* It is unclear to me why this is 180px rather than 192px (2 inches at 96dpi) */
div {height:180px;}
</style>
<div>
page 1
</div>
<div>
page 2
</div>
<title>rel=match that should pass</title>
<link rel=match href=reftest_match-print-ref.html>
<style>
* {margin: 0; padding:0}
div {page-break-after: always;}
</style>
<div>
page 1
</div>
<div>
page 2
</div>
<title>rel=match that should fail</title>
<link rel=match href=reftest_match-print-ref.html>
<style>
* {margin: 0; padding:0}
div {page-break-after: always;}
</style>
<div>
page 1
</div>
<div>
Another page
</div>
...@@ -17,7 +17,9 @@ interface Headers { ...@@ -17,7 +17,9 @@ interface Headers {
iterable<ByteString, ByteString>; iterable<ByteString, ByteString>;
}; };
typedef (Blob or BufferSource or FormData or URLSearchParams or ReadableStream or USVString) BodyInit; typedef (Blob or BufferSource or FormData or URLSearchParams or USVString) XMLHttpRequestBodyInit;
typedef (ReadableStream or XMLHttpRequestBodyInit) BodyInit;
interface mixin Body { interface mixin Body {
readonly attribute ReadableStream? body; readonly attribute ReadableStream? body;
readonly attribute boolean bodyUsed; readonly attribute boolean bodyUsed;
......
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
* Triggers a user-initiated click * Triggers a user-initiated click
* *
* This matches the behaviour of the {@link * This matches the behaviour of the {@link
* https://w3c.github.io/webdriver/webdriver-spec.html#element-click|WebDriver * https://w3c.github.io/webdriver/#element-click|WebDriver
* Element Click command}. * Element Click command}.
* *
* @param {Element} element - element to be clicked * @param {Element} element - element to be clicked
...@@ -126,7 +126,7 @@ ...@@ -126,7 +126,7 @@
* Send keys to an element * Send keys to an element
* *
* This matches the behaviour of the {@link * This matches the behaviour of the {@link
* https://w3c.github.io/webdriver/webdriver-spec.html#element-send-keys|WebDriver * https://w3c.github.io/webdriver/#element-send-keys|WebDriver
* Send Keys command}. * Send Keys command}.
* *
* @param {Element} element - element to send keys to * @param {Element} element - element to send keys to
......
...@@ -302,6 +302,12 @@ class RefTest(URLManifestItem): ...@@ -302,6 +302,12 @@ class RefTest(URLManifestItem):
**extras) **extras)
class PrintRefTest(RefTest):
__slots__ = ("references",)
item_type = "print-reftest"
class ManualTest(URLManifestItem): class ManualTest(URLManifestItem):
__slots__ = () __slots__ = ()
......
...@@ -15,8 +15,16 @@ from six import ( ...@@ -15,8 +15,16 @@ from six import (
) )
from . import vcs from . import vcs
from .item import (ConformanceCheckerTest, ManifestItem, ManualTest, RefTest, SupportFile, from .item import (ConformanceCheckerTest,
TestharnessTest, VisualTest, WebDriverSpecTest, CrashTest) CrashTest,
ManifestItem,
ManualTest,
PrintRefTest,
RefTest,
SupportFile,
TestharnessTest,
VisualTest,
WebDriverSpecTest)
from .log import get_logger from .log import get_logger
from .sourcefile import SourceFile from .sourcefile import SourceFile
from .typedata import TypeData from .typedata import TypeData
...@@ -57,6 +65,7 @@ class ManifestVersionMismatch(ManifestError): ...@@ -57,6 +65,7 @@ class ManifestVersionMismatch(ManifestError):
item_classes = {"testharness": TestharnessTest, item_classes = {"testharness": TestharnessTest,
"reftest": RefTest, "reftest": RefTest,
"print-reftest": PrintRefTest,
"crashtest": CrashTest, "crashtest": CrashTest,
"manual": ManualTest, "manual": ManualTest,
"wdspec": WebDriverSpecTest, "wdspec": WebDriverSpecTest,
......
...@@ -33,8 +33,16 @@ except ImportError: ...@@ -33,8 +33,16 @@ except ImportError:
import html5lib import html5lib
from . import XMLParser from . import XMLParser
from .item import (ManifestItem, ManualTest, WebDriverSpecTest, RefTest, TestharnessTest, from .item import (ConformanceCheckerTest,
SupportFile, CrashTest, ConformanceCheckerTest, VisualTest) CrashTest,
ManifestItem,
ManualTest,
PrintRefTest,
RefTest,
SupportFile,
TestharnessTest,
VisualTest,
WebDriverSpecTest)
from .utils import ContextManagerBytesIO, cached_property from .utils import ContextManagerBytesIO, cached_property
wd_pattern = "*.py" wd_pattern = "*.py"
...@@ -45,6 +53,7 @@ reference_file_re = re.compile(r'(^|[\-_])(not)?ref[0-9]*([\-_]|$)') ...@@ -45,6 +53,7 @@ reference_file_re = re.compile(r'(^|[\-_])(not)?ref[0-9]*([\-_]|$)')
space_chars = u"".join(html5lib.constants.spaceCharacters) # type: Text space_chars = u"".join(html5lib.constants.spaceCharacters) # type: Text
def replace_end(s, old, new): def replace_end(s, old, new):
# type: (Text, Text, Text) -> Text # type: (Text, Text, Text) -> Text
""" """
...@@ -416,6 +425,11 @@ class SourceFile(object): ...@@ -416,6 +425,11 @@ class SourceFile(object):
See https://web-platform-tests.org/writing-tests/file-names.html#test-features""" See https://web-platform-tests.org/writing-tests/file-names.html#test-features"""
return "tentative" in self.meta_flags return "tentative" in self.meta_flags
@property
def name_is_print_reftest(self):
# type: () -> bool
return self.type_flag == "print" or "print" in self.dir_path.split(os.path.sep)
@property @property
def markup_type(self): def markup_type(self):
# type: () -> Optional[Text] # type: () -> Optional[Text]
...@@ -851,6 +865,16 @@ class SourceFile(object): ...@@ -851,6 +865,16 @@ class SourceFile(object):
self.rel_path self.rel_path
)] )]
elif self.name_is_webdriver:
rv = WebDriverSpecTest.item_type, [
WebDriverSpecTest(
self.tests_root,
self.rel_path,
self.url_base,
self.rel_url,
timeout=self.timeout
)]
elif self.name_is_visual: elif self.name_is_visual:
rv = VisualTest.item_type, [ rv = VisualTest.item_type, [
VisualTest( VisualTest(
...@@ -869,6 +893,23 @@ class SourceFile(object): ...@@ -869,6 +893,23 @@ class SourceFile(object):
self.rel_url self.rel_url
)] )]
elif self.name_is_print_reftest:
references = self.references
if not references:
raise ValueError("%s detected as print reftest but doesn't have any refs" %
self.path)
rv = PrintRefTest.item_type, [
PrintRefTest(
self.tests_root,
self.rel_path,
self.url_base,
self.rel_url,
references=references,
timeout=self.timeout,
viewport_size=self.viewport_size,
fuzzy=self.fuzzy,
)]
elif self.name_is_multi_global: elif self.name_is_multi_global:
globals = u"" globals = u""
script_metadata = self.script_metadata script_metadata = self.script_metadata
...@@ -926,16 +967,6 @@ class SourceFile(object): ...@@ -926,16 +967,6 @@ class SourceFile(object):
] ]
rv = TestharnessTest.item_type, tests rv = TestharnessTest.item_type, tests
elif self.name_is_webdriver:
rv = WebDriverSpecTest.item_type, [
WebDriverSpecTest(
self.tests_root,
self.rel_path,
self.url_base,
self.rel_url,
timeout=self.timeout
)]
elif self.content_is_css_manual and not self.name_is_reference: elif self.content_is_css_manual and not self.name_is_reference:
rv = ManualTest.item_type, [ rv = ManualTest.item_type, [
ManualTest( ManualTest(
......
# WebDriver client for Python # WebDriver client for Python
This package provides Python bindings This package provides Python bindings
that conform to the [W3C WebDriver standard](https://w3c.github.io/webdriver/webdriver-spec.html), that conform to the [W3C WebDriver standard](https://w3c.github.io/webdriver/),
which specifies a remote control protocol for web browsers. which specifies a remote control protocol for web browsers.
These bindings are written with determining These bindings are written with determining
......
...@@ -462,6 +462,7 @@ class Session(object): ...@@ -462,6 +462,7 @@ class Session(object):
:raises ValueError: If the response body does not contain a :raises ValueError: If the response body does not contain a
`value` key. `value` key.
""" """
response = self.transport.send( response = self.transport.send(
method, url, body, method, url, body,
encoder=protocol.Encoder, decoder=protocol.Decoder, encoder=protocol.Encoder, decoder=protocol.Decoder,
......
...@@ -5,7 +5,8 @@ from ..executors import executor_kwargs as base_executor_kwargs ...@@ -5,7 +5,8 @@ from ..executors import executor_kwargs as base_executor_kwargs
from ..executors.executorwebdriver import (WebDriverTestharnessExecutor, # noqa: F401 from ..executors.executorwebdriver import (WebDriverTestharnessExecutor, # noqa: F401
WebDriverRefTestExecutor, # noqa: F401 WebDriverRefTestExecutor, # noqa: F401
WebDriverCrashtestExecutor) # noqa: F401 WebDriverCrashtestExecutor) # noqa: F401
from ..executors.executorchrome import ChromeDriverWdspecExecutor # noqa: F401 from ..executors.executorchrome import (ChromeDriverWdspecExecutor, # noqa: F401
ChromeDriverPrintRefTestExecutor) # noqa: F401
__wptrunner__ = {"product": "chrome", __wptrunner__ = {"product": "chrome",
...@@ -13,6 +14,7 @@ __wptrunner__ = {"product": "chrome", ...@@ -13,6 +14,7 @@ __wptrunner__ = {"product": "chrome",
"browser": "ChromeBrowser", "browser": "ChromeBrowser",
"executor": {"testharness": "WebDriverTestharnessExecutor", "executor": {"testharness": "WebDriverTestharnessExecutor",
"reftest": "WebDriverRefTestExecutor", "reftest": "WebDriverRefTestExecutor",
"print-reftest": "ChromeDriverPrintRefTestExecutor",
"wdspec": "ChromeDriverWdspecExecutor", "wdspec": "ChromeDriverWdspecExecutor",
"crashtest": "WebDriverCrashtestExecutor"}, "crashtest": "WebDriverCrashtestExecutor"},
"browser_kwargs": "browser_kwargs", "browser_kwargs": "browser_kwargs",
...@@ -81,7 +83,9 @@ def executor_kwargs(test_type, server_config, cache_manager, run_info_data, ...@@ -81,7 +83,9 @@ def executor_kwargs(test_type, server_config, cache_manager, run_info_data,
chrome_options["args"].extend(kwargs["binary_args"]) chrome_options["args"].extend(kwargs["binary_args"])
# Pass the --headless flag to Chrome if WPT's own --headless flag was set # Pass the --headless flag to Chrome if WPT's own --headless flag was set
if kwargs["headless"] and "--headless" not in chrome_options["args"]: # or if we're running print reftests because of crbug.com/753118
if ((kwargs["headless"] or test_type == "print-reftest") and
"--headless" not in chrome_options["args"]):
chrome_options["args"].append("--headless") chrome_options["args"].append("--headless")
executor_kwargs["capabilities"] = capabilities executor_kwargs["capabilities"] = capabilities
......
...@@ -24,6 +24,7 @@ from .base import (get_free_port, ...@@ -24,6 +24,7 @@ from .base import (get_free_port,
from ..executors import executor_kwargs as base_executor_kwargs from ..executors import executor_kwargs as base_executor_kwargs
from ..executors.executormarionette import (MarionetteTestharnessExecutor, # noqa: F401 from ..executors.executormarionette import (MarionetteTestharnessExecutor, # noqa: F401
MarionetteRefTestExecutor, # noqa: F401 MarionetteRefTestExecutor, # noqa: F401
MarionettePrintRefTestExecutor, # noqa: F401
MarionetteWdspecExecutor, # noqa: F401 MarionetteWdspecExecutor, # noqa: F401
MarionetteCrashtestExecutor) # noqa: F401 MarionetteCrashtestExecutor) # noqa: F401
from ..process import cast_env from ..process import cast_env
...@@ -37,6 +38,7 @@ __wptrunner__ = {"product": "firefox", ...@@ -37,6 +38,7 @@ __wptrunner__ = {"product": "firefox",
"executor": {"crashtest": "MarionetteCrashtestExecutor", "executor": {"crashtest": "MarionetteCrashtestExecutor",
"testharness": "MarionetteTestharnessExecutor", "testharness": "MarionetteTestharnessExecutor",
"reftest": "MarionetteRefTestExecutor", "reftest": "MarionetteRefTestExecutor",
"print-reftest": "MarionettePrintRefTestExecutor",
"wdspec": "MarionetteWdspecExecutor"}, "wdspec": "MarionetteWdspecExecutor"},
"browser_kwargs": "browser_kwargs", "browser_kwargs": "browser_kwargs",
"executor_kwargs": "executor_kwargs", "executor_kwargs": "executor_kwargs",
......
...@@ -182,6 +182,11 @@ class TestEnvironment(object): ...@@ -182,6 +182,11 @@ class TestEnvironment(object):
for path, format_args, content_type, route in [ for path, format_args, content_type, route in [
("testharness_runner.html", {}, "text/html", "/testharness_runner.html"), ("testharness_runner.html", {}, "text/html", "/testharness_runner.html"),
("print_reftest_runner.html", {}, "text/html", "/print_reftest_runner.html"),
(os.path.join(here, "..", "..", "third_party", "pdf_js", "pdf.js"), None,
"text/javascript", "/_pdf_js/pdf.js"),
(os.path.join(here, "..", "..", "third_party", "pdf_js", "pdf.worker.js"), None,
"text/javascript", "/_pdf_js/pdf.worker.js"),
(self.options.get("testharnessreport", "testharnessreport.js"), (self.options.get("testharnessreport", "testharnessreport.js"),
{"output": self.pause_after_test, {"output": self.pause_after_test,
"timeout_multiplier": self.testharness_timeout_multipler, "timeout_multiplier": self.testharness_timeout_multipler,
......
import os
import traceback
from six.moves.urllib.parse import urljoin
from .base import WdspecProtocol, WdspecExecutor, get_pages
from .executorwebdriver import WebDriverProtocol, WebDriverRefTestExecutor, WebDriverRun
from .protocol import PrintProtocolPart
from ..webdriver_server import ChromeDriverServer from ..webdriver_server import ChromeDriverServer
from .base import WdspecExecutor, WebDriverProtocol
here = os.path.join(os.path.split(__file__)[0])
class ChromeDriverPrintProtocolPart(PrintProtocolPart):
def setup(self):
self.webdriver = self.parent.webdriver
self.runner_handle = None
def load_runner(self):
url = urljoin(self.parent.executor.server_url("http"), "/print_reftest_runner.html")
self.logger.debug("Loading %s" % url)
try:
self.webdriver.url = url
except Exception as e:
self.logger.critical(
"Loading initial page %s failed. Ensure that the "
"there are no other programs bound to this port and "
"that your firewall rules or network setup does not "
"prevent access.\n%s" % (url, traceback.format_exc(e)))
raise
self.runner_handle = self.webdriver.window_handle
def render_as_pdf(self, width, height):
page_ranges = self.webdriver.execute_script(
"""
let elem = document.querySelector("meta[name=reftest-pages]");
return elem ? elem.content : null;
""")
margin = 0.5
body = {
"cmd": "Page.printToPDF",
"params": {
# Chrome accepts dimensions in inches; we are using cm
"paperWidth": width / 2.54,
"paperHeight": height / 2.54,
"marginLeft": margin,
"marginRight": margin,
"marginTop": margin,
"marginBottom": margin,
"shrinkToFit": False,
"printBackground": True,
}
}
return (self.webdriver.send_session_command("POST", "goog/cdp/execute", body=body)["data"],
page_ranges)
def pdf_to_png(self, pdf_base64, ranges):
handle = self.webdriver.window_handle
self.webdriver.window_handle = self.runner_handle
try:
rv = self.webdriver.execute_async_script("""
let callback = arguments[arguments.length - 1];
render('%s').then(result => callback(result))""" % pdf_base64)
page_numbers = get_pages(ranges, len(rv))
rv = [item for i, item in enumerate(rv) if i + 1 in page_numbers]
return rv
finally:
self.webdriver.window_handle = handle
class ChromeDriverProtocol(WebDriverProtocol): class ChromeDriverProtocol(WebDriverProtocol):
implements = WebDriverProtocol.implements + [ChromeDriverPrintProtocolPart]
class ChromeDriverPrintRefTestExecutor(WebDriverRefTestExecutor):
protocol_cls = ChromeDriverProtocol
def setup(self, runner):
super(ChromeDriverPrintRefTestExecutor, self).setup(runner)
self.protocol.pdf_print.load_runner()
self.has_window = False
with open(os.path.join(here, "reftest.js")) as f:
self.script = f.read()
def screenshot(self, test, viewport_size, dpi):
# https://github.com/web-platform-tests/wpt/issues/7140
assert dpi is None
if not self.has_window:
self.protocol.base.execute_script(self.script)
self.protocol.base.set_window(self.protocol.webdriver.handles[-1])
self.has_window = True
self.viewport_size = viewport_size
timeout = self.timeout_multiplier * test.timeout if self.debug_info is None else None
test_url = self.test_url(test)
return WebDriverRun(self.logger,
self._render,
self.protocol,
test_url,
timeout,
self.extra_timeout).run()
def _render(self, protocol, url, timeout):
protocol.webdriver.url = url
protocol.base.execute_script(self.wait_script, asynchronous=True)
pdf, page_ranges = protocol.pdf_print.render_as_pdf(*self.viewport_size)
screenshots = protocol.pdf_print.pdf_to_png(pdf, page_ranges)
for i, screenshot in enumerate(screenshots):
# strip off the data:img/png, part of the url
if screenshot.startswith("data:image/png;base64,"):
screenshots[i] = screenshot.split(",", 1)[1]
return screenshots
class ChromeDriverWdspecProtocol(WdspecProtocol):
server_cls = ChromeDriverServer server_cls = ChromeDriverServer
class ChromeDriverWdspecExecutor(WdspecExecutor): class ChromeDriverWdspecExecutor(WdspecExecutor):
protocol_cls = ChromeDriverProtocol protocol_cls = ChromeDriverWdspecProtocol
from ..webdriver_server import EdgeDriverServer from ..webdriver_server import EdgeDriverServer
from .base import WdspecExecutor, WebDriverProtocol from .base import WdspecExecutor, WdspecProtocol
class EdgeDriverProtocol(WebDriverProtocol): class EdgeDriverProtocol(WdspecProtocol):
server_cls = EdgeDriverServer server_cls = EdgeDriverServer
......
from ..webdriver_server import EdgeChromiumDriverServer from ..webdriver_server import EdgeChromiumDriverServer
from .base import WdspecExecutor, WebDriverProtocol from .base import WdspecExecutor, WdspecProtocol
class EdgeChromiumDriverProtocol(WebDriverProtocol): class EdgeChromiumDriverProtocol(WdspecProtocol):
server_cls = EdgeChromiumDriverServer server_cls = EdgeChromiumDriverServer
......
from ..webdriver_server import InternetExplorerDriverServer from ..webdriver_server import InternetExplorerDriverServer
from .base import WdspecExecutor, WebDriverProtocol from .base import WdspecExecutor, WdspecProtocol
class InternetExplorerDriverProtocol(WebDriverProtocol): class InternetExplorerDriverProtocol(WdspecProtocol):
server_cls = InternetExplorerDriverServer server_cls = InternetExplorerDriverServer
......
...@@ -21,7 +21,8 @@ from .base import (CallbackHandler, ...@@ -21,7 +21,8 @@ from .base import (CallbackHandler,
TestharnessExecutor, TestharnessExecutor,
TimedRunner, TimedRunner,
WdspecExecutor, WdspecExecutor,
WebDriverProtocol, WdspecProtocol,
get_pages,
strip_server) strip_server)
from .protocol import (ActionSequenceProtocolPart, from .protocol import (ActionSequenceProtocolPart,
AssertsProtocolPart, AssertsProtocolPart,
...@@ -37,7 +38,8 @@ from .protocol import (ActionSequenceProtocolPart, ...@@ -37,7 +38,8 @@ from .protocol import (ActionSequenceProtocolPart,
CoverageProtocolPart, CoverageProtocolPart,
GenerateTestReportProtocolPart, GenerateTestReportProtocolPart,
VirtualAuthenticatorProtocolPart, VirtualAuthenticatorProtocolPart,
SetPermissionProtocolPart) SetPermissionProtocolPart,
PrintProtocolPart)
from ..testrunner import Stop from ..testrunner import Stop
from ..webdriver_server import GeckoDriverServer from ..webdriver_server import GeckoDriverServer
...@@ -143,7 +145,7 @@ class MarionetteTestharnessProtocolPart(TestharnessProtocolPart): ...@@ -143,7 +145,7 @@ class MarionetteTestharnessProtocolPart(TestharnessProtocolPart):
"Loading initial page %s failed. Ensure that the " "Loading initial page %s failed. Ensure that the "
"there are no other programs bound to this port and " "there are no other programs bound to this port and "
"that your firewall rules or network setup does not " "that your firewall rules or network setup does not "
r"prevent access.\e%s" % (url, traceback.format_exc())) "prevent access.\n%s" % (url, traceback.format_exc()))
raise raise
self.runner_handle = self.marionette.current_window_handle self.runner_handle = self.marionette.current_window_handle
format_map = {"title": threading.current_thread().name.replace("'", '"')} format_map = {"title": threading.current_thread().name.replace("'", '"')}
...@@ -528,6 +530,63 @@ class MarionetteSetPermissionProtocolPart(SetPermissionProtocolPart): ...@@ -528,6 +530,63 @@ class MarionetteSetPermissionProtocolPart(SetPermissionProtocolPart):
def set_permission(self, name, state, one_realm): def set_permission(self, name, state, one_realm):
raise NotImplementedError("set_permission not yet implemented") raise NotImplementedError("set_permission not yet implemented")
class MarionettePrintProtocolPart(PrintProtocolPart):
def setup(self):
self.marionette = self.parent.marionette
self.runner_handle = None
def load_runner(self):
url = urljoin(self.parent.executor.server_url("http"), "/print_reftest_runner.html")
self.logger.debug("Loading %s" % url)
try:
self.marionette.navigate(url)
except Exception as e:
self.logger.critical(
"Loading initial page %s failed. Ensure that the "
"there are no other programs bound to this port and "
"that your firewall rules or network setup does not "
"prevent access.\n%s" % (url, traceback.format_exc(e)))
raise
self.runner_handle = self.marionette.current_window_handle
def render_as_pdf(self, width, height):
page_ranges = self.marionette.execute_script(
"""
let elem = document.querySelector("meta[name=reftest-pages]");
return elem ? elem.content : null;
""",
new_sandbox=False, sandbox=None)
margin = 0.5 * 2.54
body = {
"page": {
"width": width,
"height": height
},
"margin": {
"left": margin,
"right": margin,
"top": margin,
"bottom": margin,
},
"shrinkToFit": False,
"printBackground": True,
}
return self.marionette._send_message("WebDriver:Print", body, key="value"), page_ranges
def pdf_to_png(self, pdf_base64, ranges):
handle = self.marionette.current_window_handle
self.marionette.switch_to_window(self.runner_handle)
try:
rv = self.marionette.execute_async_script("""
let callback = arguments[arguments.length - 1];
render('%s').then(result => callback(result))""" % pdf_base64, new_sandbox=False, sandbox=None)
page_numbers = get_pages(ranges, len(rv))
rv = [item for i, item in enumerate(rv) if i + 1 in page_numbers]
return rv
finally:
self.marionette.switch_to_window(handle)
class MarionetteProtocol(Protocol): class MarionetteProtocol(Protocol):
implements = [MarionetteBaseProtocolPart, implements = [MarionetteBaseProtocolPart,
MarionetteTestharnessProtocolPart, MarionetteTestharnessProtocolPart,
...@@ -542,7 +601,8 @@ class MarionetteProtocol(Protocol): ...@@ -542,7 +601,8 @@ class MarionetteProtocol(Protocol):
MarionetteCoverageProtocolPart, MarionetteCoverageProtocolPart,
MarionetteGenerateTestReportProtocolPart, MarionetteGenerateTestReportProtocolPart,
MarionetteVirtualAuthenticatorProtocolPart, MarionetteVirtualAuthenticatorProtocolPart,
MarionetteSetPermissionProtocolPart] MarionetteSetPermissionProtocolPart,
MarionettePrintProtocolPart]
def __init__(self, executor, browser, capabilities=None, timeout_multiplier=1, e10s=True, ccov=False): def __init__(self, executor, browser, capabilities=None, timeout_multiplier=1, e10s=True, ccov=False):
do_delayed_imports() do_delayed_imports()
...@@ -781,9 +841,7 @@ class MarionetteRefTestExecutor(RefTestExecutor): ...@@ -781,9 +841,7 @@ class MarionetteRefTestExecutor(RefTestExecutor):
self.protocol = MarionetteProtocol(self, browser, capabilities, self.protocol = MarionetteProtocol(self, browser, capabilities,
timeout_multiplier, kwargs["e10s"], timeout_multiplier, kwargs["e10s"],
ccov) ccov)
self.implementation = (InternalRefTestImplementation self.implementation = self.get_implementation(reftest_internal)
if reftest_internal
else RefTestImplementation)(self)
self.implementation_kwargs = ({"screenshot": reftest_screenshot} if self.implementation_kwargs = ({"screenshot": reftest_screenshot} if
reftest_internal else {}) reftest_internal else {})
...@@ -798,6 +856,10 @@ class MarionetteRefTestExecutor(RefTestExecutor): ...@@ -798,6 +856,10 @@ class MarionetteRefTestExecutor(RefTestExecutor):
with open(os.path.join(here, "test-wait.js")) as f: with open(os.path.join(here, "test-wait.js")) as f:
self.wait_script = f.read() % {"classname": "reftest-wait"} self.wait_script = f.read() % {"classname": "reftest-wait"}
def get_implementation(self, reftest_internal):
return (InternalRefTestImplementation if reftest_internal
else RefTestImplementation)(self)
def setup(self, runner): def setup(self, runner):
super(MarionetteRefTestExecutor, self).setup(runner) super(MarionetteRefTestExecutor, self).setup(runner)
self.implementation.setup(**self.implementation_kwargs) self.implementation.setup(**self.implementation_kwargs)
...@@ -916,6 +978,9 @@ class InternalRefTestImplementation(RefTestImplementation): ...@@ -916,6 +978,9 @@ class InternalRefTestImplementation(RefTestImplementation):
"timeout": timeout, "timeout": timeout,
"width": 800, "width": 800,
"height": 600})["value"] "height": 600})["value"]
for item in rv["extra"].get("reftest_screenshots", []):
if "screenshot" in item:
item["screenshot"] = [item["screenshot"]]
return rv return rv
def get_references(self, root_test, node): def get_references(self, root_test, node):
...@@ -941,7 +1006,7 @@ class InternalRefTestImplementation(RefTestImplementation): ...@@ -941,7 +1006,7 @@ class InternalRefTestImplementation(RefTestImplementation):
self.logger.warning(traceback.format_exc()) self.logger.warning(traceback.format_exc())
class GeckoDriverProtocol(WebDriverProtocol): class GeckoDriverProtocol(WdspecProtocol):
server_cls = GeckoDriverServer server_cls = GeckoDriverServer
...@@ -1016,3 +1081,60 @@ class MarionetteCrashtestExecutor(CrashtestExecutor): ...@@ -1016,3 +1081,60 @@ class MarionetteCrashtestExecutor(CrashtestExecutor):
return {"status": "PASS", return {"status": "PASS",
"message": None} "message": None}
class MarionettePrintRefTestExecutor(MarionetteRefTestExecutor):
def __init__(self, logger, browser, server_config, timeout_multiplier=1,
screenshot_cache=None, close_after_done=True,
debug_info=None, reftest_screenshot="unexpected", ccov=False,
group_metadata=None, capabilities=None, debug=False, **kwargs):
"""Marionette-based executor for reftests"""
MarionetteRefTestExecutor.__init__(self,
logger,
browser,
server_config,
timeout_multiplier=timeout_multiplier,
screenshot_cache=screenshot_cache,
close_after_done=close_after_done,
debug_info=debug_info,
reftest_screenshot=reftest_screenshot,
reftest_internal=False,
ccov=ccov,
group_metadata=group_metadata,
capabilities=capabilities,
debug=debug,
**kwargs)
def setup(self, runner):
super(MarionettePrintRefTestExecutor, self).setup(runner)
self.protocol.pdf_print.load_runner()
def screenshot(self, test, viewport_size, dpi):
# https://github.com/web-platform-tests/wpt/issues/7140
assert dpi is None
self.viewport_size = viewport_size
timeout = self.timeout_multiplier * test.timeout if self.debug_info is None else None
test_url = self.test_url(test)
return ExecuteAsyncScriptRun(self.logger,
self._render,
self.protocol,
test_url,
timeout,
self.extra_timeout).run()
def _render(self, protocol, url, timeout):
protocol.marionette.navigate(url)
protocol.base.execute_script(self.wait_script, asynchronous=True)
pdf, page_ranges = protocol.pdf_print.render_as_pdf(*self.viewport_size)
screenshots = protocol.pdf_print.pdf_to_png(pdf, page_ranges)
for i, screenshot in enumerate(screenshots):
# strip off the data:img/png, part of the url
if screenshot.startswith("data:image/png;base64,"):
screenshots[i] = screenshot.split(",", 1)[1]
return screenshots
from ..webdriver_server import OperaDriverServer from ..webdriver_server import OperaDriverServer
from .base import WdspecExecutor, WebDriverProtocol from .base import WdspecExecutor, WdspecProtocol
class OperaDriverProtocol(WebDriverProtocol): class OperaDriverProtocol(WdspecProtocol):
server_cls = OperaDriverServer server_cls = OperaDriverServer
......
from ..webdriver_server import SafariDriverServer from ..webdriver_server import SafariDriverServer
from .base import WdspecExecutor, WebDriverProtocol from .base import WdspecExecutor, WdspecProtocol
class SafariDriverProtocol(WebDriverProtocol): class SafariDriverProtocol(WdspecProtocol):
server_cls = SafariDriverServer server_cls = SafariDriverServer
......
...@@ -20,7 +20,7 @@ from .base import (ConnectionlessProtocol, ...@@ -20,7 +20,7 @@ from .base import (ConnectionlessProtocol,
reftest_result_converter, reftest_result_converter,
TimedRunner, TimedRunner,
WdspecExecutor, WdspecExecutor,
WebDriverProtocol) WdspecProtocol)
from .process import ProcessTestExecutor from .process import ProcessTestExecutor
from ..browsers.base import browser_command from ..browsers.base import browser_command
from ..process import cast_env from ..process import cast_env
...@@ -264,7 +264,7 @@ class ServoRefTestExecutor(ProcessTestExecutor): ...@@ -264,7 +264,7 @@ class ServoRefTestExecutor(ProcessTestExecutor):
with open(output_path, "rb") as f: with open(output_path, "rb") as f:
# Might need to strip variable headers or something here # Might need to strip variable headers or something here
data = f.read() data = f.read()
return True, ensure_str(base64.b64encode(data)) return True, [ensure_str(base64.b64encode(data))]
def do_test(self, test): def do_test(self, test):
result = self.implementation.run_test(test) result = self.implementation.run_test(test)
...@@ -281,7 +281,7 @@ class ServoRefTestExecutor(ProcessTestExecutor): ...@@ -281,7 +281,7 @@ class ServoRefTestExecutor(ProcessTestExecutor):
" ".join(self.command)) " ".join(self.command))
class ServoDriverProtocol(WebDriverProtocol): class ServoDriverProtocol(WdspecProtocol):
server_cls = ServoDriverServer server_cls = ServoDriverServer
......
...@@ -349,6 +349,7 @@ class WebDriverRun(TimedRunner): ...@@ -349,6 +349,7 @@ class WebDriverRun(TimedRunner):
class WebDriverTestharnessExecutor(TestharnessExecutor): class WebDriverTestharnessExecutor(TestharnessExecutor):
supports_testdriver = True supports_testdriver = True
protocol_cls = WebDriverProtocol
def __init__(self, logger, browser, server_config, timeout_multiplier=1, def __init__(self, logger, browser, server_config, timeout_multiplier=1,
close_after_done=True, capabilities=None, debug_info=None, close_after_done=True, capabilities=None, debug_info=None,
...@@ -357,7 +358,7 @@ class WebDriverTestharnessExecutor(TestharnessExecutor): ...@@ -357,7 +358,7 @@ class WebDriverTestharnessExecutor(TestharnessExecutor):
TestharnessExecutor.__init__(self, logger, browser, server_config, TestharnessExecutor.__init__(self, logger, browser, server_config,
timeout_multiplier=timeout_multiplier, timeout_multiplier=timeout_multiplier,
debug_info=debug_info) debug_info=debug_info)
self.protocol = WebDriverProtocol(self, browser, capabilities) self.protocol = self.protocol_cls(self, browser, capabilities)
with open(os.path.join(here, "testharness_webdriver_resume.js")) as f: with open(os.path.join(here, "testharness_webdriver_resume.js")) as f:
self.script_resume = f.read() self.script_resume = f.read()
self.close_after_done = close_after_done self.close_after_done = close_after_done
...@@ -449,6 +450,8 @@ if (location.href === "about:blank") { ...@@ -449,6 +450,8 @@ if (location.href === "about:blank") {
class WebDriverRefTestExecutor(RefTestExecutor): class WebDriverRefTestExecutor(RefTestExecutor):
protocol_cls = WebDriverProtocol
def __init__(self, logger, browser, server_config, timeout_multiplier=1, def __init__(self, logger, browser, server_config, timeout_multiplier=1,
screenshot_cache=None, close_after_done=True, screenshot_cache=None, close_after_done=True,
debug_info=None, capabilities=None, **kwargs): debug_info=None, capabilities=None, **kwargs):
...@@ -460,7 +463,8 @@ class WebDriverRefTestExecutor(RefTestExecutor): ...@@ -460,7 +463,8 @@ class WebDriverRefTestExecutor(RefTestExecutor):
screenshot_cache=screenshot_cache, screenshot_cache=screenshot_cache,
timeout_multiplier=timeout_multiplier, timeout_multiplier=timeout_multiplier,
debug_info=debug_info) debug_info=debug_info)
self.protocol = WebDriverProtocol(self, browser, self.protocol = self.protocol_cls(self,
browser,
capabilities=capabilities) capabilities=capabilities)
self.implementation = RefTestImplementation(self) self.implementation = RefTestImplementation(self)
self.close_after_done = close_after_done self.close_after_done = close_after_done
...@@ -518,6 +522,8 @@ class WebDriverRefTestExecutor(RefTestExecutor): ...@@ -518,6 +522,8 @@ class WebDriverRefTestExecutor(RefTestExecutor):
class WebDriverCrashtestExecutor(CrashtestExecutor): class WebDriverCrashtestExecutor(CrashtestExecutor):
protocol_cls = WebDriverProtocol
def __init__(self, logger, browser, server_config, timeout_multiplier=1, def __init__(self, logger, browser, server_config, timeout_multiplier=1,
screenshot_cache=None, close_after_done=True, screenshot_cache=None, close_after_done=True,
debug_info=None, capabilities=None, **kwargs): debug_info=None, capabilities=None, **kwargs):
...@@ -529,7 +535,8 @@ class WebDriverCrashtestExecutor(CrashtestExecutor): ...@@ -529,7 +535,8 @@ class WebDriverCrashtestExecutor(CrashtestExecutor):
screenshot_cache=screenshot_cache, screenshot_cache=screenshot_cache,
timeout_multiplier=timeout_multiplier, timeout_multiplier=timeout_multiplier,
debug_info=debug_info) debug_info=debug_info)
self.protocol = WebDriverProtocol(self, browser, self.protocol = self.protocol_cls(self,
browser,
capabilities=capabilities) capabilities=capabilities)
with open(os.path.join(here, "test-wait.js")) as f: with open(os.path.join(here, "test-wait.js")) as f:
......
from ..webdriver_server import WebKitDriverServer from ..webdriver_server import WebKitDriverServer
from .base import WdspecExecutor, WebDriverProtocol from .base import WdspecExecutor, WdspecProtocol
class WebKitDriverProtocol(WebDriverProtocol): class WebKitDriverProtocol(WdspecProtocol):
server_cls = WebKitDriverServer server_cls = WebKitDriverServer
......
...@@ -388,6 +388,7 @@ class CoverageProtocolPart(ProtocolPart): ...@@ -388,6 +388,7 @@ class CoverageProtocolPart(ProtocolPart):
"""Dump coverage counters""" """Dump coverage counters"""
pass pass
class VirtualAuthenticatorProtocolPart(ProtocolPart): class VirtualAuthenticatorProtocolPart(ProtocolPart):
"""Protocol part for creating and manipulating virtual authenticators""" """Protocol part for creating and manipulating virtual authenticators"""
__metaclass__ = ABCMeta __metaclass__ = ABCMeta
...@@ -446,3 +447,15 @@ class VirtualAuthenticatorProtocolPart(ProtocolPart): ...@@ -446,3 +447,15 @@ class VirtualAuthenticatorProtocolPart(ProtocolPart):
:param str authenticator_id: The ID of the authenticator :param str authenticator_id: The ID of the authenticator
:param bool uv: the user verified flag""" :param bool uv: the user verified flag"""
pass pass
class PrintProtocolPart(ProtocolPart):
"""Protocol part for rendering to a PDF."""
__metaclass__ = ABCMeta
name = "pdf_print"
@abstractmethod
def render_as_pdf(self, width, height):
"""Output document as PDF"""
pass
<!doctype html>
<title></title>
<script src="/_pdf_js/pdf.js"></script>
<canvas></canvas>
<script>
function render(pdfData) {
return _render(pdfData);
}
async function _render(pdfData) {
let loadingTask = pdfjsLib.getDocument({data: atob(pdfData)});
let pdf = await loadingTask.promise;
let rendered = [];
for (let pageNumber=1; pageNumber<=pdf.numPages; pageNumber++) {
let page = await pdf.getPage(pageNumber);
var viewport = page.getViewport({scale: 96./72.});
// Prepare canvas using PDF page dimensions
var canvas = document.getElementsByTagName('canvas')[0];
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context
var renderContext = {
canvasContext: context,
viewport: viewport
};
await page.render(renderContext).promise;
rendered.push(canvas.toDataURL());
}
return rendered;
}
</script>
...@@ -8,7 +8,7 @@ from six import iteritems, string_types ...@@ -8,7 +8,7 @@ from six import iteritems, string_types
from .wptmanifest.parser import atoms from .wptmanifest.parser import atoms
atom_reset = atoms["Reset"] atom_reset = atoms["Reset"]
enabled_tests = {"testharness", "reftest", "wdspec", "crashtest"} enabled_tests = {"testharness", "reftest", "wdspec", "crashtest", "print-reftest"}
class Result(object): class Result(object):
...@@ -462,7 +462,7 @@ class ReftestTest(Test): ...@@ -462,7 +462,7 @@ class ReftestTest(Test):
raise ValueError raise ValueError
self.references = references self.references = references
self.viewport_size = viewport_size self.viewport_size = self.get_viewport_size(viewport_size)
self.dpi = dpi self.dpi = dpi
self._fuzzy = fuzzy or {} self._fuzzy = fuzzy or {}
...@@ -555,6 +555,10 @@ class ReftestTest(Test): ...@@ -555,6 +555,10 @@ class ReftestTest(Test):
reference.update_metadata(metadata) reference.update_metadata(metadata)
return metadata return metadata
def get_viewport_size(self, override):
assert override is None
return None
@property @property
def id(self): def id(self):
return self.url return self.url
...@@ -590,6 +594,13 @@ class ReftestTest(Test): ...@@ -590,6 +594,13 @@ class ReftestTest(Test):
return values return values
class PrintReftestTest(ReftestTest):
test_type = "print-reftest"
def get_viewport_size(self, override):
assert override is None
return (5*2.54, 3*2.54)
class WdspecTest(Test): class WdspecTest(Test):
result_cls = WdspecResult result_cls = WdspecResult
subtest_result_cls = WdspecSubtestResult subtest_result_cls = WdspecSubtestResult
...@@ -605,6 +616,7 @@ class CrashTest(Test): ...@@ -605,6 +616,7 @@ class CrashTest(Test):
manifest_test_cls = {"reftest": ReftestTest, manifest_test_cls = {"reftest": ReftestTest,
"print-reftest": PrintReftestTest,
"testharness": TestharnessTest, "testharness": TestharnessTest,
"manual": ManualTest, "manual": ManualTest,
"wdspec": WdspecTest, "wdspec": WdspecTest,
......
...@@ -467,6 +467,8 @@ class StaticHandler(StringHandler): ...@@ -467,6 +467,8 @@ class StaticHandler(StringHandler):
:param headers: List of headers to send with responses""" :param headers: List of headers to send with responses"""
with open(path) as f: with open(path) as f:
data = f.read() % format_args data = f.read()
if format_args:
data = data % format_args
return super(StaticHandler, self).__init__(data, content_type, **headers) return super(StaticHandler, self).__init__(data, content_type, **headers)
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Herein lies a set of conformance tests Herein lies a set of conformance tests
for the W3C web browser automation specification for the W3C web browser automation specification
known as [WebDriver](http://w3c.github.io/webdriver/webdriver-spec.html). known as [WebDriver](http://w3c.github.io/webdriver/).
The purpose of these tests is determine implementation compliance The purpose of these tests is determine implementation compliance
so that different driver implementations can determine so that different driver implementations can determine
whether they meet the recognized standard. whether they meet the recognized standard.
......
...@@ -28,7 +28,7 @@ def test_get_named_session_cookie(session, url): ...@@ -28,7 +28,7 @@ def test_get_named_session_cookie(session, url):
assert isinstance(cookie, dict) assert isinstance(cookie, dict)
# table for cookie conversion # table for cookie conversion
# https://w3c.github.io/webdriver/webdriver-spec.html#dfn-table-for-cookie-conversion # https://w3c.github.io/webdriver/#dfn-table-for-cookie-conversion
assert "name" in cookie assert "name" in cookie
assert isinstance(cookie["name"], text_type) assert isinstance(cookie["name"], text_type)
assert "value" in cookie assert "value" in cookie
......
...@@ -26,7 +26,7 @@ class Keys(object): ...@@ -26,7 +26,7 @@ class Keys(object):
""" """
Set of special keys codes. Set of special keys codes.
See also https://w3c.github.io/webdriver/#h-keyboard-actions See also https://w3c.github.io/webdriver/#keyboard-actions
""" """
NULL = u"\ue000" NULL = u"\ue000"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment