Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/devRun.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: psf/black@stable
- uses: isort/isort-action@v1
- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down
49 changes: 11 additions & 38 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,14 @@ repos:
- id: check-xml
- id: end-of-file-fixer
- id: trailing-whitespace
- id: check-docstring-first
- id: name-tests-test
- id: file-contents-sorter
- id: pretty-format-json
args: [ --autofix ]
- id: check-ast
- id: check-builtin-literals
- id: check-case-conflict
- id: check-executables-have-shebangs
- id: check-merge-conflict
- id: check-shebang-scripts-are-executable
- id: debug-statements
- id: detect-private-key
- id: no-commit-to-branch
args: [ '--branch', 'main' ]
args: ['--branch', 'main']
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.32.1
hooks:
Expand All @@ -35,33 +28,14 @@ repos:
- id: conventional-pre-commit
stages: [commit-msg]
args: []
- repo: https://github.com/psf/black
rev: 25.1.0
hooks:
- id: black
language_version: python3
args: [ '--config', 'pyproject.toml' ]
- repo: https://github.com/PyCQA/autoflake
rev: v2.3.1
hooks:
- id: autoflake
args:
[
'--in-place',
'--remove-unused-variable',
'--remove-all-unused-imports',
'--expand-star-imports',
'--ignore-init-module-imports',
]
- repo: https://github.com/PyCQA/isort
rev: 6.0.1
hooks:
- id: isort
args: [ '--settings-file', 'pyproject.toml' ]
- repo: https://github.com/asottile/pyupgrade
rev: v3.19.1
hooks:
- id: pyupgrade
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.11.4
hooks:
- id: ruff
args: [ --fix ]
continue_on_error: true
- id: ruff-format
continue_on_error: true
- repo: https://github.com/codespell-project/codespell
rev: v2.4.1
hooks:
Expand All @@ -72,11 +46,10 @@ repos:
rev: v0.24.1
hooks:
- id: validate-pyproject
# Optional extra validations from SchemaStore:
additional_dependencies: [ "validate-pyproject-schema-store[all]" ]
additional_dependencies: ["validate-pyproject-schema-store[all]"]
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
rev: v2.14.0
hooks:
- id: pretty-format-toml
exclude: poetry.lock
args: [ --autofix ]
args: [--autofix]
4 changes: 2 additions & 2 deletions .github/README.md → README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ git clone https://github.com/nirtal85/Selenium-Python-Example.git
cd selenium-python-example
```

### Create and activate a virtual environment then Install project dependencies
### Create and activate a virtual environment then Install project dependencies

#### For Windows:
```bash
Expand All @@ -72,7 +72,7 @@ uv pip sync uv.lock
```bash
python3 -m pip install uv
uv venv
source .venv/bin/activate
source .venv/bin/activate
uv pip sync uv.lock
```

Expand Down
6 changes: 2 additions & 4 deletions pages/about_page.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import Tuple

import allure
from selenium.webdriver.common.by import By

Expand All @@ -9,8 +7,8 @@
class AboutPage(BasePage):
"""About page - The first page that appears when navigating to base URL"""

LOGIN_LINK: Tuple[str, str] = (By.CSS_SELECTOR, ".login")
REGISTER_LINK: Tuple[str, str] = (By.CSS_SELECTOR, ".register")
LOGIN_LINK: tuple[str, str] = (By.CSS_SELECTOR, ".login")
REGISTER_LINK: tuple[str, str] = (By.CSS_SELECTOR, ".register")

def __init__(self, driver, wait):
super().__init__(driver, wait)
Expand Down
39 changes: 15 additions & 24 deletions pages/base_page.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
from typing import Tuple, Union

from deprecated import deprecated
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver import ActionChains, Chrome, Edge, Firefox
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.expected_conditions import (
StaleElementReferenceException,
)
from selenium.webdriver.support.expected_conditions import StaleElementReferenceException
from selenium.webdriver.support.wait import WebDriverWait


class BasePage:
"""Wrapper for selenium operations."""

def __init__(self, driver: Union[Chrome, Firefox, Edge], wait: WebDriverWait):
def __init__(self, driver: Chrome | Firefox | Edge, wait: WebDriverWait):
self.driver = driver
self.wait = wait

Expand All @@ -39,42 +35,39 @@ def set_geo_location(self, latitude: float, longitude: float) -> None:
"""Sets the geolocation for the web browser using the Chrome DevTools
Protocol (CDP).

Parameters:
Parameters
----------
- latitude (float): The latitude of the desired geolocation.
- longitude (float): The longitude of the desired geolocation.

Returns:
Returns
-------
None

Note:
This method uses the Chrome DevTools Protocol (CDP) to override the geolocation
in the web browser, allowing simulation of a specific geographic location for testing purposes.
The accuracy is set to 1 for simplicity in this method.

"""
self.driver.execute_cdp_cmd(
"Emulation.setGeolocationOverride",
{"latitude": latitude, "longitude": longitude, "accuracy": 1},
)

def click(self, locator: Tuple[str, str]) -> None:
el: WebElement = self.wait.until(
expected_conditions.element_to_be_clickable(locator)
)
def click(self, locator: tuple[str, str]) -> None:
el: WebElement = self.wait.until(expected_conditions.element_to_be_clickable(locator))
self._highlight_element(el, "green")
el.click()

def fill_text(self, locator: Tuple[str, str], txt: str) -> None:
el: WebElement = self.wait.until(
expected_conditions.element_to_be_clickable(locator)
)
def fill_text(self, locator: tuple[str, str], txt: str) -> None:
el: WebElement = self.wait.until(expected_conditions.element_to_be_clickable(locator))
el.clear()
self._highlight_element(el, "green")
el.send_keys(txt)

def clear_text(self, locator: Tuple[str, str]) -> None:
el: WebElement = self.wait.until(
expected_conditions.element_to_be_clickable(locator)
)
def clear_text(self, locator: tuple[str, str]) -> None:
el: WebElement = self.wait.until(expected_conditions.element_to_be_clickable(locator))
el.clear()

def scroll_to_bottom(self) -> None:
Expand All @@ -84,10 +77,8 @@ def submit(self, webelement: WebElement) -> None:
self._highlight_element(webelement, "green")
webelement.submit()

def get_text(self, locator: Tuple[str, str]) -> str:
el: WebElement = self.wait.until(
expected_conditions.visibility_of_element_located(locator)
)
def get_text(self, locator: tuple[str, str]) -> str:
el: WebElement = self.wait.until(expected_conditions.visibility_of_element_located(locator))
self._highlight_element(el, "green")
return el.text

Expand Down
12 changes: 5 additions & 7 deletions pages/forgot_password_page.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
from typing import Tuple

import allure
from selenium.webdriver.common.by import By

from pages.base_page import BasePage


class ForgotPasswordPage(BasePage):
EMAIL_FIELD: Tuple[str, str] = (By.CSS_SELECTOR, "[name=email]")
SEND_PASSWORD_RESET_LINK_BUTTON: Tuple[str, str] = (
EMAIL_FIELD: tuple[str, str] = (By.CSS_SELECTOR, "[name=email]")
SEND_PASSWORD_RESET_LINK_BUTTON: tuple[str, str] = (
By.CSS_SELECTOR,
"[type=submit]",
)
ERROR_MSG: Tuple[str, str] = (By.CSS_SELECTOR, ".alert-danger")
SUCCESS_MSG: Tuple[str, str] = (By.CSS_SELECTOR, ".alert-success")
PAGE_TITLE: Tuple[str, str] = (By.CSS_SELECTOR, ".e-form-heading")
ERROR_MSG: tuple[str, str] = (By.CSS_SELECTOR, ".alert-danger")
SUCCESS_MSG: tuple[str, str] = (By.CSS_SELECTOR, ".alert-success")
PAGE_TITLE: tuple[str, str] = (By.CSS_SELECTOR, ".e-form-heading")

def __init__(self, driver, wait):
super().__init__(driver, wait)
Expand Down
14 changes: 6 additions & 8 deletions pages/login_page.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import Tuple

import allure
from selenium.webdriver.common.by import By

Expand All @@ -9,12 +7,12 @@
class LoginPage(TopMenuBar):
"""Login Page."""

USERNAME_FIELD: Tuple[str, str] = (By.CSS_SELECTOR, "input[type=email]")
PASSWORD_FIELD: Tuple[str, str] = (By.CSS_SELECTOR, "input[type=password]")
LOGIN_BUTTON: Tuple[str, str] = (By.CSS_SELECTOR, "button[type=submit]")
LOGIN_ERROR_MESSAGE: Tuple[str, str] = (By.CSS_SELECTOR, "div.alert-danger")
PAGE_TITLE: Tuple[str, str] = (By.CSS_SELECTOR, ".e-form-heading")
FORGOT_PASSWORD_LINK: Tuple[str, str] = (
USERNAME_FIELD: tuple[str, str] = (By.CSS_SELECTOR, "input[type=email]")
PASSWORD_FIELD: tuple[str, str] = (By.CSS_SELECTOR, "input[type=password]")
LOGIN_BUTTON: tuple[str, str] = (By.CSS_SELECTOR, "button[type=submit]")
LOGIN_ERROR_MESSAGE: tuple[str, str] = (By.CSS_SELECTOR, "div.alert-danger")
PAGE_TITLE: tuple[str, str] = (By.CSS_SELECTOR, ".e-form-heading")
FORGOT_PASSWORD_LINK: tuple[str, str] = (
By.CSS_SELECTOR,
"[href='https://app.involve.me/password/reset']",
)
Expand Down
12 changes: 5 additions & 7 deletions pages/project_edit_page.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import Tuple

import allure
from selenium.webdriver.common.by import By

Expand All @@ -9,20 +7,20 @@
class ProjectEditPage(BasePage):
"""Project Edit page - the page where adding to and editing projects is done"""

_PROJECT_NAME_FIELD: Tuple[str, str] = (By.CSS_SELECTOR, "input#project-name")
_THANK_YOU_PAGE_TYPE_BUTTON: Tuple[str, str] = (
_PROJECT_NAME_FIELD: tuple[str, str] = (By.CSS_SELECTOR, "input#project-name")
_THANK_YOU_PAGE_TYPE_BUTTON: tuple[str, str] = (
By.CSS_SELECTOR,
"[for=select-single-outcome]",
)
_OUTCOME_PAGES_TYPE_BUTTON: Tuple[str, str] = (
_OUTCOME_PAGES_TYPE_BUTTON: tuple[str, str] = (
By.CSS_SELECTOR,
"[for=select-outcomes]",
)
_START_EDITING_BUTTON: Tuple[str, str] = (
_START_EDITING_BUTTON: tuple[str, str] = (
By.CSS_SELECTOR,
".swal-button.swal-button--confirm",
)
_SAVE_AND_EXIT_BUTTON: Tuple[str, str] = (By.CSS_SELECTOR, ".e-close.nav-link")
_SAVE_AND_EXIT_BUTTON: tuple[str, str] = (By.CSS_SELECTOR, ".e-close.nav-link")

def __init__(self, driver, wait):
super().__init__(driver, wait)
Expand Down
6 changes: 2 additions & 4 deletions pages/project_type_page.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import Tuple

import allure
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions
Expand All @@ -10,8 +8,8 @@
class ProjectTypePage(TopNavigateBar):
"""Project Type page - where one can choose which kind of templates to work with"""

_START_FROM_SCRATCH_BUTTON: Tuple[str, str] = (By.CSS_SELECTOR, ".blank div.icon")
_PROJECTS_BLOCK: Tuple[str, str] = (
_START_FROM_SCRATCH_BUTTON: tuple[str, str] = (By.CSS_SELECTOR, ".blank div.icon")
_PROJECTS_BLOCK: tuple[str, str] = (
By.CSS_SELECTOR,
"#app-layout div:nth-child(3) .title",
)
Expand Down
Loading
Loading