Skip to content

Commit

Permalink
[wdspec] Add full page screenshot tests
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
k7z45 committed Nov 26, 2020
1 parent 8d00643 commit 106e6e2
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 0 deletions.
14 changes: 14 additions & 0 deletions webdriver/tests/take_full_page_screenshot/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
def full_page_dimensions(session):
return tuple(session.execute_script("""
const {scrollWidth, scrollHeight} = document.scrollingElement;
return [
scrollWidth,
scrollHeight
];
"""))

def take_full_page_screenshot(session):
return session.transport.send(
"GET", "session/{session_id}/screenshot/full".format(**vars(session)))

95 changes: 95 additions & 0 deletions webdriver/tests/take_full_page_screenshot/iframe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import pytest
import base64

from tests.support.asserts import assert_success
from tests.support.image import png_dimensions
from tests.support.inline import iframe, inline

from six import ensure_binary

from . import full_page_dimensions
from . import take_full_page_screenshot

DEFAULT_CONTENT = "<div id='content'>Lorem ipsum dolor sit amet.</div>"

REFERENCE_CONTENT = "<div id='outer'>{}</div>".format(DEFAULT_CONTENT)
REFERENCE_STYLE = """
<style>
#outer {
display: block;
margin: 0;
border: 0;
width: 200px;
height: 200px;
}
#content {
display: block;
margin: 0;
border: 0;
width: 100px;
height: 100px;
background: green;
}
</style>
"""

OUTER_IFRAME_STYLE = """
<style>
iframe {
display: block;
margin: 0;
border: 0;
width: 200px;
height: 200px;
}
</style>
"""

INNER_IFRAME_STYLE = """
<style>
body {
margin: 0;
}
div {
display: block;
margin: 0;
border: 0;
width: 100px;
height: 100px;
background: green;
}
</style>
"""

def test_always_captures_top_browsing_context(session):
iframe_content = "{0}{1}".format(INNER_IFRAME_STYLE, DEFAULT_CONTENT)
session.url = inline("""{0}{1}""".format(OUTER_IFRAME_STYLE, iframe(iframe_content)))

response = take_full_page_screenshot(session)
reference_screenshot = assert_success(response)
assert png_dimensions(reference_screenshot) == full_page_dimensions(session)

frame = session.find.css("iframe", all=False)
session.switch_frame(frame)

response = take_full_page_screenshot(session)
screenshot = assert_success(response)

assert png_dimensions(screenshot) == png_dimensions(reference_screenshot)
assert screenshot == reference_screenshot

@pytest.mark.parametrize("domain", ["", "alt"], ids=["same_origin", "cross_origin"])
def test_source_origin(session, domain):
session.url = inline("{0}{1}".format(REFERENCE_STYLE, REFERENCE_CONTENT))

response = take_full_page_screenshot(session)
reference_screenshot = assert_success(response)
assert png_dimensions(reference_screenshot) == full_page_dimensions(session)

iframe_content = "{0}{1}".format(INNER_IFRAME_STYLE, DEFAULT_CONTENT)
session.url = inline("""{0}{1}""".format(
OUTER_IFRAME_STYLE, iframe(iframe_content, domain=domain)))

response = take_full_page_screenshot(session)
screenshot = assert_success(response)
assert png_dimensions(screenshot) == full_page_dimensions(session)
30 changes: 30 additions & 0 deletions webdriver/tests/take_full_page_screenshot/screenshot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from tests.support.asserts import assert_error, assert_png, assert_success
from tests.support.image import png_dimensions
from tests.support.inline import inline

from . import full_page_dimensions
from . import take_full_page_screenshot

def test_no_top_browsing_context(session, closed_window):
response = take_full_page_screenshot(session)
assert_error(response, "no such window")


def test_no_browsing_context(session, closed_frame):
session.url = inline("<input>")

response = take_full_page_screenshot(session)
value = assert_success(response)

assert_png(value)
assert png_dimensions(value) == full_page_dimensions(session)


def test_format_and_dimensions(session):
session.url = inline("<input>")

response = take_full_page_screenshot(session)
value = assert_success(response)

assert_png(value)
assert png_dimensions(value) == full_page_dimensions(session)
110 changes: 110 additions & 0 deletions webdriver/tests/take_full_page_screenshot/user_prompts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# META: timeout=long

import pytest

from tests.support.asserts import assert_dialog_handled, assert_error, assert_png, assert_success
from tests.support.inline import inline

from . import take_full_page_screenshot

@pytest.fixture
def check_user_prompt_closed_without_exception(session, create_dialog):
def check_user_prompt_closed_without_exception(dialog_type, retval):
session.url = inline("<input/>")

create_dialog(dialog_type, text=dialog_type)

response = take_full_page_screenshot(session)
value = assert_success(response)

assert_dialog_handled(session, expected_text=dialog_type, expected_retval=retval)

assert_png(value)

return check_user_prompt_closed_without_exception


@pytest.fixture
def check_user_prompt_closed_with_exception(session, create_dialog):
def check_user_prompt_closed_with_exception(dialog_type, retval):
session.url = inline("<input/>")

create_dialog(dialog_type, text=dialog_type)

response = take_full_page_screenshot(session)
assert_error(response, "unexpected alert open")

assert_dialog_handled(session, expected_text=dialog_type, expected_retval=retval)

return check_user_prompt_closed_with_exception


@pytest.fixture
def check_user_prompt_not_closed_but_exception(session, create_dialog):
def check_user_prompt_not_closed_but_exception(dialog_type):
session.url = inline("<input/>")

create_dialog(dialog_type, text=dialog_type)

response = take_full_page_screenshot(session)
assert_error(response, "unexpected alert open")

assert session.alert.text == dialog_type
session.alert.dismiss()

return check_user_prompt_not_closed_but_exception


@pytest.mark.capabilities({"unhandledPromptBehavior": "accept"})
@pytest.mark.parametrize("dialog_type, retval", [
("alert", None),
("confirm", True),
("prompt", ""),
])
def test_accept(check_user_prompt_closed_without_exception, dialog_type, retval):
check_user_prompt_closed_without_exception(dialog_type, retval)


@pytest.mark.capabilities({"unhandledPromptBehavior": "accept and notify"})
@pytest.mark.parametrize("dialog_type, retval", [
("alert", None),
("confirm", True),
("prompt", ""),
])
def test_accept_and_notify(check_user_prompt_closed_with_exception, dialog_type, retval):
check_user_prompt_closed_with_exception(dialog_type, retval)


@pytest.mark.capabilities({"unhandledPromptBehavior": "dismiss"})
@pytest.mark.parametrize("dialog_type, retval", [
("alert", None),
("confirm", False),
("prompt", None),
])
def test_dismiss(check_user_prompt_closed_without_exception, dialog_type, retval):
check_user_prompt_closed_without_exception(dialog_type, retval)


@pytest.mark.capabilities({"unhandledPromptBehavior": "dismiss and notify"})
@pytest.mark.parametrize("dialog_type, retval", [
("alert", None),
("confirm", False),
("prompt", None),
])
def test_dismiss_and_notify(check_user_prompt_closed_with_exception, dialog_type, retval):
check_user_prompt_closed_with_exception(dialog_type, retval)


@pytest.mark.capabilities({"unhandledPromptBehavior": "ignore"})
@pytest.mark.parametrize("dialog_type", ["alert", "confirm", "prompt"])
def test_ignore(check_user_prompt_not_closed_but_exception, dialog_type):
check_user_prompt_not_closed_but_exception(dialog_type)


@pytest.mark.parametrize("dialog_type, retval", [
("alert", None),
("confirm", False),
("prompt", None),
])
def test_default(check_user_prompt_closed_with_exception, dialog_type, retval):
check_user_prompt_closed_with_exception(dialog_type, retval)

0 comments on commit 106e6e2

Please sign in to comment.