Unreviewed. Update W3C WebDriver imported tests.
[WebKit-https.git] / WebDriverTests / imported / w3c / webdriver / tests / support / fixtures.py
1 import json
2 import os
3 import urlparse
4 import re
5
6 import webdriver
7 import mozlog
8
9 from tests.support.asserts import assert_error
10 from tests.support.http_request import HTTPRequest
11 from tests.support.wait import wait
12 from tests.support import merge_dictionaries
13
14 default_host = "http://127.0.0.1"
15 default_port = "4444"
16
17 logger = mozlog.get_default_logger()
18
19
20 def ignore_exceptions(f):
21     def inner(*args, **kwargs):
22         try:
23             return f(*args, **kwargs)
24         except webdriver.error.WebDriverException as e:
25             logger.warning("Ignored exception %s" % e)
26     inner.__name__ = f.__name__
27     return inner
28
29
30 @ignore_exceptions
31 def _ensure_valid_window(session):
32     """If current window is not open anymore, ensure to have a valid
33     one selected.
34
35     """
36     try:
37         session.window_handle
38     except webdriver.NoSuchWindowException:
39         session.window_handle = session.handles[0]
40
41
42 @ignore_exceptions
43 def _dismiss_user_prompts(session):
44     """Dismisses any open user prompts in windows."""
45     current_window = session.window_handle
46
47     for window in _windows(session):
48         session.window_handle = window
49         try:
50             session.alert.dismiss()
51         except webdriver.NoSuchAlertException:
52             pass
53
54     session.window_handle = current_window
55
56
57 @ignore_exceptions
58 def _restore_window_state(session):
59     """Reset window to an acceptable size, bringing it out of maximized,
60     minimized, or fullscreened state
61
62     """
63     session.window.size = (800, 600)
64
65
66 @ignore_exceptions
67 def _restore_windows(session):
68     """Closes superfluous windows opened by the test without ending
69     the session implicitly by closing the last window.
70     """
71     current_window = session.window_handle
72
73     for window in _windows(session, exclude=[current_window]):
74         session.window_handle = window
75         if len(session.handles) > 1:
76             session.close()
77
78     session.window_handle = current_window
79
80
81 def _switch_to_top_level_browsing_context(session):
82     """If the current browsing context selected by WebDriver is a
83     `<frame>` or an `<iframe>`, switch it back to the top-level
84     browsing context.
85     """
86     session.switch_frame(None)
87
88
89 def _windows(session, exclude=None):
90     """Set of window handles, filtered by an `exclude` list if
91     provided.
92     """
93     if exclude is None:
94         exclude = []
95     wins = [w for w in session.handles if w not in exclude]
96     return set(wins)
97
98
99 def create_frame(session):
100     """Create an `iframe` element in the current browsing context and insert it
101     into the document. Return a reference to the newly-created element."""
102     def create_frame():
103         append = """
104             var frame = document.createElement('iframe');
105             document.body.appendChild(frame);
106             return frame;
107         """
108         return session.execute_script(append)
109
110     return create_frame
111
112
113 def create_window(session):
114     """Open new window and return the window handle."""
115     def create_window():
116         windows_before = session.handles
117         name = session.execute_script("window.open()")
118         assert len(session.handles) == len(windows_before) + 1
119         new_windows = list(set(session.handles) - set(windows_before))
120         return new_windows.pop()
121     return create_window
122
123
124 def http(configuration):
125     return HTTPRequest(configuration["host"], configuration["port"])
126
127
128 def server_config():
129     return json.loads(os.environ.get("WD_SERVER_CONFIG"))
130
131
132 def configuration():
133     host = os.environ.get("WD_HOST", default_host)
134     port = int(os.environ.get("WD_PORT", default_port))
135     capabilities = json.loads(os.environ.get("WD_CAPABILITIES", "{}"))
136
137     return {
138         "host": host,
139         "port": port,
140         "capabilities": capabilities
141     }
142
143
144 _current_session = None
145
146
147 def session(configuration, request):
148     """Create and start a session for a test that does not itself test session creation.
149
150     By default the session will stay open after each test, but we always try to start a
151     new one and assume that if that fails there is already a valid session. This makes it
152     possible to recover from some errors that might leave the session in a bad state, but
153     does not demand that we start a new session per test."""
154     global _current_session
155     if _current_session is None:
156         _current_session = webdriver.Session(configuration["host"],
157                                              configuration["port"],
158                                              capabilities={"alwaysMatch": configuration["capabilities"]})
159     try:
160         _current_session.start()
161     except webdriver.error.SessionNotCreatedException:
162         if not _current_session.session_id:
163             raise
164
165     # finalisers are popped off a stack,
166     # making their ordering reverse
167     request.addfinalizer(lambda: _switch_to_top_level_browsing_context(_current_session))
168     request.addfinalizer(lambda: _restore_window_state(_current_session))
169     request.addfinalizer(lambda: _restore_windows(_current_session))
170     request.addfinalizer(lambda: _dismiss_user_prompts(_current_session))
171     request.addfinalizer(lambda: _ensure_valid_window(_current_session))
172
173     return _current_session
174
175
176 def new_session(configuration, request):
177     """Return a factory function that will attempt to start a session with a given body.
178
179     This is intended for tests that are themselves testing new session creation, and the
180     session created is closed at the end of the test."""
181     def end():
182         global _current_session
183         if _current_session is not None and _current_session.session_id:
184             _current_session.end()
185             _current_session = None
186
187     def create_session(body):
188         global _current_session
189         _session = webdriver.Session(configuration["host"],
190                                      configuration["port"],
191                                      capabilities=None)
192         value = _session.send_command("POST", "session", body=body)
193         # Don't set the global session until we are sure this succeeded
194         _current_session = _session
195         _session.session_id = value["sessionId"]
196
197         return value, _current_session
198
199     end()
200     request.addfinalizer(end)
201
202     return create_session
203
204
205 def add_browser_capabilites(configuration):
206     def update_capabilities(capabilities):
207         # Make sure there aren't keys in common.
208         assert not set(configuration["capabilities"]).intersection(set(capabilities))
209         result = dict(configuration["capabilities"])
210         result.update(capabilities)
211         return result
212     return update_capabilities
213
214
215 def url(server_config):
216     def inner(path, protocol="http", query="", fragment=""):
217         port = server_config["ports"][protocol][0]
218         host = "%s:%s" % (server_config["host"], port)
219         return urlparse.urlunsplit((protocol, host, path, query, fragment))
220
221     inner.__name__ = "url"
222     return inner
223
224 def create_dialog(session):
225     """Create a dialog (one of "alert", "prompt", or "confirm") and provide a
226     function to validate that the dialog has been "handled" (either accepted or
227     dismissed) by returning some value."""
228
229     def create_dialog(dialog_type, text=None, result_var=None):
230         assert dialog_type in ("alert", "confirm", "prompt"), (
231                "Invalid dialog type: '%s'" % dialog_type)
232
233         if text is None:
234             text = ""
235
236         assert isinstance(text, basestring), "`text` parameter must be a string"
237
238         if result_var is None:
239             result_var = "__WEBDRIVER"
240
241         assert re.search(r"^[_$a-z$][_$a-z0-9]*$", result_var, re.IGNORECASE), (
242             'The `result_var` must be a valid JavaScript identifier')
243
244         # Script completion and modal summoning are scheduled on two separate
245         # turns of the event loop to ensure that both occur regardless of how
246         # the user agent manages script execution.
247         spawn = """
248             var done = arguments[0];
249             setTimeout(done, 0);
250             setTimeout(function() {{
251                 window.{0} = window.{1}("{2}");
252             }}, 0);
253         """.format(result_var, dialog_type, text)
254
255         session.send_session_command("POST",
256                                      "execute/async",
257                                      {"script": spawn, "args": []})
258         wait(session,
259              lambda s: s.send_session_command("GET", "alert/text") == text,
260              "modal has not appeared",
261              timeout=15,
262              ignored_exceptions=webdriver.NoSuchAlertException)
263
264     return create_dialog
265
266
267 def clear_all_cookies(session):
268     """Removes all cookies associated with the current active document"""
269     session.transport.send("DELETE", "session/%s/cookie" % session.session_id)