diff --git a/src/SeleniumLibrary/__init__.py b/src/SeleniumLibrary/__init__.py index 0187df611..82ee75e5d 100644 --- a/src/SeleniumLibrary/__init__.py +++ b/src/SeleniumLibrary/__init__.py @@ -50,7 +50,7 @@ WebDriverCache, WindowKeywords, ) -from SeleniumLibrary.keywords.screenshot import EMBED +from SeleniumLibrary.keywords.screenshot import EMBED, BASE64 from SeleniumLibrary.locators import ElementFinder from SeleniumLibrary.utils import LibraryListener, is_truthy, _convert_timeout, _convert_delay @@ -614,8 +614,8 @@ def __init__( - ``run_on_failure``: Default action for the `run-on-failure functionality`. - ``screenshot_root_directory``: - Path to folder where possible screenshots are created or EMBED. - See `Set Screenshot Directory` keyword for further details about EMBED. + Path to folder where possible screenshots are created or EMBED or BASE64. + See `Set Screenshot Directory` keyword for further details about EMBED and BASE64. If not given, the directory where the log file is written is used. - ``plugins``: Allows extending the SeleniumLibrary with external Python classes. @@ -846,6 +846,8 @@ def _resolve_screenshot_root_directory(self): if is_string(screenshot_root_directory): if screenshot_root_directory.upper() == EMBED: self.screenshot_root_directory = EMBED + if screenshot_root_directory.upper() == BASE64: + self.screenshot_root_directory = BASE64 @staticmethod def _get_translation(language: Union[str, None]) -> Union[Path, None]: diff --git a/src/SeleniumLibrary/keywords/screenshot.py b/src/SeleniumLibrary/keywords/screenshot.py index 8cd8dc299..11308af85 100644 --- a/src/SeleniumLibrary/keywords/screenshot.py +++ b/src/SeleniumLibrary/keywords/screenshot.py @@ -27,6 +27,8 @@ DEFAULT_FILENAME_PAGE = "selenium-screenshot-{index}.png" DEFAULT_FILENAME_ELEMENT = "selenium-element-screenshot-{index}.png" EMBED = "EMBED" +BASE64 = "BASE64" +EMBEDDED_OPTIONS = [EMBED, BASE64] DEFAULT_FILENAME_PDF = "selenium-page-{index}.pdf" @@ -59,6 +61,8 @@ def set_screenshot_directory(self, path: Union[None, str]) -> str: path = None elif path.upper() == EMBED: path = EMBED + elif path.upper() == BASE64: + path = BASE64 else: path = os.path.abspath(path) self._create_directory(path) @@ -79,7 +83,14 @@ def capture_page_screenshot(self, filename: str = DEFAULT_FILENAME_PAGE) -> str: If ``filename`` equals to EMBED (case insensitive), then screenshot is embedded as Base64 image to the log.html. In this case file is not - created in the filesystem. + created in the filesystem. If ``filename`` equals to BASE64 (case + insensitive), then the base64 string is returned and the screenshot + is embedded to the log. This allows one to reuse the image elsewhere + in the report. + + Example: + | ${ss}= | `Capture Page Screenshot` | BASE64 | + | Set Test Message | *HTML*Test Success
|
Starting from SeleniumLibrary 1.8, if ``filename`` contains marker
``{index}``, it will be automatically replaced with an unique running
@@ -89,9 +100,10 @@ def capture_page_screenshot(self, filename: str = DEFAULT_FILENAME_PAGE) -> str:
format string syntax].
An absolute path to the created screenshot file is returned or if
- ``filename`` equals to EMBED, word `EMBED` is returned.
+ ``filename`` equals to EMBED, word `EMBED` is returned. If ``filename``
+ equals to BASE64, the base64 string containing the screenshot is returned.
- Support for EMBED is new in SeleniumLibrary 4.2
+ Support for BASE64 is new in SeleniumLibrary 6.8
Examples:
| `Capture Page Screenshot` | |
@@ -111,8 +123,9 @@ def capture_page_screenshot(self, filename: str = DEFAULT_FILENAME_PAGE) -> str:
if not self.drivers.current:
self.info("Cannot capture screenshot because no browser is open.")
return
- if self._decide_embedded(filename):
- return self._capture_page_screen_to_log()
+ is_embedded, method = self._decide_embedded(filename)
+ if is_embedded:
+ return self._capture_page_screen_to_log(method)
return self._capture_page_screenshot_to_file(filename)
def _capture_page_screenshot_to_file(self, filename):
@@ -123,9 +136,11 @@ def _capture_page_screenshot_to_file(self, filename):
self._embed_to_log_as_file(path, 800)
return path
- def _capture_page_screen_to_log(self):
+ def _capture_page_screen_to_log(self, return_val):
screenshot_as_base64 = self.driver.get_screenshot_as_base64()
- self._embed_to_log_as_base64(screenshot_as_base64, 800)
+ base64_str = self._embed_to_log_as_base64(screenshot_as_base64, 800)
+ if return_val == BASE64:
+ return base64_str
return EMBED
@keyword
@@ -140,18 +155,24 @@ def capture_element_screenshot(
See the `Locating elements` section for details about the locator
syntax.
- An absolute path to the created element screenshot is returned.
+ An absolute path to the created element screenshot is returned. If the ``filename``
+ equals to BASE64 (case insensitive), then the base64 string is returned in addition
+ to the screenshot embedded to the log. See ``Capture Page Screenshot`` for more
+ information.
Support for capturing the screenshot from an element has limited support
among browser vendors. Please check the browser vendor driver documentation
does the browser support capturing a screenshot from an element.
New in SeleniumLibrary 3.3. Support for EMBED is new in SeleniumLibrary 4.2.
+ Support for BASE64 is new in SeleniumLibrary 6.8.
Examples:
| `Capture Element Screenshot` | id:image_id | |
| `Capture Element Screenshot` | id:image_id | ${OUTPUTDIR}/id_image_id-1.png |
| `Capture Element Screenshot` | id:image_id | EMBED |
+ | ${ess}= | `Capture Element Screenshot` | id:image_id | BASE64 |
+
"""
if not self.drivers.current:
self.info(
@@ -159,8 +180,9 @@ def capture_element_screenshot(
)
return
element = self.find_element(locator, required=True)
- if self._decide_embedded(filename):
- return self._capture_element_screen_to_log(element)
+ is_embedded, method = self._decide_embedded(filename)
+ if is_embedded:
+ return self._capture_element_screen_to_log(element, method)
return self._capture_element_screenshot_to_file(element, filename)
def _capture_element_screenshot_to_file(self, element, filename):
@@ -171,8 +193,10 @@ def _capture_element_screenshot_to_file(self, element, filename):
self._embed_to_log_as_file(path, 400)
return path
- def _capture_element_screen_to_log(self, element):
- self._embed_to_log_as_base64(element.screenshot_as_base64, 400)
+ def _capture_element_screen_to_log(self, element, return_val):
+ base64_str = self._embed_to_log_as_base64(element.screenshot_as_base64, 400)
+ if return_val == BASE64:
+ return base64_str
return EMBED
@property
@@ -184,20 +208,20 @@ def _screenshot_root_directory(self, value):
self.ctx.screenshot_root_directory = value
def _decide_embedded(self, filename):
- filename = filename.lower()
+ filename = filename.upper()
if (
- filename == DEFAULT_FILENAME_PAGE
- and self._screenshot_root_directory == EMBED
+ filename == DEFAULT_FILENAME_PAGE.upper()
+ and self._screenshot_root_directory in EMBEDDED_OPTIONS
):
- return True
+ return True, self._screenshot_root_directory
if (
- filename == DEFAULT_FILENAME_ELEMENT
- and self._screenshot_root_directory == EMBED
+ filename == DEFAULT_FILENAME_ELEMENT.upper()
+ and self._screenshot_root_directory in EMBEDDED_OPTIONS
):
- return True
- if filename == EMBED.lower():
- return True
- return False
+ return True, self._screenshot_root_directory
+ if filename in EMBEDDED_OPTIONS:
+ return True, self._screenshot_root_directory
+ return False, None
def _get_screenshot_path(self, filename):
if self._screenshot_root_directory != EMBED:
diff --git a/utest/test/keywords/test_screen_shot.py b/utest/test/keywords/test_screen_shot.py
index a5cac9248..2ea09cb30 100644
--- a/utest/test/keywords/test_screen_shot.py
+++ b/utest/test/keywords/test_screen_shot.py
@@ -8,7 +8,7 @@
SCREENSHOT_FILE_NAME = "selenium-screenshot-{index}.png"
ELEMENT_FILE_NAME = "selenium-element-screenshot-{index}.png"
EMBED = "EMBED"
-
+BASE64 = "BASE64"
@pytest.fixture(scope="module")
def screen_shot():
@@ -22,24 +22,34 @@ def teardown_function():
def test_defaults(screen_shot):
- assert screen_shot._decide_embedded(SCREENSHOT_FILE_NAME) is False
- assert screen_shot._decide_embedded(ELEMENT_FILE_NAME) is False
+ assert screen_shot._decide_embedded(SCREENSHOT_FILE_NAME) == (False, None)
+ assert screen_shot._decide_embedded(ELEMENT_FILE_NAME) == (False, None)
def test_screen_shotdir_embeded(screen_shot):
screen_shot.ctx.screenshot_root_directory = EMBED
- assert screen_shot._decide_embedded(SCREENSHOT_FILE_NAME) is True
- assert screen_shot._decide_embedded(SCREENSHOT_FILE_NAME.upper()) is True
- assert screen_shot._decide_embedded(ELEMENT_FILE_NAME) is True
- assert screen_shot._decide_embedded(ELEMENT_FILE_NAME.upper()) is True
- assert screen_shot._decide_embedded("other.psn") is False
+ assert screen_shot._decide_embedded(SCREENSHOT_FILE_NAME) == (True, EMBED)
+ assert screen_shot._decide_embedded(SCREENSHOT_FILE_NAME.upper()) == (True, EMBED)
+ assert screen_shot._decide_embedded(ELEMENT_FILE_NAME) == (True, EMBED)
+ assert screen_shot._decide_embedded(ELEMENT_FILE_NAME.upper()) == (True, EMBED)
+ assert screen_shot._decide_embedded("other.psn") == (False, None)
+
+
+def test_screen_shotdir_return_base64(screen_shot):
+ screen_shot.ctx.screenshot_root_directory = BASE64
+ assert screen_shot._decide_embedded(SCREENSHOT_FILE_NAME) == (True, BASE64)
+ assert screen_shot._decide_embedded(SCREENSHOT_FILE_NAME.upper()) == (True, BASE64)
+ assert screen_shot._decide_embedded(ELEMENT_FILE_NAME) == (True, BASE64)
+ assert screen_shot._decide_embedded(ELEMENT_FILE_NAME.upper()) == (True, BASE64)
+ assert screen_shot._decide_embedded("other.psn") == (False, None)
def test_file_name_embeded(screen_shot):
- assert screen_shot._decide_embedded(EMBED) is True
- assert screen_shot._decide_embedded("other.psn") is False
+ assert screen_shot._decide_embedded("other.psn") == (False, None)
screen_shot.ctx.screenshot_root_directory = EMBED
- assert screen_shot._decide_embedded(EMBED) is True
+ assert screen_shot._decide_embedded(EMBED) == (True, EMBED)
+ screen_shot.ctx.screenshot_root_directory = BASE64
+ assert screen_shot._decide_embedded(BASE64) == (True, BASE64)
def test_screenshot_path_embedded(screen_shot):
@@ -56,6 +66,12 @@ def test_sl_init_embed():
sl = SeleniumLibrary(screenshot_root_directory=EMBED)
assert sl.screenshot_root_directory == EMBED
+ sl = SeleniumLibrary(screenshot_root_directory="bAsE64")
+ assert sl.screenshot_root_directory == BASE64
+
+ sl = SeleniumLibrary(screenshot_root_directory=BASE64)
+ assert sl.screenshot_root_directory == BASE64
+
def test_sl_init_not_embed():
sl = SeleniumLibrary(screenshot_root_directory=None)
@@ -76,6 +92,9 @@ def test_sl_set_screenshot_directory():
sl.set_screenshot_directory(EMBED)
assert sl.screenshot_root_directory == EMBED
+ sl.set_screenshot_directory(BASE64)
+ assert sl.screenshot_root_directory == BASE64
+
sl.set_screenshot_directory("EEmBedD")
assert "EEmBedD" in sl.screenshot_root_directory
assert len("EEmBedD") < len(sl.screenshot_root_directory)