Skip to main content

browser_fixtures: don't warn for local media files served over HTTP

ID
0dbcaca
date
2026-10-26 21:24:54+00:00
author
Alex Chan <alex@alexwlchan.net>
parent
5d5f56a
message
browser_fixtures: don't warn for local media files served over HTTP
changed files
8 files, 66 additions, 11 deletions

Changed files

CHANGELOG.md (8857 → 9021)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 680c834..0860ded 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # CHANGELOG
 
+## v57 - 2026-10-26
+
+Another fix for `verify_local_page_integrity` -- don't report errors on pages loaded over HTTP that load media using `<audio>` and `<video>`.
+
 ## v56 - 2026-10-25
 
 Two small changes to `verify_local_page_integrity`:

javascript/chives-image.js (6561 → 6561)

diff --git a/javascript/chives-image.js b/javascript/chives-image.js
index 515036d..2a839f9 100644
--- a/javascript/chives-image.js
+++ b/javascript/chives-image.js
@@ -1,5 +1,5 @@
 // javascript/chives-image.js
-// chives version: 56
+// chives version: 57
 
 // ChivesImage provides a <chives-image> component that renders
 // an ImageEntity on a web page.

javascript/chives-pagination.js (4929 → 4929)

diff --git a/javascript/chives-pagination.js b/javascript/chives-pagination.js
index 3909902..63c22c1 100644
--- a/javascript/chives-pagination.js
+++ b/javascript/chives-pagination.js
@@ -1,5 +1,5 @@
 // javascript/chives-pagination.js
-// chives version: 56
+// chives version: 57
 
 // ChivesPagination manages the pagination of a collection of items.
 //

javascript/chives-sorting.js (5034 → 5034)

diff --git a/javascript/chives-sorting.js b/javascript/chives-sorting.js
index c3a7d59..963249e 100644
--- a/javascript/chives-sorting.js
+++ b/javascript/chives-sorting.js
@@ -1,5 +1,5 @@
 // javascript/chives-sorting.js
-// chives version: 56
+// chives version: 57
 
 // ChivesSorting manages the sorting of a collection of items.
 //

javascript/chives-video.js (5147 → 5147)

diff --git a/javascript/chives-video.js b/javascript/chives-video.js
index ecf7480..c92194d 100644
--- a/javascript/chives-video.js
+++ b/javascript/chives-video.js
@@ -1,5 +1,5 @@
 // javascript/chives-video.js
-// chives version: 56
+// chives version: 57
 
 // ChivesVideo provides a <chives-video> component that renders
 // a VideoEntity on a web page.

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

diff --git a/python/chives/__init__.py b/python/chives/__init__.py
index bb95745..84078d7 100644
--- a/python/chives/__init__.py
+++ b/python/chives/__init__.py
@@ -11,4 +11,4 @@ I share across multiple sites.
 
 """
 
-__version__ = "56"
+__version__ = "57"

python/chives/browser_fixtures.py (12020 → 12115)

diff --git a/python/chives/browser_fixtures.py b/python/chives/browser_fixtures.py
index a64e1c2..c26f5a3 100644
--- a/python/chives/browser_fixtures.py
+++ b/python/chives/browser_fixtures.py
@@ -351,12 +351,12 @@ def _is_external_request(req: Request, original_url: str) -> bool:
     if org_url.scheme == req_url.scheme and org_url.netloc == req_url.netloc:
         return False
 
-    # Ignore URLs like blob:null/<uuid>
-    if (
-        req_url.scheme == "blob"
-        and req_url.netloc == ""
-        and req_url.path.startswith("null/")
-    ):
+    # Ignore blob: URLs, which are in-memory representation of some data,
+    # and not an external request.
+    #
+    # Playwright detects blob: URLs when loading media files; for example
+    # using the <audio> or <video> tag.
+    if req_url.scheme == "blob":
         return False
 
     return True

tests/python/test_browser_fixtures.py (17642 → 19145)

diff --git a/tests/python/test_browser_fixtures.py b/tests/python/test_browser_fixtures.py
index 51b5977..57ff927 100644
--- a/tests/python/test_browser_fixtures.py
+++ b/tests/python/test_browser_fixtures.py
@@ -3,10 +3,12 @@ Tests for `chives.browser_fixtures`.
 """
 
 from collections.abc import Iterator
+from http.client import HTTPConnection
 import os
 from pathlib import Path
 import shutil
 import subprocess
+import time
 
 from playwright.sync_api import sync_playwright, Browser
 import pytest
@@ -186,6 +188,34 @@ def test_skip_playwright(pytester: Pytester, skip_playwright_envvar: None) -> No
     pytester.runpytest().assert_outcomes(skipped=2)
 
 
+@pytest.fixture
+def static_server(tmp_path: Path) -> Iterator[str]:
+    """
+    Return the URL of a static web server that serves the contents
+    of `tmp_path`.
+
+    See https://til.simonwillison.net/pytest/subprocess-server
+    """
+    cmd = ["python", "-m", "http.server", "8123", "--directory", str(tmp_path)]
+    proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+
+    for _ in range(5):
+        conn = HTTPConnection("localhost:8123")
+        try:
+            conn.request("HEAD", "/")
+            conn.getresponse()
+            yield "http://localhost:8123"
+            break
+        except ConnectionRefusedError:
+            time.sleep(1)
+
+    else:  # pragma: no cover
+        raise RuntimeError("Failed to start http server")
+
+    proc.terminate()
+    proc.wait()
+
+
 class TestVerifyLocalPageIntegrity:
     """
     Tests for `verify_local_page_integrity`.
@@ -422,6 +452,27 @@ class TestVerifyLocalPageIntegrity:
 
         self.assert_page_verifies_ok(browser, p)
 
+    def test_video_over_http(
+        self, tmp_path: Path, static_server: str, browser: Browser
+    ) -> None:
+        """
+        Load a <video> over HTTP.
+        """
+        shutil.copyfile(
+            "tests/fixtures/media/wings_tracking_shot.mp4",
+            tmp_path / "wings_tracking_shot.mp4",
+        )
+        p = tmp_path / "video.html"
+        p.write_text(
+            """
+            <video controls height="300">
+              <source src="wings_tracking_shot.mp4">
+            </video>
+            """
+        )
+        page = browser.new_page()
+        verify_local_page_integrity(page, url=static_server + "/video.html")
+
     def test_loading_svg_from_file_uri(self, tmp_path: Path, browser: Browser) -> None:
         """
         Loading an external SVG from a file:/// URI is fine if the SVG exists,