Skip to content

Commit 172bac1

Browse files
authored
WebDriverCreator to handle browser creation (#1039)
Moves the WebDriver creation to own class. Also allows desired capabilites to be passes also to the local browsers. Fixes #550
1 parent 61bbacf commit 172bac1

6 files changed

Lines changed: 549 additions & 278 deletions

File tree

src/SeleniumLibrary/keywords/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,5 @@
2626
from .selectelement import SelectElementKeywords
2727
from .tableelement import TableElementKeywords
2828
from .waiting import WaitingKeywords
29+
from .webdrivercreator import WebDriverCreator
2930
from .window import WindowKeywords

src/SeleniumLibrary/keywords/browsermanagement.py

Lines changed: 11 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -14,40 +14,17 @@
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
1616

17-
import os.path
1817
import time
1918
import types
2019

21-
from robot.utils import NormalizedDict
2220
from selenium import webdriver
2321

2422
from SeleniumLibrary.base import keyword, LibraryComponent
2523
from SeleniumLibrary.locators import WindowManager
26-
from SeleniumLibrary.utils import (is_falsy, is_truthy, is_noney, secs_to_timestr,
27-
timestr_to_secs, SELENIUM_VERSION)
28-
29-
30-
ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
31-
FIREFOX_PROFILE_DIR = os.path.join(ROOT_DIR, 'resources', 'firefoxprofile')
32-
BROWSER_NAMES = NormalizedDict({
33-
'ff': "_make_ff",
34-
'firefox': "_make_ff",
35-
'ie': "_make_ie",
36-
'internetexplorer': "_make_ie",
37-
'googlechrome': "_make_chrome",
38-
'gc': "_make_chrome",
39-
'chrome': "_make_chrome",
40-
'opera': "_make_opera",
41-
'phantomjs': "_make_phantomjs",
42-
'htmlunit': "_make_htmlunit",
43-
'htmlunitwithjs': "_make_htmlunitwithjs",
44-
'android': "_make_android",
45-
'iphone': "_make_iphone",
46-
'safari': "_make_safari",
47-
'edge': "_make_edge",
48-
'headlessfirefox': '_make_headless_ff',
49-
'headlesschrome': '_make_headless_chrome'
50-
})
24+
from SeleniumLibrary.utils import (is_truthy, is_noney, secs_to_timestr,
25+
timestr_to_secs)
26+
27+
from .webdrivercreator import WebDriverCreator
5128

5229

5330
class BrowserManagementKeywords(LibraryComponent):
@@ -146,8 +123,7 @@ def open_browser(self, url, browser='firefox', alias=None,
146123
"remote server at '%s'." % (browser, url, remote_url))
147124
else:
148125
self.info("Opening browser '%s' to base url '%s'." % (browser, url))
149-
browser_name = browser
150-
driver = self._make_driver(browser_name, desired_capabilities,
126+
driver = self._make_driver(browser, desired_capabilities,
151127
ff_profile_dir, remote_url)
152128
try:
153129
driver.get(url)
@@ -307,8 +283,8 @@ def title_should_be(self, title, message=None):
307283
"""Verifies that current page title equals ``title``.
308284
309285
The ``message`` argument can be used to override the default error
310-
message.
311-
286+
message.
287+
312288
``message`` argument is new in SeleniumLibrary 3.1.
313289
"""
314290
actual = self.get_title()
@@ -441,145 +417,17 @@ def set_browser_implicit_wait(self, value):
441417
"""
442418
self.driver.implicitly_wait(timestr_to_secs(value))
443419

444-
def _get_driver_creation_function(self, browser_name):
445-
try:
446-
func_name = BROWSER_NAMES[browser_name]
447-
except KeyError:
448-
raise ValueError(browser_name + " is not a supported browser.")
449-
return getattr(self, func_name)
450-
451-
def _make_driver(self, browser_name, desired_capabilities=None,
420+
def _make_driver(self, browser, desired_capabilities=None,
452421
profile_dir=None, remote=None):
453-
creation_func = self._get_driver_creation_function(browser_name)
454-
driver = creation_func(remote, desired_capabilities, profile_dir)
422+
driver = WebDriverCreator(self.log_dir).create_driver(
423+
browser=browser, desired_capabilities=desired_capabilities,
424+
remote_url=remote, profile_dir=profile_dir)
455425
driver.set_script_timeout(self.ctx.timeout)
456426
driver.implicitly_wait(self.ctx.implicit_wait)
457427
if self.ctx.speed:
458428
self._monkey_patch_speed(driver)
459429
return driver
460430

461-
def _make_ff(self, remote, desired_capabilities, profile_dir, options=None):
462-
if is_falsy(profile_dir):
463-
profile = webdriver.FirefoxProfile()
464-
else:
465-
profile = webdriver.FirefoxProfile(profile_dir)
466-
if is_truthy(remote):
467-
driver = self._create_remote_web_driver(
468-
webdriver.DesiredCapabilities.FIREFOX, remote,
469-
desired_capabilities, profile, options=options)
470-
else:
471-
driver = webdriver.Firefox(firefox_profile=profile,
472-
options=options,
473-
**self._geckodriver_log_config)
474-
return driver
475-
476-
def _make_headless_ff(self, remote, desired_capabilities, profile_dir):
477-
options = webdriver.FirefoxOptions()
478-
options.set_headless()
479-
return self._make_ff(remote, desired_capabilities, profile_dir, options=options)
480-
481-
def _make_ie(self, remote, desired_capabilities, profile_dir):
482-
return self._generic_make_driver(
483-
webdriver.Ie, webdriver.DesiredCapabilities.INTERNETEXPLORER,
484-
remote, desired_capabilities)
485-
486-
def _make_chrome(self, remote, desired_capabilities, profile_dir, options=None):
487-
return self._generic_make_driver(
488-
webdriver.Chrome, webdriver.DesiredCapabilities.CHROME, remote,
489-
desired_capabilities, options=options)
490-
491-
def _make_headless_chrome(self, remote, desired_capabilities, profile_dir):
492-
options = webdriver.ChromeOptions()
493-
options.set_headless()
494-
return self._make_chrome(remote, desired_capabilities, profile_dir, options)
495-
496-
def _make_opera(self, remote, desired_capabilities, profile_dir):
497-
return self._generic_make_driver(
498-
webdriver.Opera, webdriver.DesiredCapabilities.OPERA, remote,
499-
desired_capabilities)
500-
501-
def _make_phantomjs(self, remote, desired_capabilities, profile_dir):
502-
return self._generic_make_driver(
503-
webdriver.PhantomJS, webdriver.DesiredCapabilities.PHANTOMJS,
504-
remote, desired_capabilities)
505-
506-
def _make_htmlunit(self, remote, desired_capabilities, profile_dir):
507-
return self._generic_make_driver(
508-
webdriver.Remote, webdriver.DesiredCapabilities.HTMLUNIT, remote,
509-
desired_capabilities)
510-
511-
def _make_htmlunitwithjs(self, remote, desired_capabilities, profile_dir):
512-
return self._generic_make_driver(
513-
webdriver.Remote, webdriver.DesiredCapabilities.HTMLUNITWITHJS,
514-
remote, desired_capabilities)
515-
516-
def _make_android(self, remote, desired_capabilities, profile_dir):
517-
return self._generic_make_driver(
518-
webdriver.Remote, webdriver.DesiredCapabilities.ANDROID, remote,
519-
desired_capabilities)
520-
521-
def _make_iphone(self, remote, desired_capabilities, profile_dir):
522-
return self._generic_make_driver(
523-
webdriver.Remote, webdriver.DesiredCapabilities.IPHONE, remote,
524-
desired_capabilities)
525-
526-
def _make_safari(self, remote, desired_capabilities, profile_dir):
527-
return self._generic_make_driver(
528-
webdriver.Safari, webdriver.DesiredCapabilities.SAFARI, remote,
529-
desired_capabilities)
530-
531-
def _make_edge(self, remote, desired_capabilities, profile_dir):
532-
return self._generic_make_driver(
533-
webdriver.Edge, webdriver.DesiredCapabilities.EDGE, remote,
534-
desired_capabilities)
535-
536-
def _generic_make_driver(self, webdriver_type, desired_cap_type,
537-
remote_url, desired_caps, options=None):
538-
"""Generic driver creation
539-
540-
Most of the make driver functions just call this function which
541-
creates the appropriate driver
542-
"""
543-
if is_falsy(remote_url):
544-
if options is None:
545-
driver = webdriver_type()
546-
else:
547-
driver = webdriver_type(options=options)
548-
else:
549-
driver = self._create_remote_web_driver(desired_cap_type,
550-
remote_url, desired_caps,
551-
options=options)
552-
return driver
553-
554-
def _create_remote_web_driver(self, capabilities_type, remote_url,
555-
desired_capabilities=None, profile=None,
556-
options=None):
557-
'''parses the string based desired_capabilities if neccessary and
558-
creates the associated remote web driver'''
559-
560-
desired_capabilities_object = capabilities_type.copy()
561-
if not isinstance(desired_capabilities, dict):
562-
desired_capabilities = self._parse_capabilities_string(desired_capabilities)
563-
desired_capabilities_object.update(desired_capabilities or {})
564-
return webdriver.Remote(desired_capabilities=desired_capabilities_object,
565-
command_executor=str(remote_url), browser_profile=profile,
566-
options=options)
567-
568-
def _parse_capabilities_string(self, capabilities_string):
569-
'''parses the string based desired_capabilities which should be in the form
570-
key1:val1,key2:val2
571-
'''
572-
desired_capabilities = {}
573-
574-
if is_falsy(capabilities_string):
575-
return desired_capabilities
576-
577-
for cap in capabilities_string.split(","):
578-
(key, value) = cap.split(":", 1)
579-
desired_capabilities[key.strip()] = value.strip()
580-
581-
return desired_capabilities
582-
583431
def _monkey_patch_speed(self, driver):
584432
def execute(self, driver_command, params=None):
585433
result = self._base_execute(driver_command, params)
@@ -591,9 +439,3 @@ def execute(self, driver_command, params=None):
591439
driver._base_execute = driver.execute
592440
driver.execute = types.MethodType(execute, driver)
593441
driver._speed = self.ctx.speed
594-
595-
@property
596-
def _geckodriver_log_config(self):
597-
if SELENIUM_VERSION.major == '3':
598-
return {'log_path': os.path.join(self.log_dir, 'geckodriver.log')}
599-
return {}

src/SeleniumLibrary/keywords/waiting.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
from SeleniumLibrary.base import LibraryComponent, keyword
2020
from SeleniumLibrary.errors import ElementNotFound
21-
from SeleniumLibrary.utils import is_noney, is_truthy, secs_to_timestr
21+
from SeleniumLibrary.utils import is_noney, secs_to_timestr
2222

2323

2424
class WaitingKeywords(LibraryComponent):

0 commit comments

Comments
 (0)