Skip to content

Commit 01a8bdb

Browse files
authored
Merge pull request #1956 from seleniumbase/detection-handling-and-more
Detection-handling and more
2 parents 618f12b + 54a1104 commit 01a8bdb

File tree

15 files changed

+172
-39
lines changed

15 files changed

+172
-39
lines changed

README.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ With raw Selenium, that requires more code:<br />
167167
<summary> ▶️ Learn about different ways of writing tests (<b>click to expand</b>)</summary>
168168
<div>
169169

170-
<p align="left">📘📝 An example test with the <b>BaseCase</b> class. Runs with <b><a href="https://docs.pytest.org/en/latest/how-to/usage.html">pytest</a></b> or <b>pynose</b>. (<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/ReadMe.md">Learn more</a>)</p>
170+
<p align="left">📘📝 An example test with the <b>BaseCase</b> class. Runs with <b><a href="https://docs.pytest.org/en/latest/how-to/usage.html">pytest</a></b> or <b><a href="https://github.com/mdmintz/pynose">pynose</a></b>. (<a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/ReadMe.md">Learn more</a>)</p>
171171

172172
```python
173173
from seleniumbase import BaseCase
@@ -460,14 +460,14 @@ self.assert_no_js_errors() # Verify there are no JS errors.
460460
<p>✅ SeleniumBase uses simple syntax for commands. Example:</p>
461461
462462
```python
463-
self.type("input", "dogs\n")
463+
self.type("input", "dogs\n") # (The "\n" presses ENTER)
464464
```
465465
466466
Most SeleniumBase scripts can be run with <code>pytest</code>, <code>pynose</code>, or pure <code>python</code>. Not all test runners can run all test formats. For example, tests that use the ``sb`` pytest fixture can only be run with ``pytest``. (See <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/syntax_formats.md">Syntax Formats</a>) There's also a <a href="https://behave.readthedocs.io/en/stable/gherkin.html#features" target="_blank">Gherkin</a> test format that runs with <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/behave_bdd/ReadMe.md">behave</a>.
467467
468468
```bash
469469
pytest coffee_cart_tests.py --rs
470-
pytest test_sb_fixture.py
470+
pytest test_sb_fixture.py --demo
471471
pytest test_suite.py --rs --html=report.html --dashboard
472472
473473
pynose basic_test.py --mobile
@@ -506,12 +506,14 @@ pynose [FILE_NAME.py]:[CLASS_NAME].[METHOD_NAME]
506506
507507
✅ SeleniumBase supports all major browsers and operating systems:
508508
<p><b>Browsers:</b> Chrome, Edge, Firefox, and Safari.</p>
509-
<p><b>Systems: </b>Linux/Ubuntu, macOS, and Windows.</p>
509+
<p><b>Systems:</b> Linux/Ubuntu, macOS, and Windows.</p>
510510
511511
✅ SeleniumBase works on all popular CI/CD platforms:
512512
<p><a href="https://github.com/seleniumbase/SeleniumBase/blob/master/integrations/github/workflows/ReadMe.md"><img alt="GitHub Actions integration" src="https://img.shields.io/badge/GitHub_Actions-12B2C2.svg?logo=GitHubActions&logoColor=CFFFC2" /></a> <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/integrations/azure/jenkins/ReadMe.md"><img alt="Jenkins integration" src="https://img.shields.io/badge/Jenkins-32B242.svg?logo=jenkins&logoColor=white" /></a> <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/integrations/azure/azure_pipelines/ReadMe.md"><img alt="Azure integration" src="https://img.shields.io/badge/Azure-2288EE.svg?logo=AzurePipelines&logoColor=white" /></a> <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/integrations/google_cloud/ReadMe.md"><img alt="Google Cloud integration" src="https://img.shields.io/badge/Google_Cloud-11CAE8.svg?logo=GoogleCloud&logoColor=EE0066" /></a> <a href="#utilizing_advanced_features"><img alt="AWS integration" src="https://img.shields.io/badge/AWS-4488DD.svg?logo=AmazonAWS&logoColor=FFFF44" /></a> <a href="https://en.wikipedia.org/wiki/Personal_computer" target="_blank"><img alt="Your Computer" src="https://img.shields.io/badge/💻_Your_Computer-44E6E6.svg" /></a></p>
513513
514-
<p>✅ SeleniumBase includes an automated/manual hybrid solution called <b><a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/master_qa/ReadMe.md">MasterQA</a></b> to speed up manual testing with automation while the manual tester handles validation.</p>
514+
<p>✅ SeleniumBase includes an automated/manual hybrid solution called <b><a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/master_qa/ReadMe.md">MasterQA</a></b> to speed up manual testing with automation while manual testers handle validation.</p>
515+
516+
<p>✅ SeleniumBase supports <a href="https://github.com/seleniumbase/SeleniumBase/tree/master/examples/offline_examples">running tests while offline</a> (<i>assuming webdrivers have previously been downloaded when online</i>).</p>
515517
516518
<p>✅ For a full list of SeleniumBase features, <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/features_list.md">Click Here</a>.</p>
517519
@@ -681,9 +683,9 @@ pytest test_coffee_cart.py --trace
681683
```bash
682684
cd examples/
683685
684-
pytest test_suite.py --browser=chrome
686+
pytest test_suite.py --chrome
685687
686-
pytest test_suite.py --browser=firefox
688+
pytest test_suite.py --firefox
687689
```
688690
689691
An easy way to override seleniumbase/config/settings.py is by using a custom settings file.
@@ -697,7 +699,7 @@ Inside your tests, you can use ``self.data`` to access that.
697699
<a id="directory_configuration"></a>
698700
<h2><img src="https://seleniumbase.github.io/img/logo7.png" title="SeleniumBase" width="32" /> Directory Configuration:</h2>
699701
700-
🔵 When running tests with **pytest**, you'll want a copy of **[pytest.ini](https://github.com/seleniumbase/SeleniumBase/blob/master/pytest.ini)** in your root folders. When running tests with **pynose**, you'll want a copy of **[setup.cfg](https://github.com/seleniumbase/SeleniumBase/blob/master/setup.cfg)** in your root folders. These files specify default configuration details for tests. Folders should also include a blank ``__init__.py`` file to allow your tests to import files from that folder.
702+
🔵 When running tests with **``pytest``**, you'll want a copy of **[pytest.ini](https://github.com/seleniumbase/SeleniumBase/blob/master/pytest.ini)** in your root folders. When running tests with **``pynose``**, you'll want a copy of **[setup.cfg](https://github.com/seleniumbase/SeleniumBase/blob/master/setup.cfg)** in your root folders. These files specify default configuration details for tests. Test folders should also include a blank **[__init__.py](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/offline_examples/__init__.py)** file to allow your test files to import other files from that folder.
701703
702704
🔵 ``sbase mkdir DIR`` creates a folder with config files and sample tests:
703705

examples/dialog_boxes/dialog_box_tour.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from seleniumbase import BaseCase
2+
BaseCase.main(__name__, __file__)
23

34

45
class DialogBoxTests(BaseCase):

examples/test_geolocation.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from seleniumbase import BaseCase
2+
BaseCase.main(__name__, __file__)
3+
4+
5+
class TestGeolocation(BaseCase):
6+
def tearDown(self):
7+
self.save_teardown_screenshot() # If test fails, or if "--screenshot"
8+
if self.is_chromium() and not self._multithreaded:
9+
# Reset Permissions and GeolocationOverride
10+
self.execute_cdp_cmd("Browser.resetPermissions", {})
11+
self.execute_cdp_cmd("Emulation.setGeolocationOverride", {})
12+
super().tearDown()
13+
14+
def test_geolocation(self):
15+
self.open("about:blank")
16+
if self._multithreaded:
17+
self.skip("Skipping test in multi-threaded mode.")
18+
if not self.is_chromium():
19+
print("\n* execute_cdp_cmd() is only for Chromium browsers")
20+
self.skip("execute_cdp_cmd() is only for Chromium browsers")
21+
self.execute_cdp_cmd(
22+
"Browser.grantPermissions",
23+
{
24+
"origin": "https://www.openstreetmap.org/",
25+
"permissions": ["geolocation"],
26+
},
27+
)
28+
self.execute_cdp_cmd(
29+
"Emulation.setGeolocationOverride",
30+
{
31+
"latitude": 48.87645,
32+
"longitude": 2.26340,
33+
"accuracy": 100,
34+
},
35+
)
36+
self.open("https://www.openstreetmap.org/")
37+
self.click("span.geolocate")
38+
self.assert_url_contains("48.87645/2.26340")
39+
if not (self.headless or self.headless2 or self.xvfb):
40+
self.sleep(2.5)

examples/translations/japanese_test_1.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def test_例1(self):
1717
self.要素を確認する('img[alt="握り寿司"]')
1818
self.JS入力("#searchInput", "レゴランド・ジャパン")
1919
self.クリックして("#searchform button")
20-
self.要素を確認する('img[alt*="LEGOLAND JAPAN"]')
20+
self.要素を確認する('img[src*="LEGOLAND_JAPAN"]')
2121
self.リンクテキストを確認する("名古屋城")
2222
self.リンクテキストをクリックします("テーマパーク")
2323
self.テキストを確認する("テーマパーク", "#firstHeading")

examples/uc_cdp_events.py

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,36 @@
77

88

99
class CDPTests(BaseCase):
10-
def test_display_cdp_events(self):
11-
if not (self.undetectable and self.uc_cdp_events and self.incognito):
12-
self.get_new_driver(
13-
undetectable=True, uc_cdp_events=True, incognito=True
14-
)
10+
def add_cdp_listener(self):
1511
# (To print everything, use "*". Otherwise select specific headers.)
1612
# self.driver.add_cdp_listener("*", lambda data: print(pformat(data)))
1713
self.driver.add_cdp_listener(
1814
"Network.requestWillBeSentExtraInfo",
1915
lambda data: print(pformat(data))
2016
)
21-
self.open("https://nowsecure.nl/#relax")
22-
self.assert_text("OH YEAH, you passed!", "h1", timeout=7.25)
17+
18+
def verify_success(self):
19+
self.assert_text("OH YEAH, you passed!", "h1", timeout=6.25)
2320
self.sleep(2)
21+
22+
def fail_me(self):
23+
self.fail('Selenium was detected! Try using: "pytest --uc"')
24+
25+
def test_display_cdp_events(self):
26+
if not (self.undetectable and self.uc_cdp_events and self.incognito):
27+
self.get_new_driver(
28+
undetectable=True, uc_cdp_events=True, incognito=True
29+
)
30+
self.add_cdp_listener()
31+
self.open("https://nowsecure.nl/#relax")
32+
try:
33+
self.verify_success()
34+
except Exception:
35+
self.clear_all_cookies()
36+
self.get_new_driver(devtools=True)
37+
self.add_cdp_listener()
38+
self.open("https://nowsecure.nl/#relax")
39+
try:
40+
self.verify_success()
41+
except Exception:
42+
self.fail_me()

examples/verify_undetected.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55

66
if __name__ == "__main__":
77
from pytest import main
8-
main([__file__, "--uc", "--uc-cdp", "--incognito", "-s"])
8+
main([__file__, "--uc", "-s"])
99

1010

1111
class UndetectedTest(BaseCase):
1212
def verify_success(self):
13-
self.assert_text("OH YEAH, you passed!", "h1", timeout=7.25)
13+
self.assert_text("OH YEAH, you passed!", "h1", timeout=6.25)
1414
self.post_message("Selenium wasn't detected!", duration=2.8)
1515
self._print("\n Success! Website did not detect Selenium! ")
1616

@@ -22,13 +22,9 @@ def test_browser_is_undetected(self):
2222
try:
2323
self.verify_success()
2424
except Exception:
25-
if self.is_element_visible('input[value*="Verify"]'):
26-
self.click('input[value*="Verify"]')
27-
elif self.is_element_visible('iframe[title*="challenge"]'):
28-
self.switch_to_frame('iframe[title*="challenge"]')
29-
self.click("span.mark")
30-
else:
31-
self.fail_me()
25+
self.clear_all_cookies()
26+
self.get_new_driver(devtools=True)
27+
self.open("https://nowsecure.nl/#relax")
3228
try:
3329
self.verify_success()
3430
except Exception:

help_docs/syntax_formats.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ class 私のテストクラス(セレニウムテストケース):
546546
self.要素を確認する('img[alt="握り寿司"]')
547547
self.JS入力("#searchInput", "レゴランド・ジャパン")
548548
self.クリックして("#searchform button")
549-
self.要素を確認する('img[alt*="LEGOLAND JAPAN"]')
549+
self.要素を確認する('img[src*="LEGOLAND_JAPAN"]')
550550
self.リンクテキストを確認する("名古屋城")
551551
self.リンクテキストをクリックします("テーマパーク")
552552
self.テキストを確認する("テーマパーク", "#firstHeading")

mkdocs_build/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pkginfo>=1.9.6
66
readme-renderer>=40.0
77
pymdown-extensions>=10.0.1
88
importlib-metadata>=6.8.0
9-
pipdeptree>=2.9.4
9+
pipdeptree>=2.9.5
1010
bleach>=6.0.0
1111
docutils>=0.20.1
1212
python-dateutil>=2.8.2

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.13"
2+
__version__ = "4.15.14"

seleniumbase/common/exceptions.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
""" SeleniumBase Exceptions
22
NoSuchFileException => Called when self.assert_downloaded_file(...) fails.
3+
NoSuchOptionException => Called when select_option_by_*() lacks the option.
34
NotConnectedException => Called when Internet is not reachable when needed.
45
NotUsingChromeException => Used by Chrome-only methods if not using Chrome.
56
NotUsingChromiumException => Used by Chromium-only methods if not Chromium.
@@ -15,6 +16,10 @@ class NoSuchFileException(Exception):
1516
pass
1617

1718

19+
class NoSuchOptionException(Exception):
20+
pass
21+
22+
1823
class NotConnectedException(Exception):
1924
pass
2025

0 commit comments

Comments
 (0)