1from tests.support.asserts import assert_error, assert_dialog_handled, assert_same_element
2from tests.support.fixtures import create_dialog
3from tests.support.inline import inline
4
5
6def read_global(session, name):
7    return session.execute_script("return %s;" % name)
8
9
10def get_active_element(session):
11    return session.transport.send("GET", "session/%s/element/active" % session.session_id)
12
13
14def assert_is_active_element(session, response):
15    """Ensure that the provided object is a successful WebDriver
16    response describing an element reference and that the referenced
17    element matches the element returned by the `activeElement`
18    attribute of the current browsing context's active document.
19
20    """
21    assert response.status == 200
22    assert "value" in response.body
23
24    from_js = session.execute_script("return document.activeElement")
25
26    if response.body["value"] is None:
27        assert from_js is None
28    else:
29        assert_same_element(session, response.body["value"], from_js)
30
31
32# > 1. If the current browsing context is no longer open, return error with
33# >    error code no such window.
34def test_closed_context(session, create_window):
35    new_window = create_window()
36    session.window_handle = new_window
37    session.close()
38
39    response = get_active_element(session)
40    assert_error(response, "no such window")
41
42
43# [...]
44# 2. Handle any user prompts and return its value if it is an error.
45# [...]
46# In order to handle any user prompts a remote end must take the following
47# steps:
48# 2. Run the substeps of the first matching user prompt handler:
49#
50#    [...]
51#    - dismiss state
52#      1. Dismiss the current user prompt.
53#    [...]
54#
55# 3. Return success.
56def test_handle_prompt_dismiss(new_session, add_browser_capabilites):
57    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "dismiss"})}})
58    session.url = inline("<body><p>Hello, World!</p></body>")
59
60    create_dialog(session)("alert", text="dismiss #1", result_var="dismiss1")
61
62    response = get_active_element(session)
63    assert_is_active_element(session, response)
64    assert_dialog_handled(session, "dismiss #1")
65    assert session.execute_script("return dismiss1") is None
66
67    create_dialog(session)("confirm", text="dismiss #2", result_var="dismiss2")
68
69    response = get_active_element(session)
70    assert_is_active_element(session, response)
71    assert_dialog_handled(session, "dismiss #2")
72    assert read_global(session, "dismiss2") is False
73
74    create_dialog(session)("prompt", text="dismiss #3", result_var="dismiss3")
75
76    response = get_active_element(session)
77    assert_is_active_element(session, response)
78    assert_dialog_handled(session, "dismiss #3")
79    assert read_global(session, "dismiss3") is None
80
81
82# [...]
83# 2. Handle any user prompts and return its value if it is an error.
84# [...]
85# In order to handle any user prompts a remote end must take the following
86# steps:
87# 2. Run the substeps of the first matching user prompt handler:
88#
89#    [...]
90#    - accept state
91#      1. Accept the current user prompt.
92#    [...]
93#
94# 3. Return success.
95def test_handle_prompt_accept(new_session, add_browser_capabilites):
96    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
97    session.url = inline("<body><p>Hello, World!</p></body>")
98    create_dialog(session)("alert", text="accept #1", result_var="accept1")
99
100    response = get_active_element(session)
101    assert_is_active_element(session, response)
102    assert_dialog_handled(session, "accept #1")
103    assert read_global(session, "accept1") is None
104
105    create_dialog(session)("confirm", text="accept #2", result_var="accept2")
106
107    response = get_active_element(session)
108    assert_is_active_element(session, response)
109    assert_dialog_handled(session, "accept #2")
110    assert read_global(session, "accept2") is True
111
112    create_dialog(session)("prompt", text="accept #3", result_var="accept3")
113
114    response = get_active_element(session)
115    assert_is_active_element(session, response)
116    assert_dialog_handled(session, "accept #3")
117    assert read_global(session, "accept3") == "" or read_global(session, "accept3") == "undefined"
118
119
120# [...]
121# 2. Handle any user prompts and return its value if it is an error.
122# [...]
123# In order to handle any user prompts a remote end must take the following
124# steps:
125# 2. Run the substeps of the first matching user prompt handler:
126#
127#    [...]
128#    - missing value default state
129#    - not in the table of simple dialogs
130#      1. Dismiss the current user prompt.
131#      2. Return error with error code unexpected alert open.
132def test_handle_prompt_missing_value(session, create_dialog):
133    session.url = inline("<body><p>Hello, World!</p></body>")
134
135    create_dialog("alert", text="dismiss #1", result_var="dismiss1")
136
137    response = get_active_element(session)
138    assert_error(response, "unexpected alert open")
139    assert_dialog_handled(session, "dismiss #1")
140    assert session.execute_script("return dismiss1") is None
141
142    create_dialog("confirm", text="dismiss #2", result_var="dismiss2")
143
144    response = get_active_element(session)
145    assert_error(response, "unexpected alert open")
146    assert_dialog_handled(session, "dismiss #2")
147    assert session.execute_script("return dismiss2") is False
148
149    create_dialog("prompt", text="dismiss #3", result_var="dismiss3")
150
151    response = get_active_element(session)
152    assert_error(response, "unexpected alert open")
153    assert_dialog_handled(session, "dismiss #3")
154    assert session.execute_script("return dismiss3") is None
155
156
157# > [...]
158# > 3. Let active element be the active element of the current browsing
159# >    context's document element.
160# > 4. Let active web element be the JSON Serialization of active element.
161# > 5. Return success with data active web element.
162def test_success_document(session):
163    session.url = inline("""
164        <body>
165            <h1>Heading</h1>
166            <input />
167            <input />
168            <input style="opacity: 0" />
169            <p>Another element</p>
170        </body>""")
171    response = get_active_element(session)
172    assert_is_active_element(session, response)
173
174
175def test_sucess_input(session):
176    session.url = inline("""
177        <body>
178            <h1>Heading</h1>
179            <input autofocus />
180            <input style="opacity: 0" />
181            <p>Another element</p>
182        </body>""")
183    response = get_active_element(session)
184    assert_is_active_element(session, response)
185
186
187def test_sucess_input_non_interactable(session):
188    session.url = inline("""
189        <body>
190            <h1>Heading</h1>
191            <input />
192            <input style="opacity: 0" autofocus />
193            <p>Another element</p>
194        </body>""")
195    response = get_active_element(session)
196    assert_is_active_element(session, response)
197
198
199def test_success_explicit_focus(session):
200    session.url = inline("""
201        <body>
202            <h1>Heading</h1>
203            <input />
204            <iframe></iframe>
205        </body>""")
206
207    session.execute_script("document.body.getElementsByTagName('h1')[0].focus()")
208    response = get_active_element(session)
209    assert_is_active_element(session, response)
210
211    session.execute_script("document.body.getElementsByTagName('input')[0].focus()")
212    response = get_active_element(session)
213    assert_is_active_element(session, response)
214
215    session.execute_script("document.body.getElementsByTagName('iframe')[0].focus()")
216    response = get_active_element(session)
217    assert_is_active_element(session, response)
218
219    session.execute_script("document.body.getElementsByTagName('iframe')[0].focus();")
220    session.execute_script("""
221        var iframe = document.body.getElementsByTagName('iframe')[0];
222        if (iframe.remove) {
223          iframe.remove();
224        } else {
225          iframe.removeNode(true);
226        }""")
227    response = get_active_element(session)
228    assert_is_active_element(session, response)
229
230    session.execute_script("document.body.appendChild(document.createElement('textarea'))")
231    response = get_active_element(session)
232    assert_is_active_element(session, response)
233
234
235def test_success_iframe_content(session):
236    session.url = inline("<body></body>")
237    session.execute_script("""
238        let iframe = document.createElement('iframe');
239        document.body.appendChild(iframe);
240        let input = iframe.contentDocument.createElement('input');
241        iframe.contentDocument.body.appendChild(input);
242        input.focus();
243        """)
244
245    response = get_active_element(session)
246    assert_is_active_element(session, response)
247
248
249def test_missing_document_element(session):
250    session.url = inline("<body></body>")
251    session.execute_script("""
252        if (document.body.remove) {
253          document.body.remove();
254        } else {
255          document.body.removeNode(true);
256        }""")
257
258    response = get_active_element(session)
259    assert_error(response, "no such element")
260