Skip to content

implement class methods for SauceOptions #266

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions python/saucebindings/configs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
class Configs:
base_configs = {
'platform_name': 'platformName',
'name': 'name',
'build': 'build',
'tags': 'tags',
'custom_data': 'customData',
'public': 'public',
'tunnel_identifier': 'tunnelIdentifier',
'parent_tunnel': 'parentTunnel'
}

vdc_configs = {
'browser_version': 'browserVersion',
'page_load_strategy': 'pageLoadStrategy',
'accept_insecure_certs': 'acceptInsecureCerts',
'proxy': 'proxy',
'strict_file_interactability': 'strictFileInteractability',
'unhandled_prompt_behavior': 'unhandledPromptBehavior',
'timeouts': 'timeouts',
'record_video': 'recordVideo',
'video_upload_on_pass': 'videoUploadOnPass',
'record_screenshots': 'recordScreenshots',
'record_logs': 'recordLogs',
'max_duration': 'maxDuration',
'command_timeout': 'commandTimeout',
'idle_timeout': 'idleTimeout',
'prerun': 'prerun',
'priority': 'priority',
'screen_resolution': 'screenResolution',
'time_zone': 'timeZone'
}

chrome_configs = {
'chromedriver_version': 'chromedriverVersion',
'extended_debugging': 'extendedDebugging',
'capture_performance': 'capturePerformance',
'set_window_rect': 'setWindowRect'
}

edge_configs = {
'edgedriver_version': 'edgedriverVersion',
'selenium_version': 'seleniumVersion',
'set_window_rect': 'setWindowRect'
}

firefox_configs = {
'geckodriver_version': 'geckodriverVersion',
'extended_debugging': 'extendedDebugging',
'selenium_version': 'seleniumVersion',
'set_window_rect': 'setWindowRect'
}

ie_configs = {
'iedriver_version': 'iedriverVersion',
'avoid_proxy': 'avoidProxy',
'selenium_version': 'seleniumVersion',
'set_window_rect': 'setWindowRect'
}

safari_configs = {
'avoid_proxy': 'avoidProxy',
'selenium_version': 'seleniumVersion',
'set_window_rect': 'setWindowRect'
}

def vdcConfigs(self):
return {**(self).base_configs, **self.vdc_configs}

def chromeConfigs(self):
return {**self.vdcConfigs(), **self.chrome_configs}

def edgeConfigs(self):
return {**self.vdcConfigs(), **self.edge_configs}

def firefoxConfigs(self):
return {**self.vdcConfigs(), **self.firefox_configs}

def ieConfigs(self):
return {**self.vdcConfigs(), **self.ie_configs}

def safariConfigs(self):
return {**self.vdcConfigs(), **self.safari_configs}
81 changes: 58 additions & 23 deletions python/saucebindings/options.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.firefox.options import Options as FirefoxOptions
from selenium.webdriver.edge.options import Options as EdgeOptions
from selenium.webdriver.ie.options import Options as IEOptions
import warnings
from datetime import datetime

from .configs import *
from selenium.webdriver import __version__ as seleniumVersion
import os


Expand All @@ -25,7 +25,9 @@
'chromedriver_version': 'chromedriverVersion',
'command_timeout': 'commandTimeout',
'custom_data': 'customData',
'edgedriver_version': 'edgedriverVersion',
'extended_debugging': 'extendedDebugging',
'geckodriver_version': 'geckodriverVersion',
'idle_timeout': 'idleTimeout',
'iedriver_version': 'iedriverVersion',
'max_duration': 'maxDuration',
Expand All @@ -46,15 +48,30 @@
'capture_performance': 'capturePerformance'
}

browser_names = {
FirefoxOptions: 'firefox',
ChromeOptions: 'chrome',
IEOptions: 'internet explorer',
EdgeOptions: 'MicrosoftEdge'
}
class SauceOptions(object):

@classmethod
def chrome(cls, **kwargs):
return cls('chrome', validOptions=Configs().chromeConfigs(), **kwargs)

@classmethod
def edge(cls, **kwargs):
if seleniumVersion[0] == '3':
raise NotImplementedError('Selenium 3 does not support Chromium Edge. Look for SauceBindings Support of '
'Selenium 4 soon.')
return cls('MicrosoftEdge', validOptions=Configs().edgeConfigs(), **kwargs)

@classmethod
def firefox(cls, **kwargs):
return cls('firefox', validOptions=Configs().firefoxConfigs(), **kwargs)

class SauceOptions:
@classmethod
def ie(cls, **kwargs):
return cls('internet explorer', validOptions=Configs().ieConfigs(), **kwargs)

@classmethod
def safari(cls, **kwargs):
return cls('safari', validOptions=Configs().safariConfigs(), **kwargs)

def _set_default_build_name(self):
if 'build' in self.options['sauce:options']:
Expand Down Expand Up @@ -83,18 +100,26 @@ def _set_default_build_name(self):
else:
self.build = 'Build Time: {}'.format(datetime.utcnow())

def __init__(self, browserName=None, **kwargs):
def __init__(self, browserName=None, validOptions=None, seleniumOptions=None, **kwargs):
super(SauceOptions, self).__setattr__('options', {'sauce:options': {}})
super(SauceOptions, self).__setattr__('seleniumOptions', {})
super(SauceOptions, self).__setattr__('seleniumOpts', {})
if validOptions == None:
warnings.warn('Options() is deprecated, use class methods like Options.chrome() instead',
DeprecationWarning)
validOptions = {**w3c_configs, **sauce_configs}
super(SauceOptions, self).__setattr__('validOptions', validOptions)

for key, value in kwargs.items():
if key == 'seleniumOptions':
if isinstance(value, tuple(browser_names)):
self.set_capability('browserName', browser_names[type(value)])
if self.validOptions == None:
self.validOptions = {**w3c_configs, **sauce_configs}

self.seleniumOptions['caps'] = value.to_capabilities()
else:
self.set_capability(key, value)
self.validateOptions(kwargs)

if seleniumOptions is not None:
self.set_capability('browserName', seleniumOptions.capabilities['browserName'])
self.seleniumOpts['caps'] = seleniumOptions.to_capabilities()

for key, value in kwargs.items():
self.set_capability(key, value)

if self.browser_version is None:
self.set_capability('browserVersion', 'latest')
Expand All @@ -112,12 +137,15 @@ def __init__(self, browserName=None, **kwargs):
self._set_default_build_name()

def __setattr__(self, key, value):
self.set_option(key, value)
if (self.validOptions == None and key == 'validOptions') or key in self.validOptions.keys():
self.set_option(key, value)
else:
raise AttributeError('parameter ' + key + ' not available for this configuration')

def __getattr__(self, key):
if key == 'selenium_options':
if 'caps' in self.seleniumOptions.keys():
return self.seleniumOptions['caps']
if 'caps' in self.seleniumOpts.keys():
return self.seleniumOpts['caps']
else:
return None
try:
Expand All @@ -130,8 +158,15 @@ def __getattr__(self, key):
except KeyError:
return None

def validateOptions(self, kwargs):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like method needs to be moved up to be defined before __init__

for k in kwargs.keys():
if k not in self.validOptions.values():
raise AttributeError('parameter ' + k + ' not available for this configuration')

def merge_capabilities(self, capabilities):
for key, value in capabilities.items():
if key not in self.validOptions.values():
raise AttributeError('parameter ' + key + ' not available for this configuration')
self.set_capability(key, value)

# Sets with camelCase
Expand Down
2 changes: 1 addition & 1 deletion python/saucebindings/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
class SauceSession():

def __init__(self, options=None, data_center='us-west', resolve_ip=False):
self.options = options if options else SauceOptions()
self.options = options if options else SauceOptions.chrome()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually a bit better for being explicit, so good job here

self._username = os.getenv('SAUCE_USERNAME', None)
self._access_key = os.getenv('SAUCE_ACCESS_KEY', None)
self.data_center = data_center if data_center else 'us-west'
Expand Down
5 changes: 2 additions & 3 deletions python/tests/examples/test_basic_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ class TestBasicOptions(object):

def test_creates_session(self):
# 1. Create a SauceOptions instance with the 3 primary parameters
sauceOptions = SauceOptions(browserName='firefox',
browserVersion='73.0',
platformName='Windows 8')
sauceOptions = SauceOptions.firefox(browserVersion='73.0',
platformName='Windows 8')

# 2. Create Session object with SauceOptions object instance
session = SauceSession(sauceOptions)
Expand Down
2 changes: 1 addition & 1 deletion python/tests/examples/test_browser_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def test_creates_session(self):
browserOptions.add_argument('--foo')

# 2. Create Sauce Options object with the Browser Options object instance
sauceOptions = SauceOptions(seleniumOptions=browserOptions)
sauceOptions = SauceOptions.firefox(seleniumOptions=browserOptions)

# 3. Create Session object with SauceOptions object instance
session = SauceSession(sauceOptions)
Expand Down
6 changes: 3 additions & 3 deletions python/tests/examples/test_sauce_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ class TestSauceOptions(object):

def test_creates_session(self):
# 1. Create a SauceOptions instance with Sauce Labs Specific Options
sauceOptions = SauceOptions(extendedDebugging=True,
idleTimeout=100,
timeZone='Alaska')
sauceOptions = SauceOptions.chrome(extendedDebugging=True,
idleTimeout=100,
timeZone='Alaska')

# 2. Create Session object with SauceOptions object instance
session = SauceSession(sauceOptions)
Expand Down
7 changes: 2 additions & 5 deletions python/tests/options.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,14 @@ exampleValues:
implicit: 1
pageLoad: 59
script: 29
avoidProxy: true
build: 'Sample Build Name'
capturePerformance: true
chromedriverVersion: '71'
commandTimeout: 2
customData:
foo: 'foo'
bar: 'bar'
extendedDebugging: true
idleTimeout: 3
iedriverVersion: '3.141.0'
extendedDebugging: true
geckodriverVersion: '0.23'
maxDuration: 300
name: 'Sample Test Name'
parentTunnel: 'Mommy'
Expand Down
Loading