Skip to content

Commit

Permalink
Merge e58e49d into 82ac0e2
Browse files Browse the repository at this point in the history
  • Loading branch information
Wolfe1 authored Jun 1, 2021
2 parents 82ac0e2 + e58e49d commit d990386
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 46 deletions.
4 changes: 2 additions & 2 deletions docs/APILibraryDocumentation.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/DesktopLibraryDocumentation.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/GUILibraryDocumentation.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/MobileLibraryDocumentation.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/SOAPLibraryDocumentation.html

Large diffs are not rendered by default.

59 changes: 45 additions & 14 deletions samples/WinAppDriver-DesktopTests.robot
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ Force Tags Windows
*** Variables ***
${REMOTE_URL} http://127.0.0.1:4723
${APP} Microsoft.WindowsCalculator_8wekyb3d8bbwe!App
${Notepad} C:/Windows/System32/notepad.exe

*** Keywords ***
Start App
[Documentation] Sets up the application for quick launching through 'Launch Application' and starts the winappdriver
Driver Setup
Open Application ${REMOTE_URL} platformName=Windows deviceName=Windows app=${APP}
Open Application ${REMOTE_URL} platformName=Windows deviceName=Windows app=${APP} alias=Main
Maximize Window
Quit Application

Expand Down Expand Up @@ -60,6 +61,7 @@ Mouse Over Element Keyword Test
Mouse Over Element name=Two

Mouse Over And Click Element Keyword Test
# This test will fail unless run at 1080p
Mouse Over And Click Element name=Two
Mouse Over And Click Element name=Two x_offset=400 y_offset=100
Wait Until Element Contains accessibility_id=CalculatorResults 23
Expand Down Expand Up @@ -146,24 +148,53 @@ Flick Tests

Switch Application By Name or Locator
# Select Window by Class Name
Switch Application By Locator ${REMOTE_URL} class=ApplicationFrameWindow
Wait For And Click Element accessibility_id=num2Button
Wait Until Element Contains accessibility_id=CalculatorResults 2
Open Application ${REMOTE_URL} platformName=Windows deviceName=Windows app=${Notepad}
Sleep 1s
Switch Application Main
Switch Application By Locator ${REMOTE_URL} class=Notepad
Wait For And Input Text Name=Text Editor test
Wait Until Element Contains Name=Text Editor test
Quit Application
Wait For And Click Element Name=Don't Save
# Select Window by Xpath
Switch Application By Locator ${REMOTE_URL} //Window[contains(@Name, "Calculator")]
Wait For And Click Element accessibility_id=num2Button
Wait Until Element Contains accessibility_id=CalculatorResults 22
Open Application ${REMOTE_URL} platformName=Windows deviceName=Windows app=${Notepad}
Switch Application Main
Switch Application By Locator ${REMOTE_URL} //Window[contains(@Name, "Notepad")]
Wait For And Input Text Name=Text Editor test
Wait Until Element Contains Name=Text Editor test
Quit Application
Wait For And Click Element Name=Don't Save
# Select Window by Name
Switch Application By Name ${REMOTE_URL} Calculator
Wait For And Click Element accessibility_id=num2Button
Wait Until Element Contains accessibility_id=CalculatorResults 222
Open Application ${REMOTE_URL} platformName=Windows deviceName=Windows app=${Notepad}
Switch Application Main
Switch Application By Name ${REMOTE_URL} Untitled - Notepad
Wait For And Input Text Name=Text Editor test
Wait Until Element Contains Name=Text Editor test
Quit Application
Wait For And Click Element Name=Don't Save
# Select Window by Partial Name
Switch Application By Name ${REMOTE_URL} Calculator exact_match=False
Wait For And Click Element accessibility_id=num2Button
Wait Until Element Contains accessibility_id=CalculatorResults 2,222
Open Application ${REMOTE_URL} platformName=Windows deviceName=Windows app=${Notepad}
Switch Application Main
Switch Application By Name ${REMOTE_URL} Notepad exact_match=False
Wait For And Input Text Name=Text Editor test
Wait Until Element Contains Name=Text Editor test
Quit Application
Wait For And Click Element Name=Don't Save
# Switch back to the main window to make sure it gets closed
Switch Application Main

Switch Application Multiple Desktop
# Open Application creates a new desktop session for this isnatnce, useful when running tests on multiple computers
Open Application ${REMOTE_URL} platformName=Windows deviceName=Windows app=${Notepad} alias=Notepad desktop_alias=Desktop2
Switch Application Desktop
Switch Application Desktop2
Switch Application Notepad
Quit Application
# Switch back to the main window to make sure it gets closed
Switch Application Main

Switch To Desktop Test
Close Application
[Setup] Driver Setup
Switch Application Desktop
Wait For And Click Element name=Start
Wait For And Click Element name=Start
94 changes: 72 additions & 22 deletions src/Zoomba/DesktopLibrary.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ def __init__(self, timeout=5, run_on_failure='Save Appium Screenshot',
"""
self.winappdriver = WinAppDriver(driver_path)
self.current_element = None
self.current_desktop = None
super().__init__(timeout, run_on_failure)

def get_keyword_names(self):
Expand Down Expand Up @@ -251,7 +252,7 @@ def maximize_window(self):

@keyword("Open Application")
def open_application(self, remote_url, alias=None, window_name=None, splash_delay=0,
exact_match=True, **kwargs):
exact_match=True, desktop_alias=None, **kwargs):
"""Opens a new application to given Appium server.
If your application has a splash screen please supply the window name of the final window that will appear.
For the capabilities of appium server and Windows please check http://appium.io/docs/en/drivers/windows
Expand Down Expand Up @@ -283,9 +284,9 @@ def open_application(self, remote_url, alias=None, window_name=None, splash_dela
self._info('Waiting %s seconds for splash screen' % splash_delay)
sleep(splash_delay)
return self.switch_application_by_name(remote_url, alias=alias, window_name=window_name,
exact_match=exact_match, **kwargs)
exact_match=exact_match, desktop_alias=desktop_alias, **kwargs)
# global application
self._open_desktop_session(remote_url)
self._open_desktop_session(remote_url, desktop_alias)
if "platformName" not in desired_caps:
desired_caps["platformName"] = "Windows"
if "forceMjsonwp" not in desired_caps:
Expand All @@ -294,9 +295,49 @@ def open_application(self, remote_url, alias=None, window_name=None, splash_dela
self._debug('Opened application with session id %s' % application.session_id)
return self._cache.register(application, alias)

def switch_application(self, index_or_alias, desktop_alias=None):
"""Switches the active application by index or alias.
`index_or_alias` is either application index (an integer) or alias
(a string). Index is got as the return value of `Open Application`.
This keyword returns the index of the previous active application,
which can be used to switch back to that application later.
Example:
| ${appium1}= | Open Application | http://localhost:4723/wd/hub | alias=MyApp1 | platformName=iOS | platformVersion=7.0 | deviceName='iPhone Simulator' | app=your.app |
| ${appium2}= | Open Application | http://localhost:4755/wd/hub | alias=MyApp2 | platformName=iOS | platformVersion=7.0 | deviceName='iPhone Simulator' | app=your.app |
| Click Element | sendHello | # Executed on appium running at localhost:4755 |
| Switch Application | ${appium1} | # Switch using index |
| Click Element | ackHello | # Executed on appium running at localhost:4723 |
| Switch Application | MyApp2 | # Switch using alias |
| Page Should Contain Text | ackHello Received | # Executed on appium running at localhost:4755 |
`desktop_alias` (string) is used to update the current desktop the application resides on. If only using one PC
in tests this can be ignore. Otherwise this can be used to maintain the association between your application
and desktop needed for some keywords.
Example:
| Open Application | http://localhost:4723/wd/hub | alias=MyApp1 | platformName=iOS | platformVersion=7.0 | deviceName='iPhone Simulator' | app=your.app |
| Open Application | http://localhost:4755/wd/hub | alias=MyApp2 | desktop_alias=Desktop2 | platformName=iOS | platformVersion=7.0 | deviceName='iPhone Simulator' | app=your.app |
| Select Element From ComboBox | list_element | locator_element | # Executed on MyApp2 running at localhost:4755 with Desktop2 as the desktop session |
| Switch Application | MyApp1 | Desktop | # Switch using alias and setting current desktop alias |
| Select Element From ComboBox | list_element | locator_element | # Executed on MyApp1 running at localhost:4723 with Desktop as the desktop session |
| Switch Application | MyApp2 Desktop2 | # Switch using alias and setting current desktop alias |
| Select Element From ComboBox | list_element | locator_element | # Executed on MyApp2 running at localhost:4755 with Desktop2 as the desktop session |
"""
old_index = self._cache.current_index
if index_or_alias is None:
self._cache.close()
else:
self._cache.switch(index_or_alias)
if desktop_alias is not None:
self.current_desktop = desktop_alias
return old_index

@keyword("Switch Application By Name")
def switch_application_by_name(self, remote_url, window_name, alias=None, timeout=5,
exact_match=True, **kwargs):
exact_match=True, desktop_alias=None, **kwargs):
"""Switches to a currently opened window by ``window_name``.
For the capabilities of appium server and Windows,
Please check http://appium.io/docs/en/drivers/windows
Expand All @@ -315,26 +356,30 @@ def switch_application_by_name(self, remote_url, window_name, alias=None, timeou
| Switch Application | Desktop |
"""
desired_caps = kwargs
desktop_session = self._open_desktop_session(remote_url)
self._open_desktop_session(remote_url, desktop_alias)
self.switch_application(self.current_desktop)
window_xpath = '//Window[contains(@Name, "' + window_name + '")]'
window_locator = 'name=' + window_name
try:
if exact_match:
window = desktop_session.find_element_by_name(window_name)
window = self._element_find(window_locator, True)
# print(self._current_application())
# window = desktop_session.find_element_by_name(window_name)
else:
window = desktop_session.find_element_by_xpath(window_xpath)
window = self._element_find(window_xpath, True)
self._debug('Window_name "%s" found.' % window_name)
window = hex(int(window.get_attribute("NativeWindowHandle")))
except Exception:
try:
error = "Window '%s' did not appear in <TIMEOUT>" % window_name
if exact_match:
self._wait_until(timeout, error, desktop_session.find_element_by_name,
window_name)
window = desktop_session.find_element_by_name(window_name)
# self._wait_until(timeout, error, desktop_session.find_element_by_name,
# window_name)
self._wait_until(timeout, error, self._element_find, window_locator, True)
window = self._element_find(window_name, True)
else:
self._wait_until(timeout, error, desktop_session.find_element_by_xpath,
window_xpath)
window = desktop_session.find_element_by_xpath(window_xpath)
self._wait_until(timeout, error, self._element_find, window_xpath, True)
window = self._element_find(window_xpath, True)
self._debug('Window_name "%s" found.' % window_name)
window = hex(int(window.get_attribute("NativeWindowHandle")))
except Exception as e:
Expand All @@ -360,7 +405,8 @@ def switch_application_by_name(self, remote_url, window_name, alias=None, timeou
return self._cache.register(application, alias)

@keyword("Switch Application By Locator")
def switch_application_by_locator(self, remote_url, locator=None, alias=None, timeout=5, **kwargs):
def switch_application_by_locator(self, remote_url, locator=None, alias=None, timeout=5, desktop_alias=None,
**kwargs):
"""Switches to a currently opened window by ``locator``.
For the capabilities of appium server and Windows,
Expand All @@ -385,8 +431,8 @@ def switch_application_by_locator(self, remote_url, locator=None, alias=None, ti
if locator_type in desired_caps:
locator = locator_type + "=" + desired_caps[locator_type]
del desired_caps[locator_type]
self._open_desktop_session(remote_url)
self.switch_application("Desktop")
self._open_desktop_session(remote_url, desktop_alias)
self.switch_application(self.current_desktop)
try:
window = self._element_find(locator, True)
except Exception:
Expand Down Expand Up @@ -438,7 +484,8 @@ def launch_application(self):
See `Quit Application` for quiting application but keeping Appium session running.
"""
self._open_desktop_session(self._current_application().command_executor)
# self._open_desktop_session(self._current_application().command_executor, self.current_desktop)
# self._open_desktop_session(self._current_application().command_executor)
self._current_application().launch_app()

@keyword("Wait For And Clear Text")
Expand Down Expand Up @@ -789,7 +836,7 @@ def select_element_from_combobox(self, list_locator, element_locator, skip_to_de
self.click_element(element_locator)
except ValueError:
original_index = self._cache.current_index
self.switch_application('Desktop')
self.switch_application(self.current_desktop)
try:
self.click_element(element_locator)
except NoSuchElementException:
Expand All @@ -811,7 +858,7 @@ def select_elements_from_menu(self, *args):
count += 1
except NoSuchElementException:
original_index = self._cache.current_index
self.switch_application('Desktop')
self.switch_application(self.current_desktop)
for each in args[count:]:
try:
self.click_element(each)
Expand Down Expand Up @@ -839,7 +886,7 @@ def select_elements_from_context_menu(self, *args):
count += 1
except NoSuchElementException:
original_index = self._cache.current_index
self.switch_application('Desktop')
self.switch_application(self.current_desktop)
for each in args[count:]:
try:
if count == 0:
Expand Down Expand Up @@ -992,16 +1039,19 @@ def _move_to_element(self, actions, element, x_offset=0, y_offset=0):
self._info('Moving to element "' + str(element) + '".')
actions.move_to_element(element)

def _open_desktop_session(self, remote_url, alias="Desktop"):
def _open_desktop_session(self, remote_url, alias=None):
if not alias:
alias = "Desktop"
try:
return self._cache.get_connection(alias)
except RuntimeError:
self._debug('Creating new desktop session')
desktop_capabilities = dict({"app": "Root", "platformName": "Windows",
"deviceName": "Windows", "newCommandTimeout": 3600,
"deviceName": "Windows", "alias": alias, "newCommandTimeout": 3600,
"forceMjsonwp": True})
desktop_session = webdriver.Remote(str(remote_url), desktop_capabilities)
self._cache.register(desktop_session, alias=alias)
self.current_desktop = alias
return desktop_session

def _element_find(self, locator, first_only, *kwargs):
Expand Down
10 changes: 10 additions & 0 deletions test/Desktop/test_desktop.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ def test_open_application_successful(self):
dl.open_application('remote_url')
self.assertTrue(dl._cache.current)

def test_open_multiple_applications_successful(self):
dl = DesktopLibrary()
webdriver.Remote = WebdriverRemoteMock
dl.open_application('remote_url', alias='App1')
dl.open_application('remote_url', alias='App2', desktop_alias='Desktop2')
dl.switch_application('Desktop')
dl.switch_application('Desktop2')
self.assertRaisesRegex(RuntimeError, "Non-existing index or alias 'Desktop3'.", dl.switch_application,
'Desktop3')

def test_open_application_successful_double(self):
dl = DesktopLibrary()
webdriver.Remote = WebdriverRemoteMock
Expand Down

0 comments on commit d990386

Please sign in to comment.