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..cc2321f8a93cf7
--- /dev/null
+++ b/webdriver/tests/take_full_page_screenshot/screenshot.py
@@ -0,0 +1,41 @@
+
+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)
+
+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)
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)