From 106e6e274f36f12586b84720561b41caa448f518 Mon Sep 17 00:00:00 2001 From: Shengfa Lin Date: Wed, 25 Nov 2020 18:05:48 -0600 Subject: [PATCH 1/2] [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] https://github.com/w3c/webdriver/pull/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. --- .../take_full_page_screenshot/__init__.py | 14 +++ .../tests/take_full_page_screenshot/iframe.py | 95 +++++++++++++++ .../take_full_page_screenshot/screenshot.py | 30 +++++ .../take_full_page_screenshot/user_prompts.py | 110 ++++++++++++++++++ 4 files changed, 249 insertions(+) create mode 100644 webdriver/tests/take_full_page_screenshot/__init__.py create mode 100644 webdriver/tests/take_full_page_screenshot/iframe.py create mode 100644 webdriver/tests/take_full_page_screenshot/screenshot.py create mode 100644 webdriver/tests/take_full_page_screenshot/user_prompts.py diff --git a/webdriver/tests/take_full_page_screenshot/__init__.py b/webdriver/tests/take_full_page_screenshot/__init__.py new file mode 100644 index 00000000000000..8e9525541e239e --- /dev/null +++ b/webdriver/tests/take_full_page_screenshot/__init__.py @@ -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))) + diff --git a/webdriver/tests/take_full_page_screenshot/iframe.py b/webdriver/tests/take_full_page_screenshot/iframe.py new file mode 100644 index 00000000000000..9cd9c9ad68eb59 --- /dev/null +++ b/webdriver/tests/take_full_page_screenshot/iframe.py @@ -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 = "
Lorem ipsum dolor sit amet.
" + +REFERENCE_CONTENT = "
{}
".format(DEFAULT_CONTENT) +REFERENCE_STYLE = """ + +""" + +OUTER_IFRAME_STYLE = """ + +""" + +INNER_IFRAME_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) diff --git a/webdriver/tests/take_full_page_screenshot/screenshot.py b/webdriver/tests/take_full_page_screenshot/screenshot.py new file mode 100644 index 00000000000000..ca1bb3259f7fe1 --- /dev/null +++ b/webdriver/tests/take_full_page_screenshot/screenshot.py @@ -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("") + + 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("") + + response = take_full_page_screenshot(session) + value = assert_success(response) + + assert_png(value) + assert png_dimensions(value) == full_page_dimensions(session) diff --git a/webdriver/tests/take_full_page_screenshot/user_prompts.py b/webdriver/tests/take_full_page_screenshot/user_prompts.py new file mode 100644 index 00000000000000..0b2578f75d026f --- /dev/null +++ b/webdriver/tests/take_full_page_screenshot/user_prompts.py @@ -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("") + + 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("") + + 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("") + + 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) From 69b4236e67ee01b754a5dbc57d2cf6288927d8be Mon Sep 17 00:00:00 2001 From: Shengfa Lin Date: Wed, 25 Nov 2020 18:33:38 -0600 Subject: [PATCH 2/2] [wdspec] Add a test for large page screenshot Add a large div element so that the page does not fit in viewport and test full page screenshot capture the entire page. --- .../tests/take_full_page_screenshot/screenshot.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/webdriver/tests/take_full_page_screenshot/screenshot.py b/webdriver/tests/take_full_page_screenshot/screenshot.py index ca1bb3259f7fe1..cc2321f8a93cf7 100644 --- a/webdriver/tests/take_full_page_screenshot/screenshot.py +++ b/webdriver/tests/take_full_page_screenshot/screenshot.py @@ -1,3 +1,4 @@ + from tests.support.asserts import assert_error, assert_png, assert_success from tests.support.image import png_dimensions from tests.support.inline import inline @@ -28,3 +29,13 @@ def test_format_and_dimensions(session): assert_png(value) assert png_dimensions(value) == full_page_dimensions(session) + +def test_large_page(session): + large_div = "
Lorem ipsum dolor sit amet.
" + + session.url = inline(large_div) + response = take_full_page_screenshot(session) + value = assert_success(response) + + assert_png(value) + assert png_dimensions(value) == full_page_dimensions(session)