Skip to content

Commit 8bbf269

Browse files
authored
Add wait for network idle (#165)
* Clean up * Add wait for network idle * fix iframe issue Co-authored-by: Atthaboon Sanurt <[email protected]>
1 parent 481717b commit 8bbf269

File tree

7 files changed

+107
-56
lines changed

7 files changed

+107
-56
lines changed

Examples/form-handler/iframe.robot

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
*** Settings ***
2-
Library PuppeteerLibrary
3-
Test Setup Open browser to test page
4-
Test Teardown Close All Browser
5-
Suite Teardown Close Puppeteer
2+
Library PuppeteerLibrary
3+
4+
Suite Teardown Close Puppeteer
5+
Test Setup Open browser to test page
6+
Test Teardown Close All Browser
67

78

89
*** Variables ***
9-
${DEFAULT_BROWSER} chrome
10-
${HOME_PAGE_URL} http://127.0.0.1:7272/basic-html-elements.html
10+
${DEFAULT_BROWSER} chrome
11+
${HOME_PAGE_URL} http://127.0.0.1:7272/basic-html-elements.html
1112

1213

1314
*** Test Cases ***
@@ -20,25 +21,31 @@ Interact with iframe element
2021
Click Element xpath=//*[@id='exampleCheck1']
2122
Unselect Frame
2223
Wait Until Page Contains Element id=ifrm
23-
24+
25+
Scroll element under iframe
26+
Wait Until Page Contains Element id=ifrm
27+
Select Frame id=ifrm
28+
Scroll Element Into View id=exampleCheck1
29+
2430
Get text under iframe element
2531
Wait Until Page Contains Element id=ifrm
2632
Select Frame id=ifrm
2733
${label text} = Get Text css=h2
2834
Should Be Equal As Strings Login form ${label text}
2935
${label text} = Get Text xpath=//h2
3036
Should Be Equal As Strings Login form ${label text}
31-
37+
3238
Get value under iframe element
3339
Wait Until Page Contains Element id=ifrm
3440
Select Frame id=ifrm
3541
Input Text id=exampleInputEmail1 [email protected]
3642
${email value} = Get Value id=exampleInputEmail1
3743
Should Be Equal As Strings [email protected] ${email value}
38-
44+
45+
3946
*** Keywords ***
4047
Open browser to test page
41-
${BROWSER} = Get variable value ${BROWSER} ${DEFAULT_BROWSER}
42-
${HEADLESS} Get variable value ${HEADLESS} ${False}
48+
${BROWSER} = Get variable value ${BROWSER} ${DEFAULT_BROWSER}
49+
${HEADLESS} = Get variable value ${HEADLESS} ${False}
4350
&{options} = create dictionary headless=${HEADLESS}
4451
Open browser ${HOME_PAGE_URL} browser=${BROWSER} options=${options}

Examples/utilities/wait.robot

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,30 @@
11
*** Settings ***
2-
Library PuppeteerLibrary
3-
Test Teardown Close Browser
4-
Suite Teardown Close Puppeteer
2+
Library PuppeteerLibrary
3+
4+
Suite Teardown Close Puppeteer
5+
Test Teardown Close Browser
6+
57

68
*** Variables ***
7-
${DEFAULT_BROWSER} chrome
8-
${HOME_PAGE_URL} http://127.0.0.1:7272/basic-html-elements.html
9-
${LOGIN_PAGE_URL} http://127.0.0.1:7272/login-form-example.html
9+
${DEFAULT_BROWSER} chrome
10+
${HOME_PAGE_URL} http://127.0.0.1:7272/basic-html-elements.html
11+
${LOGIN_PAGE_URL} http://127.0.0.1:7272/login-form-example.html
1012

1113

1214
*** Test Cases ***
1315
Wait for element
1416
Open browser to test page ${HOME_PAGE_URL}
1517
Wait Until Page Contains Element id:get_ajax
16-
Run Keyword And Expect Error STARTS: TimeoutError: Wait Until Page Contains Element css:no_element timeout=5s
18+
Run Keyword And Expect Error
19+
... STARTS: TimeoutError:
20+
... Wait Until Page Contains Element
21+
... css:no_element
22+
... timeout=5s
1723

1824
Wait for http request
1925
Open browser to test page ${HOME_PAGE_URL}
2026
${results} = Run Async Keywords
21-
... Wait for request url /ajax_info.json AND
27+
... Wait for request url /ajax_info.json AND
2228
... Click Element id:get_ajax
2329
Should Contain ${results[0].url} ajax
2430
Should Be Equal As Strings ${results[0].method} GET
@@ -33,6 +39,12 @@ Wait for http response
3339
Should Be Equal As Strings ${results[0].status} 200
3440
Log ${results[0].body}
3541

42+
Wait for network idle
43+
Open browser to test page ${HOME_PAGE_URL}
44+
Run Async Keywords
45+
... Click Element id:get_ajax AND
46+
... Wait For Network Idle
47+
3648
Wait for navigation
3749
Open browser to test page ${HOME_PAGE_URL}
3850
Run Async Keywords
@@ -43,7 +55,7 @@ Wait for element hidden and visible
4355
Open browser to test page ${HOME_PAGE_URL}
4456
Click Element id:click_and_hide
4557
Wait Until Element Is Hidden id:click_and_hide
46-
58+
4759
Wait for element contains text
4860
Open browser to test page ${LOGIN_PAGE_URL}
4961
Wait Until Element Contains id:emailHelp We'll never share your email
@@ -60,26 +72,27 @@ Wait for element is enabled
6072

6173
Wait for element finished moving animation
6274
Open browser to test page ${HOME_PAGE_URL}
63-
Run Async Keywords
75+
Run Async Keywords
6476
... Wait Until Element Is Visible id=close_modal AND
6577
... Click Element id=popup_modal
6678
Wait Until Element Finished Animating id=close_modal
6779
Click Element id=close_modal
6880
Wait Until Element Is Hidden id=close_modal
69-
81+
7082
Wait for element finished fading animation
7183
Open browser to test page ${HOME_PAGE_URL}
72-
Run Async Keywords
84+
Run Async Keywords
7385
... Wait Until Element Is Visible id=close_modal_fade AND
7486
... Click Element id=popup_modal_fade
7587
Wait Until Element Finished Animating id=close_modal_fade timeout=1s
7688
Click Element id=close_modal_fade
7789
Wait Until Element Is Hidden id=close_modal_fade
7890

91+
7992
*** Keywords ***
8093
Open browser to test page
8194
[Arguments] ${url}
82-
${BROWSER} = Get variable value ${BROWSER} ${DEFAULT_BROWSER}
95+
${BROWSER} = Get variable value ${BROWSER} ${DEFAULT_BROWSER}
8396
${HEADLESS} = Get variable value ${HEADLESS} ${False}
84-
&{options} = create dictionary headless=${HEADLESS}
97+
&{options} = create dictionary headless=${HEADLESS}
8598
Open browser ${url} browser=${BROWSER} options=${options}

PuppeteerLibrary/ikeywords/iwaiting_async.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
class iWaitingAsync(BaseAsyncKeywords, ABC):
66

7+
@abstractmethod
8+
async def wait_for_network_idle(self, timeout=None):
9+
pass
10+
711
@abstractmethod
812
async def wait_for_request_url(self, url, method='GET', body=None, timeout=None):
913
pass

PuppeteerLibrary/keywords/waiting.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ def __init__(self, ctx):
1111
def get_async_keyword_group(self) -> iWaitingAsync:
1212
return self.ctx.get_current_library_context().get_async_keyword_group(type(self).__name__)
1313

14+
@keyword
15+
def wait_for_network_idle(self, timeout=None):
16+
"""
17+
Wait until there are no network connections for at least 500 ms.
18+
"""
19+
return self.loop.run_until_complete(self.get_async_keyword_group().wait_for_network_idle(timeout))
20+
1421
@keyword
1522
def wait_for_request_url(self, url, method='GET', body=None, timeout=None):
1623
"""
@@ -102,7 +109,8 @@ def wait_until_page_contains_element(self, locator, timeout=None):
102109
| Open browser | ${HOME_PAGE_URL} | options=${options} |
103110
| `Wait Until Page Contains Element` | id:username | |
104111
"""
105-
self.loop.run_until_complete(self.get_async_keyword_group().wait_until_page_contains_element(locator, timeout))
112+
self.loop.run_until_complete(self.get_async_keyword_group(
113+
).wait_until_page_contains_element(locator, timeout))
106114

107115
@keyword
108116
def wait_until_element_is_hidden(self, locator, timeout=None):
@@ -141,7 +149,8 @@ def wait_until_page_contains(self, text, timeout=None):
141149
| ... | Wait For Navigation | | |
142150
| `Wait Until Page Contains` | Invalid user name or password | | |
143151
"""
144-
self.loop.run_until_complete(self.get_async_keyword_group().wait_until_page_contains(text, timeout))
152+
self.loop.run_until_complete(
153+
self.get_async_keyword_group().wait_until_page_contains(text, timeout))
145154

146155
@keyword
147156
def wait_until_page_does_not_contains(self, text, timeout=None):

PuppeteerLibrary/playwright/async_keywords/playwright_waiting.py

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,17 @@ class PlaywrightWaiting(iWaitingAsync):
1111
def __init__(self, library_ctx):
1212
super().__init__(library_ctx)
1313

14+
async def wait_for_network_idle(self, timeout=None):
15+
await self.library_ctx.get_current_page().get_page().wait_for_load_state('networkidle', timeout=self.timestr_to_secs_for_default_timeout(timeout) * 1000)
16+
1417
async def wait_for_request_url(self, url, method='GET', body=None, timeout=None):
1518
url = str2str(url)
1619
method = str2str(method)
1720
req = await self.library_ctx.get_current_page().get_page().wait_for_event(
18-
"request",
19-
predicate=lambda request: re.search(url, request.url) is not None and request.method == method,
20-
timeout=self.timestr_to_secs_for_default_timeout(timeout) * 1000
21+
"request",
22+
predicate=lambda request: re.search(
23+
url, request.url) is not None and request.method == method,
24+
timeout=self.timestr_to_secs_for_default_timeout(timeout) * 1000
2125
)
2226
try:
2327
pos_data = (await req.postData())
@@ -30,7 +34,8 @@ async def wait_for_request_url(self, url, method='GET', body=None, timeout=None)
3034
log_str + '\n' + pos_data
3135
self.info(log_str)
3236
else:
33-
raise Exception('Can\'t match request body with ' + body + ' \n ' + pos_data)
37+
raise Exception('Can\'t match request body with ' +
38+
body + ' \n ' + pos_data)
3439

3540
return DotDict({
3641
'url': req.url,
@@ -42,21 +47,23 @@ async def wait_for_response_url(self, url, status=200, body=None, timeout=None):
4247
url = str2str(url)
4348
status = str2int(status)
4449
res = await self.library_ctx.get_current_page().get_page().wait_for_event(
45-
"response",
46-
predicate=lambda response: re.search(url, response.url) is not None and response.status == status,
47-
timeout=self.timestr_to_secs_for_default_timeout(timeout) * 1000
50+
"response",
51+
predicate=lambda response: re.search(
52+
url, response.url) is not None and response.status == status,
53+
timeout=self.timestr_to_secs_for_default_timeout(timeout) * 1000
4854
)
4955
try:
5056
res_text = (await res.text())
5157
except:
5258
res_text = ''
53-
if body is None or re.search(body, res_text.replace('\n','')):
59+
if body is None or re.search(body, res_text.replace('\n', '')):
5460
log_str = 'Wait for request url: ' + res.url
5561
if res_text != '':
5662
log_str += '\n' + res_text
5763
self.info(log_str)
5864
else:
59-
raise Exception('Can\'t match response body with '+body+' \n '+res_text)
65+
raise Exception(
66+
'Can\'t match response body with '+body+' \n '+res_text)
6067
return DotDict({
6168
'url': res.url,
6269
'status': res.status,
@@ -65,8 +72,8 @@ async def wait_for_response_url(self, url, status=200, body=None, timeout=None):
6572

6673
async def wait_for_navigation(self, timeout=None):
6774
return await self.library_ctx.get_current_page().get_page().wait_for_event(
68-
'load',
69-
predicate=None,
75+
'load',
76+
predicate=None,
7077
timeout=self.timestr_to_secs_for_default_timeout(timeout) * 1000)
7178

7279
async def wait_until_page_contains_element(self, locator, timeout=None):
@@ -95,15 +102,17 @@ async def wait_until_element_contains(self, locator, text, timeout=None):
95102

96103
async def wait_until_element_does_not_contains(self, locator, text, timeout=None):
97104
text = str2str(text)
105+
98106
async def validate_element_contains_text():
99-
return (text not in (await (await ( await self.library_ctx.get_current_page().
100-
querySelector_with_selenium_locator(locator)).get_property('textContent')).json_value()))
107+
return (text not in (await (await (await self.library_ctx.get_current_page().
108+
querySelector_with_selenium_locator(locator)).get_property('textContent')).json_value()))
101109
return await self._wait_until_worker(
102110
validate_element_contains_text,
103111
self.timestr_to_secs_for_default_timeout(timeout))
104112

105113
async def wait_until_location_contains(self, expected, timeout=None):
106114
expected = str2str(expected)
115+
107116
async def validate_url_contains_text():
108117
return expected in self.library_ctx.get_current_page().get_page().url
109118
return await self._wait_until_worker(
@@ -112,6 +121,7 @@ async def validate_url_contains_text():
112121

113122
async def wait_until_location_does_not_contains(self, expected, timeout=None):
114123
expected = str2str(expected)
124+
115125
async def validate_url_not_contains_text():
116126
return expected not in self.library_ctx.get_current_page().get_page().url
117127
return await self._wait_until_worker(
@@ -129,7 +139,8 @@ async def validate_is_enabled():
129139
'Element '+locator+' was not enabled.')
130140

131141
async def wait_until_element_finished_animating(self, locator, timeout=None):
132-
prev_rect_tmp = { 'value': None }
142+
prev_rect_tmp = {'value': None}
143+
133144
async def check_finished_animating():
134145
await self.wait_until_element_is_visible(locator)
135146
element = await self.library_ctx.get_current_page().querySelector_with_selenium_locator(locator)
@@ -151,7 +162,7 @@ async def check_finished_animating():
151162
async def _wait_for_selenium_selector(self, selenium_locator, timeout=None, visible=False, hidden=False):
152163
timeout = self.timestr_to_secs_for_default_timeout(timeout)
153164
return await self.library_ctx.get_current_page().waitForSelector_with_selenium_locator(selenium_locator, timeout, visible, hidden)
154-
165+
155166
async def _wait_until_worker(self, condition, timeout, error=None):
156167
max_time = time.time() + timeout
157168
not_found = None

0 commit comments

Comments
 (0)