diff --git a/parakeet/__version__.py b/parakeet/__version__.py index 9d43a3d..78430b6 100644 --- a/parakeet/__version__.py +++ b/parakeet/__version__.py @@ -5,4 +5,4 @@ # |_| \__,_|_| \__,_|_|\_\___|\___|\__| -__version__ = '0.0.16' +__version__ = '0.0.17' diff --git a/parakeet/auth.py b/parakeet/auth.py index 0d47840..4a804e7 100644 --- a/parakeet/auth.py +++ b/parakeet/auth.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -import base64 +import base64, time from selenium.common.exceptions import TimeoutException from selenium.webdriver.common.by import By @@ -62,9 +62,7 @@ def fill_password(self, password): def login(self): LOG.debug('login') - self.browser\ - .find_element_by_id('passwordNext')\ - .click() + self.browser.find_element_by_id('passwordNext').click() return self def redirect_to_home(self): @@ -78,6 +76,7 @@ def redirect_to_home(self): def click_sign_in(self): LOG.debug('click_sign_in') self.browser.find_element_by_xpath('//md-card-actions/button').click() + time.sleep(1) return self def switch_windows_before(self): diff --git a/parakeet/browser.py b/parakeet/browser.py index 2740093..e2b6d08 100644 --- a/parakeet/browser.py +++ b/parakeet/browser.py @@ -2,6 +2,8 @@ from __future__ import division import time import re + +from selenium.common.exceptions import TimeoutException from splinter import Browser from selenium import webdriver from selenium.webdriver.common.by import By @@ -34,10 +36,14 @@ def clear(self): return self def click(self): - self.parakeet.retry(method=self.click_once_time_only) + try: + self.parakeet.retry(method=self.click_once) + except Exception as ex: + LOG.error('Attempts exceeded') + return self - def click_once_time_only(self): + def click_once(self): self.element = self.wait_element_to_be_clickable() self.element.click() return self @@ -142,6 +148,7 @@ def __init__(self, config): self.waiting_time = int(config.get('default_implicitly_wait_seconds')) self.poll_frequency = int(config.get('default_poll_frequency_seconds')) self.snapshot_debug = config.get('snapshot_debug', False) + self.color_log = config.get('color_log', False) self.type_pause = float(config.get('type_pause', 0)) self.retry_get_element = int(config.get('retry', 1)) self.selenium.implicitly_wait(self.waiting_time) @@ -167,10 +174,11 @@ def is_element_present_by_id(self, element_id): .format(element_id)) return self.splinter.is_element_present_by_id(element_id, self.waiting_time) - def is_element_present_by_xpath(self, element_xpath): - LOG.debug('is_element_present_by_xpath({})' - .format(element_xpath)) - return self.splinter.is_element_present_by_xpath(element_xpath, self.waiting_time) + def is_element_present_by_xpath(self, element_xpath, p_waiting_time=None): + _waiting_time = p_waiting_time if p_waiting_time else self.waiting_time + LOG.debug('is_element_present_by_xpath({}, {})' + .format(element_xpath, _waiting_time)) + return self.splinter.is_element_present_by_xpath(element_xpath, _waiting_time) def is_text_present(self, text): LOG.debug('is_text_present({})' @@ -193,9 +201,18 @@ def get_element_waiting_for_its_presence(self, locator, waiting_time=None): _waiting_time = waiting_time if waiting_time else self.waiting_time LOG.debug('get_element_waiting_for_its_presence({}, {}, {})' .format(locator, _waiting_time, self.poll_frequency)) - element = WebDriverWait(self.selenium, _waiting_time, self.poll_frequency).until( - ec.presence_of_element_located(locator) - ) + element = None + + try: + element = WebDriverWait(self.selenium, _waiting_time, self.poll_frequency).until( + ec.presence_of_element_located(locator) + ) + except TimeoutException: + LOG.error("Time is up! {}s".format(_waiting_time)) + self.selenium\ + .save_screenshot('parakeet_timeout_error_{:05d}.png' + .format(next_image())) + return element def get_element_waiting_for_its_presence_by_xpath(self, xpath, waiting_time=None): @@ -230,13 +247,29 @@ def retry(self, method=None, **kwargs): return result except Exception as ex: - LOG.error('Exception: {}'.format(ex.message)) + LOG.warn('Exception: {}'.format(str(ex))) + if 'md-backdrop' in str(ex): + self._remove_back_drop() + + if 'md-scroll-mask' in str(ex): + self._remove_scroll_back() + if _next_iterator < _retry: return self._perform_method(_next, _next_iterator, kwargs, method) + self.selenium.save_screenshot('parakeet_error_{:05d}_{}.png' .format(next_image(), method.__name__)) + LOG.error('Exception: {}'.format(str(ex))) raise ex + def _remove_scroll_back(self): + LOG.info('---- Remove md-scroll-mask ---') + self.splinter.execute_script("document.getElementsByClassName('md-scroll-mask')[0]['style']['display'] = 'none'") + + def _remove_back_drop(self): + LOG.info('---- Remove md-backdrop ---') + self.splinter.execute_script("document.getElementsByTagName('md-backdrop')[0].style.display = 'none'") + def _perform_method(self, next, next_iterator, kwargs, method): """ Perform the method and return the value diff --git a/parakeet/common_steps.py b/parakeet/common_steps.py index 479416d..d4638cb 100644 --- a/parakeet/common_steps.py +++ b/parakeet/common_steps.py @@ -18,7 +18,7 @@ def login(step, user_name): google_oauth(user_name) elif world.cfg['login_provider'] == 'google_oauth_gapi2': google_oauth_gapi2(user_name) - LoginPage(world.browser, world.cfg['system_page_title']).redirect_to_home() + LoginPage(world.browser, world.cfg['system_page_title']).redirect_to_home() def google_oauth(user_name): @@ -45,6 +45,7 @@ def google_oauth_gapi2(user_name): .set_window()\ .click_sign_in()\ .switch_windows_after() + google_oauth(user_name) LoginPage(world.browser, world.cfg['system_page_title'])\ .switch_windows_before() diff --git a/parakeet/lettuce_logger.py b/parakeet/lettuce_logger.py index 9418b84..de63b97 100644 --- a/parakeet/lettuce_logger.py +++ b/parakeet/lettuce_logger.py @@ -13,9 +13,11 @@ APP_LOGGER = 'google.tests.e2e' SNAPSHOT_DEBUG = 'SNAPSHOT_DEBUG' -formatter = ColoredFormatter( - "%(green)s%(asctime)s - %(name)s -%(reset)s %(log_color)s%(levelname)-8s%(reset)s" - " - %(purple)s%(message)s", +formatter_normal = logging.Formatter("[%(processName)s] %(asctime)s - %(name)s - %(levelname)-8s - %(message)s", + datefmt=None) +formatter_color = ColoredFormatter( + "%(bold_blue)s[%(processName)s]%(reset)s %(green)s%(asctime)s - %(name)s -%(reset)s " + "%(log_color)s%(levelname)-8s%(reset)s - %(purple)s%(message)s", datefmt=None, reset=True, log_colors={ @@ -39,7 +41,7 @@ def debug(self, msg, *args, **kwargs): return super(CustomLogging, self).debug(msg, *args, **kwargs) -def init_logs(level='INFO', logger=None): +def init_logs(level='INFO', logger=None, color_log=False): """ Setup the logs inside of the tests. :param level: @@ -51,7 +53,7 @@ def init_logs(level='INFO', logger=None): handler.setLevel(_level) ch = logging.StreamHandler(sys.stdout) ch.setLevel(_level) - ch.setFormatter(formatter) + ch.setFormatter(formatter_color if color_log else formatter_normal) handler.addHandler(ch)