Skip to content

Commit 0270ed5

Browse files
authored
Merge pull request #1905 from seleniumbase/update-console-scripts-and-exceptions
Update console scripts and exceptions
2 parents f755743 + 4309bcf commit 0270ed5

File tree

10 files changed

+218
-55
lines changed

10 files changed

+218
-55
lines changed

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ sniffio==1.3.0;python_version>="3.7"
4242
h11==0.14.0;python_version>="3.7"
4343
outcome==1.2.0;python_version>="3.7"
4444
trio==0.22.0;python_version>="3.7"
45-
trio-websocket==0.10.2;python_version>="3.7"
45+
trio-websocket==0.10.3;python_version>="3.7"
4646
pyopenssl==23.2.0;python_version>="3.7"
4747
wsproto==1.2.0;python_version>="3.7"
4848
selenium==3.141.0;python_version<"3.7"

seleniumbase/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# seleniumbase package
2-
__version__ = "4.15.0"
2+
__version__ = "4.15.1"

seleniumbase/common/decorators.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import warnings
55
from contextlib import contextmanager
66
from functools import wraps
7+
from seleniumbase.common.exceptions import TimeoutException
78

89

910
@contextmanager
@@ -62,7 +63,7 @@ def my_method():
6263
)
6364
if exception:
6465
message = exception.msg + "\nAND " + message
65-
raise Exception(message)
66+
raise TimeoutException(message)
6667

6768

6869
@contextmanager
@@ -108,7 +109,7 @@ def my_method():
108109
)
109110
if exception:
110111
message = exception.msg + "\nAND " + message
111-
raise Exception(message)
112+
raise TimeoutException(message)
112113

113114

114115
def retry_on_exception(tries=6, delay=1, backoff=2, max_delay=32):

seleniumbase/common/exceptions.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
OutOfScopeException => Used by BaseCase methods when setUp() is skipped.
77
TextNotVisibleException => Called when expected text fails to appear.
88
TimeLimitExceededException => Called when exceeding "--time-limit=SECONDS".
9+
TimeoutException => Called when some timeout limit has been exceeded.
910
VisualException => Called when there's a Visual Diff Assertion Failure.
1011
"""
1112

@@ -38,5 +39,64 @@ class TimeLimitExceededException(Exception):
3839
pass
3940

4041

42+
class TimeoutException(Exception):
43+
pass
44+
45+
4146
class VisualException(Exception):
4247
pass
48+
49+
50+
""" Selenium Exceptions (Simplified for SeleniumBase) """
51+
52+
53+
class WebDriverException(Exception):
54+
"""Base webdriver exception."""
55+
56+
def __init__(self, msg=None, screen=None, stacktrace=None):
57+
super().__init__()
58+
self.msg = msg
59+
self.screen = screen
60+
self.stacktrace = stacktrace
61+
62+
def __str__(self):
63+
exception_msg = "Message: %s\n" % self.msg
64+
if self.screen:
65+
exception_msg += "Screenshot: available via screen\n"
66+
if self.stacktrace:
67+
stacktrace = "\n".join(self.stacktrace)
68+
exception_msg += "Stacktrace:\n%s" % stacktrace
69+
return exception_msg
70+
71+
72+
class InvalidSwitchToTargetException(WebDriverException):
73+
"""Thrown when frame or window target to be switched doesn't exist."""
74+
75+
76+
class NoSuchFrameException(InvalidSwitchToTargetException):
77+
"""Thrown when frame target to be switched doesn't exist."""
78+
79+
80+
class NoSuchWindowException(InvalidSwitchToTargetException):
81+
"""Thrown when window target to be switched doesn't exist."""
82+
83+
84+
class NoSuchElementException(WebDriverException):
85+
"""Thrown when element could not be found."""
86+
87+
88+
class NoSuchAttributeException(WebDriverException):
89+
"""Thrown when the attribute of element could not be found."""
90+
91+
92+
class InvalidElementStateException(WebDriverException):
93+
"""Thrown when a command could not be completed because the element is in
94+
an invalid state."""
95+
96+
97+
class NoAlertPresentException(WebDriverException):
98+
"""Thrown when switching to no presented alert."""
99+
100+
101+
class ElementNotVisibleException(InvalidElementStateException):
102+
"""Thrown when an element is present in the DOM, but not visible."""

seleniumbase/console_scripts/ReadMe.md

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -359,16 +359,25 @@ sbase mkfile new_test.py
359359
``--ko`` / ``--Korean`` | ``--pt`` / ``--Portuguese``
360360
``--ru`` / ``--Russian`` | ``--es`` / ``--Spanish``
361361
362+
* Syntax Formats:
363+
364+
``--bc`` / ``--basecase`` (BaseCase class inheritance)
365+
``--pf`` / ``--pytest-fixture`` (sb pytest fixture)
366+
``--cf`` / ``--class-fixture`` (class + sb pytest fixture)
367+
``--cm`` / ``--context-manager`` (SB context manager)
368+
``--dc`` / ``--driver-context`` (DriverContext manager)
369+
``--dm`` / ``--driver-manager`` (Driver manager)
370+
362371
* Output:
363372
364-
Creates a new SeleniumBase test file with boilerplate code.
373+
Creates a new SBase test file with boilerplate code.
365374
If the file already exists, an error is raised.
366-
By default, uses English mode and creates a
367-
boilerplate with the 5 most common SeleniumBase
368-
methods, which are "open", "type", "click",
369-
"assert_element", and "assert_text". If using the
370-
basic boilerplate option, only the "open" method
371-
is included.
375+
By default, uses English with BaseCase inheritance,
376+
and creates a boilerplate with common SeleniumBase
377+
methods: "open", "type", "click", "assert_element",
378+
and "assert_text". If using the basic boilerplate
379+
option, only the "open" method is included. Only the
380+
BaseCase format supports Languages or Recorder Mode.
372381
373382
<h3>mkrec / record / codegen</h3>
374383

seleniumbase/console_scripts/run.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -267,15 +267,22 @@ def show_mkfile_usage():
267267
print(" --it / --Italian | --ja / --Japanese")
268268
print(" --ko / --Korean | --pt / --Portuguese")
269269
print(" --ru / --Russian | --es / --Spanish")
270+
print(" Syntax Formats:")
271+
print(" --bc / --basecase (BaseCase class inheritance)")
272+
print(" --pf / --pytest-fixture (sb pytest fixture)")
273+
print(" --cf / --class-fixture (class + sb pytest fixture)")
274+
print(" --cm / --context-manager (SB context manager)")
275+
print(" --dc / --driver-context (DriverContext manager)")
276+
print(" --dm / --driver-manager (Driver manager)")
270277
print(" Output:")
271278
print(" Creates a new SBase test file with boilerplate code.")
272279
print(" If the file already exists, an error is raised.")
273-
print(" By default, uses English mode and creates a")
274-
print(" boilerplate with the 5 most common SeleniumBase")
275-
print(' methods, which are "open", "type", "click",')
276-
print(' "assert_element", and "assert_text". If using the')
277-
print(' basic boilerplate option, only the "open" method')
278-
print(" is included.")
280+
print(" By default, uses English with BaseCase inheritance,")
281+
print(" and creates a boilerplate with common SeleniumBase")
282+
print(' methods: "open", "type", "click", "assert_element",')
283+
print(' and "assert_text". If using the basic boilerplate')
284+
print(' option, only the "open" method is included. Only the')
285+
print(" BaseCase format supports Languages or Recorder Mode.")
279286
print("")
280287

281288

seleniumbase/console_scripts/sb_mkfile.py

Lines changed: 104 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,23 @@
1919
--ko / --Korean | --pt / --Portuguese
2020
--ru / --Russian | --es / --Spanish
2121
22+
Syntax Formats:
23+
--bc / --basecase (BaseCase class inheritance)
24+
--pf / --pytest-fixture (sb pytest fixture)
25+
--cf / --class-fixture (class + sb pytest fixture)
26+
--cm / --context-manager (SB context manager)
27+
--dc / --driver-context (DriverContext manager)
28+
--dm / --driver-manager (Driver manager)
29+
2230
Output:
2331
Creates a new SBase test file with boilerplate code.
2432
If the file already exists, an error is raised.
25-
By default, uses English mode and creates a
26-
boilerplate with the 5 most common SeleniumBase
27-
methods, which are "open", "type", "click",
28-
"assert_element", and "assert_text". If using the
29-
basic boilerplate option, only the "open" method
30-
is included.
33+
By default, uses English with BaseCase inheritance,
34+
and creates a boilerplate with common SeleniumBase
35+
methods: "open", "type", "click", "assert_element",
36+
and "assert_text". If using the basic boilerplate
37+
option, only the "open" method is included. Only the
38+
BaseCase format supports Languages or Recorder Mode.
3139
"""
3240
import codecs
3341
import colorama
@@ -51,15 +59,22 @@ def invalid_run_command(msg=None):
5159
exp += " --it / --Italian | --ja / --Japanese\n"
5260
exp += " --ko / --Korean | --pt / --Portuguese\n"
5361
exp += " --ru / --Russian | --es / --Spanish\n"
62+
exp += " Syntax Formats:\n"
63+
exp += " --bc / --basecase (BaseCase class inheritance)\n"
64+
exp += " --pf / --pytest-fixture (sb pytest fixture)\n"
65+
exp += " --cf / --class-fixture (class + sb pytest fixture)\n"
66+
exp += " --cm / --context-manager (SB context manager)\n"
67+
exp += " --dc / --driver-context (DriverContext manager)\n"
68+
exp += " --dm / --driver-manager (Driver manager)\n"
5469
exp += " Output:\n"
5570
exp += " Creates a new SBase test file with boilerplate code.\n"
5671
exp += " If the file already exists, an error is raised.\n"
57-
exp += " By default, uses English mode and creates a\n"
58-
exp += " boilerplate with the 5 most common SeleniumBase\n"
59-
exp += ' methods, which are "open", "type", "click",\n'
60-
exp += ' "assert_element", and "assert_text". If using the\n'
61-
exp += ' basic boilerplate option, only the "open" method\n'
62-
exp += " is included.\n"
72+
exp += " By default, uses English with BaseCase inheritance,\n"
73+
exp += " and creates a boilerplate with common SeleniumBase\n"
74+
exp += ' methods: "open", "type", "click", "assert_element",\n'
75+
exp += ' and "assert_text". If using the basic boilerplate\n'
76+
exp += ' option, only the "open" method is included. Only the\n'
77+
exp += " BaseCase format supports Languages or Recorder Mode.\n"
6378
if not msg:
6479
raise Exception("INVALID RUN COMMAND!\n\n%s" % exp)
6580
elif msg == "help":
@@ -86,6 +101,7 @@ def main():
86101
recorder = False
87102
error_msg = None
88103
invalid_cmd = None
104+
syntax = "BaseCase"
89105
language = "English"
90106

91107
command_args = sys.argv[2:]
@@ -138,6 +154,18 @@ def main():
138154
language = "Russian"
139155
elif option == "--es" or option == "--spanish":
140156
language = "Spanish"
157+
elif option == "--bc" or option == "--basecase":
158+
syntax = "BaseCase"
159+
elif option == "--pf" or option == "--pytest-fixture":
160+
syntax = "PytestFixture"
161+
elif option == "--cf" or option == "--class-fixture":
162+
syntax = "ClassFixture"
163+
elif option == "--cm" or option == "--context-manager":
164+
syntax = "ContextManager"
165+
elif option == "--dc" or option == "--driver-context":
166+
syntax = "DriverContext"
167+
elif option == "--dm" or option == "--driver-manager":
168+
syntax = "DriverManager"
141169
else:
142170
invalid_cmd = "\n===> INVALID OPTION: >> %s <<\n" % option
143171
invalid_cmd = invalid_cmd.replace(">> ", ">>" + c5 + " ")
@@ -239,7 +267,70 @@ def main():
239267
data.append("")
240268

241269
new_data = []
242-
if language == "English":
270+
if language == "English" and syntax == "BaseCase":
271+
new_data = data
272+
elif language == "English" and syntax == "PytestFixture":
273+
data = []
274+
data.append("def test_base(sb):")
275+
data.append(' sb.open("data:text/html,<p>Hello<br><input>")')
276+
if not basic:
277+
data.append(' sb.type("input", "Goodbye") # selector, text')
278+
data.append(' sb.click("html body > p") # selector')
279+
data.append(' sb.assert_element("body") # selector')
280+
data.append(' sb.assert_text("Hello", "p") # text, selector')
281+
data.append("")
282+
new_data = data
283+
elif language == "English" and syntax == "ClassFixture":
284+
data = []
285+
data.append("class %s:" % class_name)
286+
data.append(" def test_base(self, sb):")
287+
data.append(' sb.open("data:text/html,<p>Hello<br><input>")')
288+
if not basic:
289+
data.append(
290+
' sb.type("input", "Goodbye") # selector, text'
291+
)
292+
data.append(' sb.click("html body > p") # selector')
293+
data.append(' sb.assert_element("body") # selector')
294+
data.append(
295+
' sb.assert_text("Hello", "p") # text, selector'
296+
)
297+
data.append("")
298+
new_data = data
299+
elif language == "English" and syntax == "ContextManager":
300+
data = []
301+
data.append("from seleniumbase import SB")
302+
data.append("")
303+
data.append('with SB(browser="chrome") as sb:')
304+
data.append(
305+
' sb.open("data:text/html,<div>Hello<br><input></div>")'
306+
)
307+
if not basic:
308+
data.append(' sb.type("input", "Goodbye") # selector, text')
309+
data.append(' sb.click("html body > div") # selector')
310+
data.append(' sb.assert_element("input") # selector')
311+
data.append(' sb.assert_text("Hello", "div") # text, selector')
312+
data.append(' sb.highlight("div") # selector')
313+
data.append(" sb.sleep(0.5) # seconds")
314+
data.append("")
315+
new_data = data
316+
elif language == "English" and syntax == "DriverContext":
317+
data = []
318+
data.append("from seleniumbase import DriverContext")
319+
data.append("")
320+
data.append('with DriverContext(browser="chrome") as driver:')
321+
data.append(' driver.get("data:text/html,<p>Hello<br><input>")')
322+
data.append("")
323+
new_data = data
324+
elif language == "English" and syntax == "DriverManager":
325+
data = []
326+
data.append("from seleniumbase import Driver")
327+
data.append("")
328+
data.append('driver = Driver(browser="chrome")')
329+
data.append("try:")
330+
data.append(' driver.get("data:text/html,<p>Hello<br><input>")')
331+
data.append("finally:")
332+
data.append(" driver.quit()")
333+
data.append("")
243334
new_data = data
244335
else:
245336
from seleniumbase.translate.master_dict import MD

seleniumbase/fixtures/shared_utils.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -124,42 +124,43 @@ def format_exc(exception, message):
124124
from selenium.common.exceptions import NoSuchWindowException
125125
from seleniumbase.common.exceptions import NoSuchFileException
126126
from seleniumbase.common.exceptions import TextNotVisibleException
127+
from seleniumbase.common import exceptions
127128

128129
if exception == Exception:
129130
exc = Exception
130131
return exc, message
131132
elif exception == ElementNotVisibleException:
132-
exc = ElementNotVisibleException
133+
exc = exceptions.ElementNotVisibleException
133134
elif exception == "ElementNotVisibleException":
134-
exc = ElementNotVisibleException
135+
exc = exceptions.ElementNotVisibleException
135136
elif exception == NoSuchElementException:
136-
exc = NoSuchElementException
137+
exc = exceptions.NoSuchElementException
137138
elif exception == "NoSuchElementException":
138-
exc = NoSuchElementException
139+
exc = exceptions.NoSuchElementException
139140
elif exception == TextNotVisibleException:
140-
exc = TextNotVisibleException
141+
exc = exceptions.TextNotVisibleException
141142
elif exception == "TextNotVisibleException":
142-
exc = TextNotVisibleException
143+
exc = exceptions.TextNotVisibleException
143144
elif exception == NoAlertPresentException:
144-
exc = NoAlertPresentException
145+
exc = exceptions.NoAlertPresentException
145146
elif exception == "NoAlertPresentException":
146-
exc = NoAlertPresentException
147+
exc = exceptions.NoAlertPresentException
147148
elif exception == NoSuchAttributeException:
148-
exc = NoSuchAttributeException
149+
exc = exceptions.NoSuchAttributeException
149150
elif exception == "NoSuchAttributeException":
150-
exc = NoSuchAttributeException
151+
exc = exceptions.NoSuchAttributeException
151152
elif exception == NoSuchFrameException:
152-
exc = NoSuchFrameException
153+
exc = exceptions.NoSuchFrameException
153154
elif exception == "NoSuchFrameException":
154-
exc = NoSuchFrameException
155+
exc = exceptions.NoSuchFrameException
155156
elif exception == NoSuchWindowException:
156-
exc = NoSuchWindowException
157+
exc = exceptions.NoSuchWindowException
157158
elif exception == "NoSuchWindowException":
158-
exc = NoSuchWindowException
159+
exc = exceptions.NoSuchWindowException
159160
elif exception == NoSuchFileException:
160-
exc = NoSuchFileException
161+
exc = exceptions.NoSuchFileException
161162
elif exception == "NoSuchFileException":
162-
exc = NoSuchFileException
163+
exc = exceptions.NoSuchFileException
163164
elif type(exception) is str:
164165
exc = Exception
165166
message = "%s: %s" % (exception, message)

0 commit comments

Comments
 (0)