Skip to content

Commit

Permalink
Merge pull request #5 from dmberezovskyii/reporter
Browse files Browse the repository at this point in the history
Reporter
  • Loading branch information
dmberezovskyii authored Oct 13, 2024
2 parents 48d7cb5 + 6049375 commit 5beaa14
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 52 deletions.
35 changes: 35 additions & 0 deletions .github/workflows/ruff_lint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Linting

on:
pull_request:
branches:
- main
push:
branches:
- main

jobs:
lint:
runs-on: macos-latest

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Setup Python
uses: actions/setup-python@v3
with:
python-version: "3.12"

- name: Install Poetry
run: |
python -m pip install --upgrade pip
pip install poetry
- name: Install dependencies with Poetry
run: |
poetry install
- name: Run Linting
run: |
poetry run ruff check .
18 changes: 8 additions & 10 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@

settings = Dynaconf(
settings_files=[
"configs/settings.toml", # a file for main settings
"configs/.secrets.toml" # a file for sensitive data must be (gitignored)
"configs/settings.toml", # a file for main settings
"configs/.secrets.toml", # a file for sensitive data must be (gitignored)
],
environments=True,
load_dotenv=True, # Load envvars from a file named `.env`
# TIP: probably you don't want to load dotenv on production environments
# pass `load_dotenv={"when": {"env": {"is_in": ["development"]}}}
envvar_prefix="PW", # variables exported as `PW_FOO=bar` becomes `settings.FOO == "bar"`
env_switcher="ENV_FOR_PW", # to switch environments `export ENV_FOR_PW=production`

dotenv_path="configs/.env" # custom path for .env file to be loaded
load_dotenv=True, # Load envvars from a file named `.env`
# TIP: probably you don't want to load dotenv on production environments
# pass `load_dotenv={"when": {"env": {"is_in": ["development"]}}}
envvar_prefix="PW", # variables as `PW_FOO=bar` becomes `settings.FOO == "bar"`
env_switcher="ENV_FOR_PW", # to switch environments `export ENV_FOR_PW=production`
dotenv_path="configs/.env", # custom path for .env file to be loaded
)

52 changes: 24 additions & 28 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,47 +11,44 @@
# Registering pytest options for command-line argument parsing
def pytest_addoption(parser):
parser.addoption(
"--env",
action="store",
default="dev",
help="Default environment"
"--env", action="store", default="dev", help="Default environment"
)
parser.addoption(
"--browser-type",
action="store",
default="chromium",
choices=["chromium", "firefox", "webkit"],
help="Browser type: chromium, firefox, or webkit"
help="Browser type: chromium, firefox, or webkit",
)
parser.addoption(
"--headless",
action="store_true",
default=False,
help="Run tests in headless mode"
help="Run tests in headless mode",
)
parser.addoption(
"--devtools",
action="store_true",
default=False,
help="Open browser with devtools"
help="Open browser with devtools",
)
parser.addoption(
"--proxy",
action="store",
default=None,
help="Proxy server address (e.g., http://proxy-server:port)"
help="Proxy server address (e.g., http://proxy-server:port)",
)
parser.addoption(
"--listeners",
action="store",
default="",
help="Comma-separated event listeners (options: console, request, response, click)"
help="Comma-separated event listeners (console, request, response, click)",
)
parser.addoption(
"--slow-mo",
action="store",
default="0",
help="Slow down operations by this amount of milliseconds"
help="Slow down operations by this amount of milliseconds",
)


Expand All @@ -67,25 +64,22 @@ def browser(request, playwright):

# Fetching options from pytest command-line arguments
headless = request.config.getoption("--headless")
slow_mo = float(request.config.getoption("--slow-mo")) # Convert to float
launch_options = {
"headless": headless,
"slow_mo": slow_mo
}
slow_mo = request.config.getoption("--slow-mo")
launch_options = {"headless": headless, "slow_mo": slow_mo}

if browser_type == "chromium":
args = ["--start-maximized"]
browser_instance = playwright.chromium.launch(
headless=launch_options["headless"],
args=args,
slow_mo=launch_options["slow_mo"],
devtools=request.config.getoption("--devtools")
devtools=request.config.getoption("--devtools"),
)
else:
# For other browsers, launch normally
browser_launch_func = {
"firefox": playwright.firefox.launch,
"webkit": playwright.webkit.launch
"webkit": playwright.webkit.launch,
}.get(browser_type)

browser_instance = browser_launch_func(**launch_options)
Expand All @@ -101,7 +95,7 @@ def pytest_runtest_makereport(item):
This works for both failed tests and expected failures (xfail).
"""
# Retrieve the HTML plugin for embedding screenshots
pytest_html = item.config.pluginmanager.getplugin('html')
pytest_html = item.config.pluginmanager.getplugin("html")
outcome = yield
report = outcome.get_result()

Expand All @@ -110,17 +104,19 @@ def pytest_runtest_makereport(item):
return

# Add screenshots for failed tests or expected failures (xfail)
if report.when in ('call', 'setup'):
xfail = hasattr(report, 'wasxfail')
if (report.failed or xfail) and 'page' in item.funcargs:
page = item.funcargs['page']
if report.when in ("call", "setup"):
xfail = hasattr(report, "wasxfail")
if (report.failed or xfail) and "page" in item.funcargs:
page = item.funcargs["page"]
try:
# Capture screenshot as base64
screenshot_bytes = page.screenshot()
screenshot_base64 = base64.b64encode(screenshot_bytes).decode()
# Embed screenshot in the HTML report
extra = getattr(report, 'extra', [])
extra.append(pytest_html.extras.image(screenshot_base64, 'Screenshot'))
extra = getattr(report, "extra", [])
extra.append(
pytest_html.extras.image(screenshot_base64, "Screenshot")
)
report.extra = extra
except Exception as e:
print(f"Error capturing screenshot: {e}")
Expand All @@ -136,7 +132,7 @@ def page(browser, request):
page = browser.new_page(no_viewport=True)

# Fetching and attaching event listeners
selected_listeners = request.config.getoption("--listeners").strip().split(',')
selected_listeners = request.config.getoption("--listeners").strip().split(",")
EventListenerManager(page, selected_listeners, log)

yield page
Expand All @@ -150,7 +146,7 @@ def get_browser_options(request):
return {
"headless": request.config.getoption("--headless"),
"devtools": request.config.getoption("--devtools"),
"proxy": {
"server": request.config.getoption("--proxy")
} if request.config.getoption("--proxy") else None
"proxy": {"server": request.config.getoption("--proxy")}
if request.config.getoption("--proxy")
else None,
}
8 changes: 6 additions & 2 deletions src/drivers/browsers_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ def create_browser(self, launch_options):
with sync_playwright() as p:
match self.browser_type:
case "chromium":
return p.chromium.launch(headless=self.headless, **launch_options)
return p.chromium.launch(
headless=self.headless, **launch_options
)
case "firefox":
return p.firefox.launch(headless=self.headless, **launch_options)
case "webkit":
return p.webkit.launch(headless=self.headless, **launch_options)
case _:
raise ValueError(f"Unsupported browser type: {self.browser_type}")
raise ValueError(
f"Unsupported browser type: {self.browser_type}"
)
12 changes: 6 additions & 6 deletions src/drivers/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ def __init__(self, page, selected_listeners, logger):

def attach_listeners(self):
"""Attach event listeners based on selected options."""
if 'console' in self.selected_listeners:
if "console" in self.selected_listeners:
self.page.on("console", self.handle_console_log)

if 'request' in self.selected_listeners:
if "request" in self.selected_listeners:
self.page.on("request", self.handle_request)

if 'response' in self.selected_listeners:
if "response" in self.selected_listeners:
self.page.on("response", self.handle_response)

if 'events' in self.selected_listeners:
self.page.on('load', self.handle_page_load)
self.page.on('close', self.handle_page_close)
if "events" in self.selected_listeners:
self.page.on("load", self.handle_page_load)
self.page.on("close", self.handle_page_close)

def handle_console_log(self, msg):
self.logger.annotate(f"Console log: {msg.text()}", "info")
Expand Down
22 changes: 17 additions & 5 deletions src/utils/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,33 @@ def __call__(cls, *args, **kwargs) -> Any:


class Logger(metaclass=Singleton):
def __init__(self, log_lvl: LogLevel = LogLevel.INFO, log_base_directory: Optional[str] = None) -> None:
def __init__(
self,
log_lvl: LogLevel = LogLevel.INFO,
log_base_directory: Optional[str] = None,
) -> None:
self._log = logging.getLogger("selenium")
self._log.setLevel(LogLevel.DEBUG.value)
self.log_base_directory = log_base_directory or os.path.abspath(os.path.join(os.path.dirname(__file__), '../..')) # Default to the project's root directory
self.log_base_directory = log_base_directory or os.path.abspath(
os.path.join(os.path.dirname(__file__), "../..")
) # Default to the project's root directory
self.log_file = self._create_log_file()
self._initialize_logging(log_lvl)

def _create_log_file(self) -> str:
current_time = time.strftime("%Y-%m-%d")
log_directory = os.path.join(self.log_base_directory, "reports/logs") # Build the path to reports/logs
log_directory = os.path.join(
self.log_base_directory, "reports/logs"
) # Build the path to reports/logs

try:
os.makedirs(log_directory, exist_ok=True) # Create directory if it doesn't exist
os.makedirs(
log_directory, exist_ok=True
) # Create directory if it doesn't exist
except Exception as e:
raise RuntimeError(f"Failed to create log directory '{log_directory}': {e}")
raise RuntimeError(
f"Failed to create log directory '{log_directory}': {e}"
)

return os.path.join(log_directory, f"log_{current_time}.log")

Expand Down
1 change: 0 additions & 1 deletion tests/test_1.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import pytest
from playwright.sync_api import Page


Expand Down

0 comments on commit 5beaa14

Please sign in to comment.