diff options
Diffstat (limited to 'bitbake/lib/toaster/tests/browser/selenium_helpers_base.py')
-rw-r--r-- | bitbake/lib/toaster/tests/browser/selenium_helpers_base.py | 77 |
1 files changed, 65 insertions, 12 deletions
diff --git a/bitbake/lib/toaster/tests/browser/selenium_helpers_base.py b/bitbake/lib/toaster/tests/browser/selenium_helpers_base.py index 6c94684e86..393be75496 100644 --- a/bitbake/lib/toaster/tests/browser/selenium_helpers_base.py +++ b/bitbake/lib/toaster/tests/browser/selenium_helpers_base.py @@ -19,12 +19,15 @@ import os import time import unittest -from django.contrib.staticfiles.testing import StaticLiveServerTestCase +import pytest from selenium import webdriver +from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.common.by import By from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.common.exceptions import NoSuchElementException, \ - StaleElementReferenceException, TimeoutException + StaleElementReferenceException, TimeoutException, \ + SessionNotCreatedException def create_selenium_driver(cls,browser='chrome'): # set default browser string based on env (if available) @@ -33,9 +36,32 @@ def create_selenium_driver(cls,browser='chrome'): browser = env_browser if browser == 'chrome': - return webdriver.Chrome( - service_args=["--verbose", "--log-path=selenium.log"] - ) + options = webdriver.ChromeOptions() + options.add_argument('--headless') + options.add_argument('--disable-infobars') + options.add_argument('--disable-dev-shm-usage') + options.add_argument('--no-sandbox') + options.add_argument('--remote-debugging-port=9222') + try: + return webdriver.Chrome(options=options) + except SessionNotCreatedException as e: + exit_message = "Halting tests prematurely to avoid cascading errors." + # check if chrome / chromedriver exists + chrome_path = os.popen("find ~/.cache/selenium/chrome/ -name 'chrome' -type f -print -quit").read().strip() + if not chrome_path: + pytest.exit(f"Failed to install/find chrome.\n{exit_message}") + chromedriver_path = os.popen("find ~/.cache/selenium/chromedriver/ -name 'chromedriver' -type f -print -quit").read().strip() + if not chromedriver_path: + pytest.exit(f"Failed to install/find chromedriver.\n{exit_message}") + # check if depends on each are fulfilled + depends_chrome = os.popen(f"ldd {chrome_path} | grep 'not found'").read().strip() + if depends_chrome: + pytest.exit(f"Missing chrome dependencies.\n{depends_chrome}\n{exit_message}") + depends_chromedriver = os.popen(f"ldd {chromedriver_path} | grep 'not found'").read().strip() + if depends_chromedriver: + pytest.exit(f"Missing chromedriver dependencies.\n{depends_chromedriver}\n{exit_message}") + # print original error otherwise + pytest.exit(f"Failed to start chromedriver.\n{e}\n{exit_message}") elif browser == 'firefox': return webdriver.Firefox() elif browser == 'marionette': @@ -67,7 +93,9 @@ class Wait(WebDriverWait): _TIMEOUT = 10 _POLL_FREQUENCY = 0.5 - def __init__(self, driver): + def __init__(self, driver, timeout=_TIMEOUT, poll=_POLL_FREQUENCY): + self._TIMEOUT = timeout + self._POLL_FREQUENCY = poll super(Wait, self).__init__(driver, self._TIMEOUT, self._POLL_FREQUENCY) def until(self, method, message=''): @@ -139,6 +167,8 @@ class SeleniumTestCaseBase(unittest.TestCase): """ Clean up webdriver driver """ cls.driver.quit() + # Allow driver resources to be properly freed before proceeding with further tests + time.sleep(5) super(SeleniumTestCaseBase, cls).tearDownClass() def get(self, url): @@ -152,13 +182,20 @@ class SeleniumTestCaseBase(unittest.TestCase): abs_url = '%s%s' % (self.live_server_url, url) self.driver.get(abs_url) + try: # Ensure page is loaded before proceeding + self.wait_until_visible("#global-nav", poll=3) + except NoSuchElementException: + self.driver.implicitly_wait(3) + except TimeoutException: + self.driver.implicitly_wait(3) + def find(self, selector): """ Find single element by CSS selector """ - return self.driver.find_element_by_css_selector(selector) + return self.driver.find_element(By.CSS_SELECTOR, selector) def find_all(self, selector): """ Find all elements matching CSS selector """ - return self.driver.find_elements_by_css_selector(selector) + return self.driver.find_elements(By.CSS_SELECTOR, selector) def element_exists(self, selector): """ @@ -171,18 +208,34 @@ class SeleniumTestCaseBase(unittest.TestCase): """ Return the element which currently has focus on the page """ return self.driver.switch_to.active_element - def wait_until_present(self, selector): + def wait_until_present(self, selector, poll=0.5): """ Wait until element matching CSS selector is on the page """ is_present = lambda driver: self.find(selector) msg = 'An element matching "%s" should be on the page' % selector - element = Wait(self.driver).until(is_present, msg) + element = Wait(self.driver, poll=poll).until(is_present, msg) + if poll > 2: + time.sleep(poll) # element need more delay to be present return element - def wait_until_visible(self, selector): + def wait_until_visible(self, selector, poll=1): """ Wait until element matching CSS selector is visible on the page """ is_visible = lambda driver: self.find(selector).is_displayed() msg = 'An element matching "%s" should be visible' % selector - Wait(self.driver).until(is_visible, msg) + Wait(self.driver, poll=poll).until(is_visible, msg) + time.sleep(poll) # wait for visibility to settle + return self.find(selector) + + def wait_until_clickable(self, selector, poll=1): + """ Wait until element matching CSS selector is visible on the page """ + WebDriverWait( + self.driver, + Wait._TIMEOUT, + poll_frequency=poll + ).until( + EC.element_to_be_clickable((By.ID, selector.removeprefix('#') + ) + ) + ) return self.find(selector) def wait_until_focused(self, selector): |