Non-blocking visual signals (banners/flash) for Selenium runs; optional pytest auto-annotation.
Project description
Browser Signals — Visual in‑browser cues for Selenium tests
Non‑blocking, DOM-based visual signals that appear inside the page during automated UI tests. Great for CI/Xvfb recordings so you can instantly see when a test failed.
Quick links:
- Example project:
examples/basic-pytest - Pytest usage: auto-annotates failures when your test has a
driverfixture - Script usage (no pytest): call
mark_failure,mark_info, or wrap withannotate_failures
Install for local dev:
pip install -e ".[pytest,selenium]"
# alternatively, install from requirements.txt at repo root
pip install -r requirements.txt
Run the example:
cd examples/basic-pytest
# Headed run with a small pause so you can see the banner
../../.venv/bin/python -m pytest -q
# Customize the pause
BROWSER_SIGNALS_PAUSE_SECONDS=4 ../../.venv/bin/python -m pytest -q
# CI/headless (no pause by default)
HEADLESS=true ../../.venv/bin/python -m pytest -q
Features
- Failure banners (top-of-page red banner with message)
- Brief translucent "timeline" flash
- Optional info/warning banners
- Non-blocking (no alerts that halt execution)
- Works with or without pytest (pytest plugin auto-annotates failures)
Usage with pytest
The plugin is auto-discovered by pytest via entry-points. If your test has a Selenium driver fixture named driver, browser, or web_driver, a failure will inject a red banner and a short flash into the DOM.
def test_missing_element_injects_banner(driver):
driver.find_element("css selector", "#definitely-not-here") # fails -> banner + flash
Controls:
- Disable plugin:
BROWSER_SIGNALS_DISABLE_PYTEST=true - Pause after banner (for local visibility):
BROWSER_SIGNALS_PAUSE_SECONDS=2 - Show a running banner during tests (opt-in):
BROWSER_SIGNALS_SHOW_RUNNING=true
Usage without pytest
from browser_signals import mark_failure, mark_warning, mark_info, annotate_failures
mark_info(driver, "Starting login", use_flash=True)
with annotate_failures(driver, label="Login flow"):
driver.get("https://example.com")
driver.find_element("css selector", "#definitely-not-here") # banners + re-raise
API:
mark_failure(driver, message, use_flash=True, frame=None)mark_warning(driver, message, use_flash=False, frame=None)mark_info(driver, message, use_flash=False, frame=None)annotate_failures(driver, label="", use_flash=True, frame=None)(context manager)alert_on_exception(driver, label="", use_flash=True, frame=None)(decorator)
Running banner helpers:
show_test_banner(driver, text="Running Test...", color="#facc15", frame=None)remove_test_banner(driver, frame=None)navigate_with_banner(driver, url, banner_text="Running Test...", color="#facc15", frame=None)
Unified banners:
show_banner(driver, text, persistent=False, flash=False, duration_ms=5000, position="top-left", full_banner=False, color=None, log=True, frame=None, id=None)- Chips (full_banner=False): position can be
top-leftortop-right. Persistent chips remain until you callremove_banner; otherwise they auto-remove afterduration_ms. - Full-width (full_banner=True): uses the large page-top banner; transient by default, or simulated persistent if
persistent=True. flash=Trueadds a short translucent flash.log=Truewrites a console entry with a millisecond timestamp.
- Chips (full_banner=False): position can be
remove_banner(driver, id=None, full_banner=False, frame=None)- Removes by id; defaults to the running chip id when
full_banner=False, or the main banner id whenfull_banner=True.
- Removes by id; defaults to the running chip id when
Examples:
# Chip (top-right), persistent
from browser_signals import show_banner, remove_banner
show_banner(driver, "Running: checkout flow", position="top-right", persistent=True, color="#fde047")
# ... later
remove_banner(driver)
# Full-width transient info banner
show_banner(driver, "Fetched dashboard data", full_banner=True, duration_ms=4000)
# Chip with a timeline flash
show_banner(driver, "Step complete", flash=True, duration_ms=1200)
Configuration and env vars
BROWSER_SIGNALS_DISABLE_PYTEST— set totrue/1to disable the pytest plugin.BROWSER_SIGNALS_PAUSE_SECONDS— seconds to sleep after injecting a failure (useful for local demos). Disabled by default; the example enables 2s in headed runs.HEADLESS— if set totrue/1, the example fixture runs Chrome headless and does not add the pause.
Recommended Chrome flags for CI/Xvfb (used in the example fixture): --no-sandbox, --disable-dev-shm-usage, --disable-gpu, --window-size=1280,800.
Troubleshooting
- Chromedriver not found / version mismatch: ensure a compatible chromedriver is on PATH, or install
webdriver-managerand let the example fall back automatically. - Duplicate plugin registration: avoid manually adding
pytest_plugins = ["browser_signals.pytest_plugin"]if the package is installed with the pytest entry-point; use one or the other. - Not seeing the banner in recordings: increase
BROWSER_SIGNALS_PAUSE_SECONDSlocally, or adjust banner duration incore.pyfor your needs.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file browser_signals-0.1.0.tar.gz.
File metadata
- Download URL: browser_signals-0.1.0.tar.gz
- Upload date:
- Size: 12.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d3c06050eb020c540d31f808702f6d709201a3ce0e80d7f8cc512b0e4ff4b92
|
|
| MD5 |
680c9a2a10ce255517c0287c6391ee45
|
|
| BLAKE2b-256 |
201d6875ccef64db574ebf7ae37a4f4d404fe69af09157a4430b5f67ac77d5e6
|
File details
Details for the file browser_signals-0.1.0-py3-none-any.whl.
File metadata
- Download URL: browser_signals-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
118311f52428543032e3d1dafe932d705fc0dc3009a9295bf12f93c0ce5c29f8
|
|
| MD5 |
d09220ac89860e189104b1cf1564727d
|
|
| BLAKE2b-256 |
c82ce4c44f4ba83a1982de0f27f65e446149901c8972383e276d3494d357cacd
|