Skip to content

Commit 106e6e2

Browse files
committed
[wdspec] Add full page screenshot tests
This commit is to add tests using GET screenshot/full for WebDriver proposed at [1]. The tests are copied from take_screenshot/ and modified to use the full page screenshot endpoint. In iframe.py test_source_origin test, the cross origin test full page screenshot does not generate the same png as the same origin one. This behavior has been verified by taking the full page screenshot in browser DevTools directly using Capture full size screenshot[2]. Added a function to get full page dimensions using document.scrollingElement.scroll{Width,Height}. [1] w3c/webdriver#1536 [2] https://www.deconetwork.com/blog/how-to-take-full-webpage-screenshots-instantly/#:~:text=Click%20Command%2BShift%2BP%20on,Select%20Capture%20full%20size%20screenshot.
1 parent 8d00643 commit 106e6e2

File tree

4 files changed

+249
-0
lines changed

4 files changed

+249
-0
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
def full_page_dimensions(session):
2+
return tuple(session.execute_script("""
3+
const {scrollWidth, scrollHeight} = document.scrollingElement;
4+
5+
return [
6+
scrollWidth,
7+
scrollHeight
8+
];
9+
"""))
10+
11+
def take_full_page_screenshot(session):
12+
return session.transport.send(
13+
"GET", "session/{session_id}/screenshot/full".format(**vars(session)))
14+
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import pytest
2+
import base64
3+
4+
from tests.support.asserts import assert_success
5+
from tests.support.image import png_dimensions
6+
from tests.support.inline import iframe, inline
7+
8+
from six import ensure_binary
9+
10+
from . import full_page_dimensions
11+
from . import take_full_page_screenshot
12+
13+
DEFAULT_CONTENT = "<div id='content'>Lorem ipsum dolor sit amet.</div>"
14+
15+
REFERENCE_CONTENT = "<div id='outer'>{}</div>".format(DEFAULT_CONTENT)
16+
REFERENCE_STYLE = """
17+
<style>
18+
#outer {
19+
display: block;
20+
margin: 0;
21+
border: 0;
22+
width: 200px;
23+
height: 200px;
24+
}
25+
#content {
26+
display: block;
27+
margin: 0;
28+
border: 0;
29+
width: 100px;
30+
height: 100px;
31+
background: green;
32+
}
33+
</style>
34+
"""
35+
36+
OUTER_IFRAME_STYLE = """
37+
<style>
38+
iframe {
39+
display: block;
40+
margin: 0;
41+
border: 0;
42+
width: 200px;
43+
height: 200px;
44+
}
45+
</style>
46+
"""
47+
48+
INNER_IFRAME_STYLE = """
49+
<style>
50+
body {
51+
margin: 0;
52+
}
53+
div {
54+
display: block;
55+
margin: 0;
56+
border: 0;
57+
width: 100px;
58+
height: 100px;
59+
background: green;
60+
}
61+
</style>
62+
"""
63+
64+
def test_always_captures_top_browsing_context(session):
65+
iframe_content = "{0}{1}".format(INNER_IFRAME_STYLE, DEFAULT_CONTENT)
66+
session.url = inline("""{0}{1}""".format(OUTER_IFRAME_STYLE, iframe(iframe_content)))
67+
68+
response = take_full_page_screenshot(session)
69+
reference_screenshot = assert_success(response)
70+
assert png_dimensions(reference_screenshot) == full_page_dimensions(session)
71+
72+
frame = session.find.css("iframe", all=False)
73+
session.switch_frame(frame)
74+
75+
response = take_full_page_screenshot(session)
76+
screenshot = assert_success(response)
77+
78+
assert png_dimensions(screenshot) == png_dimensions(reference_screenshot)
79+
assert screenshot == reference_screenshot
80+
81+
@pytest.mark.parametrize("domain", ["", "alt"], ids=["same_origin", "cross_origin"])
82+
def test_source_origin(session, domain):
83+
session.url = inline("{0}{1}".format(REFERENCE_STYLE, REFERENCE_CONTENT))
84+
85+
response = take_full_page_screenshot(session)
86+
reference_screenshot = assert_success(response)
87+
assert png_dimensions(reference_screenshot) == full_page_dimensions(session)
88+
89+
iframe_content = "{0}{1}".format(INNER_IFRAME_STYLE, DEFAULT_CONTENT)
90+
session.url = inline("""{0}{1}""".format(
91+
OUTER_IFRAME_STYLE, iframe(iframe_content, domain=domain)))
92+
93+
response = take_full_page_screenshot(session)
94+
screenshot = assert_success(response)
95+
assert png_dimensions(screenshot) == full_page_dimensions(session)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from tests.support.asserts import assert_error, assert_png, assert_success
2+
from tests.support.image import png_dimensions
3+
from tests.support.inline import inline
4+
5+
from . import full_page_dimensions
6+
from . import take_full_page_screenshot
7+
8+
def test_no_top_browsing_context(session, closed_window):
9+
response = take_full_page_screenshot(session)
10+
assert_error(response, "no such window")
11+
12+
13+
def test_no_browsing_context(session, closed_frame):
14+
session.url = inline("<input>")
15+
16+
response = take_full_page_screenshot(session)
17+
value = assert_success(response)
18+
19+
assert_png(value)
20+
assert png_dimensions(value) == full_page_dimensions(session)
21+
22+
23+
def test_format_and_dimensions(session):
24+
session.url = inline("<input>")
25+
26+
response = take_full_page_screenshot(session)
27+
value = assert_success(response)
28+
29+
assert_png(value)
30+
assert png_dimensions(value) == full_page_dimensions(session)
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# META: timeout=long
2+
3+
import pytest
4+
5+
from tests.support.asserts import assert_dialog_handled, assert_error, assert_png, assert_success
6+
from tests.support.inline import inline
7+
8+
from . import take_full_page_screenshot
9+
10+
@pytest.fixture
11+
def check_user_prompt_closed_without_exception(session, create_dialog):
12+
def check_user_prompt_closed_without_exception(dialog_type, retval):
13+
session.url = inline("<input/>")
14+
15+
create_dialog(dialog_type, text=dialog_type)
16+
17+
response = take_full_page_screenshot(session)
18+
value = assert_success(response)
19+
20+
assert_dialog_handled(session, expected_text=dialog_type, expected_retval=retval)
21+
22+
assert_png(value)
23+
24+
return check_user_prompt_closed_without_exception
25+
26+
27+
@pytest.fixture
28+
def check_user_prompt_closed_with_exception(session, create_dialog):
29+
def check_user_prompt_closed_with_exception(dialog_type, retval):
30+
session.url = inline("<input/>")
31+
32+
create_dialog(dialog_type, text=dialog_type)
33+
34+
response = take_full_page_screenshot(session)
35+
assert_error(response, "unexpected alert open")
36+
37+
assert_dialog_handled(session, expected_text=dialog_type, expected_retval=retval)
38+
39+
return check_user_prompt_closed_with_exception
40+
41+
42+
@pytest.fixture
43+
def check_user_prompt_not_closed_but_exception(session, create_dialog):
44+
def check_user_prompt_not_closed_but_exception(dialog_type):
45+
session.url = inline("<input/>")
46+
47+
create_dialog(dialog_type, text=dialog_type)
48+
49+
response = take_full_page_screenshot(session)
50+
assert_error(response, "unexpected alert open")
51+
52+
assert session.alert.text == dialog_type
53+
session.alert.dismiss()
54+
55+
return check_user_prompt_not_closed_but_exception
56+
57+
58+
@pytest.mark.capabilities({"unhandledPromptBehavior": "accept"})
59+
@pytest.mark.parametrize("dialog_type, retval", [
60+
("alert", None),
61+
("confirm", True),
62+
("prompt", ""),
63+
])
64+
def test_accept(check_user_prompt_closed_without_exception, dialog_type, retval):
65+
check_user_prompt_closed_without_exception(dialog_type, retval)
66+
67+
68+
@pytest.mark.capabilities({"unhandledPromptBehavior": "accept and notify"})
69+
@pytest.mark.parametrize("dialog_type, retval", [
70+
("alert", None),
71+
("confirm", True),
72+
("prompt", ""),
73+
])
74+
def test_accept_and_notify(check_user_prompt_closed_with_exception, dialog_type, retval):
75+
check_user_prompt_closed_with_exception(dialog_type, retval)
76+
77+
78+
@pytest.mark.capabilities({"unhandledPromptBehavior": "dismiss"})
79+
@pytest.mark.parametrize("dialog_type, retval", [
80+
("alert", None),
81+
("confirm", False),
82+
("prompt", None),
83+
])
84+
def test_dismiss(check_user_prompt_closed_without_exception, dialog_type, retval):
85+
check_user_prompt_closed_without_exception(dialog_type, retval)
86+
87+
88+
@pytest.mark.capabilities({"unhandledPromptBehavior": "dismiss and notify"})
89+
@pytest.mark.parametrize("dialog_type, retval", [
90+
("alert", None),
91+
("confirm", False),
92+
("prompt", None),
93+
])
94+
def test_dismiss_and_notify(check_user_prompt_closed_with_exception, dialog_type, retval):
95+
check_user_prompt_closed_with_exception(dialog_type, retval)
96+
97+
98+
@pytest.mark.capabilities({"unhandledPromptBehavior": "ignore"})
99+
@pytest.mark.parametrize("dialog_type", ["alert", "confirm", "prompt"])
100+
def test_ignore(check_user_prompt_not_closed_but_exception, dialog_type):
101+
check_user_prompt_not_closed_but_exception(dialog_type)
102+
103+
104+
@pytest.mark.parametrize("dialog_type, retval", [
105+
("alert", None),
106+
("confirm", False),
107+
("prompt", None),
108+
])
109+
def test_default(check_user_prompt_closed_with_exception, dialog_type, retval):
110+
check_user_prompt_closed_with_exception(dialog_type, retval)

0 commit comments

Comments
 (0)