1import pytest
2
3from webdriver.error import NoSuchAlertException
4from webdriver.transport import Response
5
6from tests.support.asserts import assert_error, assert_success
7from tests.support.sync import Poll
8
9
10def execute_script(session, script, args=None):
11    if args is None:
12        args = []
13    body = {"script": script, "args": args}
14
15    return session.transport.send(
16        "POST", "/session/{session_id}/execute/sync".format(
17            session_id=session.session_id),
18        body)
19
20
21def test_null_parameter_value(session, http):
22    path = "/session/{session_id}/execute/sync".format(**vars(session))
23    with http.post(path, None) as response:
24        assert_error(Response.from_http(response), "invalid argument")
25
26
27def test_no_top_browsing_context(session, closed_window):
28    response = execute_script(session, "return 1;")
29    assert_error(response, "no such window")
30
31
32def test_no_browsing_context(session, closed_frame):
33    response = execute_script(session, "return 1;")
34    assert_error(response, "no such window")
35
36
37def test_opening_new_window_keeps_current_window_handle(session, inline):
38    original_handle = session.window_handle
39    original_handles = session.handles
40
41    url = inline("""<a href="javascript:window.open();">open window</a>""")
42    session.url = url
43    session.find.css("a", all=False).click()
44    wait = Poll(
45        session,
46        timeout=5,
47        message="No new window has been opened")
48    new_handles = wait.until(lambda s: set(s.handles) - set(original_handles))
49
50    assert len(new_handles) == 1
51    assert session.window_handle == original_handle
52    assert session.url == url
53
54
55def test_ending_comment(session):
56    response = execute_script(session, "return 1; // foo")
57    assert_success(response, 1)
58
59
60def test_override_listeners(session, inline):
61    session.url = inline("""
62<script>
63called = [];
64window.addEventListener = () => {called.push("Internal addEventListener")}
65window.removeEventListener = () => {called.push("Internal removeEventListener")}
66</script>
67})""")
68    response = execute_script(session, "return !window.onunload")
69    assert_success(response, True)
70    response = execute_script(session, "return called")
71    assert_success(response, [])
72
73
74@pytest.mark.parametrize("dialog_type", ["alert", "confirm", "prompt"])
75def test_abort_by_user_prompt(session, dialog_type):
76    response = execute_script(
77        session, "window.{}('Hello'); return 1;".format(dialog_type))
78    assert_success(response, None)
79
80    session.alert.accept()
81
82
83@pytest.mark.parametrize("dialog_type", ["alert", "confirm", "prompt"])
84def test_abort_by_user_prompt_twice(session, dialog_type):
85    response = execute_script(
86        session, "window.{0}('Hello'); window.{0}('Bye'); return 1;".format(dialog_type))
87    assert_success(response, None)
88
89    session.alert.accept()
90
91    # The first alert has been accepted by the user prompt handler, the second
92    # alert will still be opened because the current step isn't aborted.
93    wait = Poll(
94        session,
95        timeout=5,
96        message="Second alert has not been opened",
97        ignored_exceptions=NoSuchAlertException
98    )
99    text = wait.until(lambda s: s.alert.text)
100
101    assert text == "Bye"
102
103    session.alert.accept()
104