setup-selenium-testing 0.2.0__py3-none-any.whl → 1.0.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,14 +2,12 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import errno
6
5
  import logging
7
6
  import os as os
8
7
  from enum import Enum
9
8
  from typing import TYPE_CHECKING, Optional, Union
10
9
 
11
10
  from selenium import __version__, webdriver
12
- from selenium.common.exceptions import NoSuchWindowException, WebDriverException
13
11
  from selenium.webdriver.chrome.service import Service as ChromeService
14
12
  from selenium.webdriver.common.selenium_manager import SeleniumManager
15
13
  from selenium.webdriver.edge.service import Service as EdgeService
@@ -18,7 +16,6 @@ from semantic_version import Version # type: ignore[import-untyped]
18
16
  from typing_extensions import TypeAlias
19
17
 
20
18
  if TYPE_CHECKING:
21
- from collections.abc import Mapping
22
19
 
23
20
  from selenium.webdriver import Chrome, Edge, Firefox
24
21
  from selenium.webdriver.common.options import ArgOptions
@@ -68,27 +65,10 @@ class Browser(str, Enum):
68
65
  ################################################################################
69
66
  ################################################################################
70
67
  class SetupSelenium:
71
- DIMENSIONS: Mapping[str, tuple[int, int]] = {
72
- # ratio 4:3
73
- "1024": (1024, 768),
74
- "1280": (1280, 960),
75
- "1600": (1600, 1200),
76
- "1920": (1920, 1440),
77
- # ratio 16:9
78
- "720": (1280, 720),
79
- "1080": (1920, 1080),
80
- "1440": (2560, 1440),
81
- "2160": (3840, 2160), # 4k
82
- "4320": (7680, 4320), # 8k
83
- }
84
-
85
68
  def __init__(
86
69
  self,
87
70
  browser: Browser = Browser.CHROME,
88
- baseurl: str = "",
89
- timeout: int = 15,
90
71
  headless: bool = False,
91
- window_size: str = "720",
92
72
  enable_log_performance: bool = False,
93
73
  enable_log_console: bool = False,
94
74
  enable_log_driver: bool = False,
@@ -99,11 +79,6 @@ class SetupSelenium:
99
79
  browser_path: str | None = None,
100
80
  ) -> None:
101
81
  log_path = os.path.abspath(os.path.expanduser(log_path))
102
- self.main_window_handle: str = ""
103
- self.screenshot_path: str = self.make_screenshot_path(log_path)
104
- self.log_path: str = log_path
105
- self.timeout: int = timeout
106
- self.baseurl: str = baseurl
107
82
 
108
83
  if driver_path:
109
84
  driver_path = os.path.abspath(os.path.expanduser(driver_path))
@@ -131,35 +106,11 @@ class SetupSelenium:
131
106
  driver_path=driver_path,
132
107
  )
133
108
 
134
- # driver must be setup before the following
135
- self.driver.set_window_position(0, 0)
136
- self.set_window_size(window_size)
137
- self.set_main_window_handle()
138
-
139
- ############################################################################
140
- @staticmethod
141
- def make_screenshot_path(
142
- output_dir: str = "./logs", screenshots: str = "screenshots"
143
- ) -> str:
144
- """Set the output directory for where screenshots should go."""
145
- output_dir = os.path.abspath(os.path.expanduser(output_dir))
146
- if os.path.split(output_dir)[-1].lower() != screenshots:
147
- output_dir = os.path.join(output_dir, screenshots)
148
-
149
- try:
150
- os.makedirs(output_dir)
151
- except OSError as e:
152
- if e.errno == errno.EEXIST and os.path.isdir(output_dir):
153
- pass
154
- else:
155
- raise
156
-
157
- return output_dir
158
-
159
109
  ############################################################################
160
110
  @staticmethod
161
111
  def log_options(options: ArgOptions) -> None:
162
112
  """Logs the browser option in clean format"""
113
+ # logger.debug(f"{json.dumps(options.capabilities, indent=2)}") # noqa: ERA001
163
114
  opts = "\n".join(options.arguments)
164
115
  logger.debug(f"{opts}")
165
116
 
@@ -282,6 +233,24 @@ class SetupSelenium:
282
233
  options.set_preference(
283
234
  "extensions.formautofill.addresses.capture.enabled", False
284
235
  )
236
+ # By default, headless Firefox runs as though no pointers capabilities
237
+ # are available.
238
+ # https://github.com/microsoft/playwright/issues/7769#issuecomment-966098074
239
+ #
240
+ # This impacts React Spectrum which uses an '(any-pointer: fine)'
241
+ # media query to determine font size. It also causes certain chart
242
+ # elements to always be visible that should only be visible on
243
+ # hover.
244
+ #
245
+ # Available values for pointer capabilities:
246
+ # NO_POINTER 0x00
247
+ # COARSE_POINTER 0x01
248
+ # FINE_POINTER 0x02
249
+ # HOVER_CAPABLE_POINTER 0x04
250
+ #
251
+ # Setting to 0x02 | 0x04 says the system supports a mouse
252
+ options.set_preference("ui.primaryPointerCapabilities", 0x02 | 0x04)
253
+ options.set_preference("ui.allPointerCapabilities", 0x02 | 0x04)
285
254
  return options
286
255
 
287
256
  @staticmethod
@@ -338,9 +307,29 @@ class SetupSelenium:
338
307
  def chrome_options() -> webdriver.ChromeOptions:
339
308
  """Default options for chrome"""
340
309
  logger.debug("Setting up chrome options")
310
+ # the ultimate list of flags (created by the chromium dev group)
311
+ # https://peter.sh/experiments/chromium-command-line-switches/
312
+
341
313
  # The list of options set below mostly came from this StackOverflow post
342
314
  # https://stackoverflow.com/q/48450594/2532408
343
315
  opts = (
316
+ # "--disable-features=ImprovedCookieControls,LazyFrameLoading,GlobalMediaControls,DestroyProfileOnBrowserClose,MediaRouter,DialMediaRouteProvider,AcceptCHFrame,AutoExpandDetailsElement,CertificateTransparencyComponentUpdater,AvoidUnnecessaryBeforeUnloadCheckSync", # noqa: ERA001
317
+ "--disable-back-forward-cache",
318
+ "--disable-background-timer-throttling",
319
+ "--disable-breakpad",
320
+ "--disable-component-extensions-with-background-pages",
321
+ "--disable-ipc-flooding-protection",
322
+ "--enable-features=NetworkService,NetworkServiceInProcess",
323
+ "--enable-logging",
324
+ "--export-tagged-pdf",
325
+ "--force-color-profile=srgb",
326
+ "--metrics-recording-only",
327
+ "--mute-audio",
328
+ "--remote-debugging-pipe",
329
+ # fixes MUI fade issue
330
+ "--disable-renderer-backgrounding",
331
+ # fixes actionchains in headless
332
+ "--disable-backgrounding-occluded-windows",
344
333
  "--disable-extensions",
345
334
  "--allow-running-insecure-content",
346
335
  "--ignore-certificate-errors",
@@ -378,7 +367,7 @@ class SetupSelenium:
378
367
  options.binary_location = binary
379
368
 
380
369
  if headless:
381
- options.add_argument("--headless")
370
+ options.add_argument("--headless=new")
382
371
 
383
372
  logging_prefs = {"browser": "OFF", "performance": "OFF", "driver": "OFF"}
384
373
 
@@ -475,9 +464,29 @@ class SetupSelenium:
475
464
  def edge_options() -> webdriver.EdgeOptions:
476
465
  """Default options for edgedriver"""
477
466
  logger.debug("Setting up edge options")
467
+ # the ultimate list of flags (created by the chromium dev group)
468
+ # https://peter.sh/experiments/chromium-command-line-switches/
469
+
478
470
  # The list of options set below mostly came from this StackOverflow post
479
471
  # https://stackoverflow.com/q/48450594/2532408
480
472
  opts = (
473
+ # "--disable-features=ImprovedCookieControls,LazyFrameLoading,GlobalMediaControls,DestroyProfileOnBrowserClose,MediaRouter,DialMediaRouteProvider,AcceptCHFrame,AutoExpandDetailsElement,CertificateTransparencyComponentUpdater,AvoidUnnecessaryBeforeUnloadCheckSync", # noqa: ERA001
474
+ "--disable-back-forward-cache",
475
+ "--disable-background-timer-throttling",
476
+ "--disable-breakpad",
477
+ "--disable-component-extensions-with-background-pages",
478
+ "--disable-ipc-flooding-protection",
479
+ "--enable-features=NetworkService,NetworkServiceInProcess",
480
+ "--enable-logging",
481
+ "--export-tagged-pdf",
482
+ "--force-color-profile=srgb",
483
+ "--metrics-recording-only",
484
+ "--mute-audio",
485
+ "--remote-debugging-pipe",
486
+ # fixes MUI fade issue
487
+ "--disable-renderer-backgrounding",
488
+ # fixes actionchains in headless
489
+ "--disable-backgrounding-occluded-windows",
481
490
  "--disable-extensions",
482
491
  "--allow-running-insecure-content",
483
492
  "--ignore-certificate-errors",
@@ -523,12 +532,11 @@ class SetupSelenium:
523
532
  # by default performance is disabled.
524
533
  if enable_log_performance:
525
534
  logging_prefs["performance"] = "ALL"
526
- options.set_capability(
535
+ options.add_experimental_option(
527
536
  "perfLoggingPrefs",
528
537
  {
529
538
  "enableNetwork": True,
530
539
  "enablePage": False,
531
- "enableTimeline": False,
532
540
  },
533
541
  )
534
542
 
@@ -579,42 +587,3 @@ class SetupSelenium:
579
587
  logger.info(bsrmsg)
580
588
  SetupSelenium.log_options(options)
581
589
  return driver
582
-
583
- ############################################################################
584
- def set_window_size(self, size: str = "720") -> None:
585
- """Helper to set the window size after driver has been instantiated."""
586
- if size == "max":
587
- self.driver.maximize_window()
588
- return
589
-
590
- width, height = SetupSelenium.DIMENSIONS.get(
591
- size, SetupSelenium.DIMENSIONS.get(size, (1280, 720))
592
- )
593
- self.driver.set_window_size(width, height)
594
-
595
- def set_main_window_handle(self, window: str | None = None) -> str:
596
- """
597
- Maintains the initial window handle as an attribute
598
-
599
- Most users will never utilize this. It's part of a legacy requirement for
600
- an old test suite
601
- """
602
- # does the main_window_handle exist and point to an available window?
603
- if not window and not self.main_window_handle:
604
- try:
605
- window = self.driver.current_window_handle
606
- except NoSuchWindowException:
607
- try:
608
- window = self.driver.window_handles[0]
609
- except WebDriverException: # noqa: TRY203
610
- # Have we closed all the windows?
611
- raise
612
- if window:
613
- self.main_window_handle = window
614
- return self.main_window_handle
615
-
616
- ############################################################################
617
- def __repr__(self) -> str:
618
- browser = self.driver.name if self.driver is not None else "NoBrowserSet"
619
- url = self.baseurl
620
- return f"{self.__class__.__name__} :: {browser} -> {url}"
@@ -1,18 +1,16 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: setup-selenium-testing
3
- Version: 0.2.0
3
+ Version: 1.0.0
4
4
  Summary: Setup Selenium for automation testing
5
- Home-page: https://github.com/bandophahita/setup_selenium
6
5
  License: MIT
7
6
  Author: Marcel Wilson
8
7
  Author-email: trenchrats+pypi@gmail.com
9
- Requires-Python: >=3.8,<4.0
8
+ Requires-Python: >=3.9,<4.0
10
9
  Classifier: Intended Audience :: Developers
11
10
  Classifier: License :: OSI Approved :: MIT License
12
11
  Classifier: Natural Language :: English
13
12
  Classifier: Operating System :: OS Independent
14
13
  Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.8
16
14
  Classifier: Programming Language :: Python :: 3.9
17
15
  Classifier: Programming Language :: Python :: 3.10
18
16
  Classifier: Programming Language :: Python :: 3.11
@@ -52,7 +50,42 @@ in every project. Time to consolidate.
52
50
  [![Build Status](https://github.com/bandophahita/setup_selenium/actions/workflows/lint.yml/badge.svg)](https://github.com/bandophahita/setup_selenium/actions/workflows/lint.yml)
53
51
 
54
52
 
55
- # Basic usage
53
+ # Instantiating SetupSelenium
54
+
55
+ This will automatically handle any downloading of drivers or browsers via `SeleniumManager`
56
+
57
+ ```python
58
+ from setup_selenium import SetupSelenium
59
+
60
+ s = SetupSelenium(headless=True)
61
+ assert s.driver.service.is_connectable()
62
+ ```
63
+
64
+ Advanced usage:
65
+
66
+ ```python
67
+ from setup_selenium import Browser, SetupSelenium
68
+
69
+ s = SetupSelenium(Browser.FIREFOX, headless=True, driver_version="118.0.5993.70")
70
+ s = SetupSelenium(Browser.CHROME, headless=True, driver_version="118.0.5993.70",
71
+ driver_path="/path/to/webdriver"
72
+ )
73
+ ```
74
+
75
+ > [!NOTE]
76
+ > Version and path arguments follow the logic of
77
+ > [SeleniumManager](https://www.selenium.dev/documentation/selenium_manager/).
78
+ > Caution is advised in cases where version and path do not match.
79
+ > See their documentation.
80
+
81
+ # Install Driver only
82
+ ```python
83
+ from setup_selenium import Browser, SetupSelenium
84
+
85
+ driver_path, browser_path = SetupSelenium.install_driver(Browser.CHROME, driver_version="118.0.5993.70")
86
+ ```
87
+
88
+ # Create driver only
56
89
 
57
90
  ```python
58
91
  from setup_selenium import Browser, SetupSelenium
@@ -60,7 +93,8 @@ from setup_selenium import Browser, SetupSelenium
60
93
  driver = SetupSelenium.create_driver(browser=Browser.CHROME, headless=True)
61
94
  ```
62
95
 
63
- # Advanced usage
96
+ Advanced usage:
97
+
64
98
  ```python
65
99
  from setup_selenium import Browser, SetupSelenium
66
100
 
@@ -77,19 +111,11 @@ driver = SetupSelenium.create_driver(
77
111
  ```
78
112
 
79
113
  > [!NOTE]
80
- > It is possible to enable the performance and console logging
114
+ > It is possible to enable the performance and console logging
81
115
  > but only for chrome based browsers. This only enables the browser ability.
82
116
  > It is up to the tester to handle logging the messages.
83
117
 
84
118
 
85
-
86
- # Driver installation
87
- ```python
88
- from setup_selenium import Browser, SetupSelenium
89
-
90
- driver_path, browser_path = SetupSelenium.install_driver(Browser.CHROME, "118.0.5993.70")
91
- ```
92
-
93
119
  # Custom logger
94
120
  ```python
95
121
  import logging
@@ -99,18 +125,6 @@ set_logger(logging.getLogger("your_custom_logger"))
99
125
  driver = SetupSelenium.create_driver(browser=Browser.CHROME, headless=True)
100
126
  ```
101
127
 
102
- # Instantiating SetupSelenium
103
- While it is possible to use the class directly caution is advised; as the class
104
- will create the driver upon instantiation.
105
-
106
- ```python
107
- from setup_selenium import SetupSelenium
108
-
109
- s = SetupSelenium(headless=True)
110
- assert s.driver.service.is_connectable()
111
- ```
112
-
113
-
114
128
  # Automatic driver and browser installation
115
129
  This package not only handles setup of the webdriver but also will
116
130
  automatically install the webdriver and/or browser depending on your
@@ -0,0 +1,7 @@
1
+ setup_selenium/__init__.py,sha256=-w9Vvo72ZLaEyIEfc_Nh0bDDJz9W0pOy4rkRXurIJHI,63
2
+ setup_selenium/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ setup_selenium/setup_selenium.py,sha256=6IijZ0maMo7t3_W1vUyn0l2SnEi8vsZoVZRUeQmu5kA,21834
4
+ setup_selenium_testing-1.0.0.dist-info/LICENSE,sha256=KGdE-1D1chm3UNFtfE8x-EpVxhmv2zFx8oltbO8M1qE,1070
5
+ setup_selenium_testing-1.0.0.dist-info/METADATA,sha256=N0t4a2Zf4wGPcc6lVTtdpFDlSDQ2QsgCUF1lhsP6Kjs,5847
6
+ setup_selenium_testing-1.0.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
7
+ setup_selenium_testing-1.0.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.0.0
2
+ Generator: poetry-core 2.1.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,7 +0,0 @@
1
- setup_selenium/__init__.py,sha256=-w9Vvo72ZLaEyIEfc_Nh0bDDJz9W0pOy4rkRXurIJHI,63
2
- setup_selenium/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- setup_selenium/setup_selenium.py,sha256=asqQhE6fXcivb2MK3PL90TcQcCBVr_2Mgx-_CULxfUk,21921
4
- setup_selenium_testing-0.2.0.dist-info/LICENSE,sha256=KGdE-1D1chm3UNFtfE8x-EpVxhmv2zFx8oltbO8M1qE,1070
5
- setup_selenium_testing-0.2.0.dist-info/METADATA,sha256=0asqR9fuACtsQwpq_LcFCI38lB6ALuCtS7LcCFn_l8M,5413
6
- setup_selenium_testing-0.2.0.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
7
- setup_selenium_testing-0.2.0.dist-info/RECORD,,