Skip to content

Commit 2685fc7

Browse files
committed
Merge pull request robotframework#499 from aaltat/fix_alert_in_chrome
Fix for alerts in Chrome Browsers
2 parents 17b6f52 + 2644d14 commit 2685fc7

File tree

5 files changed

+143
-123
lines changed

5 files changed

+143
-123
lines changed

src/Selenium2Library/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ class Selenium2Library(
1616
_JavaScriptKeywords,
1717
_CookieKeywords,
1818
_ScreenshotKeywords,
19-
_WaitingKeywords
19+
_WaitingKeywords,
20+
_AlertKeywords
2021
):
2122
"""Selenium2Library is a web testing library for Robot Framework.
2223

src/Selenium2Library/keywords/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from _cookie import _CookieKeywords
1010
from _screenshot import _ScreenshotKeywords
1111
from _waiting import _WaitingKeywords
12+
from _alert import _AlertKeywords
1213

1314
__all__ = [
1415
"_LoggingKeywords",
@@ -21,5 +22,6 @@
2122
"_JavaScriptKeywords",
2223
"_CookieKeywords",
2324
"_ScreenshotKeywords",
24-
"_WaitingKeywords"
25+
"_WaitingKeywords",
26+
"_AlertKeywords"
2527
]
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
from selenium.common.exceptions import WebDriverException
2+
from selenium.webdriver.support.ui import WebDriverWait
3+
from selenium.webdriver.support import expected_conditions as EC
4+
from keywordgroup import KeywordGroup
5+
6+
7+
class _AlertKeywords(KeywordGroup):
8+
9+
def __init__(self):
10+
self._cancel_on_next_confirmation = False
11+
12+
# Public
13+
14+
def input_text_into_prompt(self, text):
15+
"""Types the given `text` into alert box. """
16+
alert = None
17+
try:
18+
alert = self._wait_alert()
19+
alert.send_keys(text)
20+
except WebDriverException:
21+
raise RuntimeError('There were no alerts')
22+
23+
def alert_should_be_present(self, text=''):
24+
"""Verifies an alert is present and dismisses it.
25+
26+
If `text` is a non-empty string, then it is also verified that the
27+
message of the alert equals to `text`.
28+
29+
Will fail if no alert is present. Note that following keywords
30+
will fail unless the alert is dismissed by this
31+
keyword or another like `Get Alert Message`.
32+
"""
33+
alert_text = self.get_alert_message()
34+
if text and alert_text != text:
35+
raise AssertionError("Alert text should have been "
36+
"'%s' but was '%s'"
37+
% (text, alert_text))
38+
39+
def choose_cancel_on_next_confirmation(self):
40+
"""Cancel will be selected the next time `Confirm Action` is used."""
41+
self._cancel_on_next_confirmation = True
42+
43+
def choose_ok_on_next_confirmation(self):
44+
"""Undo the effect of using keywords `Choose Cancel On Next Confirmation`. Note
45+
that Selenium's overridden window.confirm() function will normally
46+
automatically return true, as if the user had manually clicked OK, so
47+
you shouldn't need to use this command unless for some reason you need
48+
to change your mind prior to the next confirmation. After any
49+
confirmation, Selenium will resume using the default behavior for
50+
future confirmations, automatically returning true (OK) unless/until
51+
you explicitly use `Choose Cancel On Next Confirmation` for each
52+
confirmation.
53+
54+
Note that every time a confirmation comes up, you must
55+
consume it by using a keywords such as `Get Alert Message`, or else
56+
the following selenium operations will fail.
57+
"""
58+
self._cancel_on_next_confirmation = False
59+
60+
def confirm_action(self):
61+
"""Dismisses currently shown confirmation dialog and returns it's message.
62+
63+
By default, this keyword chooses 'OK' option from the dialog. If
64+
'Cancel' needs to be chosen, keyword `Choose Cancel On Next
65+
Confirmation` must be called before the action that causes the
66+
confirmation dialog to be shown.
67+
68+
Examples:
69+
| Click Button | Send | # Shows a confirmation dialog |
70+
| ${message}= | Confirm Action | # Chooses Ok |
71+
| Should Be Equal | ${message} | Are your sure? |
72+
| | | |
73+
| Choose Cancel On Next Confirmation | | |
74+
| Click Button | Send | # Shows a confirmation dialog |
75+
| Confirm Action | | # Chooses Cancel |
76+
"""
77+
text = self._close_alert(not self._cancel_on_next_confirmation)
78+
self._cancel_on_next_confirmation = False
79+
return text
80+
81+
def get_alert_message(self, dismiss=True):
82+
"""Returns the text of current JavaScript alert.
83+
84+
By default the current JavaScript alert will be dismissed.
85+
This keyword will fail if no alert is present. Note that
86+
following keywords will fail unless the alert is
87+
dismissed by this keyword or another like `Get Alert Message`.
88+
"""
89+
if dismiss:
90+
return self._close_alert()
91+
else:
92+
return self._read_alert()
93+
94+
def dismiss_alert(self, accept=True):
95+
""" Returns true if alert was confirmed, false if it was dismissed
96+
97+
This keyword will fail if no alert is present. Note that
98+
following keywords will fail unless the alert is
99+
dismissed by this keyword or another like `Get Alert Message`.
100+
"""
101+
return self._handle_alert(accept)
102+
103+
# Private
104+
105+
def _close_alert(self, confirm=True):
106+
try:
107+
text = self._read_alert()
108+
self._handle_alert(confirm)
109+
return text
110+
except WebDriverException:
111+
raise RuntimeError('There were no alerts')
112+
113+
def _read_alert(self):
114+
alert = None
115+
try:
116+
alert = self._wait_alert()
117+
# collapse new lines chars
118+
return ' '.join(alert.text.splitlines())
119+
except WebDriverException:
120+
raise RuntimeError('There were no alerts')
121+
122+
def _handle_alert(self, confirm=True):
123+
try:
124+
alert = self._wait_alert()
125+
if not confirm:
126+
alert.dismiss()
127+
return False
128+
else:
129+
alert.accept()
130+
return True
131+
except WebDriverException:
132+
raise RuntimeError('There were no alerts')
133+
134+
def _wait_alert(self):
135+
return WebDriverWait(self._current_browser(), 1).until(
136+
EC.alert_is_present())

src/Selenium2Library/keywords/_formelement.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -198,15 +198,6 @@ def input_text(self, locator, text):
198198
self._info("Typing text '%s' into text field '%s'" % (text, locator))
199199
self._input_text_into_text_field(locator, text)
200200

201-
def input_text_into_prompt(self, text):
202-
"""Types the given `text` into alert box. """
203-
alert = None
204-
try:
205-
alert = self._current_browser().switch_to_alert()
206-
alert.send_keys(text)
207-
except WebDriverException:
208-
raise RuntimeError('There were no alerts')
209-
210201
def page_should_contain_textfield(self, locator, message='', loglevel='INFO'):
211202
"""Verifies text field identified by `locator` is found from current page.
212203
Lines changed: 2 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,11 @@
11
import os
2-
from selenium.common.exceptions import WebDriverException
32
from keywordgroup import KeywordGroup
43

5-
class _JavaScriptKeywords(KeywordGroup):
64

7-
def __init__(self):
8-
self._cancel_on_next_confirmation = False
5+
class _JavaScriptKeywords(KeywordGroup):
96

107
# Public
118

12-
def alert_should_be_present(self, text=''):
13-
"""Verifies an alert is present and dismisses it.
14-
15-
If `text` is a non-empty string, then it is also verified that the
16-
message of the alert equals to `text`.
17-
18-
Will fail if no alert is present. Note that following keywords
19-
will fail unless the alert is dismissed by this
20-
keyword or another like `Get Alert Message`.
21-
"""
22-
alert_text = self.get_alert_message()
23-
if text and alert_text != text:
24-
raise AssertionError("Alert text should have been '%s' but was '%s'"
25-
% (text, alert_text))
26-
27-
def choose_cancel_on_next_confirmation(self):
28-
"""Cancel will be selected the next time `Confirm Action` is used."""
29-
self._cancel_on_next_confirmation = True
30-
31-
def choose_ok_on_next_confirmation(self):
32-
"""Undo the effect of using keywords `Choose Cancel On Next Confirmation`. Note
33-
that Selenium's overridden window.confirm() function will normally automatically
34-
return true, as if the user had manually clicked OK, so you shouldn't
35-
need to use this command unless for some reason you need to change
36-
your mind prior to the next confirmation. After any confirmation, Selenium will resume using the
37-
default behavior for future confirmations, automatically returning
38-
true (OK) unless/until you explicitly use `Choose Cancel On Next Confirmation` for each
39-
confirmation.
40-
41-
Note that every time a confirmation comes up, you must
42-
consume it by using a keywords such as `Get Alert Message`, or else
43-
the following selenium operations will fail.
44-
"""
45-
self._cancel_on_next_confirmation = False
46-
47-
def confirm_action(self):
48-
"""Dismisses currently shown confirmation dialog and returns it's message.
49-
50-
By default, this keyword chooses 'OK' option from the dialog. If
51-
'Cancel' needs to be chosen, keyword `Choose Cancel On Next
52-
Confirmation` must be called before the action that causes the
53-
confirmation dialog to be shown.
54-
55-
Examples:
56-
| Click Button | Send | # Shows a confirmation dialog |
57-
| ${message}= | Confirm Action | # Chooses Ok |
58-
| Should Be Equal | ${message} | Are your sure? |
59-
| | | |
60-
| Choose Cancel On Next Confirmation | | |
61-
| Click Button | Send | # Shows a confirmation dialog |
62-
| Confirm Action | | # Chooses Cancel |
63-
"""
64-
text = self._close_alert(not self._cancel_on_next_confirmation)
65-
self._cancel_on_next_confirmation = False
66-
return text
67-
689
def execute_javascript(self, *code):
6910
"""Executes the given JavaScript code.
7011
@@ -120,59 +61,8 @@ def execute_async_javascript(self, *code):
12061
self._info("Executing Asynchronous JavaScript:\n%s" % js)
12162
return self._current_browser().execute_async_script(js)
12263

123-
def get_alert_message(self, dismiss=True):
124-
"""Returns the text of current JavaScript alert.
125-
126-
By default the current JavaScript alert will be dismissed.
127-
This keyword will fail if no alert is present. Note that
128-
following keywords will fail unless the alert is
129-
dismissed by this keyword or another like `Get Alert Message`.
130-
"""
131-
if dismiss:
132-
return self._close_alert()
133-
else:
134-
return self._read_alert()
135-
136-
def dismiss_alert(self, accept=True):
137-
""" Returns true if alert was confirmed, false if it was dismissed
138-
139-
This keyword will fail if no alert is present. Note that
140-
following keywords will fail unless the alert is
141-
dismissed by this keyword or another like `Get Alert Message`.
142-
"""
143-
return self._handle_alert(accept)
144-
14564
# Private
14665

147-
def _close_alert(self, confirm=True):
148-
try:
149-
text = self._read_alert()
150-
alert = self._handle_alert(confirm)
151-
return text
152-
except WebDriverException:
153-
raise RuntimeError('There were no alerts')
154-
155-
def _read_alert(self):
156-
alert = None
157-
try:
158-
alert = self._current_browser().switch_to_alert()
159-
text = ' '.join(alert.text.splitlines()) # collapse new lines chars
160-
return text
161-
except WebDriverException:
162-
raise RuntimeError('There were no alerts')
163-
164-
def _handle_alert(self, confirm=True):
165-
try:
166-
alert = self._current_browser().switch_to_alert()
167-
if not confirm:
168-
alert.dismiss()
169-
return False
170-
else:
171-
alert.accept()
172-
return True
173-
except WebDriverException:
174-
raise RuntimeError('There were no alerts')
175-
17666
def _get_javascript_to_execute(self, code):
17767
codepath = code.replace('/', os.sep)
17868
if not (os.path.isabs(codepath) and os.path.isfile(codepath)):
@@ -183,4 +73,4 @@ def _get_javascript_to_execute(self, code):
18373
try:
18474
return codefile.read().strip()
18575
finally:
186-
codefile.close()
76+
codefile.close()

0 commit comments

Comments
 (0)