seleniumbase 4.33.5__py3-none-any.whl → 4.33.7__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.
@@ -268,6 +268,7 @@ class CDPMethods():
268
268
  if number < 0:
269
269
  number = 0
270
270
  element = elements[number]
271
+ element.scroll_into_view()
271
272
  element.click()
272
273
 
273
274
  def click_nth_visible_element(self, selector, number):
@@ -284,6 +285,7 @@ class CDPMethods():
284
285
  if number < 0:
285
286
  number = 0
286
287
  element = elements[number]
288
+ element.scroll_into_view()
287
289
  element.click()
288
290
 
289
291
  def click_link(self, link_text):
@@ -311,6 +313,13 @@ class CDPMethods():
311
313
  return result
312
314
 
313
315
  def __flash(self, element, *args, **kwargs):
316
+ element.scroll_into_view()
317
+ if len(args) < 3 and "x_offset" not in kwargs:
318
+ x_offset = self.__get_x_scroll_offset()
319
+ kwargs["x_offset"] = x_offset
320
+ if len(args) < 3 and "y_offset" not in kwargs:
321
+ y_offset = self.__get_y_scroll_offset()
322
+ kwargs["y_offset"] = y_offset
314
323
  return (
315
324
  self.loop.run_until_complete(
316
325
  element.flash_async(*args, **kwargs)
@@ -382,9 +391,9 @@ class CDPMethods():
382
391
  )
383
392
 
384
393
  def __scroll_into_view(self, element):
385
- return (
386
- self.loop.run_until_complete(element.scroll_into_view_async())
387
- )
394
+ self.loop.run_until_complete(element.scroll_into_view_async())
395
+ self.__add_light_pause()
396
+ return None
388
397
 
389
398
  def __select_option(self, element):
390
399
  return (
@@ -431,6 +440,18 @@ class CDPMethods():
431
440
  self.loop.run_until_complete(element.get_js_attributes_async())
432
441
  )
433
442
 
443
+ def __get_x_scroll_offset(self):
444
+ x_scroll_offset = self.loop.run_until_complete(
445
+ self.page.evaluate("window.pageXOffset")
446
+ )
447
+ return x_scroll_offset or 0
448
+
449
+ def __get_y_scroll_offset(self):
450
+ y_scroll_offset = self.loop.run_until_complete(
451
+ self.page.evaluate("window.pageYOffset")
452
+ )
453
+ return y_scroll_offset or 0
454
+
434
455
  def tile_windows(self, windows=None, max_columns=0):
435
456
  """Tile windows and return the grid of tiled windows."""
436
457
  driver = self.driver
@@ -504,7 +525,7 @@ class CDPMethods():
504
525
  def click(self, selector, timeout=settings.SMALL_TIMEOUT):
505
526
  self.__slow_mode_pause_if_set()
506
527
  element = self.find_element(selector, timeout=timeout)
507
- self.__add_light_pause()
528
+ element.scroll_into_view()
508
529
  element.click()
509
530
  self.__slow_mode_pause_if_set()
510
531
  self.loop.run_until_complete(self.page.wait())
@@ -518,7 +539,9 @@ class CDPMethods():
518
539
 
519
540
  def click_if_visible(self, selector):
520
541
  if self.is_element_visible(selector):
521
- self.find_element(selector).click()
542
+ element = self.find_element(selector)
543
+ element.scroll_into_view()
544
+ element.click()
522
545
  self.__slow_mode_pause_if_set()
523
546
  self.loop.run_until_complete(self.page.wait())
524
547
 
@@ -545,9 +568,10 @@ class CDPMethods():
545
568
  except Exception:
546
569
  continue
547
570
  if (width != 0 or height != 0):
571
+ element.scroll_into_view()
548
572
  element.click()
549
573
  click_count += 1
550
- time.sleep(0.044)
574
+ time.sleep(0.042)
551
575
  self.__slow_mode_pause_if_set()
552
576
  self.loop.run_until_complete(self.page.wait())
553
577
  except Exception:
@@ -557,7 +581,7 @@ class CDPMethods():
557
581
  """(Attempt simulating a mouse click)"""
558
582
  self.__slow_mode_pause_if_set()
559
583
  element = self.find_element(selector, timeout=timeout)
560
- self.__add_light_pause()
584
+ element.scroll_into_view()
561
585
  element.mouse_click()
562
586
  self.__slow_mode_pause_if_set()
563
587
  self.loop.run_until_complete(self.page.wait())
@@ -579,6 +603,7 @@ class CDPMethods():
579
603
 
580
604
  def select_option_by_text(self, dropdown_selector, option):
581
605
  element = self.find_element(dropdown_selector)
606
+ element.scroll_into_view()
582
607
  options = element.query_selector_all("option")
583
608
  for found_option in options:
584
609
  if found_option.text.strip() == option.strip():
@@ -599,7 +624,10 @@ class CDPMethods():
599
624
  """Paint a quickly-vanishing dot over an element."""
600
625
  selector = self.__convert_to_css_if_xpath(selector)
601
626
  element = self.find_element(selector)
602
- element.flash(duration=duration, color=color)
627
+ element.scroll_into_view()
628
+ x_offset = self.__get_x_scroll_offset()
629
+ y_offset = self.__get_y_scroll_offset()
630
+ element.flash(duration, color, x_offset, y_offset)
603
631
  if pause and isinstance(pause, (int, float)):
604
632
  time.sleep(pause)
605
633
 
@@ -607,17 +635,22 @@ class CDPMethods():
607
635
  """Highlight an element with multi-colors."""
608
636
  selector = self.__convert_to_css_if_xpath(selector)
609
637
  element = self.find_element(selector)
610
- element.flash(0.46, "44CC88")
638
+ element.scroll_into_view()
639
+ x_offset = self.__get_x_scroll_offset()
640
+ y_offset = self.__get_y_scroll_offset()
641
+ element.flash(0.46, "44CC88", x_offset, y_offset)
611
642
  time.sleep(0.15)
612
- element.flash(0.42, "8844CC")
643
+ element.flash(0.42, "8844CC", x_offset, y_offset)
613
644
  time.sleep(0.15)
614
- element.flash(0.38, "CC8844")
645
+ element.flash(0.38, "CC8844", x_offset, y_offset)
615
646
  time.sleep(0.15)
616
- element.flash(0.30, "44CC88")
647
+ element.flash(0.30, "44CC88", x_offset, y_offset)
617
648
  time.sleep(0.30)
618
649
 
619
650
  def focus(self, selector):
620
- self.find_element(selector).focus()
651
+ element = self.find_element(selector)
652
+ element.scroll_into_view()
653
+ element.focus()
621
654
 
622
655
  def highlight_overlay(self, selector):
623
656
  self.find_element(selector).highlight_overlay()
@@ -646,7 +679,7 @@ class CDPMethods():
646
679
  def send_keys(self, selector, text, timeout=settings.SMALL_TIMEOUT):
647
680
  self.__slow_mode_pause_if_set()
648
681
  element = self.select(selector, timeout=timeout)
649
- self.__add_light_pause()
682
+ element.scroll_into_view()
650
683
  if text.endswith("\n") or text.endswith("\r"):
651
684
  text = text[:-1] + "\r\n"
652
685
  element.send_keys(text)
@@ -657,7 +690,7 @@ class CDPMethods():
657
690
  """Similar to send_keys(), but presses keys at human speed."""
658
691
  self.__slow_mode_pause_if_set()
659
692
  element = self.select(selector, timeout=timeout)
660
- self.__add_light_pause()
693
+ element.scroll_into_view()
661
694
  submit = False
662
695
  if text.endswith("\n") or text.endswith("\r"):
663
696
  submit = True
@@ -675,7 +708,7 @@ class CDPMethods():
675
708
  """Similar to send_keys(), but clears the text field first."""
676
709
  self.__slow_mode_pause_if_set()
677
710
  element = self.select(selector, timeout=timeout)
678
- self.__add_light_pause()
711
+ element.scroll_into_view()
679
712
  with suppress(Exception):
680
713
  element.clear_input()
681
714
  if text.endswith("\n") or text.endswith("\r"):
@@ -688,8 +721,8 @@ class CDPMethods():
688
721
  """Similar to send_keys(), but clears the text field first."""
689
722
  self.__slow_mode_pause_if_set()
690
723
  selector = self.__convert_to_css_if_xpath(selector)
691
- self.select(selector, timeout=timeout)
692
- self.__add_light_pause()
724
+ element = self.select(selector, timeout=timeout)
725
+ element.scroll_into_view()
693
726
  press_enter = False
694
727
  if text.endswith("\n"):
695
728
  text = text[:-1]
@@ -1019,6 +1052,10 @@ class CDPMethods():
1019
1052
  with suppress(Exception):
1020
1053
  self.loop.run_until_complete(self.page.evaluate(js_code))
1021
1054
 
1055
+ def __make_sure_pyautogui_lock_is_writable(self):
1056
+ with suppress(Exception):
1057
+ shared_utils.make_writable(constants.MultiBrowser.PYAUTOGUILOCK)
1058
+
1022
1059
  def __verify_pyautogui_has_a_headed_browser(self):
1023
1060
  """PyAutoGUI requires a headed browser so that it can
1024
1061
  focus on the correct element when performing actions."""
@@ -1039,6 +1076,8 @@ class CDPMethods():
1039
1076
  constants.PipInstall.FINDLOCK
1040
1077
  )
1041
1078
  with pip_find_lock: # Prevent issues with multiple processes
1079
+ with suppress(Exception):
1080
+ shared_utils.make_writable(constants.PipInstall.FINDLOCK)
1042
1081
  try:
1043
1082
  import pyautogui
1044
1083
  with suppress(Exception):
@@ -1124,6 +1163,7 @@ class CDPMethods():
1124
1163
  constants.MultiBrowser.PYAUTOGUILOCK
1125
1164
  )
1126
1165
  with gui_lock:
1166
+ self.__make_sure_pyautogui_lock_is_writable()
1127
1167
  pyautogui.press(key)
1128
1168
  time.sleep(0.044)
1129
1169
  self.__slow_mode_pause_if_set()
@@ -1137,6 +1177,7 @@ class CDPMethods():
1137
1177
  constants.MultiBrowser.PYAUTOGUILOCK
1138
1178
  )
1139
1179
  with gui_lock:
1180
+ self.__make_sure_pyautogui_lock_is_writable()
1140
1181
  for key in keys:
1141
1182
  pyautogui.press(key)
1142
1183
  time.sleep(0.044)
@@ -1151,6 +1192,7 @@ class CDPMethods():
1151
1192
  constants.MultiBrowser.PYAUTOGUILOCK
1152
1193
  )
1153
1194
  with gui_lock:
1195
+ self.__make_sure_pyautogui_lock_is_writable()
1154
1196
  pyautogui.write(text)
1155
1197
  self.__slow_mode_pause_if_set()
1156
1198
  self.loop.run_until_complete(self.page.wait())
@@ -1171,6 +1213,7 @@ class CDPMethods():
1171
1213
  constants.MultiBrowser.PYAUTOGUILOCK
1172
1214
  )
1173
1215
  with gui_lock: # Prevent issues with multiple processes
1216
+ self.__make_sure_pyautogui_lock_is_writable()
1174
1217
  pyautogui.moveTo(x, y, timeframe, pyautogui.easeOutQuad)
1175
1218
  if timeframe >= 0.25:
1176
1219
  time.sleep(0.056) # Wait if moving at human-speed
@@ -1191,6 +1234,7 @@ class CDPMethods():
1191
1234
  constants.MultiBrowser.PYAUTOGUILOCK
1192
1235
  )
1193
1236
  with gui_lock: # Prevent issues with multiple processes
1237
+ self.__make_sure_pyautogui_lock_is_writable()
1194
1238
  self.__install_pyautogui_if_missing()
1195
1239
  import pyautogui
1196
1240
  pyautogui = self.__get_configured_pyautogui(pyautogui)
@@ -1408,6 +1452,7 @@ class CDPMethods():
1408
1452
  constants.MultiBrowser.PYAUTOGUILOCK
1409
1453
  )
1410
1454
  with gui_lock:
1455
+ self.__make_sure_pyautogui_lock_is_writable()
1411
1456
  self.bring_active_window_to_front()
1412
1457
  self.gui_hover_element(hover_selector)
1413
1458
  time.sleep(0.15)
@@ -1643,17 +1688,24 @@ class CDPMethods():
1643
1688
  raise Exception(error % (expected, actual))
1644
1689
 
1645
1690
  def assert_text(
1646
- self, text, selector="html", timeout=settings.SMALL_TIMEOUT
1691
+ self, text, selector="body", timeout=settings.SMALL_TIMEOUT
1647
1692
  ):
1693
+ start_ms = time.time() * 1000.0
1694
+ stop_ms = start_ms + (timeout * 1000.0)
1648
1695
  text = text.strip()
1649
1696
  element = None
1650
1697
  try:
1651
1698
  element = self.find_element(selector, timeout=timeout)
1652
1699
  except Exception:
1653
1700
  raise Exception("Element {%s} not found!" % selector)
1654
- for i in range(30):
1701
+ for i in range(int(timeout * 10)):
1702
+ with suppress(Exception):
1703
+ element = self.find_element(selector, timeout=0.1)
1655
1704
  if text in element.text_all:
1656
1705
  return True
1706
+ now_ms = time.time() * 1000.0
1707
+ if now_ms >= stop_ms:
1708
+ break
1657
1709
  time.sleep(0.1)
1658
1710
  raise Exception(
1659
1711
  "Text {%s} not found in {%s}! Actual text: {%s}"
@@ -1661,20 +1713,27 @@ class CDPMethods():
1661
1713
  )
1662
1714
 
1663
1715
  def assert_exact_text(
1664
- self, text, selector="html", timeout=settings.SMALL_TIMEOUT
1716
+ self, text, selector="body", timeout=settings.SMALL_TIMEOUT
1665
1717
  ):
1718
+ start_ms = time.time() * 1000.0
1719
+ stop_ms = start_ms + (timeout * 1000.0)
1666
1720
  text = text.strip()
1667
1721
  element = None
1668
1722
  try:
1669
1723
  element = self.select(selector, timeout=timeout)
1670
1724
  except Exception:
1671
1725
  raise Exception("Element {%s} not found!" % selector)
1672
- for i in range(30):
1726
+ for i in range(int(timeout * 10)):
1727
+ with suppress(Exception):
1728
+ element = self.select(selector, timeout=0.1)
1673
1729
  if (
1674
1730
  self.is_element_visible(selector)
1675
1731
  and text.strip() == element.text_all.strip()
1676
1732
  ):
1677
1733
  return True
1734
+ now_ms = time.time() * 1000.0
1735
+ if now_ms >= stop_ms:
1736
+ break
1678
1737
  time.sleep(0.1)
1679
1738
  raise Exception(
1680
1739
  "Expected Text {%s}, is not equal to {%s} in {%s}!"
@@ -1715,26 +1774,31 @@ class CDPMethods():
1715
1774
  with suppress(Exception):
1716
1775
  self.loop.run_until_complete(self.page.evaluate(js_code))
1717
1776
  self.loop.run_until_complete(self.page.wait())
1777
+ self.__add_light_pause()
1718
1778
 
1719
1779
  def scroll_to_top(self):
1720
1780
  js_code = "window.scrollTo(0, 0);"
1721
1781
  with suppress(Exception):
1722
1782
  self.loop.run_until_complete(self.page.evaluate(js_code))
1723
1783
  self.loop.run_until_complete(self.page.wait())
1784
+ self.__add_light_pause()
1724
1785
 
1725
1786
  def scroll_to_bottom(self):
1726
1787
  js_code = "window.scrollTo(0, 10000);"
1727
1788
  with suppress(Exception):
1728
1789
  self.loop.run_until_complete(self.page.evaluate(js_code))
1729
1790
  self.loop.run_until_complete(self.page.wait())
1791
+ self.__add_light_pause()
1730
1792
 
1731
1793
  def scroll_up(self, amount=25):
1732
1794
  self.loop.run_until_complete(self.page.scroll_up(amount))
1733
1795
  self.loop.run_until_complete(self.page.wait())
1796
+ self.__add_light_pause()
1734
1797
 
1735
1798
  def scroll_down(self, amount=25):
1736
1799
  self.loop.run_until_complete(self.page.scroll_down(amount))
1737
1800
  self.loop.run_until_complete(self.page.wait())
1801
+ self.__add_light_pause()
1738
1802
 
1739
1803
  def save_screenshot(self, name, folder=None, selector=None):
1740
1804
  filename = name
@@ -1,4 +1,5 @@
1
1
  import sys
2
+ import textwrap
2
3
  from seleniumbase.fixtures import constants
3
4
 
4
5
 
@@ -116,6 +117,7 @@ def get_report_style():
116
117
  }
117
118
  </style>"""
118
119
  )
120
+ style = textwrap.dedent(style)
119
121
  Saved.report_style = style
120
122
  return style
121
123
 
@@ -132,6 +134,7 @@ def get_bt_backdrop_style():
132
134
  box-shadow: 0 0 0 88422px rgba(0, 0, 0, 0.42);
133
135
  pointer-events: auto !important;
134
136
  }"""
137
+ bt_backdrop_style = textwrap.dedent(bt_backdrop_style)
135
138
  Saved.bt_backdrop_style = bt_backdrop_style
136
139
  return bt_backdrop_style
137
140
 
@@ -150,6 +153,7 @@ def get_dt_backdrop_style():
150
153
  button.driver-prev-btn.driver-disabled {
151
154
  visibility: hidden;
152
155
  }"""
156
+ dt_backdrop_style = textwrap.dedent(dt_backdrop_style)
153
157
  Saved.dt_backdrop_style = dt_backdrop_style
154
158
  return dt_backdrop_style
155
159
 
@@ -167,6 +171,7 @@ def get_messenger_style():
167
171
  box-shadow: 2px 2px 9px 4px rgba(32, 142, 120, 0.28),
168
172
  2px 2px 9px 4px rgba(200, 240, 80, 0.34) !important;
169
173
  }""" % font_family
174
+ messenger_style = textwrap.dedent(messenger_style)
170
175
  Saved.messenger_style = messenger_style
171
176
  return messenger_style
172
177
 
@@ -181,6 +186,7 @@ def get_sh_style_test():
181
186
  scrollTo: true
182
187
  }
183
188
  });"""
189
+ sh_style_test = textwrap.dedent(sh_style_test)
184
190
  Saved.sh_style_test = sh_style_test
185
191
  return sh_style_test
186
192
 
@@ -193,6 +199,7 @@ def get_hops_backdrop_style():
193
199
  .hopscotch-bubble-container {
194
200
  font-size: 110%;
195
201
  }"""
202
+ hops_backdrop_style = textwrap.dedent(hops_backdrop_style)
196
203
  Saved.hops_backdrop_style = hops_backdrop_style
197
204
  return hops_backdrop_style
198
205
 
@@ -227,6 +234,7 @@ def get_introjs_style():
227
234
  box-sizing: content-box;
228
235
  position: absolute;
229
236
  }"""
237
+ introjs_style = textwrap.dedent(introjs_style)
230
238
  Saved.introjs_style = introjs_style
231
239
  return introjs_style
232
240
 
@@ -261,6 +269,7 @@ def get_sh_backdrop_style():
261
269
  body.shepherd-active {
262
270
  pointer-events: none !important;
263
271
  }"""
272
+ sh_backdrop_style = textwrap.dedent(sh_backdrop_style)
264
273
  Saved.sh_backdrop_style = sh_backdrop_style
265
274
  return sh_backdrop_style
266
275
 
@@ -387,5 +396,6 @@ def get_pytest_style():
387
396
  .desc.active .sort-icon {
388
397
  border-top: 8px solid #999;
389
398
  }"""
399
+ pytest_style = textwrap.dedent(pytest_style)
390
400
  Saved.pytest_style = pytest_style
391
401
  return pytest_style