Skip to content

Commit

Permalink
Merge 1aaddde into 2fdc4d4
Browse files Browse the repository at this point in the history
  • Loading branch information
Wolfe1 committed Dec 7, 2020
2 parents 2fdc4d4 + 1aaddde commit 2a79ea4
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 7 deletions.
2 changes: 1 addition & 1 deletion docs/APILibraryDocumentation.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/DesktopLibraryDocumentation.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/GUILibraryDocumentation.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/MobileLibraryDocumentation.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/SOAPLibraryDocumentation.html
Original file line number Diff line number Diff line change
Expand Up @@ -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<e.childNodes.length;a++){a+=jQuery.highlight(e.childNodes[a],t,n,r)}}return 0}});jQuery.fn.unhighlight=function(e){var t={className:"highlight",element:"span"};jQuery.extend(t,e);return this.find(t.element+"."+t.className).each(function(){var e=this.parentNode;e.replaceChild(this.firstChild,this);e.normalize()}).end()};jQuery.fn.highlight=function(e,t){var n={className:"highlight",element:"span",caseSensitive:false,wordsOnly:false};jQuery.extend(n,t);if(e.constructor===String){e=[e]}e=jQuery.grep(e,function(e,t){return e!=""});e=jQuery.map(e,function(e,t){return e.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&")});if(e.length==0){return this}var r=n.caseSensitive?"":"i";var i="("+e.join("|")+")";if(n.wordsOnly){i="\\b"+i+"\\b"}var s=new RegExp(i,r);return this.each(function(){jQuery.highlight(this,s,n.element,n.className)})}
</script>
<script type="text/javascript">
libdoc = {"all_tags":[],"contains_tags":false,"doc":"<p>Zoomba SOAP Library\x3c/p>\n<p>This class is the base Library used to generate automated SOAP Tests in the Zoomba Automation Framework.\x3c/p>","generated":"2020-11-25 15:10:57","inits":[],"keywords":[{"args":["action=None","soap_object=None"],"doc":"<p>Call Soap Method. Calls soap method with list object\x3c/p>\n<p>action: (string) SOAP Action to be called.\x3c/p>\n<p>soap_object: (list) Soap Object in list format, list must be ordered wrt schema\x3c/p>","matched":true,"name":"Call Soap Method With List Object","shortdoc":"Call Soap Method. Calls soap method with list object ","tags":[]},{"args":["action=None","**soap_object"],"doc":"<p>Call Soap Method with dictionary object. Calls soap method\x3c/p>\n<p>action: (string) SOAP Action to be called.\x3c/p>\n<p>soap_object: (dict) Soap Object in dict format, dict must contain all required parts of schema object.\x3c/p>","matched":true,"name":"Call Soap Method With Object","shortdoc":"Call Soap Method with dictionary object. Calls soap method ","tags":[]},{"args":["soap_response=None"],"doc":"<p>Convert Soap Response To Dictionary: This keyword builds a dictionary from the sudsLibrary response\x3c/p>\n<p>json_actual_response: (request response object) The response from an API.\x3c/p>\n<p>return: There is no actual returned output, other than error messages when comparisons fail.\x3c/p>","matched":true,"name":"Convert Soap Response To Json","shortdoc":"Convert Soap Response To Dictionary: This keyword builds a dictionary from the sudsLibrary response","tags":[]},{"args":["host=None","endpoint=None","alias=None","**kwargs"],"doc":"<p>Create Soap Session. This Keyword utilizes the WSDL to create a soap client.\x3c/p>\n<p>host: (string) The host url.\x3c/p>\n<p>endpoint: (string) SOAP API endpoint containing the actions to be referenced.\x3c/p>\n<p>**kwargs: (optional) Parameters that could be included to add options to client creation. Current supported parameters are:\x3c/p>\n<p>set_location: http address\x3c/p>","matched":true,"name":"Create Soap Session","shortdoc":"Create Soap Session. This Keyword utilizes the WSDL to create a soap client.","tags":[]},{"args":["host=None","endpoint=None","alias=None","**kwargs"],"doc":"<p>Create Soap Session. This Keyword utilizes the WSDL and directly accesses calls from sudsLibrary.\x3c/p>\n<p>host: (string) The host url.\x3c/p>\n<p>endpoint: (string) SOAP API endpoint containing the actions to be referenced.\x3c/p>\n<p>alias: (string} Sets the alias for the SudsLibrary Framework **kwargs: (optional) Parameters that could be included to add options to client creation. Current supported parameters are:\x3c/p>\n<p>set_location: http address\x3c/p>","matched":true,"name":"Create Soap Session And Fix Wsdl","shortdoc":"Create Soap Session. This Keyword utilizes the WSDL and directly accesses calls from sudsLibrary.","tags":[]},{"args":["host=None","endpoint=None","alias=None","set_location=None","fix=False"],"doc":"<p>Create Soap Session and Set Location. In addition to the client creation, this keyword sets the location as specified.\x3c/p>\n<p>host: (string) The host url.\x3c/p>\n<p>endpoint: (string) SOAP API endpoint containing the actions to be referenced.\x3c/p>\n<p>set_location: (string) If set will overwrite the WSDL location with specified address.\x3c/p>\n<p>If set to None will replace location with host and endpoint specified\x3c/p>","matched":true,"name":"Create Soap Session And Set Location","shortdoc":"Create Soap Session and Set Location. In addition to the client creation, this keyword sets the location as specified.","tags":[]},{"args":["wsdl_type=None","object_dict=None"],"doc":"<p>Create Wsdl Objects. This Keyword utilizes the WSDL to create a WSDL object based on the information provided.\x3c/p>\n<p>wsdl_type: (string) Wsdl object to be created.\x3c/p>\n<p>object_dict: (dict) Python Dictionary containing values and nested dictionaries with construction similar to wsdl defined objects.\x3c/p>\n<p>return: (response object) Returns the SOAP client object.\x3c/p>","matched":true,"name":"Create Wsdl Objects","shortdoc":"Create Wsdl Objects. This Keyword utilizes the WSDL to create a WSDL object based on the information provided.","tags":[]}],"name":"SOAP_Library","named_args":true,"scope":"TEST","version":"2.7.0"};
libdoc = {"all_tags":[],"contains_tags":false,"doc":"<p>Zoomba SOAP Library\x3c/p>\n<p>This class is the base Library used to generate automated SOAP Tests in the Zoomba Automation Framework.\x3c/p>","generated":"2020-12-07 13:52:59","inits":[],"keywords":[{"args":["action=None","soap_object=None"],"doc":"<p>Call Soap Method. Calls soap method with list object\x3c/p>\n<p>action: (string) SOAP Action to be called.\x3c/p>\n<p>soap_object: (list) Soap Object in list format, list must be ordered wrt schema\x3c/p>","matched":true,"name":"Call Soap Method With List Object","shortdoc":"Call Soap Method. Calls soap method with list object ","tags":[]},{"args":["action=None","**soap_object"],"doc":"<p>Call Soap Method with dictionary object. Calls soap method\x3c/p>\n<p>action: (string) SOAP Action to be called.\x3c/p>\n<p>soap_object: (dict) Soap Object in dict format, dict must contain all required parts of schema object.\x3c/p>","matched":true,"name":"Call Soap Method With Object","shortdoc":"Call Soap Method with dictionary object. Calls soap method ","tags":[]},{"args":["soap_response=None"],"doc":"<p>Convert Soap Response To Dictionary: This keyword builds a dictionary from the sudsLibrary response\x3c/p>\n<p>json_actual_response: (request response object) The response from an API.\x3c/p>\n<p>return: There is no actual returned output, other than error messages when comparisons fail.\x3c/p>","matched":true,"name":"Convert Soap Response To Json","shortdoc":"Convert Soap Response To Dictionary: This keyword builds a dictionary from the sudsLibrary response","tags":[]},{"args":["host=None","endpoint=None","alias=None","**kwargs"],"doc":"<p>Create Soap Session. This Keyword utilizes the WSDL to create a soap client.\x3c/p>\n<p>host: (string) The host url.\x3c/p>\n<p>endpoint: (string) SOAP API endpoint containing the actions to be referenced.\x3c/p>\n<p>**kwargs: (optional) Parameters that could be included to add options to client creation. Current supported parameters are:\x3c/p>\n<p>set_location: http address\x3c/p>","matched":true,"name":"Create Soap Session","shortdoc":"Create Soap Session. This Keyword utilizes the WSDL to create a soap client.","tags":[]},{"args":["host=None","endpoint=None","alias=None","**kwargs"],"doc":"<p>Create Soap Session. This Keyword utilizes the WSDL and directly accesses calls from sudsLibrary.\x3c/p>\n<p>host: (string) The host url.\x3c/p>\n<p>endpoint: (string) SOAP API endpoint containing the actions to be referenced.\x3c/p>\n<p>alias: (string} Sets the alias for the SudsLibrary Framework **kwargs: (optional) Parameters that could be included to add options to client creation. Current supported parameters are:\x3c/p>\n<p>set_location: http address\x3c/p>","matched":true,"name":"Create Soap Session And Fix Wsdl","shortdoc":"Create Soap Session. This Keyword utilizes the WSDL and directly accesses calls from sudsLibrary.","tags":[]},{"args":["host=None","endpoint=None","alias=None","set_location=None","fix=False"],"doc":"<p>Create Soap Session and Set Location. In addition to the client creation, this keyword sets the location as specified.\x3c/p>\n<p>host: (string) The host url.\x3c/p>\n<p>endpoint: (string) SOAP API endpoint containing the actions to be referenced.\x3c/p>\n<p>set_location: (string) If set will overwrite the WSDL location with specified address.\x3c/p>\n<p>If set to None will replace location with host and endpoint specified\x3c/p>","matched":true,"name":"Create Soap Session And Set Location","shortdoc":"Create Soap Session and Set Location. In addition to the client creation, this keyword sets the location as specified.","tags":[]},{"args":["wsdl_type=None","object_dict=None"],"doc":"<p>Create Wsdl Objects. This Keyword utilizes the WSDL to create a WSDL object based on the information provided.\x3c/p>\n<p>wsdl_type: (string) Wsdl object to be created.\x3c/p>\n<p>object_dict: (dict) Python Dictionary containing values and nested dictionaries with construction similar to wsdl defined objects.\x3c/p>\n<p>return: (response object) Returns the SOAP client object.\x3c/p>","matched":true,"name":"Create Wsdl Objects","shortdoc":"Create Wsdl Objects. This Keyword utilizes the WSDL to create a WSDL object based on the information provided.","tags":[]}],"name":"SOAP_Library","named_args":true,"scope":"TEST","version":"2.7.0"};
</script>
<title></title>
</head>
Expand Down
9 changes: 9 additions & 0 deletions samples/Appium-DesktopTests.robot
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
81 changes: 79 additions & 2 deletions src/Zoomba/DesktopLibrary.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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('</td></tr><tr><td colspan="3"><a href="{vid}">'
'<video width="800px" controls>'
'<source src="{vid}" type="video/mp4">'
'</video></a>'.format(vid=link)
)
# Empty Screen Record Variable
self._recording = None
return path

# End Screen Recorder Keywords

@keyword("Driver Setup")
def driver_setup(self, path=None):
"""Starts the WinAppDriver.
Expand Down
8 changes: 8 additions & 0 deletions test/Desktop/test_desktop.py
Original file line number Diff line number Diff line change
Expand Up @@ -698,3 +698,11 @@ def test_drag_and_drop_by_touch_offset(self, tap_and_hold):
mock_desk = MagicMock()
DesktopLibrary.drag_and_drop_by_touch_offset(mock_desk, "some_locator", 50, 100)
tap_and_hold.assert_called_with(unittest.mock.ANY, unittest.mock.ANY)

def test_start_screen_recording(self):
mock_desk = MagicMock()
DesktopLibrary.start_screen_recording(mock_desk)

def test_stop_screen_recording(self):
mock_desk = MagicMock()
DesktopLibrary.stop_screen_recording(mock_desk)

0 comments on commit 2a79ea4

Please sign in to comment.