Skip to content

Commit

Permalink
Wait until window opens fix (#83)
Browse files Browse the repository at this point in the history
* revert code not ready

* test

* cleanup failing test

* test clean up and added test for failure coverage

* More cleanup, added timeout for keyword, new test to run timeout

* update docs
  • Loading branch information
Wolfe1 authored Oct 29, 2019
1 parent cee5ba0 commit c44381c
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 24 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/SOAPLibraryDocumentation.html
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,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":"2019-10-17 16:29: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 case","version":"2.1.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":"2019-10-28 16:23:46","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 case","version":"2.1.2"};
</script>
<title></title>
</head>
Expand Down
23 changes: 16 additions & 7 deletions src/Zoomba/GUILibrary.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from robot.libraries.BuiltIn import BuiltIn
from robot.api.deco import keyword
from robot.libraries.Collections import Collections
from time import time

zoomba = BuiltIn()
zoomba_collections = Collections()
Expand Down Expand Up @@ -136,13 +137,21 @@ def wait_for_and_focus_on_element(self, locator):
self.wait_until_element_is_visible(locator)

@keyword("Wait Until Window Opens")
def wait_until_window_opens(self, title):
"""This is a series of chained Selenium keywords, used to get the titles of the current browser windows, then
verify that the provided window title is among them.\n
title: (string) The title of the window you are waiting for.
def wait_until_window_opens(self, title, timeout=None):
"""Used to get the titles of the current browser windows, then verify that the provided window title
is among them.\n
title: (string) The title of the window you are waiting for.\n
timeout: (float) Time in seconds to wait, will use global timeout if not set.
"""
titles = self.get_window_titles()
zoomba_collections.list_should_contain_value(titles, title)
if timeout:
timeout = time() + float(timeout)
else:
timeout = time() + self.timeout
while time() < timeout:
titles = self.get_window_titles()
if title in titles:
return
zoomba.fail("Window with the title: '" + title + "' not found.")

@keyword("Window Should Not Be Open")
def window_should_not_be_open(self, title):
Expand All @@ -158,7 +167,7 @@ def wait_for_and_select_window(self, title):
then it selects that window.\n
title: (string) The title of the window you are waiting for.
"""
zoomba.wait_until_keyword_succeeds(self.timeout, 1, "Wait Until Window Opens", title)
self.wait_until_window_opens(title)
self.switch_window(title)

@keyword("Scroll To Bottom Of Page")
Expand Down
7 changes: 7 additions & 0 deletions test/GUI/GUITests.robot
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@ Scroll To Bottom of Page Test
${position} = Execute Javascript return window.pageYOffset
should be equal "767" "${position}"

Wait Until Window Opens Test
[Teardown] Close All Browsers
Open Browser https://www.seleniumeasy.com/test/window-popup-modal-demo.html browser=${browser}
Maximize Browser Window
Click Element //a[contains(text(),'Follow On Twitter')]
Wait Until Window Opens Selenium Easy (@seleniumeasy) on Twitter 10

Wait For and Select Window Test
[Teardown] Close All Browsers
Open Browser https://www.seleniumeasy.com/test/window-popup-modal-demo.html browser=${browser}
Expand Down
34 changes: 21 additions & 13 deletions test/GUI/test_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,24 @@ def test_wait_for_and_select_checkbox_simple(self):
mock_gui.wait_for_and_focus_on_element.assert_called_with("some_locator")
mock_gui.select_checkbox.assert_called_with("some_locator")

@patch('robot.libraries.Collections.Collections.list_should_contain_value')
def test_wait_until_window_opens_simple(self, robot_call):
def test_wait_until_window_opens_simple(self):
mock_gui = Mock()
mock_gui.timeout = 15
mock_gui.get_window_titles = Mock(return_value=["title"])
GUILibrary.wait_until_window_opens(mock_gui, "title")
robot_call.assert_called_with(["title"], "title")

def test_wait_until_window_opens_with_timeout(self):
mock_gui = Mock()
mock_gui.get_window_titles = Mock(return_value=["title"])
GUILibrary.wait_until_window_opens(mock_gui, "title", 15)

@patch('robot.libraries.BuiltIn.BuiltIn.fail')
def test_wait_until_window_opens_with_error(self, fail):
mock_gui = Mock()
mock_gui.timeout = 0.0001
mock_gui.get_window_titles = Mock(return_value=["wrong_title"])
GUILibrary.wait_until_window_opens(mock_gui, "title")
fail.assert_called_with("Window with the title: 'title' not found.")

@patch('robot.libraries.Collections.Collections.list_should_not_contain_value')
def test_window_should_not_be_open_simple(self, robot_call):
Expand All @@ -107,12 +119,11 @@ def test_window_should_not_be_open_simple(self, robot_call):
GUILibrary.window_should_not_be_open(mock_gui, "title")
robot_call.assert_called_with(["main"], "title")

@patch('robot.libraries.BuiltIn.BuiltIn.wait_until_keyword_succeeds')
def test_wait_for_and_select_window_simple(self, robot_call):
def test_wait_for_and_select_window_simple(self):
mock_gui = Mock()
type(mock_gui).timeout = PropertyMock(return_value=15)
mock_gui.timeout = 15
GUILibrary.wait_for_and_select_window(mock_gui, "title")
robot_call.assert_called_with(15, 1, 'Wait Until Window Opens', 'title')
mock_gui.wait_until_window_opens.assert_called_with("title")
mock_gui.switch_window.assert_called_with("title")

@patch('robot.libraries.BuiltIn.BuiltIn.sleep')
Expand All @@ -122,20 +133,17 @@ def test_wait_until_javascript_is_complete_simple(self, robot_call):
GUILibrary.wait_until_javascript_is_complete(mock_gui)
robot_call.assert_called()

@patch('SeleniumLibrary.ElementKeywords.get_text')
def test_get_text_from_web_elements_list_simple(self, robot_call):
def test_get_text_from_web_elements_list_simple(self):
mock_gui = Mock()
mock_gui.get_text = Mock(side_effect=['a', 'b'])
assert GUILibrary.get_text_from_web_elements_list(mock_gui, ['a', 'b']) == ['a', 'b']

@patch('SeleniumLibrary.ElementKeywords.get_value')
def test_get_values_from_web_elements_list_simple(self, robot_call):
def test_get_values_from_web_elements_list_simple(self):
mock_gui = Mock()
mock_gui.get_value = Mock(side_effect=['a', 'b'])
assert GUILibrary.get_values_from_web_elements_list(mock_gui, ['a', 'b']) == ['a', 'b']

@patch('SeleniumLibrary.ElementKeywords.get_vertical_position')
def test_get_vertical_position_from_web_elements_list_simple(self, robot_call):
def test_get_vertical_position_from_web_elements_list_simple(self):
mock_gui = Mock()
mock_gui.get_vertical_position = Mock(side_effect=[1, 2])
assert GUILibrary.get_vertical_position_from_web_elements_list(mock_gui, ['a', 'b']) == [1, 2]
Expand Down

0 comments on commit c44381c

Please sign in to comment.