diff --git a/WebDriverTests/ChangeLog b/WebDriverTests/ChangeLog index 1067ef9e4934..ab24b212bf85 100644 --- a/WebDriverTests/ChangeLog +++ b/WebDriverTests/ChangeLog @@ -1,3 +1,44 @@ +2018-01-10 Carlos Garcia Campos + + Unreviewed. Update W3C WebDriver imported tests. + + * imported/w3c/importer.json: + * imported/w3c/tools/wptrunner/wptrunner/browsers/firefox.py: + * imported/w3c/tools/wptrunner/wptrunner/browsers/servo.py: + * imported/w3c/tools/wptrunner/wptrunner/environment.py: + * imported/w3c/tools/wptrunner/wptrunner/executors/base.py: + * imported/w3c/tools/wptrunner/wptrunner/executors/executormarionette.py: + * imported/w3c/tools/wptrunner/wptrunner/executors/executorservo.py: + * imported/w3c/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py: + * imported/w3c/tools/wptrunner/wptrunner/testrunner.py: + * imported/w3c/tools/wptrunner/wptrunner/update/update.py: + * imported/w3c/tools/wptrunner/wptrunner/webdriver_server.py: + * imported/w3c/tools/wptrunner/wptrunner/wptlogging.py: + * imported/w3c/tools/wptrunner/wptrunner/wptrunner.py: + * imported/w3c/webdriver/OWNERS: + * imported/w3c/webdriver/interface/interface.html: Removed. + * imported/w3c/webdriver/tests/actions/modifier_click.py: + * imported/w3c/webdriver/tests/actions/mouse.py: + * imported/w3c/webdriver/tests/actions/mouse_dblclick.py: Added. + * imported/w3c/webdriver/tests/actions/sequence.py: + * imported/w3c/webdriver/tests/actions/support/mouse.py: Added. + * imported/w3c/webdriver/tests/cookies/add_cookie.py: + * imported/w3c/webdriver/tests/cookies/get_named_cookie.py: + * imported/w3c/webdriver/tests/element_retrieval/__init__.py: Copied from WebDriverTests/imported/w3c/webdriver/tests/retrieval/__init__.py. + * imported/w3c/webdriver/tests/element_retrieval/find_element.py: Renamed from WebDriverTests/imported/w3c/webdriver/tests/retrieval/find_element.py. + * imported/w3c/webdriver/tests/element_retrieval/find_element_from_element.py: Renamed from WebDriverTests/imported/w3c/webdriver/tests/retrieval/find_element_from_element.py. + * imported/w3c/webdriver/tests/element_retrieval/find_elements.py: Renamed from WebDriverTests/imported/w3c/webdriver/tests/retrieval/find_elements.py. + * imported/w3c/webdriver/tests/element_retrieval/find_elements_from_element.py: Renamed from WebDriverTests/imported/w3c/webdriver/tests/retrieval/find_element_from_elements.py. + * imported/w3c/webdriver/tests/element_send_keys/__init__.py: Renamed from WebDriverTests/imported/w3c/webdriver/tests/retrieval/__init__.py. + * imported/w3c/webdriver/tests/element_send_keys/interactability.py: Added. + * imported/w3c/webdriver/tests/element_send_keys/scroll_into_view.py: Added. + * imported/w3c/webdriver/tests/execute_script/cyclic.py: Added. + * imported/w3c/webdriver/tests/get_window_rect.py: + * imported/w3c/webdriver/tests/interface.html: + * imported/w3c/webdriver/tests/navigation/current_url.py: + * imported/w3c/webdriver/tests/support/asserts.py: + * imported/w3c/webdriver/tests/support/fixtures.py: + 2017-12-14 Carlos Garcia Campos WebDriver: add a common way to run tests with pytest diff --git a/WebDriverTests/imported/w3c/importer.json b/WebDriverTests/imported/w3c/importer.json index af46c5897556..6778b25e1668 100644 --- a/WebDriverTests/imported/w3c/importer.json +++ b/WebDriverTests/imported/w3c/importer.json @@ -1,6 +1,6 @@ { "repository": "https://github.com/w3c/web-platform-tests.git", - "revision": "267d6b27ffd416577702653c0987b30239daae3f", + "revision": "941f6aa2949e24475a7dcd53fd1cb70142059d37", "paths_to_import": [ "tools/webdriver", "tools/wptrunner", diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/firefox.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/firefox.py index 552cd15b4598..b324bccd91e2 100644 --- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/firefox.py +++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/firefox.py @@ -51,7 +51,10 @@ def get_timeout_multiplier(test_type, run_info_data, **kwargs): else: return 2 elif run_info_data["debug"] or run_info_data.get("asan"): - return 3 + if run_info_data.get("ccov"): + return 4 + else: + return 3 return 1 diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/servo.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/servo.py index 89d69ab9e543..3738ce4bddcd 100644 --- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/servo.py +++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/browsers/servo.py @@ -42,6 +42,8 @@ def executor_kwargs(test_type, server_config, cache_manager, run_info_data, rv = base_executor_kwargs(test_type, server_config, cache_manager, **kwargs) rv["pause_after_test"] = kwargs["pause_after_test"] + if test_type == "wdspec": + rv["capabilities"] = {} return rv diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/environment.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/environment.py index e8734405e00e..874595cbff3f 100644 --- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/environment.py +++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/environment.py @@ -36,8 +36,6 @@ def do_delayed_imports(logger, test_paths): try: from tools.serve import serve - except ImportError: - from wpt_tools.serve import serve except ImportError: failed.append("serve") @@ -86,7 +84,6 @@ def __init__(self, test_paths, ssl_env, pause_after_test, debug_info, options, e self.ssl_env = ssl_env self.server = None self.config = None - self.external_config = None self.pause_after_test = pause_after_test self.test_server_port = options.pop("test_server_port", True) self.debug_info = debug_info @@ -105,9 +102,10 @@ def __enter__(self): cm.__enter__(self.options) self.setup_server_logging() self.config = self.load_config() - serve.set_computed_defaults(self.config) - self.external_config, self.servers = serve.start(self.config, self.ssl_env, - self.get_routes()) + ports = serve.get_ports(self.config, self.ssl_env) + self.config = serve.normalise_config(self.config, ports) + self.servers = serve.start(self.config, self.ssl_env, + self.get_routes()) if self.options.get("supports_debugger") and self.debug_info and self.debug_info.interactive: self.ignore_interrupts() return self @@ -160,6 +158,8 @@ def load_config(self): config["key_file"] = key_file config["certificate"] = certificate + serve.set_computed_defaults(config) + return config def setup_server_logging(self): diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/base.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/base.py index cc04d767f8b3..d87e4ab9924f 100644 --- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/base.py +++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/base.py @@ -113,7 +113,7 @@ def __init__(self, browser, server_config, timeout_multiplier=1, :param browser: ExecutorBrowser instance providing properties of the browser that will be tested. :param server_config: Dictionary of wptserve server configuration of the - form stored in TestEnvironment.external_config + form stored in TestEnvironment.config :param timeout_multiplier: Multiplier relative to base timeout to use when setting test timeout. """ diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executormarionette.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executormarionette.py index edea3f14aa4d..2d0dc914d105 100644 --- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executormarionette.py +++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executormarionette.py @@ -175,7 +175,11 @@ def wait(self): # This can happen if there was a crash return if socket_timeout: - self.marionette.timeout.script = socket_timeout / 2 + try: + self.marionette.timeout.script = socket_timeout / 2 + except (socket.error, IOError): + self.logger.debug("Socket closed") + return self.marionette.switch_to_window(self.runner_handle) while True: @@ -564,7 +568,7 @@ def teardown(self): self.executor.protocol.marionette.set_context(self.executor.protocol.marionette.CONTEXT_CONTENT) except Exception as e: # Ignore errors during teardown - self.logger.warning(traceback.traceback.format_exc(e)) + self.logger.warning(traceback.format_exc(e)) diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executorservo.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executorservo.py index 97fe304305ed..33ff10df9287 100644 --- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executorservo.py +++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/executorservo.py @@ -18,7 +18,7 @@ RefTestImplementation, testharness_result_converter, reftest_result_converter, - WdspecExecutor) + WdspecExecutor, WebDriverProtocol) from .process import ProcessTestExecutor from ..browsers.base import browser_command from ..wpttest import WdspecResult, WdspecSubtestResult @@ -286,82 +286,9 @@ def on_output(self, line): line, " ".join(self.command)) -class ServoWdspecProtocol(Protocol): - def __init__(self, executor, browser): - self.do_delayed_imports() - Protocol.__init__(self, executor, browser) - self.session = None - self.server = None - - def setup(self, runner): - try: - self.server = ServoDriverServer(self.logger, binary=self.browser.binary, binary_args=self.browser.binary_args) - self.server.start(block=False) - self.logger.info( - "WebDriver HTTP server listening at %s" % self.server.url) - - self.logger.info( - "Establishing new WebDriver session with %s" % self.server.url) - self.session = webdriver.Session( - self.server.host, self.server.port, self.server.base_path) - except Exception: - self.logger.error(traceback.format_exc()) - self.executor.runner.send_message("init_failed") - else: - self.executor.runner.send_message("init_succeeded") - - def teardown(self): - if self.server is not None: - try: - if self.session.session_id is not None: - self.session.end() - except Exception: - pass - if self.server.is_alive: - self.server.stop() - - @property - def is_alive(self): - conn = httplib.HTTPConnection(self.server.host, self.server.port) - conn.request("HEAD", self.server.base_path + "invalid") - res = conn.getresponse() - return res.status == 404 - - def do_delayed_imports(self): - global pytestrunner, webdriver - from . import pytestrunner - import webdriver +class ServoDriverProtocol(WebDriverProtocol): + server_cls = ServoDriverServer class ServoWdspecExecutor(WdspecExecutor): - def __init__(self, browser, server_config, - timeout_multiplier=1, close_after_done=True, debug_info=None, - **kwargs): - WdspecExecutor.__init__(self, browser, server_config, - timeout_multiplier=timeout_multiplier, - debug_info=debug_info) - self.protocol = ServoWdspecProtocol(self, browser) - - def is_alive(self): - return self.protocol.is_alive - - def on_environment_change(self, new_environment): - pass - - def do_test(self, test): - timeout = test.timeout * self.timeout_multiplier + extra_timeout - - success, data = WdspecRun(self.do_wdspec, - self.protocol.session, - test.path, - timeout).run() - - if success: - return self.convert_result(test, data) - - return (test.result_cls(*data), []) - - def do_wdspec(self, session, path, timeout): - harness_result = ("OK", None) - subtest_results = pytestrunner.run(path, session, timeout=timeout) - return (harness_result, subtest_results) + protocol_cls = ServoDriverProtocol diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py index a2b603dd0443..0870b1232ad5 100644 --- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py +++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py @@ -117,7 +117,7 @@ def record_skip(self, report): def record(self, test, status, message=None, stack=None): if stack is not None: stack = str(stack) - new_result = (test, status, message, stack) + new_result = (test.split("::")[-1], status, message, stack) self.results.append(new_result) diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/testrunner.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/testrunner.py index 64418285e66f..75f4825f9525 100644 --- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/testrunner.py +++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/testrunner.py @@ -120,6 +120,13 @@ def start_runner(runner_command_queue, runner_result_queue, executor_browser_cls, executor_browser_kwargs, stop_flag): """Launch a TestRunner in a new process""" + def log(level, msg): + runner_result_queue.put(("log", (level, {"message": msg}))) + + def handle_error(e): + log("critical", traceback.format_exc()) + stop_flag.set() + try: browser = executor_browser_cls(**executor_browser_kwargs) executor = executor_cls(browser, **executor_kwargs) @@ -128,10 +135,10 @@ def start_runner(runner_command_queue, runner_result_queue, runner.run() except KeyboardInterrupt: stop_flag.set() - except Exception: - runner_result_queue.put(("log", ("critical", {"message": traceback.format_exc()}))) - print >> sys.stderr, traceback.format_exc() - stop_flag.set() + except Exception as e: + handle_error(e) + except Exception as e: + handle_error(e) finally: runner_command_queue = None runner_result_queue = None @@ -389,6 +396,7 @@ def wait_event(self): } try: command, data = self.command_queue.get(True, 1) + self.logger.debug("Got command: %r" % command) except IOError: self.logger.error("Got IOError from poll") return RunnerManagerState.restarting(0) @@ -676,7 +684,18 @@ def cleanup(self): self.browser.cleanup() while True: try: - self.logger.warning(" ".join(map(repr, self.command_queue.get_nowait()))) + cmd, data = self.command_queue.get_nowait() + except Empty: + break + else: + if cmd == "log": + self.log(*data) + else: + self.logger.warning("%r: %r" % (cmd, data)) + while True: + try: + cmd, data = self.remote_queue.get_nowait() + self.logger.warning("%r: %r" % (cmd, data)) except Empty: break diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/update/update.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/update/update.py index d9ef40fcda83..c985d3513ace 100644 --- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/update/update.py +++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/update/update.py @@ -11,10 +11,7 @@ def setup_paths(sync_path): sys.path.insert(0, os.path.abspath(sync_path)) - try: - from tools import localpaths - except ImportError: - from wpt_tools import localpaths + from tools import localpaths class LoadConfig(Step): """Step for loading configuration from the ini file and kwargs.""" diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/webdriver_server.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/webdriver_server.py index 4a3c48c58000..fc853bfb97e6 100644 --- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/webdriver_server.py +++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/webdriver_server.py @@ -195,10 +195,11 @@ def make_command(self): class ServoDriverServer(WebDriverServer): - def __init__(self, logger, binary="servo", binary_args=None, host="127.0.0.1", port=None): + def __init__(self, logger, binary="servo", binary_args=None, host="127.0.0.1", + port=None, args=None): env = os.environ.copy() env["RUST_BACKTRACE"] = "1" - WebDriverServer.__init__(self, logger, binary, host=host, port=port, env=env) + WebDriverServer.__init__(self, logger, binary, host=host, port=port, env=env, args=args) self.binary_args = binary_args def make_command(self): diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/wptlogging.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/wptlogging.py index 4d320617859c..26d174c066bc 100644 --- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/wptlogging.py +++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/wptlogging.py @@ -1,13 +1,20 @@ import logging import sys import threading +from Queue import Empty from StringIO import StringIO from multiprocessing import Queue -from mozlog import commandline, stdadapter +from mozlog import commandline, stdadapter, set_default_logger +from mozlog.structuredlog import StructuredLogger def setup(args, defaults): - logger = commandline.setup_logging("web-platform-tests", args, defaults) + logger = args.pop('log', None) + if logger: + set_default_logger(logger) + StructuredLogger._logger_states["web-platform-tests"] = logger._state + else: + logger = commandline.setup_logging("web-platform-tests", args, defaults) setup_stdlib_logger() for name in args.keys(): @@ -45,7 +52,6 @@ def __call__(self, data): return self.inner(data) - class LogThread(threading.Thread): def __init__(self, queue, logger, level): self.queue = queue @@ -120,5 +126,10 @@ def __exit__(self, *args, **kwargs): self.logging_queue.put(None) if self.logging_thread is not None: self.logging_thread.join(10) + while not self.logging_queue.empty(): + try: + self.logger.warning("Dropping log message: %r", self.logging_queue.get()) + except Exception: + pass self.logging_queue.close() self.logger.info("queue closed") diff --git a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/wptrunner.py b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/wptrunner.py index be81eb982a5e..637cbe57b6f4 100644 --- a/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/wptrunner.py +++ b/WebDriverTests/imported/w3c/tools/wptrunner/wptrunner/wptrunner.py @@ -201,7 +201,7 @@ def run_tests(config, test_paths, product, **kwargs): logger.info("Repetition %i / %i" % (repeat_count, repeat)) unexpected_count = 0 - logger.suite_start(test_loader.test_ids, run_info) + logger.suite_start(test_loader.test_ids, name='web-platform-test', run_info=run_info) for test_type in kwargs["test_types"]: logger.info("Running %s tests" % test_type) @@ -222,7 +222,7 @@ def run_tests(config, test_paths, product, **kwargs): executor_cls = executor_classes.get(test_type) executor_kwargs = get_executor_kwargs(test_type, - test_environment.external_config, + test_environment.config, test_environment.cache_manager, run_info, **kwargs) diff --git a/WebDriverTests/imported/w3c/webdriver/OWNERS b/WebDriverTests/imported/w3c/webdriver/OWNERS index 07296e312b35..c004c0467e02 100644 --- a/WebDriverTests/imported/w3c/webdriver/OWNERS +++ b/WebDriverTests/imported/w3c/webdriver/OWNERS @@ -4,3 +4,4 @@ @lukeis @mjzffr @shs96c +@whimboo diff --git a/WebDriverTests/imported/w3c/webdriver/interface/interface.html b/WebDriverTests/imported/w3c/webdriver/interface/interface.html deleted file mode 100644 index f3c149b1cee0..000000000000 --- a/WebDriverTests/imported/w3c/webdriver/interface/interface.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - diff --git a/WebDriverTests/imported/w3c/webdriver/tests/actions/modifier_click.py b/WebDriverTests/imported/w3c/webdriver/tests/actions/modifier_click.py index 73de161119d8..fdd43e2ebcb9 100644 --- a/WebDriverTests/imported/w3c/webdriver/tests/actions/modifier_click.py +++ b/WebDriverTests/imported/w3c/webdriver/tests/actions/modifier_click.py @@ -6,30 +6,55 @@ from tests.actions.support.keys import Keys +# Using local fixtures because we want to start a new session between +# each test, otherwise the clicks in each test interfere with each other. +@pytest.fixture(autouse=True) +def release_actions(mod_click_session, request): + request.addfinalizer(mod_click_session.actions.release) + + +@pytest.fixture +def mod_click_session(new_session, url, add_browser_capabilites): + _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({})}}) + session.url = url("/webdriver/tests/actions/support/test_actions_wdspec.html") + + return session + + +@pytest.fixture +def key_chain(mod_click_session): + return mod_click_session.actions.sequence("key", "keyboard_id") + + +@pytest.fixture +def mouse_chain(mod_click_session): + return mod_click_session.actions.sequence( + "pointer", + "pointer_id", + {"pointerType": "mouse"}) + + @pytest.mark.parametrize("modifier, prop", [ - (Keys.CONTROL, "ctrlKey"), - (Keys.ALT, "altKey"), - (Keys.META, "metaKey"), - (Keys.SHIFT, "shiftKey"), - (Keys.R_CONTROL, "ctrlKey"), - (Keys.R_ALT, "altKey"), - (Keys.R_META, "metaKey"), - (Keys.R_SHIFT, "shiftKey"), + (Keys.ALT, "altKey"), + (Keys.R_ALT, "altKey"), + (Keys.META, "metaKey"), + (Keys.R_META, "metaKey"), + (Keys.SHIFT, "shiftKey"), + (Keys.R_SHIFT, "shiftKey"), ]) -def test_modifier_click(session, - test_actions_page, +def test_modifier_click(mod_click_session, key_chain, mouse_chain, modifier, prop): key_chain \ - .pause(0) \ + .pause(200) \ .key_down(modifier) \ .pause(200) \ .key_up(modifier) - outer = session.find.css("#outer", all=False) + outer = mod_click_session.find.css("#outer", all=False) mouse_chain.click(element=outer) - session.actions.perform([key_chain.dict, mouse_chain.dict]) + mod_click_session.actions.perform([key_chain.dict, mouse_chain.dict]) expected = [ {"type": "mousemove"}, {"type": "mousedown"}, @@ -46,29 +71,47 @@ def test_modifier_click(session, e.update(defaults) if e["type"] != "mousemove": e[prop] = True - filtered_events = [filter_dict(e, expected[0]) for e in get_events(session)] + filtered_events = [filter_dict(e, expected[0]) for e in get_events(mod_click_session)] assert expected == filtered_events -def test_release_control_click(session, key_reporter, key_chain, mouse_chain): +def test_many_modifiers_click(mod_click_session, key_chain, mouse_chain): + outer = mod_click_session.find.css("#outer", all=False) key_chain \ .pause(0) \ - .key_down(Keys.CONTROL) + .key_down(Keys.CONTROL) \ + .key_down(Keys.SHIFT) \ + .pause(0) \ + .key_up(Keys.CONTROL) \ + .key_up(Keys.SHIFT) mouse_chain \ - .pointer_move(0, 0, origin=key_reporter) \ + .pointer_move(0, 0, origin=outer) \ + .pause(0) \ + .pointer_down() \ + .pointer_up() \ + .pause(0) \ + .pause(0) \ .pointer_down() - session.actions.perform([key_chain.dict, mouse_chain.dict]) - session.execute_script(""" - var keyReporter = document.getElementById("keys"); - ["mousedown", "mouseup"].forEach((e) => { - keyReporter.addEventListener(e, recordPointerEvent); - }); - resetEvents(); - """) - session.actions.release() + mod_click_session.actions.perform([key_chain.dict, mouse_chain.dict]) expected = [ + {"type": "mousemove"}, + # shift and ctrl presses + {"type": "mousedown"}, {"type": "mouseup"}, - {"type": "keyup"}, + {"type": "click"}, + # no modifiers pressed + {"type": "mousedown"}, ] - events = [filter_dict(e, expected[0]) for e in get_events(session)] + defaults = { + "altKey": False, + "metaKey": False, + "shiftKey": False, + "ctrlKey": False + } + for e in expected: + e.update(defaults) + for e in expected[1:4]: + e["shiftKey"] = True + e["ctrlKey"] = True + events = [filter_dict(e, expected[0]) for e in get_events(mod_click_session)] assert events == expected diff --git a/WebDriverTests/imported/w3c/webdriver/tests/actions/mouse.py b/WebDriverTests/imported/w3c/webdriver/tests/actions/mouse.py index 07f7809e918f..95d284c4b72b 100644 --- a/WebDriverTests/imported/w3c/webdriver/tests/actions/mouse.py +++ b/WebDriverTests/imported/w3c/webdriver/tests/actions/mouse.py @@ -1,7 +1,8 @@ import pytest -from tests.support.inline import inline +from tests.actions.support.mouse import assert_move_to_coordinates, get_center from tests.actions.support.refine import get_events, filter_dict +from tests.support.inline import inline from tests.support.wait import wait @@ -10,13 +11,6 @@ def link_doc(dest): return inline(content) -def get_center(rect): - return { - "x": rect["width"] / 2 + rect["x"], - "y": rect["height"] / 2 + rect["y"], - } - - # TODO use pytest.approx once we upgrade to pytest > 3.0 def approx(n, m, tolerance=1): return abs(n - m) <= tolerance @@ -33,11 +27,8 @@ def test_click_at_coordinates(session, test_actions_page, mouse_chain): .perform() events = get_events(session) assert len(events) == 4 + assert_move_to_coordinates(div_point, "outer", events) for e in events: - if e["type"] != "mousemove": - assert e["pageX"] == div_point["x"] - assert e["pageY"] == div_point["y"] - assert e["target"] == "outer" if e["type"] != "mousedown": assert e["buttons"] == 0 assert e["button"] == 0 @@ -89,7 +80,7 @@ def test_click_element_center(session, test_actions_page, mouse_chain): assert e["target"] == "outer" -def test_click_navigation(session, url): +def test_click_navigation(session, url, release_actions): destination = url("/webdriver/tests/actions/support/test_actions_wdspec.html") start = link_doc(destination) @@ -112,7 +103,12 @@ def click(link): @pytest.mark.parametrize("drag_duration", [0, 300, 800]) @pytest.mark.parametrize("dx, dy", [(20, 0), (0, 15), (10, 15), (-20, 0), (10, -15), (-10, -15)]) -def test_drag_and_drop(session, test_actions_page, mouse_chain, dx, dy, drag_duration): +def test_drag_and_drop(session, + test_actions_page, + mouse_chain, + dx, + dy, + drag_duration): drag_target = session.find.css("#dragTarget", all=False) initial_rect = drag_target.rect initial_center = get_center(initial_rect) diff --git a/WebDriverTests/imported/w3c/webdriver/tests/actions/mouse_dblclick.py b/WebDriverTests/imported/w3c/webdriver/tests/actions/mouse_dblclick.py new file mode 100644 index 000000000000..f73f780a7a7e --- /dev/null +++ b/WebDriverTests/imported/w3c/webdriver/tests/actions/mouse_dblclick.py @@ -0,0 +1,108 @@ +import pytest + +from tests.actions.support.mouse import assert_move_to_coordinates, get_center +from tests.actions.support.refine import get_events, filter_dict + + +_DBLCLICK_INTERVAL = 640 + + +# Using local fixtures because we want to start a new session between +# each test, otherwise the clicks in each test interfere with each other. +@pytest.fixture(autouse=True) +def release_actions(dblclick_session, request): + # release all actions after each test + # equivalent to a teardown_function, but with access to session fixture + request.addfinalizer(dblclick_session.actions.release) + + +@pytest.fixture +def dblclick_session(new_session, url, add_browser_capabilites): + _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({})}}) + session.url = url("/webdriver/tests/actions/support/test_actions_wdspec.html") + + return session + + +@pytest.fixture +def mouse_chain(dblclick_session): + return dblclick_session.actions.sequence( + "pointer", + "pointer_id", + {"pointerType": "mouse"}) + + +@pytest.mark.parametrize("click_pause", [0, 200]) +def test_dblclick_at_coordinates(dblclick_session, mouse_chain, click_pause): + div_point = { + "x": 82, + "y": 187, + } + mouse_chain \ + .pointer_move(div_point["x"], div_point["y"]) \ + .click() \ + .pause(click_pause) \ + .click() \ + .perform() + events = get_events(dblclick_session) + assert_move_to_coordinates(div_point, "outer", events) + expected = [ + {"type": "mousedown", "button": 0}, + {"type": "mouseup", "button": 0}, + {"type": "click", "button": 0}, + {"type": "mousedown", "button": 0}, + {"type": "mouseup", "button": 0}, + {"type": "click", "button": 0}, + {"type": "dblclick", "button": 0}, + ] + assert len(events) == 8 + filtered_events = [filter_dict(e, expected[0]) for e in events] + assert expected == filtered_events[1:] + + +def test_dblclick_with_pause_after_second_pointerdown(dblclick_session, mouse_chain): + outer = dblclick_session.find.css("#outer", all=False) + center = get_center(outer.rect) + mouse_chain \ + .pointer_move(int(center["x"]), int(center["y"])) \ + .click() \ + .pointer_down() \ + .pause(_DBLCLICK_INTERVAL + 10) \ + .pointer_up() \ + .perform() + events = get_events(dblclick_session) + expected = [ + {"type": "mousedown", "button": 0}, + {"type": "mouseup", "button": 0}, + {"type": "click", "button": 0}, + {"type": "mousedown", "button": 0}, + {"type": "mouseup", "button": 0}, + {"type": "click", "button": 0}, + {"type": "dblclick", "button": 0}, + ] + assert len(events) == 8 + filtered_events = [filter_dict(e, expected[0]) for e in events] + assert expected == filtered_events[1:] + + +def test_no_dblclick(dblclick_session, mouse_chain): + outer = dblclick_session.find.css("#outer", all=False) + center = get_center(outer.rect) + mouse_chain \ + .pointer_move(int(center["x"]), int(center["y"])) \ + .click() \ + .pause(_DBLCLICK_INTERVAL + 10) \ + .click() \ + .perform() + events = get_events(dblclick_session) + expected = [ + {"type": "mousedown", "button": 0}, + {"type": "mouseup", "button": 0}, + {"type": "click", "button": 0}, + {"type": "mousedown", "button": 0}, + {"type": "mouseup", "button": 0}, + {"type": "click", "button": 0}, + ] + assert len(events) == 7 + filtered_events = [filter_dict(e, expected[0]) for e in events] + assert expected == filtered_events[1:] diff --git a/WebDriverTests/imported/w3c/webdriver/tests/actions/sequence.py b/WebDriverTests/imported/w3c/webdriver/tests/actions/sequence.py index 3092034c46fd..426dbe82f48e 100644 --- a/WebDriverTests/imported/w3c/webdriver/tests/actions/sequence.py +++ b/WebDriverTests/imported/w3c/webdriver/tests/actions/sequence.py @@ -37,45 +37,3 @@ def test_release_no_actions_sends_no_events(session, key_reporter): session.actions.release() assert len(get_keys(key_reporter)) == 0 assert len(get_events(session)) == 0 - - -def test_many_modifiers_click(session, test_actions_page, key_chain, mouse_chain): - outer = session.find.css("#outer", all=False) - key_chain \ - .pause(0) \ - .key_down(Keys.CONTROL) \ - .key_down(Keys.SHIFT) \ - .pause(0) \ - .key_up(Keys.CONTROL) \ - .key_up(Keys.SHIFT) - mouse_chain \ - .pointer_move(0, 0, origin=outer) \ - .pause(0) \ - .pointer_down() \ - .pointer_up() \ - .pause(0) \ - .pause(0) \ - .pointer_down() - session.actions.perform([key_chain.dict, mouse_chain.dict]) - expected = [ - {"type": "mousemove"}, - # shift and ctrl presses - {"type": "mousedown"}, - {"type": "mouseup"}, - {"type": "click"}, - # no modifiers pressed - {"type": "mousedown"}, - ] - defaults = { - "altKey": False, - "metaKey": False, - "shiftKey": False, - "ctrlKey": False - } - for e in expected: - e.update(defaults) - for e in expected[1:4]: - e["shiftKey"] = True - e["ctrlKey"] = True - events = [filter_dict(e, expected[0]) for e in get_events(session)] - assert events == expected diff --git a/WebDriverTests/imported/w3c/webdriver/tests/actions/support/mouse.py b/WebDriverTests/imported/w3c/webdriver/tests/actions/support/mouse.py new file mode 100644 index 000000000000..63a771d9487a --- /dev/null +++ b/WebDriverTests/imported/w3c/webdriver/tests/actions/support/mouse.py @@ -0,0 +1,13 @@ +def assert_move_to_coordinates(point, target, events): + for e in events: + if e["type"] != "mousemove": + assert e["pageX"] == point["x"] + assert e["pageY"] == point["y"] + assert e["target"] == target + + +def get_center(rect): + return { + "x": rect["width"] / 2 + rect["x"], + "y": rect["height"] / 2 + rect["y"], + } diff --git a/WebDriverTests/imported/w3c/webdriver/tests/cookies/add_cookie.py b/WebDriverTests/imported/w3c/webdriver/tests/cookies/add_cookie.py index 86a5f86f3746..1ebbcb41de71 100644 --- a/WebDriverTests/imported/w3c/webdriver/tests/cookies/add_cookie.py +++ b/WebDriverTests/imported/w3c/webdriver/tests/cookies/add_cookie.py @@ -1,15 +1,14 @@ from tests.support.fixtures import clear_all_cookies -from tests.support.fixtures import server_config from datetime import datetime, timedelta -def test_add_domain_cookie(session, url): +def test_add_domain_cookie(session, url, server_config): session.url = url("/common/blank.html") clear_all_cookies(session) create_cookie_request = { "cookie": { "name": "hello", "value": "world", - "domain": "web-platform.test", + "domain": server_config["domains"][""], "path": "/", "httpOnly": False, "secure": False @@ -37,16 +36,16 @@ def test_add_domain_cookie(session, url): assert cookie["name"] == "hello" assert cookie["value"] == "world" - assert cookie["domain"] == ".web-platform.test" + assert cookie["domain"] == ".%s" % server_config["domains"][""] -def test_add_cookie_for_ip(session, url, server_config): +def test_add_cookie_for_ip(session, url, server_config, configuration): session.url = "http://127.0.0.1:%s/404" % (server_config["ports"]["http"][0]) clear_all_cookies(session) create_cookie_request = { "cookie": { "name": "hello", "value": "world", - "domain": "127.0.0.1", + "domain": configuration["host"], "path": "/", "httpOnly": False, "secure": False @@ -142,3 +141,37 @@ def test_add_session_cookie(session, url): assert cookie["name"] == "hello" assert cookie["value"] == "world" + +def test_add_session_cookie_with_leading_dot_character_in_domain(session, url, server_config): + session.url = url("/common/blank.html") + clear_all_cookies(session) + create_cookie_request = { + "cookie": { + "name": "hello", + "value": "world", + "domain": ".%s" % server_config["domains"][""] + } + } + result = session.transport.send("POST", "session/%s/cookie" % session.session_id, create_cookie_request) + assert result.status == 200 + assert "value" in result.body + assert isinstance(result.body["value"], dict) + + result = session.transport.send("GET", "session/%s/cookie" % session.session_id) + assert result.status == 200 + assert "value" in result.body + assert isinstance(result.body["value"], list) + assert len(result.body["value"]) == 1 + assert isinstance(result.body["value"][0], dict) + + cookie = result.body["value"][0] + assert "name" in cookie + assert isinstance(cookie["name"], basestring) + assert "value" in cookie + assert isinstance(cookie["value"], basestring) + assert "domain" in cookie + assert isinstance(cookie["domain"], basestring) + + assert cookie["name"] == "hello" + assert cookie["value"] == "world" + assert cookie["domain"] == ".%s" % server_config["domains"][""] diff --git a/WebDriverTests/imported/w3c/webdriver/tests/cookies/get_named_cookie.py b/WebDriverTests/imported/w3c/webdriver/tests/cookies/get_named_cookie.py index 027859dd7f9d..f367eccf947a 100644 --- a/WebDriverTests/imported/w3c/webdriver/tests/cookies/get_named_cookie.py +++ b/WebDriverTests/imported/w3c/webdriver/tests/cookies/get_named_cookie.py @@ -61,14 +61,14 @@ def test_get_named_cookie(session, url): # convert from seconds since epoch assert datetime.utcfromtimestamp(cookie["expiry"]).strftime(utc_string_format) == a_year_from_now -def test_duplicated_cookie(session, url): +def test_duplicated_cookie(session, url, server_config): session.url = url("/common/blank.html") clear_all_cookies(session) create_cookie_request = { "cookie": { "name": "hello", "value": "world", - "domain": "web-platform.test", + "domain": server_config["domains"][""], "path": "/", "httpOnly": False, "secure": False @@ -79,7 +79,7 @@ def test_duplicated_cookie(session, url): assert "value" in result.body assert isinstance(result.body["value"], dict) - session.url = inline("") + session.url = inline("" % server_config["domains"][""]) result = session.transport.send("GET", "session/%s/cookie" % session.session_id) assert result.status == 200 assert "value" in result.body diff --git a/WebDriverTests/imported/w3c/webdriver/tests/retrieval/__init__.py b/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/__init__.py similarity index 100% rename from WebDriverTests/imported/w3c/webdriver/tests/retrieval/__init__.py rename to WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/__init__.py diff --git a/WebDriverTests/imported/w3c/webdriver/tests/retrieval/find_element.py b/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_element.py similarity index 88% rename from WebDriverTests/imported/w3c/webdriver/tests/retrieval/find_element.py rename to WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_element.py index a0047eb9f080..454e3c38bdcc 100644 --- a/WebDriverTests/imported/w3c/webdriver/tests/retrieval/find_element.py +++ b/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_element.py @@ -71,3 +71,13 @@ def test_xhtml_namespace(session, using, value): response = find_element(session, using, value) value = assert_success(response) assert_same_element(session, value, expected) + + +@pytest.mark.parametrize("using,value", + [("css selector", ":root"), + ("tag name", "html"), + ("xpath", "/html")]) +def test_htmldocument(session, using, value): + session.url = inline("") + response = find_element(session, using, value) + assert_success(response) diff --git a/WebDriverTests/imported/w3c/webdriver/tests/retrieval/find_element_from_element.py b/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_element_from_element.py similarity index 92% rename from WebDriverTests/imported/w3c/webdriver/tests/retrieval/find_element_from_element.py rename to WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_element_from_element.py index 3bf1d860bd44..d79d512a13c5 100644 --- a/WebDriverTests/imported/w3c/webdriver/tests/retrieval/find_element_from_element.py +++ b/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_element_from_element.py @@ -72,3 +72,11 @@ def test_xhtml_namespace(session, using, value): response = find_element(session, from_element.id, using, value) value = assert_success(response) assert_same_element(session, value, expected) + + +def test_parent_htmldocument(session): + session.url = inline("") + from_element = session.execute_script("return document.documentElement") + + response = find_element(session, from_element.id, "xpath", "..") + assert_success(response) diff --git a/WebDriverTests/imported/w3c/webdriver/tests/retrieval/find_elements.py b/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_elements.py similarity index 87% rename from WebDriverTests/imported/w3c/webdriver/tests/retrieval/find_elements.py rename to WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_elements.py index 8bc2113a84ac..a00ae2358c20 100644 --- a/WebDriverTests/imported/w3c/webdriver/tests/retrieval/find_elements.py +++ b/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_elements.py @@ -77,3 +77,15 @@ def test_xhtml_namespace(session, using, value): found_element = value[0] assert_same_element(session, found_element, expected) + + +@pytest.mark.parametrize("using,value", + [("css selector", ":root"), + ("tag name", "html"), + ("xpath", "/html")]) +def test_htmldocument(session, using, value): + session.url = inline("") + response = find_elements(session, using, value) + value = assert_success(response) + assert isinstance(value, list) + assert len(value) == 1 diff --git a/WebDriverTests/imported/w3c/webdriver/tests/retrieval/find_element_from_elements.py b/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_elements_from_element.py similarity index 90% rename from WebDriverTests/imported/w3c/webdriver/tests/retrieval/find_element_from_elements.py rename to WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_elements_from_element.py index 933d69d1e600..486d7cb7aee2 100644 --- a/WebDriverTests/imported/w3c/webdriver/tests/retrieval/find_element_from_elements.py +++ b/WebDriverTests/imported/w3c/webdriver/tests/element_retrieval/find_elements_from_element.py @@ -75,3 +75,13 @@ def test_xhtml_namespace(session, using, value): found_element = value[0] assert_same_element(session, found_element, expected) + + +def test_parent_htmldocument(session): + session.url = inline("") + from_element = session.execute_script("return document.documentElement") + + response = find_elements(session, from_element.id, "xpath", "..") + value = assert_success(response) + assert isinstance(value, list) + assert len(value) == 1 diff --git a/WebDriverTests/imported/w3c/webdriver/tests/element_send_keys/__init__.py b/WebDriverTests/imported/w3c/webdriver/tests/element_send_keys/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/WebDriverTests/imported/w3c/webdriver/tests/element_send_keys/interactability.py b/WebDriverTests/imported/w3c/webdriver/tests/element_send_keys/interactability.py new file mode 100644 index 000000000000..5812f2b305fa --- /dev/null +++ b/WebDriverTests/imported/w3c/webdriver/tests/element_send_keys/interactability.py @@ -0,0 +1,136 @@ +from tests.support.asserts import assert_error, assert_same_element, assert_success +from tests.support.inline import iframe, inline + + +def send_keys_to_element(session, element, text): + return session.transport.send( + "POST", + "/session/{session_id}/element/{element_id}/value".format( + session_id=session.session_id, + element_id=element.id), + {"text": text}) + + +def test_body_is_interactable(session): + session.url = inline(""" + + + + """) + + element = session.find.css("body", all=False) + result = session.find.css("input", all=False) + + # By default body is the active element + assert_same_element(session, element, session.active_element) + + response = send_keys_to_element(session, element, "foo") + assert_success(response) + assert_same_element(session, element, session.active_element) + assert result.property("value") == "foo" + + +def test_document_element_is_interactable(session): + session.url = inline(""" + + + + """) + + body = session.find.css("body", all=False) + element = session.find.css(":root", all=False) + result = session.find.css("input", all=False) + + # By default body is the active element + assert_same_element(session, body, session.active_element) + + response = send_keys_to_element(session, element, "foo") + assert_success(response) + assert_same_element(session, element, session.active_element) + assert result.property("value") == "foo" + + +def test_iframe_is_interactable(session): + session.url = inline(iframe(""" + + + + """)) + + body = session.find.css("body", all=False) + frame = session.find.css("iframe", all=False) + + # By default the body has the focus + assert_same_element(session, body, session.active_element) + + response = send_keys_to_element(session, frame, "foo") + assert_success(response) + assert_same_element(session, frame, session.active_element) + + # Any key events are immediately routed to the nested + # browsing context's active document. + session.switch_frame(frame) + result = session.find.css("input", all=False) + assert result.property("value") == "foo" + + +def test_transparent_element(session): + session.url = inline("") + element = session.find.css("input", all=False) + + response = send_keys_to_element(session, element, "foo") + assert_success(response) + assert element.property("value") == "foo" + + +def test_readonly_element(session): + session.url = inline("") + element = session.find.css("input", all=False) + + response = send_keys_to_element(session, element, "foo") + assert_success(response) + assert element.property("value") == "" + + +def test_obscured_element(session): + session.url = inline(""" + +
+ """) + element = session.find.css("input", all=False) + + response = send_keys_to_element(session, element, "foo") + assert_success(response) + assert element.property("value") == "foo" + + +def test_not_a_focusable_element(session): + session.url = inline("
foo
") + element = session.find.css("div", all=False) + + response = send_keys_to_element(session, element, "foo") + assert_error(response, "element not interactable") + + +def test_not_displayed_element(session): + session.url = inline("") + element = session.find.css("input", all=False) + + response = send_keys_to_element(session, element, "foo") + assert_error(response, "element not interactable") + + +def test_hidden_element(session): + session.url = inline("") + element = session.find.css("input", all=False) + + response = send_keys_to_element(session, element, "foo") + assert_error(response, "element not interactable") + + +def test_disabled_element(session): + session.url = inline("") + element = session.find.css("input", all=False) + + response = send_keys_to_element(session, element, "foo") + assert_error(response, "element not interactable") diff --git a/WebDriverTests/imported/w3c/webdriver/tests/element_send_keys/scroll_into_view.py b/WebDriverTests/imported/w3c/webdriver/tests/element_send_keys/scroll_into_view.py new file mode 100644 index 000000000000..a1d454d1fe23 --- /dev/null +++ b/WebDriverTests/imported/w3c/webdriver/tests/element_send_keys/scroll_into_view.py @@ -0,0 +1,78 @@ +from tests.support.asserts import assert_success +from tests.support.fixtures import is_element_in_viewport +from tests.support.inline import inline + + +def send_keys_to_element(session, element, text): + return session.transport.send( + "POST", + "/session/{session_id}/element/{element_id}/value".format( + session_id=session.session_id, + element_id=element.id), + {"text": text}) + + +def test_element_outside_of_not_scrollable_viewport(session): + session.url = inline("") + element = session.find.css("input", all=False) + + response = send_keys_to_element(session, element, "foo") + assert_success(response) + + assert not is_element_in_viewport(session, element) + + +def test_element_outside_of_scrollable_viewport(session): + session.url = inline("") + element = session.find.css("input", all=False) + + response = send_keys_to_element(session, element, "foo") + assert_success(response) + + assert is_element_in_viewport(session, element) + + +def test_option_select_container_outside_of_scrollable_viewport(session): + session.url = inline(""" + + """) + element = session.find.css("option#bar", all=False) + select = session.find.css("select", all=False) + + response = send_keys_to_element(session, element, "bar") + assert_success(response) + + assert is_element_in_viewport(session, select) + assert is_element_in_viewport(session, element) + + +def test_option_stays_outside_of_scrollable_viewport(session): + session.url = inline(""" + + """) + select = session.find.css("select", all=False) + option_foo = session.find.css("option#foo", all=False) + option_bar = session.find.css("option#bar", all=False) + + response = send_keys_to_element(session, option_bar, "bar") + assert_success(response) + + assert is_element_in_viewport(session, select) + assert is_element_in_viewport(session, option_foo) + assert not is_element_in_viewport(session, option_bar) + + +def test_contenteditable_element_outside_of_scrollable_viewport(session): + session.url = inline("
") + element = session.find.css("div", all=False) + + response = send_keys_to_element(session, element, "foo") + assert_success(response) + + assert is_element_in_viewport(session, element) diff --git a/WebDriverTests/imported/w3c/webdriver/tests/execute_script/cyclic.py b/WebDriverTests/imported/w3c/webdriver/tests/execute_script/cyclic.py new file mode 100644 index 000000000000..ae9d2f5775c2 --- /dev/null +++ b/WebDriverTests/imported/w3c/webdriver/tests/execute_script/cyclic.py @@ -0,0 +1,48 @@ +from tests.support.asserts import assert_error + + +def execute_script(session, script, args=None): + if args is None: + args = [] + body = {"script": script, "args": args} + return session.transport.send( + "POST", + "/session/{session_id}/execute/sync".format( + session_id=session.session_id), + body) + + +def test_array(session): + response = execute_script(session, """ + let arr = []; + arr.push(arr); + return arr; + """) + assert_error(response, "javascript error") + + +def test_object(session): + response = execute_script(session, """ + let obj = {}; + obj.reference = obj; + return obj; + """) + assert_error(response, "javascript error") + + +def test_array_in_object(session): + response = execute_script(session, """ + let arr = []; + arr.push(arr); + return {arr}; + """) + assert_error(response, "javascript error") + + +def test_object_in_array(session): + response = execute_script(session, """ + let obj = {}; + obj.reference = obj; + return [obj]; + """) + assert_error(response, "javascript error") diff --git a/WebDriverTests/imported/w3c/webdriver/tests/get_window_rect.py b/WebDriverTests/imported/w3c/webdriver/tests/get_window_rect.py index b25ca28692f2..cb3398ecccc7 100644 --- a/WebDriverTests/imported/w3c/webdriver/tests/get_window_rect.py +++ b/WebDriverTests/imported/w3c/webdriver/tests/get_window_rect.py @@ -151,11 +151,10 @@ def test_payload(session): assert response.status == 200 assert isinstance(response.body["value"], dict) value = response.body["value"] - assert "width" in value - assert "height" in value - assert "x" in value - assert "y" in value - assert isinstance(value["width"], int) - assert isinstance(value["height"], int) - assert isinstance(value["x"], int) - assert isinstance(value["y"], int) + expected = session.execute_script("""return { + x: window.screenX, + y: window.screenY, + width: window.outerWidth, + height: window.outerHeight + }""") + assert expected == value diff --git a/WebDriverTests/imported/w3c/webdriver/tests/interface.html b/WebDriverTests/imported/w3c/webdriver/tests/interface.html index 143a8643f3c9..31637285e408 100644 --- a/WebDriverTests/imported/w3c/webdriver/tests/interface.html +++ b/WebDriverTests/imported/w3c/webdriver/tests/interface.html @@ -1,15 +1,38 @@ - - -WebDriver interface test - - + + + + + + diff --git a/WebDriverTests/imported/w3c/webdriver/tests/navigation/current_url.py b/WebDriverTests/imported/w3c/webdriver/tests/navigation/current_url.py index 45e462fb8e1d..b3dfe1ffbd7a 100644 --- a/WebDriverTests/imported/w3c/webdriver/tests/navigation/current_url.py +++ b/WebDriverTests/imported/w3c/webdriver/tests/navigation/current_url.py @@ -4,6 +4,7 @@ from tests.support.inline import inline from tests.support.asserts import assert_error, assert_success +from tests.support.wait import wait alert_doc = inline("") frame_doc = inline("

frame") @@ -75,8 +76,11 @@ def test_set_malformed_url(session): assert_error(result, "invalid argument") def test_get_current_url_after_modified_location(session): + start = session.transport.send("GET", "session/%s/url" % session.session_id) session.execute_script("window.location.href = 'about:blank#wd_test_modification'") - + wait(session, + lambda s: s.transport.send("GET", "session/%s/url" % session.session_id) != start.body["value"], + "URL did not change") result = session.transport.send("GET", "session/%s/url" % session.session_id) assert_success(result, "about:blank#wd_test_modification") diff --git a/WebDriverTests/imported/w3c/webdriver/tests/support/asserts.py b/WebDriverTests/imported/w3c/webdriver/tests/support/asserts.py index 41747911351f..95859ac3d2b5 100644 --- a/WebDriverTests/imported/w3c/webdriver/tests/support/asserts.py +++ b/WebDriverTests/imported/w3c/webdriver/tests/support/asserts.py @@ -1,5 +1,6 @@ from webdriver import Element, WebDriverException + # WebDriver specification ID: dfn-error-response-data errors = { "element click intercepted": 400, @@ -32,6 +33,7 @@ "unsupported operation": 500, } + # WebDriver specification ID: dfn-send-an-error # # > When required to send an error, with error code, a remote end must run the @@ -98,7 +100,7 @@ def assert_dialog_handled(session, expected_text): except: assert (result.status == 200 and result.body["value"] != expected_text), ( - "Dialog with text '%s' was not handled." % expected_text) + "Dialog with text '%s' was not handled." % expected_text) def assert_same_element(session, a, b): @@ -123,7 +125,7 @@ def assert_same_element(session, a, b): return message = ("Expected element references to describe the same element, " + - "but they did not.") + "but they did not.") # Attempt to provide more information, accounting for possible errors such # as stale element references or not visible elements. diff --git a/WebDriverTests/imported/w3c/webdriver/tests/support/fixtures.py b/WebDriverTests/imported/w3c/webdriver/tests/support/fixtures.py index 8da0d5cc09f9..844ae039e571 100644 --- a/WebDriverTests/imported/w3c/webdriver/tests/support/fixtures.py +++ b/WebDriverTests/imported/w3c/webdriver/tests/support/fixtures.py @@ -267,3 +267,19 @@ def create_dialog(dialog_type, text=None, result_var=None): def clear_all_cookies(session): """Removes all cookies associated with the current active document""" session.transport.send("DELETE", "session/%s/cookie" % session.session_id) + + +def is_element_in_viewport(session, element): + """Check if element is outside of the viewport""" + return session.execute_script(""" + let el = arguments[0]; + + let rect = el.getBoundingClientRect(); + let viewport = { + height: window.innerHeight || document.documentElement.clientHeight, + width: window.innerWidth || document.documentElement.clientWidth, + }; + + return !(rect.right < 0 || rect.bottom < 0 || + rect.left > viewport.width || rect.top > viewport.height) + """, args=(element,))