diff --git a/README.md b/README.md index 622ad78..61cbaeb 100644 --- a/README.md +++ b/README.md @@ -48,8 +48,9 @@ From version **2.0.0+**, Caqui includes a high-level API that mirrors Selenium Chrome Devtools Protocol example: ```python import time -from pytest import raises +from pytest import raises, fixture from caqui.cdp.by import By +from caqui.cdp.connection import SyncCDPConnection from caqui.cdp.synchronous.drivers import SyncDriverCDP from caqui.exceptions import WebDriverError from tests.constants import OTHER_URL diff --git a/caqui/cdp/asynchronous/drivers.py b/caqui/cdp/asynchronous/drivers.py index 007bfdd..a051b51 100644 --- a/caqui/cdp/asynchronous/drivers.py +++ b/caqui/cdp/asynchronous/drivers.py @@ -14,6 +14,7 @@ from caqui.cdp.by import By from caqui.cdp.connection import AsyncCDPConnection from caqui.cdp.engine import asynchronous +from caqui.helper import deprecated TIMEOUT = 120 # seconds @@ -190,6 +191,11 @@ async def add_cookie(self, cookie: dict) -> None: cookie, ) + @deprecated + async def implicitly_wait(self, timeouts: int) -> None: + """Set implicty timeouts. `NOte` Present for backward-compatibility only""" + pass + async def back(self) -> None: """This command causes the browser to traverse one step backward in the joint session history of the diff --git a/caqui/cdp/synchronous/drivers.py b/caqui/cdp/synchronous/drivers.py index 4b690a1..3ac9188 100644 --- a/caqui/cdp/synchronous/drivers.py +++ b/caqui/cdp/synchronous/drivers.py @@ -13,6 +13,7 @@ from caqui.cdp.synchronous.element import Element from caqui.cdp.synchronous.switch_to import SwitchTo from caqui.cdp.synchronous.window import Window +from caqui.helper import deprecated TIMEOUT = 120 # seconds @@ -57,6 +58,7 @@ def switch_to(self) -> SwitchTo: """Returns the `SwithTo` object""" return SwitchTo(self) + # TODO test it def get_current_window_handle(self) -> str: """Returns the current window handle""" @@ -187,6 +189,11 @@ def add_cookie(self, cookie: dict) -> None: cookie, ) + @deprecated + def implicitly_wait(self, timeouts: int) -> None: + """Set implicty timeouts.`Note` Present for backward-compatibility only""" + pass + def back(self) -> None: """This command causes the browser to traverse one step backward in the joint session history of the diff --git a/caqui/cdp/synchronous/element.py b/caqui/cdp/synchronous/element.py index f09c3af..68775b0 100644 --- a/caqui/cdp/synchronous/element.py +++ b/caqui/cdp/synchronous/element.py @@ -23,6 +23,11 @@ def __init__(self, element: str, driver: "SyncDriverCDP") -> None: def __str__(self) -> str: return f"type: Element. NodeId: {self._element}" + + @property + def text(self): + return self.get_text() + @property def element_id(self) -> str: return self._element diff --git a/caqui/helper.py b/caqui/helper.py index ab9f869..dddeb63 100644 --- a/caqui/helper.py +++ b/caqui/helper.py @@ -4,6 +4,7 @@ # Visit: https://github.com/douglasdcm/caqui import base64 +import warnings from functools import lru_cache from caqui.by import By @@ -159,3 +160,16 @@ def convert_locator_to_css_selector_or_xpath(locator_type: str, locator_value: s locator_type = By.XPATH return locator_type, locator_value return locator_type, locator_value + +def deprecated(func): + """Use this decorator to mark functions as deprecated. + Every time the decorated function runs, it will emit + a "deprecation" warning.""" + def new_func(*args, **kwargs): + warnings.simplefilter('always', DeprecationWarning) # turn off filter + warnings.warn(f"Call to a deprecated function '{func.__name__}'.", + category=DeprecationWarning, + stacklevel=2) + warnings.simplefilter('default', DeprecationWarning) # reset filter + return func(*args, **kwargs) + return new_func \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index ed854ba..056c0e8 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -22,7 +22,7 @@ author = "Douglas Cardoso" # The full version, including alpha/beta/rc tags -release = "5.0.0-rc" +release = "5.0.0rc2" # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 2baa3c0..d00870c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,28 +1,23 @@ [build-system] -requires = ["setuptools>=61.8", "wheel"] +requires = ["setuptools", "wheel"] build-backend = "setuptools.build_meta" -[tool.setuptools.packages.find] -include = ["caqui*"] -exclude = ["tests*", "utils", ".vscode", ".git*", "dist"] - [project] name = "caqui" -version = "5.0.0-rc" -authors = [ - { name="Douglas Cardoso", email="noemail@noemail.com" }, -] +version = "5.0.0rc2" description = "Run asynchronous commands in WebDrivers" -keywords = ["automation", "asynchronous", "test", "crawler", "robotic process automation", "rpa"] readme = "README.md" requires-python = ">=3.7" + +authors = [ + { name="Douglas Cardoso", email="noemail@noemail.com" } +] + classifiers = [ "Development Status :: 4 - Beta", "Programming Language :: Python :: 3", "Operating System :: OS Independent", ] -[project.license] -"file" = "LICENSE" dependencies = [ "requests", @@ -30,9 +25,15 @@ dependencies = [ "webdriver_manager", "types-requests", "beautifulsoup4", - "git+https://github.com/HyperionGray/python-chrome-devtools-protocol.git@5915dce242d4f0cd8c5f8a5e843a535dacc57fc3" + "chrome-devtools-protocol @ git+https://github.com/HyperionGray/python-chrome-devtools-protocol.git@5915dce242d4f0cd8c5f8a5e843a535dacc57fc3" ] +license = { file = "LICENSE" } + [project.urls] -"Homepage" = "https://github.com/douglasdcm/caqui" +Homepage = "https://github.com/douglasdcm/caqui" "Bug Tracker" = "https://github.com/douglasdcm/caqui/issues" + +[tool.setuptools.packages.find] +where = ["."] +include = ["caqui*"] diff --git a/tests/feature/test_sync_cdp_driver.py b/tests/feature/test_sync_cdp_driver.py index 3f6c5cc..621455c 100644 --- a/tests/feature/test_sync_cdp_driver.py +++ b/tests/feature/test_sync_cdp_driver.py @@ -26,6 +26,10 @@ def test_cdp_refresh_page(self, setup_sync_cdp_playground: SyncDriverCDP): element_after = driver.find_element(By.XPATH, "//input") assert element_before != element_after + def test_cdp_implicity_wait_is_deprecated(self, setup_sync_cdp_playground: SyncDriverCDP): + driver = setup_sync_cdp_playground + assert driver.implicitly_wait(3) is None + def test_cdp_go_forward(self, setup_sync_cdp_playground: SyncDriverCDP): driver = setup_sync_cdp_playground title = "Sample page" diff --git a/tests/test_sniffer.py b/tests/test_sniffer.py deleted file mode 100644 index 97e7f84..0000000 --- a/tests/test_sniffer.py +++ /dev/null @@ -1,220 +0,0 @@ -# # File used to figure out requests format and parameters #### - -# from pytest import fixture, mark -# from selenium import webdriver -# from selenium.webdriver.chrome.options import Options -# from selenium.webdriver.chrome.service import Service -# from selenium.webdriver.common.action_chains import ActionChains -# from selenium.webdriver.common.alert import Alert -# from selenium.webdriver.common.by import By - -# from tests.constants import PAGE_URL - - -# @fixture -# def setup(): -# # desired_capabilities = { -# # # 'deviceName': 'Device', -# # "deviceName": "Emulator", -# # "deviceIpAddress": "127.0.0.1", -# # "locale": "en-US", -# # "debugCodedUI": False, -# # "app": "chromedriver", -# # } - -# options = Options() -# # options.set_capability("deviceName", "Emulator") -# # options.set_capability("deviceIpAddress", "127.0.0.1") -# # options.set_capability("locale", "en-US") -# # options.set_capability("debugCodedUI", False) -# options.set_capability("app", "geckodriver") -# driver = webdriver.Remote( -# command_executor="http://localhost:9999", -# options=options, -# ) -# driver.get(PAGE_URL) -# # driver.find_element().value_of_css_property() -# yield driver -# driver.quit() - - -# @fixture -# def setup_binary(): -# service = Service("/home/douglas/web_drivers/chromedriver.113") -# options = Options() -# # options.add_argument('--headless') -# options.add_argument("window-size=1920,1080") -# browser = webdriver.Chrome(service=service, options=options) -# browser.get(PAGE_URL) - -# browser._shadowroot_cls - -# yield browser -# # browser.quit() - - -# @mark.skip("used just to discover request data") -# def test_action_chains(setup): -# driver = setup - -# resource = driver.find_element("xpath", "//button") - -# action = ActionChains(driver) -# action.move_to_element(resource) -# action.perform() - - -# @mark.skip("used just to discover request data") -# def test_switch_to_frame_sniffer(setup): -# driver = setup -# # Click the link to activate the alert -# import time - -# time.sleep(3) -# element = driver.find_element(By.ID, "my-iframe") -# driver.switch_to.frame(element) - -# element_alert = driver.find_element(By.ID, "alert-button-iframe") -# element_alert.click() -# time.sleep(3) - - -# @mark.skip("used just to discover request data") -# def test_switch_to_frame_sniffer_v2(setup): -# driver = setup -# # Click the link to activate the alert -# import time - -# time.sleep(3) -# element = driver.find_element(By.ID, "my-iframe") -# driver.switch_to.frame(element) - -# element_alert = driver.find_element(By.ID, "alert-button-iframe") -# element_alert.click() -# time.sleep(3) - - -# @mark.skip("used just to discover request data") -# def test_send_text_to_alert(setup): -# driver = setup -# # Click the link to activate the alert -# driver.find_element(By.CSS_SELECTOR, "#alert-button-prompt").click() -# import time - -# time.sleep(3) - -# # Wait for the alert to be displayed -# # wait.until(expected_conditions.alert_is_present()) - -# # Store the alert in a variable for reuse -# alert = Alert(driver) -# print("alert ", alert.text) - -# # Type your message -# alert.send_keys("Selenium") -# time.sleep(3) - -# # Press the OK button -# alert.accept() -# time.sleep(3) - - -# @mark.skip("used just to discover request data") -# def test_add_cookie(setup): -# driver = setup -# driver.add_cookie({"name": "firstname", "value": "James"}) - - -# @mark.skip("used just to discover request data") -# def test_submit(setup): -# driver = setup -# search_button = driver.find_element("name", "my-form") -# search_button.submit() - - -# @mark.skip("used just to discover request data") -# def test_sniffer_is_displayed(setup_binary): -# driver = setup_binary -# search_button = driver.find_element("xpath", "//button") -# search_button.is_displayed() - - -# @mark.skip("used just to discover request data") -# def test_sniffer_actions_scroll_to_element(setup_binary): -# driver = setup_binary -# search_button = driver.find_element("xpath", "//button") -# ActionChains(driver).scroll_to_element(search_button).perform() - - -# @mark.skip("used just to discover request data") -# def test_sniffer_actions_click(setup): -# driver = setup -# search_button = driver.find_element("xpath", "//button") -# ActionChains(driver).click(search_button).perform() - - -# @mark.skip("used just to discover request data") -# def test_sniffer_find_children_elements(setup): -# driver = setup -# element = driver.find_element(By.XPATH, '//div[@class="parent"]') -# elements = element.find_elements(By.XPATH, "//div") -# for e in elements: -# print("element_text:", e.text) - - -# @mark.skip("used just to discover request data") -# def test_exec_script(setup): -# driver = setup -# assert driver.execute_script("return document.body.scrollHeight") == "any" - - -# @mark.skip("used just to discover request data") -# def test_clear(setup): -# driver = setup -# element = driver.find_element("xpath", "//input") -# assert element.clear() == "any" - - -# @mark.skip("used just to discover request data") -# def test_back(setup): -# assert setup.back() == "any" - - -# @mark.skip("used just to discover request data") -# def test_get_title(setup): -# assert setup.title == "any" - - -# @mark.skip("used just to discover request data") -# def test_get_attribute(setup): -# driver = setup -# element = driver.find_element("xpath", "//a") -# assert element.get_property("href") == "any" - - -# @mark.skip("used just to discover request data") -# def test_find_elements(setup): -# driver = setup -# actual = driver.find_elements("xpath", "//input") -# assert actual == "any" - - -# @mark.skip("used just to discover request data") -# def test_get_attribute_from_input(setup): -# driver = setup -# search_box = driver.find_element("xpath", "//input") -# search_box.send_keys("cat") - -# data = driver.find_element("xpath", "//input").get_property("value") -# assert data == "cat" - - -# @mark.skip("used just to discover request data") -# def test_sniff(setup): -# driver = setup -# search_box = driver.find_element("xpath", "//input") -# search_button = driver.find_element("xpath", "//button") -# end = driver.find_element("xpath", "//p[@id='end']") -# search_box.send_keys("cat") -# search_button.click() -# assert end.text == "end"