seleniumbase 4.44.2__py3-none-any.whl → 4.45.10__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. seleniumbase/__version__.py +1 -1
  2. seleniumbase/behave/behave_sb.py +14 -0
  3. seleniumbase/console_scripts/run.py +1 -0
  4. seleniumbase/console_scripts/sb_install.py +142 -11
  5. seleniumbase/console_scripts/sb_mkdir.py +76 -0
  6. seleniumbase/console_scripts/sb_mkrec.py +25 -0
  7. seleniumbase/console_scripts/sb_recorder.py +40 -3
  8. seleniumbase/core/browser_launcher.py +279 -117
  9. seleniumbase/core/detect_b_ver.py +8 -6
  10. seleniumbase/core/log_helper.py +11 -16
  11. seleniumbase/core/mysql.py +1 -1
  12. seleniumbase/core/report_helper.py +3 -7
  13. seleniumbase/core/sb_cdp.py +275 -78
  14. seleniumbase/core/sb_driver.py +36 -5
  15. seleniumbase/core/session_helper.py +2 -4
  16. seleniumbase/drivers/chromium_drivers/__init__.py +0 -0
  17. seleniumbase/fixtures/base_case.py +251 -201
  18. seleniumbase/fixtures/constants.py +1 -0
  19. seleniumbase/fixtures/js_utils.py +52 -14
  20. seleniumbase/fixtures/page_actions.py +18 -7
  21. seleniumbase/fixtures/page_utils.py +4 -2
  22. seleniumbase/fixtures/shared_utils.py +2 -4
  23. seleniumbase/masterqa/master_qa.py +16 -2
  24. seleniumbase/plugins/base_plugin.py +8 -0
  25. seleniumbase/plugins/driver_manager.py +15 -5
  26. seleniumbase/plugins/pytest_plugin.py +43 -57
  27. seleniumbase/plugins/sb_manager.py +23 -19
  28. seleniumbase/plugins/selenium_plugin.py +20 -13
  29. seleniumbase/undetected/__init__.py +11 -10
  30. seleniumbase/undetected/cdp.py +1 -12
  31. seleniumbase/undetected/cdp_driver/browser.py +330 -128
  32. seleniumbase/undetected/cdp_driver/cdp_util.py +48 -14
  33. seleniumbase/undetected/cdp_driver/config.py +78 -11
  34. seleniumbase/undetected/cdp_driver/connection.py +15 -43
  35. seleniumbase/undetected/cdp_driver/element.py +37 -22
  36. seleniumbase/undetected/cdp_driver/tab.py +414 -39
  37. {seleniumbase-4.44.2.dist-info → seleniumbase-4.45.10.dist-info}/METADATA +140 -152
  38. {seleniumbase-4.44.2.dist-info → seleniumbase-4.45.10.dist-info}/RECORD +42 -41
  39. {seleniumbase-4.44.2.dist-info → seleniumbase-4.45.10.dist-info}/licenses/LICENSE +1 -1
  40. {seleniumbase-4.44.2.dist-info → seleniumbase-4.45.10.dist-info}/WHEEL +0 -0
  41. {seleniumbase-4.44.2.dist-info → seleniumbase-4.45.10.dist-info}/entry_points.txt +0 -0
  42. {seleniumbase-4.44.2.dist-info → seleniumbase-4.45.10.dist-info}/top_level.txt +0 -0
@@ -1,2 +1,2 @@
1
1
  # seleniumbase package
2
- __version__ = "4.44.2"
2
+ __version__ = "4.45.10"
@@ -113,6 +113,7 @@ import sys
113
113
  from contextlib import suppress
114
114
  from seleniumbase import config as sb_config
115
115
  from seleniumbase.config import settings
116
+ from seleniumbase.core import detect_b_ver
116
117
  from seleniumbase.core import download_helper
117
118
  from seleniumbase.core import log_helper
118
119
  from seleniumbase.core import proxy_helper
@@ -493,6 +494,12 @@ def get_configured_sb(context):
493
494
  sb.binary_location = binary_location
494
495
  sb_config.binary_location = binary_location
495
496
  continue
497
+ # Handle: -D use-chromium
498
+ if low_key in ["use-chromium"] and not sb_config.binary_location:
499
+ binary_location = "_chromium_"
500
+ sb.binary_location = binary_location
501
+ sb_config.binary_location = binary_location
502
+ continue
496
503
  # Handle: -D cft
497
504
  if low_key in ["cft"] and not sb_config.binary_location:
498
505
  binary_location = "cft"
@@ -890,6 +897,13 @@ def get_configured_sb(context):
890
897
  "\nOnly ONE default browser is allowed!\n"
891
898
  "%s browsers were selected: %s" % (len(browsers), browsers)
892
899
  )
900
+ if sb.browser in ["opera", "brave", "comet", "atlas"]:
901
+ bin_loc = detect_b_ver.get_binary_location(sb.browser)
902
+ if bin_loc and os.path.exists(bin_loc):
903
+ sb_config._cdp_browser = sb.browser
904
+ sb_config._cdp_bin_loc = bin_loc
905
+ sb_config.binary_location = bin_loc
906
+ sb.binary_location = bin_loc
893
907
  # Recorder Mode can still optimize scripts in "-D headless2" mode.
894
908
  if sb.recorder_ext and sb.headless:
895
909
  sb.headless = False
@@ -248,6 +248,7 @@ def show_mkdir_usage():
248
248
  print(" sbase mkdir ui_tests")
249
249
  print(" Options:")
250
250
  print(" -b / --basic (Only config files. No tests added.)")
251
+ print(" --gha (Include GitHub Actions YML with defaults.)")
251
252
  print(" Output:")
252
253
  print(" Creates a new folder for running SBase scripts.")
253
254
  print(" The new folder contains default config files,")
@@ -19,6 +19,7 @@ Examples:
19
19
  sbase get chromedriver stable
20
20
  sbase get chromedriver beta
21
21
  sbase get chromedriver -p
22
+ sbase get chromium
22
23
  sbase get cft 131
23
24
  sbase get chs
24
25
  Output:
@@ -46,16 +47,21 @@ from seleniumbase import config as sb_config
46
47
  from seleniumbase import drivers # webdriver storage folder for SeleniumBase
47
48
  from seleniumbase.drivers import cft_drivers # chrome-for-testing
48
49
  from seleniumbase.drivers import chs_drivers # chrome-headless-shell
50
+ from seleniumbase.drivers import chromium_drivers # base chromium
49
51
 
50
52
  urllib3.disable_warnings()
51
53
  ARCH = platform.architecture()[0]
52
54
  IS_ARM_MAC = shared_utils.is_arm_mac()
53
55
  IS_MAC = shared_utils.is_mac()
56
+ IS_ARM_LINUX = shared_utils.is_arm_linux()
54
57
  IS_LINUX = shared_utils.is_linux()
55
58
  IS_WINDOWS = shared_utils.is_windows()
56
59
  DRIVER_DIR = os.path.dirname(os.path.realpath(drivers.__file__))
57
60
  DRIVER_DIR_CFT = os.path.dirname(os.path.realpath(cft_drivers.__file__))
58
61
  DRIVER_DIR_CHS = os.path.dirname(os.path.realpath(chs_drivers.__file__))
62
+ DRIVER_DIR_CHROMIUM = os.path.dirname(
63
+ os.path.realpath(chromium_drivers.__file__)
64
+ )
59
65
  LOCAL_PATH = "/usr/local/bin/" # On Mac and Linux systems
60
66
  DEFAULT_CHROMEDRIVER_VERSION = "114.0.5735.90" # (If can't find LATEST_STABLE)
61
67
  DEFAULT_GECKODRIVER_VERSION = "v0.36.0"
@@ -177,7 +183,7 @@ def requests_get_with_retry(url):
177
183
 
178
184
 
179
185
  def get_cft_known_good_versions():
180
- if hasattr(sb_config, "cft_kgv_json") and sb_config.cft_kgv_json:
186
+ if getattr(sb_config, "cft_kgv_json", None):
181
187
  return sb_config.cft_kgv_json
182
188
  cft_ngv_url = (
183
189
  "https://googlechromelabs.github.io/"
@@ -188,7 +194,7 @@ def get_cft_known_good_versions():
188
194
 
189
195
 
190
196
  def get_cft_latest_versions_per_milestone():
191
- if hasattr(sb_config, "cft_lvpm_json") and sb_config.cft_lvpm_json:
197
+ if getattr(sb_config, "cft_lvpm_json", None):
192
198
  return sb_config.cft_lvpm_json
193
199
  cft_lvpm_url = (
194
200
  "https://googlechromelabs.github.io/"
@@ -203,9 +209,62 @@ def get_cft_latest_version_from_milestone(milestone):
203
209
  return url_request.json()["milestones"][milestone]["version"]
204
210
 
205
211
 
212
+ def get_chromium_channel_revision(platform_code, channel):
213
+ """Snapshots only exist for revisions where a build occurred.
214
+ Therefore, not all found revisions will lead to snapshots."""
215
+ platform_key = None
216
+ if platform_code in ["Mac_Arm", "Mac"]:
217
+ platform_key = "Mac"
218
+ elif platform_code in ["Linux_x64"]:
219
+ platform_key = "Linux"
220
+ elif platform_code in ["Win_x64"]:
221
+ platform_key = "Windows"
222
+ elif platform_code in ["Win"]:
223
+ platform_key = "Win32"
224
+ channel_key = None
225
+ if channel.lower() == "stable":
226
+ channel_key = "Stable"
227
+ elif channel.lower() == "beta":
228
+ channel_key = "Beta"
229
+ elif channel.lower() == "dev":
230
+ channel_key = "Dev"
231
+ elif channel.lower() == "canary":
232
+ channel_key = "Canary"
233
+ base_url = "https://chromiumdash.appspot.com/fetch_releases"
234
+ url = f"{base_url}?channel={channel_key}&platform={platform_key}&num=1"
235
+ url_request = requests_get_with_retry(url)
236
+ data = None
237
+ if url_request.ok:
238
+ data = url_request.text
239
+ else:
240
+ raise Exception("Could not determine Chromium revision!")
241
+ if data:
242
+ try:
243
+ import ast
244
+
245
+ result = ast.literal_eval(data)
246
+ revision = result[0]["chromium_main_branch_position"]
247
+ return str(revision)
248
+ except Exception:
249
+ return get_latest_chromedriver_version(platform_code)
250
+ else:
251
+ return get_latest_chromedriver_version(platform_code)
252
+
253
+
254
+ def get_chromium_latest_revision(platform_code):
255
+ base_url = "https://storage.googleapis.com/chromium-browser-snapshots"
256
+ url = f"{base_url}/{platform_code}/LAST_CHANGE"
257
+ url_request = requests_get_with_retry(url)
258
+ if url_request.ok:
259
+ latest_revision = url_request.text
260
+ else:
261
+ raise Exception("Could not determine latest Chromium revision!")
262
+ return latest_revision
263
+
264
+
206
265
  def get_latest_chromedriver_version(channel="Stable"):
207
266
  try:
208
- if hasattr(sb_config, "cft_lkgv_json") and sb_config.cft_lkgv_json:
267
+ if getattr(sb_config, "cft_lkgv_json", None):
209
268
  return sb_config.cft_lkgv_json["channels"][channel]["version"]
210
269
  req = requests_get(
211
270
  "https://googlechromelabs.github.io/"
@@ -239,10 +298,7 @@ def get_latest_canary_chromedriver_version():
239
298
  def log_d(message):
240
299
  """If setting sb_config.settings.HIDE_DRIVER_DOWNLOADS to True,
241
300
  output from driver downloads are logged instead of printed."""
242
- if (
243
- hasattr(sb_config.settings, "HIDE_DRIVER_DOWNLOADS")
244
- and sb_config.settings.HIDE_DRIVER_DOWNLOADS
245
- ):
301
+ if getattr(sb_config.settings, "HIDE_DRIVER_DOWNLOADS", None):
246
302
  logging.debug(message)
247
303
  else:
248
304
  print(message)
@@ -251,7 +307,7 @@ def log_d(message):
251
307
  def main(override=None, intel_for_uc=None, force_uc=None):
252
308
  if override:
253
309
  found_proxy = None
254
- if hasattr(sb_config, "proxy_driver") and sb_config.proxy_driver:
310
+ if getattr(sb_config, "proxy_driver", None):
255
311
  if " --proxy=" in " ".join(sys.argv):
256
312
  for arg in sys.argv:
257
313
  if arg.startswith("--proxy="):
@@ -277,6 +333,11 @@ def main(override=None, intel_for_uc=None, force_uc=None):
277
333
  elif override.startswith("iedriver "):
278
334
  extra = override.split("iedriver ")[1]
279
335
  sys.argv = ["seleniumbase", "get", "iedriver", extra]
336
+ elif override == "chromium":
337
+ sys.argv = ["seleniumbase", "get", "chromium"]
338
+ elif override.startswith("chromium "):
339
+ extra = override.split("chromium ")[1]
340
+ sys.argv = ["seleniumbase", "get", "chromium", extra]
280
341
  elif override == "cft":
281
342
  sys.argv = ["seleniumbase", "get", "cft"]
282
343
  elif override.startswith("cft "):
@@ -311,8 +372,7 @@ def main(override=None, intel_for_uc=None, force_uc=None):
311
372
  downloads_folder = DRIVER_DIR
312
373
  if (
313
374
  hasattr(sb_config, "settings")
314
- and hasattr(sb_config.settings, "NEW_DRIVER_DIR")
315
- and sb_config.settings.NEW_DRIVER_DIR
375
+ and getattr(sb_config.settings, "NEW_DRIVER_DIR", None)
316
376
  and os.path.exists(sb_config.settings.NEW_DRIVER_DIR)
317
377
  ):
318
378
  downloads_folder = sb_config.settings.NEW_DRIVER_DIR
@@ -320,6 +380,8 @@ def main(override=None, intel_for_uc=None, force_uc=None):
320
380
  downloads_folder = DRIVER_DIR_CFT
321
381
  elif override == "chs" or name == "chs":
322
382
  downloads_folder = DRIVER_DIR_CHS
383
+ elif override == "chromium":
384
+ downloads_folder = DRIVER_DIR_CHROMIUM
323
385
  expected_contents = None
324
386
  platform_code = None
325
387
  copy_to_path = False
@@ -647,6 +709,31 @@ def main(override=None, intel_for_uc=None, force_uc=None):
647
709
  "https://storage.googleapis.com/chrome-for-testing-public/"
648
710
  "%s/%s/%s" % (use_version, platform_code, file_name)
649
711
  )
712
+ elif name == "chromium":
713
+ if IS_MAC:
714
+ if IS_ARM_MAC:
715
+ platform_code = "Mac_Arm"
716
+ else:
717
+ platform_code = "Mac"
718
+ file_name = "chrome-mac.zip"
719
+ elif IS_LINUX:
720
+ platform_code = "Linux_x64"
721
+ file_name = "chrome-linux.zip"
722
+ elif IS_WINDOWS:
723
+ if "64" in ARCH:
724
+ platform_code = "Win_x64"
725
+ else:
726
+ platform_code = "Win"
727
+ file_name = "chrome-win.zip"
728
+ revision = get_chromium_latest_revision(platform_code)
729
+ msg = c2 + "Chromium revision to download" + cr
730
+ p_version = c3 + revision + cr
731
+ log_d("\n*** %s = %s" % (msg, p_version))
732
+ download_url = (
733
+ "https://storage.googleapis.com/chromium-browser-snapshots/"
734
+ "%s/%s/%s" % (platform_code, revision, file_name)
735
+ )
736
+ downloads_folder = DRIVER_DIR_CHROMIUM
650
737
  elif name == "chrome-headless-shell" or name == "chs":
651
738
  set_version = None
652
739
  found_version = None
@@ -1007,12 +1094,12 @@ def main(override=None, intel_for_uc=None, force_uc=None):
1007
1094
  remote_file = requests_get_with_retry(download_url)
1008
1095
  with open(file_path, "wb") as file:
1009
1096
  file.write(remote_file.content)
1010
- log_d("%sDownload Complete!%s\n" % (c1, cr))
1011
1097
 
1012
1098
  if file_name.endswith(".zip"):
1013
1099
  zip_file_path = file_path
1014
1100
  zip_ref = zipfile.ZipFile(zip_file_path, "r")
1015
1101
  contents = zip_ref.namelist()
1102
+ log_d("%sDownload Complete!%s\n" % (c1, cr))
1016
1103
  if (
1017
1104
  len(contents) >= 1
1018
1105
  and name in ["chromedriver", "uc_driver", "geckodriver"]
@@ -1253,6 +1340,48 @@ def main(override=None, intel_for_uc=None, force_uc=None):
1253
1340
  "Chrome for Testing was saved inside:\n%s%s\n%s\n"
1254
1341
  % (pr_base_path, pr_sep, pr_folder_name)
1255
1342
  )
1343
+ elif name == "chromium":
1344
+ # Zip file is valid. Proceed.
1345
+ driver_path = None
1346
+ driver_file = None
1347
+ base_path = os.sep.join(zip_file_path.split(os.sep)[:-1])
1348
+ folder_name = contents[0].split("/")[0]
1349
+ folder_path = os.path.join(base_path, folder_name)
1350
+ if IS_MAC or IS_LINUX:
1351
+ if (
1352
+ "chromium" in folder_path
1353
+ and "drivers" in folder_path
1354
+ and os.path.exists(folder_path)
1355
+ ):
1356
+ shutil.rmtree(folder_path)
1357
+ subprocess.run(
1358
+ ["unzip", zip_file_path, "-d", downloads_folder]
1359
+ )
1360
+ elif IS_WINDOWS:
1361
+ subprocess.run(
1362
+ [
1363
+ "powershell",
1364
+ "Expand-Archive",
1365
+ "-Path",
1366
+ zip_file_path,
1367
+ "-DestinationPath",
1368
+ downloads_folder,
1369
+ "-Force",
1370
+ ]
1371
+ )
1372
+ else:
1373
+ zip_ref.extractall(downloads_folder)
1374
+ zip_ref.close()
1375
+ with suppress(Exception):
1376
+ os.remove(zip_file_path)
1377
+ log_d("%sUnzip Complete!%s\n" % (c2, cr))
1378
+ pr_base_path = c3 + base_path + cr
1379
+ pr_sep = c3 + os.sep + cr
1380
+ pr_folder_name = c3 + folder_name + cr
1381
+ log_d(
1382
+ "Chromium was saved inside:\n%s%s\n%s\n"
1383
+ % (pr_base_path, pr_sep, pr_folder_name)
1384
+ )
1256
1385
  elif name == "chrome-headless-shell" or name == "chs":
1257
1386
  # Zip file is valid. Proceed.
1258
1387
  driver_path = None
@@ -1304,6 +1433,7 @@ def main(override=None, intel_for_uc=None, force_uc=None):
1304
1433
  tar = tarfile.open(file_path)
1305
1434
  contents = tar.getnames()
1306
1435
  if len(contents) == 1:
1436
+ log_d("%sDownload Complete!%s\n" % (c1, cr))
1307
1437
  for f_name in contents:
1308
1438
  # Remove existing version if exists
1309
1439
  new_file = os.path.join(downloads_folder, str(f_name))
@@ -1341,6 +1471,7 @@ def main(override=None, intel_for_uc=None, force_uc=None):
1341
1471
  else:
1342
1472
  # Not a .zip file or a .tar.gz file. Just a direct download.
1343
1473
  if "Driver" in file_name or "driver" in file_name:
1474
+ log_d("%sDownload Complete!%s\n" % (c1, cr))
1344
1475
  log_d("Making [%s] executable ..." % file_name)
1345
1476
  make_executable(file_path)
1346
1477
  log_d("%s[%s] is now ready for use!%s" % (c1, file_name, cr))
@@ -10,6 +10,7 @@ Example:
10
10
 
11
11
  Options:
12
12
  -b / --basic (Only config files. No tests added.)
13
+ --gha (Include GitHub Actions YML with defaults.)
13
14
 
14
15
  Output:
15
16
  Creates a new folder for running SBase scripts.
@@ -32,6 +33,7 @@ def invalid_run_command(msg=None):
32
33
  exp += " sbase mkdir ui_tests\n"
33
34
  exp += " Options:\n"
34
35
  exp += " -b / --basic (Only config files. No tests added.)\n"
36
+ exp += " --gha (Include GitHub Actions YML with defaults.)\n"
35
37
  exp += " Output:\n"
36
38
  exp += " Creates a new folder for running SBase scripts.\n"
37
39
  exp += " The new folder contains default config files,\n"
@@ -58,6 +60,7 @@ def main():
58
60
  c7 = colorama.Fore.BLACK + colorama.Back.MAGENTA
59
61
  cr = colorama.Style.RESET_ALL
60
62
 
63
+ gha = False
61
64
  basic = False
62
65
  help_me = False
63
66
  error_msg = None
@@ -89,6 +92,8 @@ def main():
89
92
  help_me = True
90
93
  elif option == "-b" or option == "--basic":
91
94
  basic = True
95
+ elif option == "--gha":
96
+ gha = True
92
97
  else:
93
98
  invalid_cmd = "\n===> INVALID OPTION: >> %s <<\n" % option
94
99
  invalid_cmd = invalid_cmd.replace(">> ", ">>" + c5 + " ")
@@ -246,6 +251,12 @@ def main():
246
251
  data.append("msedgedriver.exe")
247
252
  data.append("operadriver.exe")
248
253
  data.append("uc_driver.exe")
254
+ data.append("chrome-mac.zip")
255
+ data.append("chrome-linux.zip")
256
+ data.append("chrome-win.zip")
257
+ data.append("chrome-mac")
258
+ data.append("chrome-linux")
259
+ data.append("chrome-win")
249
260
  data.append("chrome-mac-arm64.zip")
250
261
  data.append("chrome-mac-x64.zip")
251
262
  data.append("chrome-linux64.zip")
@@ -315,9 +326,69 @@ def main():
315
326
  file.writelines("\r\n".join(data))
316
327
  file.close()
317
328
 
329
+ if gha:
330
+ dir_name_b = dir_name + "/" + ".github"
331
+ os.mkdir(dir_name_b)
332
+ dir_name_c = dir_name_b + "/" + "workflows"
333
+ os.mkdir(dir_name_c)
334
+
335
+ data = []
336
+ data.append("name: CI build")
337
+ data.append("on:")
338
+ data.append(" push:")
339
+ data.append(" branches:")
340
+ data.append(" pull_request:")
341
+ data.append(" branches:")
342
+ data.append(" workflow_dispatch:")
343
+ data.append(" branches:")
344
+ data.append("jobs:")
345
+ data.append(" build:")
346
+ data.append(" env:")
347
+ data.append(' PY_COLORS: "1"')
348
+ data.append(" strategy:")
349
+ data.append(" fail-fast: false")
350
+ data.append(" max-parallel: 15")
351
+ data.append(" matrix:")
352
+ data.append(" os: [ubuntu-latest]")
353
+ data.append(' python-version: ["3.x"]')
354
+ data.append(" runs-on: ${{ matrix.os }}")
355
+ data.append(" steps:")
356
+ data.append(" - uses: actions/checkout@v6")
357
+ data.append(" - name: Set up Python ${{ matrix.python-version }}")
358
+ data.append(" uses: actions/setup-python@v6")
359
+ data.append(" with:")
360
+ data.append(" python-version: ${{ matrix.python-version }}")
361
+ data.append(" - name: Install dependencies")
362
+ data.append(" run: |")
363
+ data.append(" python -m pip install --upgrade pip")
364
+ data.append(" pip install -r requirements.txt")
365
+ data.append(" - name: Install Chrome")
366
+ data.append(" if: matrix.os == 'ubuntu-latest'")
367
+ data.append(" run: sudo apt install google-chrome-stable")
368
+ data.append(" - name: Download chromedriver")
369
+ data.append(" run: sbase get chromedriver")
370
+ data.append(" - name: Run pytest")
371
+ data.append(" run: pytest -v -s --rs --crumbs --reruns=1")
372
+ data.append(" - name: Upload artifacts")
373
+ data.append(" if: ${{ always() }}")
374
+ data.append(" uses: actions/upload-artifact@v6")
375
+ data.append(" with:")
376
+ data.append(" name: seleniumbase-artifacts")
377
+ data.append(" path: ./latest_logs/")
378
+ data.append(" if-no-files-found: ignore")
379
+ data.append("")
380
+ file_path = "%s/%s" % (dir_name_c, "python-package.yml")
381
+ file = open(file_path, mode="w+", encoding="utf-8")
382
+ file.writelines("\r\n".join(data))
383
+ file.close()
384
+
318
385
  if basic:
319
386
  data = []
320
387
  data.append(" %s/" % dir_name)
388
+ if gha:
389
+ data.append(" ├── .github")
390
+ data.append(" │ └── workflows/")
391
+ data.append(" │ └── python-package.yml")
321
392
  data.append(" ├── __init__.py")
322
393
  data.append(" ├── pytest.ini")
323
394
  data.append(" ├── requirements.txt")
@@ -497,6 +568,7 @@ def main():
497
568
  )
498
569
  data.append(' self.click(\'mark:contains("%s")\' % keyword)')
499
570
  data.append(' self.assert_title_contains(title_text)')
571
+ data.append(' self.save_screenshot_to_logs()')
500
572
  data.append("")
501
573
  file_path = "%s/%s" % (dir_name, "parameterized_test.py")
502
574
  file = open(file_path, mode="w+", encoding="utf-8")
@@ -734,6 +806,10 @@ def main():
734
806
 
735
807
  data = []
736
808
  data.append(" %s/" % dir_name)
809
+ if gha:
810
+ data.append(" ├── .github")
811
+ data.append(" │ └── workflows/")
812
+ data.append(" │ └── python-package.yml")
737
813
  data.append(" ├── __init__.py")
738
814
  data.append(" ├── my_first_test.py")
739
815
  data.append(" ├── parameterized_test.py")
@@ -84,6 +84,11 @@ def main():
84
84
  error_msg = None
85
85
  invalid_cmd = None
86
86
  use_edge = False
87
+ use_opera = False
88
+ use_brave = False
89
+ use_comet = False
90
+ use_atlas = False
91
+ use_chromium = False
87
92
  use_uc = False
88
93
  esc_end = False
89
94
  start_page = None
@@ -138,6 +143,16 @@ def main():
138
143
  help_me = True
139
144
  elif option.lower() == "--edge":
140
145
  use_edge = True
146
+ elif option.lower() == "--opera":
147
+ use_opera = True
148
+ elif option.lower() == "--brave":
149
+ use_brave = True
150
+ elif option.lower() == "--comet":
151
+ use_comet = True
152
+ elif option.lower() == "--atlas":
153
+ use_atlas = True
154
+ elif option.lower() == "--use-chromium":
155
+ use_chromium = True
141
156
  elif option.lower() == "--ee":
142
157
  esc_end = True
143
158
  elif option.lower() in ("--gui", "--headed"):
@@ -275,6 +290,16 @@ def main():
275
290
  )
276
291
  if use_edge:
277
292
  run_cmd += " --edge"
293
+ elif use_opera:
294
+ run_cmd += " --opera"
295
+ elif use_brave:
296
+ run_cmd += " --brave"
297
+ elif use_comet:
298
+ run_cmd += " --comet"
299
+ elif use_atlas:
300
+ run_cmd += " --atlas"
301
+ elif use_chromium:
302
+ run_cmd += " --use-chromium"
278
303
  if force_gui:
279
304
  run_cmd += " --gui"
280
305
  if use_uc:
@@ -144,6 +144,16 @@ def do_recording(file_name, url, overwrite_enabled, use_chrome, window):
144
144
  )
145
145
  if not use_chrome:
146
146
  command += " --edge"
147
+ elif "--opera" in command_args:
148
+ command += " --opera"
149
+ elif "--brave" in command_args:
150
+ command += " --brave"
151
+ elif "--comet" in command_args:
152
+ command += " --comet"
153
+ elif "--atlas" in command_args:
154
+ command += " --atlas"
155
+ elif "--use-chromium" in command_args:
156
+ command += " --use-chromium"
147
157
  if (
148
158
  "--uc" in command_args
149
159
  or "--cdp" in command_args
@@ -226,10 +236,37 @@ def create_tkinter_gui():
226
236
  chk = tk.Checkbutton(window, text="Overwrite existing files", variable=cbx)
227
237
  chk.pack()
228
238
  chk.select()
239
+ use_stealth = False
240
+ command_args = sys.argv[2:]
241
+ if (
242
+ "--uc" in command_args
243
+ or "--cdp" in command_args
244
+ or "--undetected" in command_args
245
+ or "--undetectable" in command_args
246
+ ):
247
+ use_stealth = True
248
+ browser_display = "Use Chrome over Edge"
249
+ if "--opera" in command_args:
250
+ browser_display = "Use Opera over Edge"
251
+ elif "--brave" in command_args:
252
+ browser_display = "Use Brave over Edge"
253
+ elif "--comet" in command_args:
254
+ browser_display = "Use Comet over Edge"
255
+ elif "--atlas" in command_args:
256
+ browser_display = "Use Atlas over Edge"
229
257
  cbb = tk.IntVar()
230
- chkb = tk.Checkbutton(window, text="Use Chrome over Edge", variable=cbb)
231
- chkb.pack()
232
- chkb.select()
258
+ if not use_stealth:
259
+ chkb = tk.Checkbutton(window, text=browser_display, variable=cbb)
260
+ chkb.pack()
261
+ if "--edge" not in command_args:
262
+ chkb.select()
263
+ else:
264
+ chkb = tk.Checkbutton(
265
+ window, text="Stealthy Chrome Mode", variable=cbb
266
+ )
267
+ chkb.pack()
268
+ chkb.select()
269
+ chkb.config(state=tk.DISABLED)
233
270
  tk.Label(window, text="").pack()
234
271
  url = tk.StringVar()
235
272
  tk.Label(window, text="Enter the URL to start recording on:").pack()