From 033161edef00ed41ef7a0cda01cf49b92261ff43 Mon Sep 17 00:00:00 2001 From: ravishankar Date: Wed, 30 Jun 2021 01:07:57 +0530 Subject: [PATCH 1/3] #10 added type annotation --- s_tool/utils.py | 187 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 s_tool/utils.py diff --git a/s_tool/utils.py b/s_tool/utils.py new file mode 100644 index 0000000..9de3492 --- /dev/null +++ b/s_tool/utils.py @@ -0,0 +1,187 @@ +from typing import Union + +from selenium import webdriver +from selenium.common.exceptions import NoSuchElementException, TimeoutException +from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.ui import WebDriverWait + +from s_tool.exceptions import SToolException + + +def get_session(driver: webdriver) -> str: + """Return Selenium Driver session id""" + return driver.session_id + + +def visit(driver: webdriver, url: str) -> None: + """visit given url""" + driver.get(url) + + +def page_source(driver: webdriver) -> str: + """Return html page source""" + return driver.page_source + + +def current_url(driver: webdriver) -> str: + """Return current url""" + return driver.current_url + + +def get_locator(locator_type: str, locator_text: str) -> tuple: + """Return element locator + + Args: + locator_type : provide any attribute type + id,class_name,tag_name + xpath, css_selector + + locator_text : attribute value + """ + locator = locator_type.upper() + return getattr(By, locator), locator_text + + +def get_element( + driver: webdriver, locator_type: str, locator_text: str, many: bool = None +): + """Get element using locator type and locator text + + Args: + locator_type : provide any attribute type + id,class_name,tag_name + xpath, css_selector + + locator_text : attribute value + + many : optional default None, + 1: select multiple element + 0: select single element + + Returns: + Return an element object if found otherwise + return None + """ + + locator_type = locator_type.upper() + if hasattr(By, locator_type): + try: + locator = get_locator(locator_type, locator_text) + is_multiple = "s" if many else "" + func = getattr(driver, f"find_element{is_multiple}") + return func(*locator) + except NoSuchElementException: + return None + else: + raise SToolException("INVALID_SELECTOR") + + +def click( + driver: webdriver, locator_type: str, locator_text: str, click_time: int = 10 +) -> Union[bool, None]: + """Return True if element clicked otherwise return None + + Args: + locator_type : provide any attribute type + id,class_name,tag_name + xpath, css_selector + + locator_text : attribute value + + Returns: + True : If element clicked + None : Not clicked or Not Found + """ + try: + elem_locator = get_locator(locator_type, locator_text) + element = WebDriverWait(driver, click_time).until( + EC.element_to_be_clickable(elem_locator) + ) + element.click() + return True + except TimeoutException: + return None + except Exception as ex: + raise SToolException(ex) + + +def get_cookies(driver: webdriver) -> dict: + """Accept driver object and return cookies in dictionary + + Args: + driver : A selenium WebDriver + + Returns: + cookies_dict : return cookies in dicionary format if + no cookies return an empty dictionary + """ + cookies = driver.get_cookies() + cookies_dict = {cookie["name"]: cookie["value"] for cookie in cookies} + return cookies_dict or {} + + +def take_screenshot(driver: webdriver, element: tuple = None) -> Union[bytes, None]: + """take screenshot of given element if element is + not given take a full page screeenshot and return + data in bytes + + Args: + driver : selenium Webdriver + element : default None, provide element locator + example : element=('id','element_id') + + Returns: + returns byte object,if element not present + it will return None. + + full screenshot will work only in headless mode. + """ + if element and isinstance(element, tuple): + locator_type, locator_text = element + ele = get_element(driver, locator_type, locator_text) + if ele: + return ele.screenshot_as_png + return None + else: + width = driver.execute_script("return document.body.offsetWidth") + height = driver.execute_script("return document.body.offsetHeight") + driver.set_window_size(width, height) + return driver.get_screenshot_as_png() + + +def display_element(driver: webdriver, element, hide=None) -> None: + """hide or show single element + + Args: + driver : selenium webdriver + element : an selenium element + hide : default value is None, to hide element + hide=1 to display hidden element + Returns: + None + """ + + hide_or_show = "inline" if hide else "None" + driver.execute_script(f"arguments[0].style.display = '{hide_or_show}';", element) + + +def hide_show_elements(driver: webdriver, elements: list, hide: bool = None) -> None: + """hide or show multiple elements + + Args: + driver : selenium webdriver + elements : list of tuples,[('locator_type','value')] + example : [('id','id_value')] + hide : default value is None, to hide element + hide=1 to display hidden element + + Returns: + None + """ + for element_locator in elements: + locator_type, locator_value = element_locator + element_list = get_element(driver, locator_type, locator_value, many=True) + if element_list: + for element in element_list: + display_element(driver, element, hide) From 286f5f41525e4b56884a4376b1ec8c57f4315334 Mon Sep 17 00:00:00 2001 From: ravishankar Date: Wed, 30 Jun 2021 01:09:44 +0530 Subject: [PATCH 2/3] #10 resolved project structure --- s_tool/driver.py | 8 ++------ s_tool/exceptions.py | 10 ++++++++++ s_tool/parser.py | 29 +++++++++++++++++++++++++---- 3 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 s_tool/exceptions.py diff --git a/s_tool/driver.py b/s_tool/driver.py index 235b818..e0762c2 100644 --- a/s_tool/driver.py +++ b/s_tool/driver.py @@ -5,8 +5,8 @@ from webdriver_manager.firefox import GeckoDriverManager from webdriver_manager.utils import ChromeType +from s_tool.exceptions import SToolException from s_tool.utils import ( - SToolException, click, current_url, get_cookies, @@ -93,8 +93,4 @@ def _load_methods(self): if __name__ == "__main__": - - # Create A Driver Object - with SeleniumDriver("firefox", headless=False) as obj: - # visit https:example.com - obj.visit(r"https://quotes.toscrape.com/") + pass diff --git a/s_tool/exceptions.py b/s_tool/exceptions.py new file mode 100644 index 0000000..149c63f --- /dev/null +++ b/s_tool/exceptions.py @@ -0,0 +1,10 @@ +class SToolException(Exception): + """ + Base Class for selenium tools Exceptions + """ + + def __init__(self, message): + self.message = message + + def __str__(self): + return str(self.message) diff --git a/s_tool/parser.py b/s_tool/parser.py index 5a73247..3161e84 100644 --- a/s_tool/parser.py +++ b/s_tool/parser.py @@ -1,5 +1,26 @@ -class Parser(object): - """Parse data from webdriver""" +from s_tool.utils import get_element - def __init__(self, driver): - self.driver = driver + +def select_options(element, swap=None, text_exclude=[]): + """Return dropdown option in key value pair + + Args: + element : An select element + text_exclude : list of values to exclude from result + + Returns: + return dict of values and text of select element, + return empty dict() if element is not valid or not exists + """ + option_dict = dict() + if element and hasattr(element, "tag_name") and element.tag_name == "select": + options = get_element(element, "tag_name", "option", many=True) + for option in options: + func = option.get_attribute + text, value = func("text"), func("value") + if text not in text_exclude: + if swap: + text, value = value, text + option_dict[value] = text + + return option_dict From c9f5c13eb20f8c7711b1636e88666595370ad964 Mon Sep 17 00:00:00 2001 From: ravishankar Date: Wed, 30 Jun 2021 01:10:35 +0530 Subject: [PATCH 3/3] [test] Added new testcase for validating firefox browser --- s_tool/utils/__init__.py | 29 ----- s_tool/utils/driver_exceptions.py | 10 -- s_tool/utils/driver_utils.py | 180 ------------------------------ tests/test_webdrivers.py | 7 ++ 4 files changed, 7 insertions(+), 219 deletions(-) delete mode 100644 s_tool/utils/__init__.py delete mode 100644 s_tool/utils/driver_exceptions.py delete mode 100644 s_tool/utils/driver_utils.py create mode 100644 tests/test_webdrivers.py diff --git a/s_tool/utils/__init__.py b/s_tool/utils/__init__.py deleted file mode 100644 index c2687b1..0000000 --- a/s_tool/utils/__init__.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- - -from utils.driver_exceptions import SToolException -from utils.driver_utils import ( - click, - current_url, - get_cookies, - get_element, - get_locator, - get_session, - hide_show_elements, - page_source, - take_screenshot, - visit, -) - -__all__ = [ - "SToolException", - "current_url", - "get_element", - "get_session", - "page_source", - "visit", - "get_locator", - "click", - "get_cookies", - "take_screenshot", - "hide_show_elements", -] diff --git a/s_tool/utils/driver_exceptions.py b/s_tool/utils/driver_exceptions.py deleted file mode 100644 index 149c63f..0000000 --- a/s_tool/utils/driver_exceptions.py +++ /dev/null @@ -1,10 +0,0 @@ -class SToolException(Exception): - """ - Base Class for selenium tools Exceptions - """ - - def __init__(self, message): - self.message = message - - def __str__(self): - return str(self.message) diff --git a/s_tool/utils/driver_utils.py b/s_tool/utils/driver_utils.py deleted file mode 100644 index e216078..0000000 --- a/s_tool/utils/driver_utils.py +++ /dev/null @@ -1,180 +0,0 @@ -from selenium.common.exceptions import NoSuchElementException, TimeoutException -from selenium.webdriver.common.by import By -from selenium.webdriver.support import expected_conditions as EC -from selenium.webdriver.support.ui import WebDriverWait - -from s_tool.utils.driver_exceptions import SToolException - - -def get_session(driver): - """Return Selenium Driver session id""" - return driver.session_id - - -def visit(driver, url): - """visit given url""" - driver.get(url) - - -def page_source(driver): - """Return html page source""" - return driver.page_source - - -def current_url(driver): - """Return current url""" - return driver.current_url - - -def get_locator(locator_type, locator_text): - """Return element locator - - Args: - locator_type : provide any attribute type - id,class_name,tag_name - xpath, css_selector - - locator_text : attribute value - """ - locator = locator_type.upper() - return getattr(By, locator), locator_text - - -def get_element(driver, locator_type, locator_text, many=None): - """Get element using locator type and locator text - - Args: - locator_type : provide any attribute type - id,class_name,tag_name - xpath, css_selector - - locator_text : attribute value - - many : optional default None, - 1: select multiple element - 0: select single element - - Returns: - Return an element object if found otherwise - return None - """ - - locator_type = locator_type.upper() - if hasattr(By, locator_type): - try: - locator = get_locator(locator_type, locator_text) - is_multiple = "s" if many else "" - func = getattr(driver, f"find_element{is_multiple}") - return func(*locator) - except NoSuchElementException: - return None - else: - raise SToolException("INVALID_SELECTOR") - - -def click(driver, locator_type, locator_text, click_time=10): - """Return True if element clicked otherwise return None - - Args: - locator_type : provide any attribute type - id,class_name,tag_name - xpath, css_selector - - locator_text : attribute value - - Returns: - True : If element clicked - None : Not clicked or Not Found - """ - try: - elem_locator = get_locator(locator_type, locator_text) - element = WebDriverWait(driver, click_time).until( - EC.element_to_be_clickable(elem_locator) - ) - element.click() - return True - except TimeoutException: - return None - except Exception as ex: - raise SToolException(ex) - - -def get_cookies(driver): - """Accept driver object and return cookies in dictionary - - Args: - driver : A selenium WebDriver - - Returns: - cookies_dict : return cookies in dicionary format if - no cookies return an empty dictionary - """ - cookies = driver.get_cookies() - cookies_dict = {cookie["name"]: cookie["value"] for cookie in cookies} - return cookies_dict or {} - - -def take_screenshot(driver, element=None): - """take screenshot of given element if element is - not given take a full page screeenshot and return - data in bytes - - Args: - driver : selenium Webdriver - element : default None, provide element locator - example : element=('id','element_id') - - Returns: - returns byte object,if element not present - it will return None. - - full screenshot will work only in headless mode. - """ - if element and isinstance(element, tuple): - locator_type, locator_text = element - ele = get_element(driver, locator_type, locator_text) - if ele: - return ele.screenshot_as_png - return None - else: - width = driver.execute_script("return document.body.offsetWidth") - height = driver.execute_script("return document.body.offsetHeight") - driver.set_window_size(width, height) - return driver.get_screenshot_as_png() - - -def display_element(driver, element, hide=None): - """hide or show single element - - Args: - driver : selenium webdriver - element : an selenium element - hide : default value is None, to hide element - hide=1 to display hidden element - Returns: - None - """ - - hide_or_show = "inline" if hide else "None" - driver.execute_script(f"arguments[0].style.display = '{hide_or_show}';", element) - - -def hide_show_elements(driver, elements, hide=None): - """hide or show multiple elements - - Args: - driver : selenium webdriver - elements : list of tuples,[('locator_type','value')] - example : [('id','id_value')] - hide : default value is None, to hide element - hide=1 to display hidden element - - Returns: - None - """ - for element_locator in elements: - locator_type, locator_value = element_locator - element_list = get_element(driver, locator_type, locator_value, 1) - if element_list: - for element in element_list: - display_element(driver, element, hide) diff --git a/tests/test_webdrivers.py b/tests/test_webdrivers.py new file mode 100644 index 0000000..f25e4ef --- /dev/null +++ b/tests/test_webdrivers.py @@ -0,0 +1,7 @@ +from s_tool.driver import SeleniumDriver + + +def test_firefox_driver(): + """Test firefox driver with headless""" + with SeleniumDriver("firefox", headless=True) as obj: + assert "firefox" in obj.browser_list