diff --git a/docs/APILibraryDocumentation.html b/docs/APILibraryDocumentation.html
index 138646ff..1726833e 100644
--- a/docs/APILibraryDocumentation.html
+++ b/docs/APILibraryDocumentation.html
@@ -614,7 +614,7 @@
jQuery.extend({highlight:function(e,t,n,r){if(e.nodeType===3){var i=e.data.match(t);if(i){var s=document.createElement(n||"span");s.className=r||"highlight";var o=e.splitText(i.index);o.splitText(i[0].length);var u=o.cloneNode(true);s.appendChild(u);o.parentNode.replaceChild(s,o);return 1}}else if(e.nodeType===1&&e.childNodes&&!/(script|style)/i.test(e.tagName)&&!(e.tagName===n.toUpperCase()&&e.className===r)){for(var a=0;a
diff --git a/docs/DesktopLibraryDocumentation.html b/docs/DesktopLibraryDocumentation.html
index 86de05dd..bc18229e 100644
--- a/docs/DesktopLibraryDocumentation.html
+++ b/docs/DesktopLibraryDocumentation.html
@@ -614,7 +614,7 @@
jQuery.extend({highlight:function(e,t,n,r){if(e.nodeType===3){var i=e.data.match(t);if(i){var s=document.createElement(n||"span");s.className=r||"highlight";var o=e.splitText(i.index);o.splitText(i[0].length);var u=o.cloneNode(true);s.appendChild(u);o.parentNode.replaceChild(s,o);return 1}}else if(e.nodeType===1&&e.childNodes&&!/(script|style)/i.test(e.tagName)&&!(e.tagName===n.toUpperCase()&&e.className===r)){for(var a=0;a
diff --git a/docs/GUILibraryDocumentation.html b/docs/GUILibraryDocumentation.html
index 97c63c1d..f34304f9 100644
--- a/docs/GUILibraryDocumentation.html
+++ b/docs/GUILibraryDocumentation.html
@@ -614,7 +614,7 @@
jQuery.extend({highlight:function(e,t,n,r){if(e.nodeType===3){var i=e.data.match(t);if(i){var s=document.createElement(n||"span");s.className=r||"highlight";var o=e.splitText(i.index);o.splitText(i[0].length);var u=o.cloneNode(true);s.appendChild(u);o.parentNode.replaceChild(s,o);return 1}}else if(e.nodeType===1&&e.childNodes&&!/(script|style)/i.test(e.tagName)&&!(e.tagName===n.toUpperCase()&&e.className===r)){for(var a=0;a
diff --git a/docs/MobileLibraryDocumentation.html b/docs/MobileLibraryDocumentation.html
index 8f8fc4dd..e0a189fc 100644
--- a/docs/MobileLibraryDocumentation.html
+++ b/docs/MobileLibraryDocumentation.html
@@ -614,7 +614,7 @@
jQuery.extend({highlight:function(e,t,n,r){if(e.nodeType===3){var i=e.data.match(t);if(i){var s=document.createElement(n||"span");s.className=r||"highlight";var o=e.splitText(i.index);o.splitText(i[0].length);var u=o.cloneNode(true);s.appendChild(u);o.parentNode.replaceChild(s,o);return 1}}else if(e.nodeType===1&&e.childNodes&&!/(script|style)/i.test(e.tagName)&&!(e.tagName===n.toUpperCase()&&e.className===r)){for(var a=0;a
diff --git a/docs/SOAPLibraryDocumentation.html b/docs/SOAPLibraryDocumentation.html
index 29d6cab7..4c7f5c9a 100644
--- a/docs/SOAPLibraryDocumentation.html
+++ b/docs/SOAPLibraryDocumentation.html
@@ -614,7 +614,7 @@
jQuery.extend({highlight:function(e,t,n,r){if(e.nodeType===3){var i=e.data.match(t);if(i){var s=document.createElement(n||"span");s.className=r||"highlight";var o=e.splitText(i.index);o.splitText(i[0].length);var u=o.cloneNode(true);s.appendChild(u);o.parentNode.replaceChild(s,o);return 1}}else if(e.nodeType===1&&e.childNodes&&!/(script|style)/i.test(e.tagName)&&!(e.tagName===n.toUpperCase()&&e.className===r)){for(var a=0;a
diff --git a/samples/Appium-DesktopTests.robot b/samples/Appium-DesktopTests.robot
index 0f0fb69f..79af6cd2 100644
--- a/samples/Appium-DesktopTests.robot
+++ b/samples/Appium-DesktopTests.robot
@@ -147,6 +147,15 @@ Flick Tests
Wait Until Page Contains Element accessibility_id=Standard
Wait For And Click Element accessibility_id=Standard
+Screen Recording Keyword Test - See video with logs or in log.html
+ Start Screen Recording
+ Wait For And Click Element accessibility_id=num2Button
+ Wait For And Click Element accessibility_id=num3Button
+ Wait For And Click Element accessibility_id=num4Button
+ Wait For And Click Element accessibility_id=num5Button
+ Wait Until Element Contains accessibility_id=CalculatorResults 2,345
+ Stop Screen Recording
+
Switch To Desktop Test
Close Application
Switch Application Desktop
diff --git a/src/Zoomba/DesktopLibrary.py b/src/Zoomba/DesktopLibrary.py
index a8a0039c..57049a77 100644
--- a/src/Zoomba/DesktopLibrary.py
+++ b/src/Zoomba/DesktopLibrary.py
@@ -9,9 +9,9 @@
from selenium.common.exceptions import NoSuchElementException, InvalidSelectorException
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.touch_actions import TouchActions
-
from time import sleep, time
from robot import utils
+from base64 import b64decode
try:
AppiumCommon = importlib.import_module('Helpers.AppiumCommon', package='Helpers')
@@ -109,6 +109,10 @@ def __init__(self, timeout=5, run_on_failure='Save Appium Screenshot',
| Library | DesktopLibrary | timeout=10 | driver_path="C:/WinAppDriver.exe" | # Sets a new path for the WinAppDriver |
"""
self.winappdriver = WinAppDriver(driver_path)
+ # self.recorder = _ScreenrecordKeywords()
+ self._screenrecord_index = 0
+ self._recording = None
+ self._output_format = None
super().__init__(timeout, run_on_failure)
def get_keyword_names(self):
@@ -146,9 +150,82 @@ def get_keyword_names(self):
'text_should_be_visible', 'wait_until_element_is_visible', 'wait_until_page_contains',
'wait_until_page_contains_element', 'wait_until_page_does_not_contain',
'wait_until_page_does_not_contain_element', 'get_matching_xpath_count',
- 'xpath_should_match_x_times', 'tap'
+ 'xpath_should_match_x_times', 'tap', 'start_screen_recording', 'stop_screen_recording'
]
+ # Screen Recorder - adapted from AppiumLibrary
+ @keyword("Start Screen Recording")
+ def start_screen_recording(self, time_limit='180s', **options):
+ """Starts an asynchronous Screen Recording for the current open application.
+
+ ``timeLimit`` sets the actual time limit of the recorded video (defaulting to 180 seconds).
+
+ `Start Screen Recording` is used hand in hand with `Stop Screen Recording`.
+ See `Stop Screen Recording` for more details.
+
+ Keyword requires Appium to be used.
+
+ Example:
+ | `Start Screen Recording` | | # starts a screen record session |
+ | .... keyword actions | | |
+ | `Stop Screen Recording` | filename=output | # saves the recorded session |
+ """
+ options['time_limit'] = utils.timestr_to_secs(time_limit)
+ self._output_format = '.mp4'
+ if self._recording is None:
+ self._recording = self._current_application().start_recording_screen(**options)
+
+ @keyword("Stop Screen Recording")
+ def stop_screen_recording(self, filename=None, **options):
+ """Gathers the output from the previously started screen recording \
+ to a media file, then embeds it to the log.html(Android Only).
+
+ Requires an active or exhausted Screen Recording Session.
+ See `Start Screen Recording` for more details.
+
+ === Optional Args ===
+
+ - ``remotePath`` The path to the remote location, where the resulting video should be \
+ uploaded. The following protocols are supported _http/https_, ftp. Null or empty \
+ string value (the default setting) means the content of resulting file should \
+ be encoded as Base64 and passed as the endpoint response value. An \
+ exception will be thrown if the generated media file is too big to fit \
+ into the available process memory.
+
+ - ``username`` The name of the user for the remote authentication.
+
+ - ``password`` The password for the remote authentication.
+
+ - ``method`` The http multipart upload method name. The _PUT_ one is used by default.
+
+ Keyword requires Appium to be used.
+
+ Example:
+ | `Start Screen Recording` | | # starts a screen record session |
+ | .... keyword actions | | |
+ | `Stop Screen Recording` | filename=output | # saves the recorded session |
+ """
+ self._recording = self._current_application().stop_recording_screen(**options)
+ return self._save_recording(filename, options)
+
+ def _save_recording(self, filename, options):
+ path, link = self._get_screenrecord_paths(options, filename)
+ decoded = b64decode(self._recording)
+ with open(path, 'wb') as screenrecording:
+ screenrecording.write(decoded)
+ # Embed the Screen Recording to the log file
+ if not self._is_remotepath_set(options):
+ self._html('