Skip to main content

browser_fixtures: make browser be session-scoped; improve docs

ID
108ddb5
date
2026-07-16 20:41:19+00:00
author
Alex Chan <alex@alexwlchan.net>
parent
76d0c27
message
browser_fixtures: make browser be session-scoped; improve docs
changed files
3 files, 58 additions, 7 deletions

Changed files

CHANGELOG.md (5957) → CHANGELOG.md (6148)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9726b45..a1e39f3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # CHANGELOG
 
+## v46 - 2026-07-16
+
+Change the `browser` fixture to be session-scoped, so the browser only needs to be started once per test suite.
+
+Also, improve the documentation for `browser_fixtures`.
+
 ## v45 - 2026-07-16
 
 Fix a bug with SRT subtitle files that contain a [byte order mark (BOM)][wiki-bom].

src/chives/__init__.py (391) → src/chives/__init__.py (391)

diff --git a/src/chives/__init__.py b/src/chives/__init__.py
index 1ac2f82..eec5a4d 100644
--- a/src/chives/__init__.py
+++ b/src/chives/__init__.py
@@ -11,4 +11,4 @@ I share across multiple sites.
 
 """
 
-__version__ = "45"
+__version__ = "46"

src/chives/browser_fixtures.py (1614) → src/chives/browser_fixtures.py (3361)

diff --git a/src/chives/browser_fixtures.py b/src/chives/browser_fixtures.py
index 71854b3..0141729 100644
--- a/src/chives/browser_fixtures.py
+++ b/src/chives/browser_fixtures.py
@@ -1,7 +1,38 @@
 """
 Provide a set of Playwright fixtures to use when testing static sites.
 
-See https://alexwlchan.net/2026/playwright/
+You can start an instance of a web browser, open a URL or local HTML file,
+and make Playwright assertions about the page.
+
+The `browser` fixture gives you an instance of a Playwright Browser.
+In this example, we open the local file `greeting.html` and check it
+contains the phrase `Hello world!`:
+
+    from playwright.sync_api import Browser, expect
+    from chives.browser_fixtures import browser, file_uri
+
+
+    def test_browser(browser: Browser) -> None:
+        uri = file_uri("greeting.html")
+
+        p = browser.new_page()
+        p.goto(uri)
+        expect(p.get_by_text("Hello world!")).to_be_visible()
+
+The `page` fixture gives you an instance of a Playwright Page.
+It automatically listens for console warnings, console errors, and
+page errors, and raises an assertion error on teardown if any occurred:
+
+    from playwright.sync_api import Page, expect
+    from chives.browser_fixtures import page, file_uri
+
+
+    def test_page(page: Page) -> None:
+        uri = file_uri("greeting.html")
+        page.goto(uri)
+        expect(page.get_by_text("Hello world!")).to_be_visible()
+
+For more information, see https://alexwlchan.net/2026/playwright/
 """
 
 from collections.abc import Iterator
@@ -13,19 +44,29 @@ import pytest
 from playwright.sync_api import Browser, Page, sync_playwright
 
 
+__all__ = ["file_uri", "browser", "page"]
+
+
 def file_uri(p: Path | str) -> str:
     """
-    Convert a path to a file:/// URI.
+    Convert a file path into a valid `file:///` URI for browser loading.
     """
     p = Path(p)
     absolute_path = str(p.absolute())
     return pathname2url(absolute_path, add_scheme=True)
 
 
-@pytest.fixture
+@pytest.fixture(scope="session")
 def browser() -> Iterator[Browser]:
     """
-    Launch an instance of WebKit we can interact with in tests.
+    Launch an instance of WebKit for testing.
+
+    WebKit is my primary browser, so it's the only engine where I need
+    my static websites to work. My sites are simple enough that they're
+    unlikely to rely on WebKit-specific behavior or break in other browsers.
+
+    If the environment variable `SKIP_PLAYWRIGHT` is set, this fixture will
+    automatically skip any tests that depend on it to speed up test runs.
     """
     if "SKIP_PLAYWRIGHT" in os.environ:
         pytest.skip(reason="skip slow Playwright tests")
@@ -36,10 +77,14 @@ def browser() -> Iterator[Browser]:
         browser.close()
 
 
-@pytest.fixture
+@pytest.fixture(scope="function")
 def page(browser: Browser) -> Iterator[Page]:
     """
-    Open a new browser page which checks for errors and warnings.
+    Open a browser page that monitors for errors.
+
+    On teardown (after your test function finishes), this fixture asserts
+    that no console warnings, console errors, or unhandled exceptions
+    occurred during the page session.
     """
     p = browser.new_page()