seleniumbase 4.43.1__py3-none-any.whl → 4.43.3__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.

Potentially problematic release.


This version of seleniumbase might be problematic. Click here for more details.

Files changed (42) hide show
  1. seleniumbase/__version__.py +1 -1
  2. seleniumbase/behave/behave_sb.py +7 -7
  3. seleniumbase/console_scripts/sb_caseplans.py +3 -3
  4. seleniumbase/console_scripts/sb_mkchart.py +1 -1
  5. seleniumbase/console_scripts/sb_mkdir.py +21 -21
  6. seleniumbase/console_scripts/sb_mkfile.py +1 -1
  7. seleniumbase/console_scripts/sb_mkpres.py +1 -1
  8. seleniumbase/console_scripts/sb_mkrec.py +1 -1
  9. seleniumbase/console_scripts/sb_objectify.py +4 -4
  10. seleniumbase/console_scripts/sb_print.py +1 -1
  11. seleniumbase/core/browser_launcher.py +82 -5
  12. seleniumbase/core/detect_b_ver.py +214 -8
  13. seleniumbase/core/log_helper.py +4 -4
  14. seleniumbase/core/report_helper.py +6 -4
  15. seleniumbase/core/sb_cdp.py +52 -6
  16. seleniumbase/core/tour_helper.py +1 -1
  17. seleniumbase/drivers/atlas_drivers/__init__.py +0 -0
  18. seleniumbase/drivers/brave_drivers/__init__.py +0 -0
  19. seleniumbase/drivers/comet_drivers/__init__.py +0 -0
  20. seleniumbase/drivers/opera_drivers/__init__.py +0 -0
  21. seleniumbase/fixtures/constants.py +29 -0
  22. seleniumbase/fixtures/js_utils.py +14 -2
  23. seleniumbase/fixtures/page_utils.py +13 -7
  24. seleniumbase/plugins/basic_test_info.py +2 -2
  25. seleniumbase/plugins/driver_manager.py +114 -0
  26. seleniumbase/plugins/page_source.py +2 -2
  27. seleniumbase/plugins/pytest_plugin.py +148 -21
  28. seleniumbase/plugins/sb_manager.py +118 -1
  29. seleniumbase/plugins/selenium_plugin.py +123 -0
  30. seleniumbase/translate/translator.py +2 -2
  31. seleniumbase/undetected/cdp_driver/cdp_util.py +56 -38
  32. seleniumbase/undetected/cdp_driver/connection.py +1 -0
  33. seleniumbase/utilities/selenium_grid/download_selenium_server.py +1 -1
  34. seleniumbase/utilities/selenium_grid/grid_hub.py +1 -1
  35. seleniumbase/utilities/selenium_grid/grid_node.py +2 -2
  36. seleniumbase/utilities/selenium_ide/convert_ide.py +2 -2
  37. {seleniumbase-4.43.1.dist-info → seleniumbase-4.43.3.dist-info}/METADATA +6 -2
  38. {seleniumbase-4.43.1.dist-info → seleniumbase-4.43.3.dist-info}/RECORD +42 -38
  39. {seleniumbase-4.43.1.dist-info → seleniumbase-4.43.3.dist-info}/WHEEL +0 -0
  40. {seleniumbase-4.43.1.dist-info → seleniumbase-4.43.3.dist-info}/entry_points.txt +0 -0
  41. {seleniumbase-4.43.1.dist-info → seleniumbase-4.43.3.dist-info}/licenses/LICENSE +0 -0
  42. {seleniumbase-4.43.1.dist-info → seleniumbase-4.43.3.dist-info}/top_level.txt +0 -0
@@ -40,6 +40,10 @@ class OSType(object):
40
40
  class ChromeType(object):
41
41
  GOOGLE = "google-chrome"
42
42
  MSEDGE = "edge"
43
+ OPERA = "opera"
44
+ BRAVE = "brave"
45
+ COMET = "comet"
46
+ ATLAS = "atlas"
43
47
 
44
48
 
45
49
  PATTERN = {
@@ -96,7 +100,9 @@ def linux_browser_apps_to_cmd(*apps):
96
100
  )
97
101
 
98
102
 
99
- def chrome_on_linux_path(chromium_ok=False):
103
+ def chrome_on_linux_path(chromium_ok=False, browser_type=None):
104
+ if browser_type and browser_type != ChromeType.GOOGLE:
105
+ return ""
100
106
  if os_name() != OSType.LINUX:
101
107
  return ""
102
108
  paths = ["/bin/google-chrome", "/bin/google-chrome-stable"]
@@ -126,7 +132,9 @@ def chrome_on_linux_path(chromium_ok=False):
126
132
  return "/usr/bin/google-chrome"
127
133
 
128
134
 
129
- def edge_on_linux_path():
135
+ def edge_on_linux_path(browser_type=None):
136
+ if browser_type and browser_type != ChromeType.MSEDGE:
137
+ return ""
130
138
  if os_name() != OSType.LINUX:
131
139
  return ""
132
140
  paths = os.environ["PATH"].split(os.pathsep)
@@ -143,7 +151,60 @@ def edge_on_linux_path():
143
151
  return "/usr/bin/microsoft-edge"
144
152
 
145
153
 
146
- def chrome_on_windows_path():
154
+ def opera_on_linux_path(browser_type=None):
155
+ if browser_type and browser_type != ChromeType.OPERA:
156
+ return ""
157
+ if os_name() != OSType.LINUX:
158
+ return ""
159
+ paths = os.environ["PATH"].split(os.pathsep)
160
+ binaries = []
161
+ binaries.append("opera")
162
+ binaries.append("opera-stable")
163
+ for binary in binaries:
164
+ for path in paths:
165
+ full_path = os.path.join(path, binary)
166
+ if os.path.exists(full_path) and os.access(full_path, os.X_OK):
167
+ return full_path
168
+ return "/usr/bin/opera-stable"
169
+
170
+
171
+ def brave_on_linux_path(browser_type=None):
172
+ if browser_type and browser_type != ChromeType.BRAVE:
173
+ return ""
174
+ if os_name() != OSType.LINUX:
175
+ return ""
176
+ paths = os.environ["PATH"].split(os.pathsep)
177
+ binaries = []
178
+ binaries.append("brave-browser")
179
+ binaries.append("brave")
180
+ binaries.append("brave-browser-stable")
181
+ for binary in binaries:
182
+ for path in paths:
183
+ full_path = os.path.join(path, binary)
184
+ if os.path.exists(full_path) and os.access(full_path, os.X_OK):
185
+ return full_path
186
+ return "/usr/bin/brave-browser"
187
+
188
+
189
+ def comet_on_linux_path(browser_type=None):
190
+ if browser_type and browser_type != ChromeType.COMET:
191
+ return ""
192
+ if os_name() != OSType.LINUX:
193
+ return ""
194
+ return "" # Comet Browser isn't supported on Linux yet
195
+
196
+
197
+ def atlas_on_linux_path(browser_type=None):
198
+ if browser_type and browser_type != ChromeType.ATLAS:
199
+ return ""
200
+ if os_name() != OSType.LINUX:
201
+ return ""
202
+ return "" # Atlas Browser isn't supported on Linux yet
203
+
204
+
205
+ def chrome_on_windows_path(browser_type=None):
206
+ if browser_type and browser_type != ChromeType.GOOGLE:
207
+ return ""
147
208
  if os_name() != OSType.WIN:
148
209
  return ""
149
210
  candidates = []
@@ -171,7 +232,9 @@ def chrome_on_windows_path():
171
232
  return ""
172
233
 
173
234
 
174
- def edge_on_windows_path():
235
+ def edge_on_windows_path(browser_type=None):
236
+ if browser_type and browser_type != ChromeType.MSEDGE:
237
+ return ""
175
238
  if os_name() != OSType.WIN:
176
239
  return ""
177
240
  candidates = []
@@ -199,6 +262,119 @@ def edge_on_windows_path():
199
262
  return ""
200
263
 
201
264
 
265
+ def opera_on_windows_path(browser_type=None):
266
+ if browser_type and browser_type != ChromeType.OPERA:
267
+ return ""
268
+ if os_name() != OSType.WIN:
269
+ return ""
270
+ candidates = []
271
+ for item in map(
272
+ os.environ.get,
273
+ (
274
+ "PROGRAMFILES",
275
+ "PROGRAMFILES(X86)",
276
+ "LOCALAPPDATA",
277
+ "PROGRAMW6432",
278
+ ),
279
+ ):
280
+ for subitem in (
281
+ "Opera",
282
+ "Opera/Application",
283
+ ):
284
+ try:
285
+ candidates.append(os.sep.join((item, subitem, "opera.exe")))
286
+ except TypeError:
287
+ pass
288
+ for candidate in candidates:
289
+ if os.path.exists(candidate) and os.access(candidate, os.X_OK):
290
+ return os.path.normpath(candidate)
291
+ return ""
292
+
293
+
294
+ def brave_on_windows_path(browser_type=None):
295
+ if browser_type and browser_type != ChromeType.BRAVE:
296
+ return ""
297
+ if os_name() != OSType.WIN:
298
+ return ""
299
+ candidates = []
300
+ for item in map(
301
+ os.environ.get,
302
+ (
303
+ "PROGRAMFILES",
304
+ "PROGRAMFILES(X86)",
305
+ "LOCALAPPDATA",
306
+ "PROGRAMW6432",
307
+ ),
308
+ ):
309
+ for subitem in (
310
+ "BraveSoftware/Brave-Browser/Application",
311
+ ):
312
+ try:
313
+ candidates.append(os.sep.join((item, subitem, "brave.exe")))
314
+ except TypeError:
315
+ pass
316
+ for candidate in candidates:
317
+ if os.path.exists(candidate) and os.access(candidate, os.X_OK):
318
+ return os.path.normpath(candidate)
319
+ return ""
320
+
321
+
322
+ def comet_on_windows_path(browser_type=None):
323
+ if browser_type and browser_type != ChromeType.COMET:
324
+ return ""
325
+ if os_name() != OSType.WIN:
326
+ return ""
327
+ candidates = []
328
+ for item in map(
329
+ os.environ.get,
330
+ (
331
+ "PROGRAMFILES",
332
+ "PROGRAMFILES(X86)",
333
+ "LOCALAPPDATA",
334
+ "PROGRAMW6432",
335
+ ),
336
+ ):
337
+ for subitem in (
338
+ "Comet/Application",
339
+ ):
340
+ try:
341
+ candidates.append(os.sep.join((item, subitem, "Comet.exe")))
342
+ except TypeError:
343
+ pass
344
+ for candidate in candidates:
345
+ if os.path.exists(candidate) and os.access(candidate, os.X_OK):
346
+ return os.path.normpath(candidate)
347
+ return ""
348
+
349
+
350
+ def atlas_on_windows_path(browser_type=None):
351
+ if browser_type and browser_type != ChromeType.ATLAS:
352
+ return ""
353
+ if os_name() != OSType.WIN:
354
+ return ""
355
+ candidates = []
356
+ for item in map(
357
+ os.environ.get,
358
+ (
359
+ "PROGRAMFILES",
360
+ "PROGRAMFILES(X86)",
361
+ "LOCALAPPDATA",
362
+ "PROGRAMW6432",
363
+ ),
364
+ ):
365
+ for subitem in (
366
+ "Atlas/Application",
367
+ ):
368
+ try:
369
+ candidates.append(os.sep.join((item, subitem, "Atlas.exe")))
370
+ except TypeError:
371
+ pass
372
+ for candidate in candidates:
373
+ if os.path.exists(candidate) and os.access(candidate, os.X_OK):
374
+ return os.path.normpath(candidate)
375
+ return ""
376
+
377
+
202
378
  def windows_browser_apps_to_cmd(*apps):
203
379
  """Create analogue of browser --version command for windows."""
204
380
  powershell = determine_powershell()
@@ -211,18 +387,48 @@ def windows_browser_apps_to_cmd(*apps):
211
387
 
212
388
  def get_binary_location(browser_type, chromium_ok=False):
213
389
  """Return the full path of the browser binary."""
390
+ if browser_type.lower() == "chrome":
391
+ browser_type = "google-chrome"
392
+ elif browser_type.lower() == "msedge":
393
+ browser_type = "edge"
394
+ else:
395
+ browser_type = browser_type.lower()
214
396
  cmd_mapping = {
215
397
  ChromeType.GOOGLE: {
216
- OSType.LINUX: chrome_on_linux_path(chromium_ok),
398
+ OSType.LINUX: chrome_on_linux_path(chromium_ok, browser_type),
217
399
  OSType.MAC: r"/Applications/Google Chrome.app"
218
400
  r"/Contents/MacOS/Google Chrome",
219
- OSType.WIN: chrome_on_windows_path(),
401
+ OSType.WIN: chrome_on_windows_path(browser_type),
220
402
  },
221
403
  ChromeType.MSEDGE: {
222
- OSType.LINUX: edge_on_linux_path(),
404
+ OSType.LINUX: edge_on_linux_path(browser_type),
223
405
  OSType.MAC: r"/Applications/Microsoft Edge.app"
224
406
  r"/Contents/MacOS/Microsoft Edge",
225
- OSType.WIN: edge_on_windows_path(),
407
+ OSType.WIN: edge_on_windows_path(browser_type),
408
+ },
409
+ ChromeType.OPERA: {
410
+ OSType.LINUX: opera_on_linux_path(browser_type),
411
+ OSType.MAC: r"/Applications/Opera.app"
412
+ r"/Contents/MacOS/Opera",
413
+ OSType.WIN: opera_on_windows_path(browser_type),
414
+ },
415
+ ChromeType.BRAVE: {
416
+ OSType.LINUX: brave_on_linux_path(browser_type),
417
+ OSType.MAC: r"/Applications/Brave Browser.app"
418
+ r"/Contents/MacOS/Brave Browser",
419
+ OSType.WIN: brave_on_windows_path(browser_type),
420
+ },
421
+ ChromeType.COMET: {
422
+ OSType.LINUX: comet_on_linux_path(browser_type),
423
+ OSType.MAC: r"/Applications/Comet.app"
424
+ r"/Contents/MacOS/Comet",
425
+ OSType.WIN: comet_on_windows_path(browser_type),
426
+ },
427
+ ChromeType.ATLAS: {
428
+ OSType.LINUX: atlas_on_linux_path(browser_type),
429
+ OSType.MAC: r"/Applications/Atlas.app"
430
+ r"/Contents/MacOS/Atlas",
431
+ OSType.WIN: atlas_on_windows_path(browser_type),
226
432
  },
227
433
  }
228
434
  return cmd_mapping[browser_type][os_name()]
@@ -36,7 +36,7 @@ def log_screenshot(test_logpath, driver, screenshot=None, get=False):
36
36
  element = driver.find_element("tag name", "body")
37
37
  screenshot = element.screenshot_as_base64
38
38
  if screenshot != screenshot_warning:
39
- with open(screenshot_path, "wb") as file:
39
+ with open(screenshot_path, mode="wb") as file:
40
40
  file.write(screenshot)
41
41
  with suppress(Exception):
42
42
  shared_utils.make_writable(screenshot_path)
@@ -297,7 +297,7 @@ def log_test_failure_data(test, test_logpath, driver, browser, url=None):
297
297
  with suppress(Exception):
298
298
  os.makedirs(test_logpath)
299
299
  with suppress(Exception):
300
- log_file = open(basic_file_path, "w+", encoding="utf-8")
300
+ log_file = open(basic_file_path, mode="w+", encoding="utf-8")
301
301
  log_file.writelines("\r\n".join(data_to_save))
302
302
  log_file.close()
303
303
  shared_utils.make_writable(basic_file_path)
@@ -352,7 +352,7 @@ def log_skipped_test_data(test, test_logpath, driver, browser, reason):
352
352
  data_to_save.append("")
353
353
  file_path = os.path.join(test_logpath, "skip_reason.txt")
354
354
  with suppress(Exception):
355
- log_file = open(file_path, "w+", encoding="utf-8")
355
+ log_file = open(file_path, mode="w+", encoding="utf-8")
356
356
  log_file.writelines("\r\n".join(data_to_save))
357
357
  log_file.close()
358
358
  shared_utils.make_writable(file_path)
@@ -387,7 +387,7 @@ def log_page_source(test_logpath, driver, source=None):
387
387
  os.makedirs(test_logpath)
388
388
  html_file_path = os.path.join(test_logpath, html_file_name)
389
389
  with suppress(Exception):
390
- html_file = open(html_file_path, "w+", encoding="utf-8")
390
+ html_file = open(html_file_path, mode="w+", encoding="utf-8")
391
391
  html_file.write(page_source)
392
392
  html_file.close()
393
393
  shared_utils.make_writable(html_file_path)
@@ -47,7 +47,9 @@ def save_test_failure_data(test, name, folder=None):
47
47
  failure_data_file_path = os.path.join(file_path, name)
48
48
  else:
49
49
  failure_data_file_path = name
50
- failure_data_file = open(failure_data_file_path, "w+", "utf-8")
50
+ failure_data_file = open(
51
+ failure_data_file_path, mode="w+", encoding="utf-8"
52
+ )
51
53
  data_to_save = []
52
54
  if not hasattr(sb_config, "_report_test_id"):
53
55
  exc_message = "(Unknown Exception)"
@@ -99,7 +101,7 @@ def process_failures(test, test_count, duration):
99
101
  bad_page_data = "failure_%s.txt" % test_count
100
102
  screenshot_path = os.path.join(LATEST_REPORT_DIR, bad_page_image)
101
103
  if hasattr(test, "_last_page_screenshot") and test._last_page_screenshot:
102
- with open(screenshot_path, "wb") as file:
104
+ with open(screenshot_path, mode="wb") as file:
103
105
  file.write(test._last_page_screenshot)
104
106
  save_test_failure_data(test, bad_page_data, folder=LATEST_REPORT_DIR)
105
107
  exc_message = None
@@ -172,7 +174,7 @@ def add_bad_page_log_file(page_results_list):
172
174
  abs_path = os.path.abspath(".")
173
175
  file_path = os.path.join(abs_path, LATEST_REPORT_DIR)
174
176
  log_file = os.path.join(file_path, RESULTS_TABLE)
175
- f = open(log_file, "w")
177
+ f = open(log_file, mode="w")
176
178
  h_p1 = '"Num","Result","Stacktrace","Screenshot",'
177
179
  h_p2 = '"URL","Browser","Epoch Time","Duration",'
178
180
  h_p3 = '"Test Case Address","Additional Info"\n'
@@ -197,7 +199,7 @@ def add_results_page(html):
197
199
  file_path = os.path.join(abs_path, LATEST_REPORT_DIR)
198
200
  results_file_name = HTML_REPORT
199
201
  results_file = os.path.join(file_path, results_file_name)
200
- f = open(results_file, "w")
202
+ f = open(results_file, mode="w")
201
203
  f.write(html)
202
204
  f.close()
203
205
  return results_file
@@ -1333,6 +1333,17 @@ class CDPMethods():
1333
1333
  x = window_rect["x"] + element_rect["x"]
1334
1334
  y = w_bottom_y - viewport_height + element_rect["y"]
1335
1335
  y_scroll_offset = window_rect["pageYOffset"]
1336
+ if (
1337
+ hasattr(sb_config, "_cdp_browser")
1338
+ and sb_config._cdp_browser == "opera"
1339
+ ):
1340
+ # Handle special case where Opera side panel shifts coordinates
1341
+ x_offset = window_rect["outerWidth"] - window_rect["innerWidth"]
1342
+ if x_offset > 56:
1343
+ x_offset = 56
1344
+ elif x_offset < 22:
1345
+ x_offset = 0
1346
+ x = x + x_offset
1336
1347
  y = y - y_scroll_offset
1337
1348
  x = x + window_rect["scrollX"]
1338
1349
  y = y + window_rect["scrollY"]
@@ -1726,8 +1737,8 @@ class CDPMethods():
1726
1737
  self.__add_light_pause()
1727
1738
  self.__set_window_rect(win_x, win_y, width, height)
1728
1739
  self.__add_light_pause()
1729
- x = x * width_ratio
1730
- y = y * width_ratio
1740
+ x = x * (width_ratio + 0.03)
1741
+ y = y * (width_ratio - 0.03)
1731
1742
  self.bring_active_window_to_front()
1732
1743
  self.__gui_click_x_y(x, y, timeframe=timeframe, uc_lock=False)
1733
1744
 
@@ -1755,8 +1766,43 @@ class CDPMethods():
1755
1766
  return True
1756
1767
  return False
1757
1768
 
1769
+ def _on_a_g_recaptcha_page(self):
1770
+ time.sleep(0.042)
1771
+ source = self.get_page_source()
1772
+ if not source or len(source) < 400:
1773
+ time.sleep(0.22)
1774
+ source = self.get_page_source()
1775
+ if (
1776
+ 'id="recaptcha-token"' in source
1777
+ or 'title="reCAPTCHA"' in source
1778
+ ):
1779
+ return True
1780
+ return False
1781
+
1782
+ def __gui_click_recaptcha(self):
1783
+ selector = None
1784
+ if self.is_element_visible('iframe[title="reCAPTCHA"]'):
1785
+ selector = 'iframe[title="reCAPTCHA"]'
1786
+ else:
1787
+ return
1788
+ with suppress(Exception):
1789
+ time.sleep(0.08)
1790
+ element_rect = self.get_gui_element_rect(selector, timeout=1)
1791
+ e_x = element_rect["x"]
1792
+ e_y = element_rect["y"]
1793
+ x = e_x + 29
1794
+ y = e_y + 35
1795
+ sb_config._saved_cf_x_y = (x, y)
1796
+ time.sleep(0.08)
1797
+ self.gui_click_x_y(x, y)
1798
+
1758
1799
  def gui_click_captcha(self):
1759
- if not self._on_a_cf_turnstile_page():
1800
+ if self._on_a_cf_turnstile_page():
1801
+ pass
1802
+ elif self._on_a_g_recaptcha_page():
1803
+ self.__gui_click_recaptcha()
1804
+ return
1805
+ else:
1760
1806
  return
1761
1807
  selector = None
1762
1808
  if (
@@ -1921,7 +1967,7 @@ class CDPMethods():
1921
1967
  if not shared_utils.is_windows():
1922
1968
  y = e_y + 32
1923
1969
  else:
1924
- y = e_y + 22
1970
+ y = e_y + 28
1925
1971
  sb_config._saved_cf_x_y = (x, y)
1926
1972
  time.sleep(0.08)
1927
1973
  self.gui_click_x_y(x, y)
@@ -2102,7 +2148,7 @@ class CDPMethods():
2102
2148
  if width > 0 and height > 0:
2103
2149
  x, y = self.get_gui_element_center(selector)
2104
2150
  self.bring_active_window_to_front()
2105
- self.__gui_hover_x_y(x, y, timeframe=timeframe)
2151
+ self.__gui_hover_x_y(x, y, timeframe=timeframe, uc_lock=False)
2106
2152
  self.__slow_mode_pause_if_set()
2107
2153
  self.loop.run_until_complete(self.page.wait())
2108
2154
 
@@ -2694,7 +2740,7 @@ class CDPMethods():
2694
2740
  rendered_source = "%s\n%s" % (base_href_html, page_source)
2695
2741
  else:
2696
2742
  rendered_source = page_source
2697
- html_file = open(html_file_path, "w+", "utf-8")
2743
+ html_file = open(html_file_path, mode="w+", encoding="utf-8")
2698
2744
  html_file.write(rendered_source)
2699
2745
  html_file.close()
2700
2746
 
@@ -1136,7 +1136,7 @@ def export_tour(tour_steps, name=None, filename="my_tour.js", url=None):
1136
1136
  pass
1137
1137
 
1138
1138
  file_path = exported_tours_folder + "/" + filename
1139
- out_file = open(file_path, "w+", encoding="utf-8")
1139
+ out_file = open(file_path, mode="w+", encoding="utf-8")
1140
1140
  out_file.writelines(instructions)
1141
1141
  out_file.close()
1142
1142
  print("\n>>> [%s] was saved!\n" % file_path)
File without changes
File without changes
File without changes
File without changes
@@ -387,6 +387,20 @@ class ValidBrowsers:
387
387
  "ie",
388
388
  "safari",
389
389
  "remote",
390
+ "opera",
391
+ "brave",
392
+ "comet",
393
+ "atlas",
394
+ ]
395
+
396
+
397
+ class ChromiumSubs:
398
+ # Chromium browsers that still use chromedriver
399
+ chromium_subs = [
400
+ "opera",
401
+ "brave",
402
+ "comet",
403
+ "atlas",
390
404
  ]
391
405
 
392
406
 
@@ -406,7 +420,14 @@ class ValidBinaries:
406
420
  "brave",
407
421
  "opera",
408
422
  "opera-stable",
423
+ "comet",
424
+ "comet-browser",
425
+ "comet-stable",
426
+ "atlas",
427
+ "atlas-browser",
428
+ "atlas-stable",
409
429
  "chrome.exe", # WSL (Windows Subsystem for Linux)
430
+ "chromium.exe", # WSL (Windows Subsystem for Linux)
410
431
  ]
411
432
  valid_edge_binaries_on_linux = [
412
433
  "microsoft-edge",
@@ -423,7 +444,13 @@ class ValidBinaries:
423
444
  "Google Chrome Beta",
424
445
  "Google Chrome Dev",
425
446
  "Brave Browser",
447
+ "Brave",
448
+ "Opera Browser",
426
449
  "Opera",
450
+ "Comet Browser",
451
+ "Comet",
452
+ "Atlas Browser",
453
+ "Atlas",
427
454
  ]
428
455
  valid_edge_binaries_on_macos = [
429
456
  "Microsoft Edge",
@@ -434,6 +461,8 @@ class ValidBinaries:
434
461
  "chrome-headless-shell.exe",
435
462
  "brave.exe",
436
463
  "opera.exe",
464
+ "comet.exe",
465
+ "atlas.exe",
437
466
  ]
438
467
  valid_edge_binaries_on_windows = [
439
468
  "msedge.exe",
@@ -1269,10 +1269,16 @@ def scroll_to_element(driver, element):
1269
1269
  return False
1270
1270
  try:
1271
1271
  element_location_x = element.location["x"]
1272
+ except Exception:
1273
+ element_location_x = 0
1274
+ try:
1272
1275
  element_width = element.size["width"]
1276
+ except Exception:
1277
+ element_width = 0
1278
+ try:
1273
1279
  screen_width = driver.get_window_size()["width"]
1274
1280
  except Exception:
1275
- element_location_x = 0
1281
+ screen_width = execute_script(driver, "return window.innerWidth;")
1276
1282
  element_location_y = element_location_y - constants.Scroll.Y_OFFSET
1277
1283
  if element_location_y < 0:
1278
1284
  element_location_y = 0
@@ -1312,10 +1318,16 @@ def slow_scroll_to_element(driver, element, *args, **kwargs):
1312
1318
  return
1313
1319
  try:
1314
1320
  element_location_x = element.location["x"]
1321
+ except Exception:
1322
+ element_location_x = 0
1323
+ try:
1315
1324
  element_width = element.size["width"]
1325
+ except Exception:
1326
+ element_width = 0
1327
+ try:
1316
1328
  screen_width = driver.get_window_size()["width"]
1317
1329
  except Exception:
1318
- element_location_x = 0
1330
+ screen_width = execute_script(driver, "return window.innerWidth;")
1319
1331
  element_location_y = element_location_y - constants.Scroll.Y_OFFSET
1320
1332
  if element_location_y < 0:
1321
1333
  element_location_y = 0
@@ -109,10 +109,10 @@ def looks_like_a_page_url(url):
109
109
  navigate to the page if a URL is detected, but will instead call
110
110
  self.get_element(URL_AS_A_SELECTOR) if the input is not a URL."""
111
111
  return url.startswith((
112
- "http:", "https:", "://", "about:", "blob:", "chrome:",
112
+ "http:", "https:", "://", "about:", "blob:", "chrome:", "opera:",
113
113
  "data:", "edge:", "file:", "view-source:", "chrome-search:",
114
114
  "chrome-extension:", "chrome-untrusted:", "isolated-app:",
115
- "chrome-devtools:", "devtools:"
115
+ "chrome-devtools:", "devtools:", "brave:", "comet:", "atlas:"
116
116
  ))
117
117
 
118
118
 
@@ -304,7 +304,7 @@ def _download_file_to(file_url, destination_folder, new_file_name=None):
304
304
  constants.MultiBrowser.DOWNLOAD_FILE_LOCK
305
305
  )
306
306
  with download_file_lock:
307
- with open(file_path, "wb") as code:
307
+ with open(file_path, mode="wb") as code:
308
308
  code.write(r.content)
309
309
 
310
310
 
@@ -314,7 +314,9 @@ def _save_data_as(data, destination_folder, file_name):
314
314
  )
315
315
  with file_io_lock:
316
316
  out_file = open(
317
- os.path.join(destination_folder, file_name), "w+", encoding="utf-8"
317
+ os.path.join(destination_folder, file_name),
318
+ mode="w+",
319
+ encoding="utf-8",
318
320
  )
319
321
  out_file.writelines(data)
320
322
  out_file.close()
@@ -327,12 +329,16 @@ def _append_data_to_file(data, destination_folder, file_name):
327
329
  with file_io_lock:
328
330
  existing_data = ""
329
331
  if os.path.exists(os.path.join(destination_folder, file_name)):
330
- with open(os.path.join(destination_folder, file_name), "r") as f:
332
+ with open(
333
+ os.path.join(destination_folder, file_name), mode="r"
334
+ ) as f:
331
335
  existing_data = f.read()
332
336
  if not existing_data.split("\n")[-1] == "":
333
337
  existing_data += "\n"
334
338
  out_file = open(
335
- os.path.join(destination_folder, file_name), "w+", encoding="utf-8"
339
+ os.path.join(destination_folder, file_name),
340
+ mode="w+",
341
+ encoding="utf-8",
336
342
  )
337
343
  out_file.writelines("%s%s" % (existing_data, data))
338
344
  out_file.close()
@@ -345,7 +351,7 @@ def _get_file_data(folder, file_name):
345
351
  with file_io_lock:
346
352
  if not os.path.exists(os.path.join(folder, file_name)):
347
353
  raise Exception("File not found!")
348
- with open(os.path.join(folder, file_name), "r") as f:
354
+ with open(os.path.join(folder, file_name), mode="r") as f:
349
355
  data = f.read()
350
356
  return data
351
357
 
@@ -25,7 +25,7 @@ class BasicTestInfo(Plugin):
25
25
  if not os.path.exists(test_logpath):
26
26
  os.makedirs(test_logpath)
27
27
  file_name = "%s/%s" % (test_logpath, self.logfile_name)
28
- basic_info_file = open(file_name, "w+", "utf-8")
28
+ basic_info_file = open(file_name, mode="w+", encoding="utf-8")
29
29
  self.__log_test_error_data(basic_info_file, test, err, "Error")
30
30
  basic_info_file.close()
31
31
 
@@ -34,7 +34,7 @@ class BasicTestInfo(Plugin):
34
34
  if not os.path.exists(test_logpath):
35
35
  os.makedirs(test_logpath)
36
36
  file_name = "%s/%s" % (test_logpath, self.logfile_name)
37
- basic_info_file = open(file_name, "w+", "utf-8")
37
+ basic_info_file = open(file_name, mode="w+", encoding="utf-8")
38
38
  self.__log_test_error_data(basic_info_file, test, err, "Error")
39
39
  basic_info_file.close()
40
40