diff --git a/AppiumLibrary/keywords/_applicationmanagement.py b/AppiumLibrary/keywords/_applicationmanagement.py index 0bb4d0f..ba065ed 100644 --- a/AppiumLibrary/keywords/_applicationmanagement.py +++ b/AppiumLibrary/keywords/_applicationmanagement.py @@ -380,15 +380,43 @@ def switch_to_window(self, window_name): """ self._current_application().switch_to.window(window_name) - def go_to_url(self, url): + def go_to_url(self, url, timeout=None): """ Opens the ``url`` in the default web browser. - Example: + The optional ``timeout`` argument specifies the maximum time to wait + for the page to load. If not specified, the default page load timeout + is used. The timeout can be given as a number (seconds) or as a time + string (e.g., '1 minute', '2 min 3 s', '4.5'). + + Examples: | Open Application | http://localhost:4755/wd/hub | platformName=iOS | platformVersion=7.0 | deviceName='iPhone Simulator' | browserName=Safari | - | Go To URL | http://m.webapp.com | + | Go To URL | http://m.webapp.com | | + | Go To URL | http://m.webapp.com | timeout=30 | + | Go To URL | http://m.webapp.com | timeout=1 minute | """ - self._current_application().get(url) + driver = self._current_application() + + if timeout is not None: + # Convert timeout to seconds + timeout_secs = robot.utils.timestr_to_secs(timeout) + # Get current timeout to restore it later + current_timeouts = driver.timeouts + original_page_load = None + + if current_timeouts is not None and hasattr(current_timeouts, 'page_load'): + original_page_load = current_timeouts.page_load + + try: + # Set the page load timeout + driver.set_page_load_timeout(timeout_secs) + driver.get(url) + finally: + # Restore the original page load timeout if it was set and is a valid positive value + if original_page_load is not None and original_page_load > 0: + driver.set_page_load_timeout(original_page_load / 1000) # Convert from ms to seconds + else: + driver.get(url) def get_capability(self, capability_name): """ diff --git a/tests/keywords/test_applicationmanagement.py b/tests/keywords/test_applicationmanagement.py index e6cc3f3..8c1c932 100644 --- a/tests/keywords/test_applicationmanagement.py +++ b/tests/keywords/test_applicationmanagement.py @@ -43,3 +43,99 @@ def test_switch_application(self): am.switch_application(2) self.assertEqual(2, am._cache.current_index) self.assertEqual(2, am.switch_application(None)) + + def test_go_to_url_without_timeout(self): + am = _ApplicationManagementKeywords() + appium.webdriver.Remote = WebdriverRemoteMock + am._debug = mock.Mock() + am.open_application('remote_url') + + # Mock the methods + driver = am._current_application() + driver.get = mock.Mock() + driver.set_page_load_timeout = mock.Mock() + + # Call go_to_url without timeout + am.go_to_url('http://example.com') + + # Verify get was called with the URL + driver.get.assert_called_once_with('http://example.com') + + # Verify set_page_load_timeout was NOT called when timeout is None + driver.set_page_load_timeout.assert_not_called() + + def test_go_to_url_with_timeout_seconds(self): + am = _ApplicationManagementKeywords() + appium.webdriver.Remote = WebdriverRemoteMock + am._debug = mock.Mock() + am.open_application('remote_url') + + # Mock necessary methods + driver = am._current_application() + driver.get = mock.Mock() + driver.set_page_load_timeout = mock.Mock() + + # Create a mock timeouts object + mock_timeouts = mock.Mock() + mock_timeouts.page_load = 30000 # 30 seconds in milliseconds + driver.timeouts = mock_timeouts + + # Call go_to_url with timeout in seconds + am.go_to_url('http://example.com', timeout=10) + + # Verify set_page_load_timeout was called with 10 seconds + self.assertEqual(driver.set_page_load_timeout.call_count, 2) # Once to set, once to restore + driver.set_page_load_timeout.assert_any_call(10) + + # Verify get was called + driver.get.assert_called_once_with('http://example.com') + + def test_go_to_url_with_timeout_timestr(self): + am = _ApplicationManagementKeywords() + appium.webdriver.Remote = WebdriverRemoteMock + am._debug = mock.Mock() + am.open_application('remote_url') + + # Mock necessary methods + driver = am._current_application() + driver.get = mock.Mock() + driver.set_page_load_timeout = mock.Mock() + + # Create a mock timeouts object + mock_timeouts = mock.Mock() + mock_timeouts.page_load = 30000 # 30 seconds in milliseconds + driver.timeouts = mock_timeouts + + # Call go_to_url with timeout as time string + am.go_to_url('http://example.com', timeout='1 minute') + + # Verify set_page_load_timeout was called with 60 seconds + driver.set_page_load_timeout.assert_any_call(60) + + # Verify get was called + driver.get.assert_called_once_with('http://example.com') + + def test_go_to_url_restores_timeout_on_error(self): + am = _ApplicationManagementKeywords() + appium.webdriver.Remote = WebdriverRemoteMock + am._debug = mock.Mock() + am.open_application('remote_url') + + # Mock necessary methods + driver = am._current_application() + driver.get = mock.Mock(side_effect=Exception("Navigation failed")) + driver.set_page_load_timeout = mock.Mock() + + # Create a mock timeouts object + mock_timeouts = mock.Mock() + mock_timeouts.page_load = 30000 # 30 seconds in milliseconds + driver.timeouts = mock_timeouts + + # Call go_to_url with timeout - should raise exception but still restore timeout + with self.assertRaises(Exception): + am.go_to_url('http://example.com', timeout=10) + + # Verify timeout was restored even after error + self.assertEqual(driver.set_page_load_timeout.call_count, 2) # Once to set, once to restore + driver.set_page_load_timeout.assert_any_call(10) # Initial set + driver.set_page_load_timeout.assert_any_call(30) # Restore (30000ms / 1000 = 30s)