mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-24 07:42:21 +02:00
test(css): pin computed styles against a committed baseline
static/style.css is 51,425 lines in one file. Hundreds of selectors are declared more than once and !important is used throughout, so the rendered result is a function of source order. Extracting a block into its own file changes that order, and nothing in the suite would notice - which makes a 51k-line split unfalsifiable and "looks fine to me" the only available evidence. This moves no CSS. It captures getComputedStyle over a fixed inventory of 676 elements across three pages, four viewports, both themes and the three density modes - 16,224 element snapshots - hashes them, and compares against tests/css_snapshot/baseline.json. A capture takes about 21 seconds. The bench page synthesises one element per selector from an evidence-driven list: every selector declared more than once in style.css that can be expressed as a static compound chain, plus a curated set per feature area. Redeclared selectors are the ones a reorder can flip. The bench loads whatever stylesheets index.html ships, so it keeps measuring the real set once the file is split. tests/test_css_computed_style_snapshot.py also carries a self-test that swaps two conflicting .attach-strip declarations and asserts the digest moves, so the harness cannot silently stop watching. The second half is the asset-manifest check specs/frontend.md asks for, scoped to stylesheets: every stylesheet referenced by shipped HTML and by the sw.js precache exists, and index.html and sw.js agree on the ?v= string. They hardcode it independently today, so a split that updates one and not the other ships an offline cache nobody notices until a plane.
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
"""Stylesheet asset manifest: shipped HTML and the service worker must agree.
|
||||
|
||||
``specs/frontend.md`` records that nothing validates the service-worker
|
||||
precache against what ``index.html`` actually loads, and that a static asset
|
||||
manifest regression should confirm referenced files exist. Both matter more
|
||||
once ``static/style.css`` starts being split: every new stylesheet has to be
|
||||
registered in ``static/index.html`` *and* in the ``static/sw.js`` precache,
|
||||
with the same ``?v=`` cache-bust string in both. Today those two strings are
|
||||
hardcoded independently, so a split that updates one and not the other ships an
|
||||
offline cache that serves a stale or missing stylesheet - invisible until
|
||||
someone loads the app without a network.
|
||||
|
||||
This test reads the shipped files rather than driving a browser: the artifact
|
||||
under test *is* the URL string in two files, and a browser would only see one
|
||||
of them at a time.
|
||||
"""
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
INDEX_HTML = ROOT / "static" / "index.html"
|
||||
SERVICE_WORKER = ROOT / "static" / "sw.js"
|
||||
|
||||
_STYLESHEET_LINK = re.compile(
|
||||
r"""<link\b[^>]*\brel=["']stylesheet["'][^>]*>""", re.IGNORECASE)
|
||||
_HREF = re.compile(r"""\bhref=["']([^"']+)["']""", re.IGNORECASE)
|
||||
|
||||
|
||||
def _stylesheet_hrefs(html_path):
|
||||
"""Every href from a <link rel="stylesheet"> in one HTML file."""
|
||||
html = html_path.read_text(encoding="utf-8")
|
||||
hrefs = []
|
||||
for tag in _STYLESHEET_LINK.findall(html):
|
||||
match = _HREF.search(tag)
|
||||
if match:
|
||||
hrefs.append(match.group(1))
|
||||
return hrefs
|
||||
|
||||
|
||||
def _precache_entries(name):
|
||||
"""The quoted URLs of one precache array in sw.js.
|
||||
|
||||
Entries built by spreading another list (``...KATEX_FONTS``) are skipped:
|
||||
they carry no literal URL at this level, and the fonts they add are not
|
||||
stylesheets.
|
||||
"""
|
||||
source = SERVICE_WORKER.read_text(encoding="utf-8")
|
||||
match = re.search(rf"const {name} = \[(.*?)\n\];", source, re.DOTALL)
|
||||
assert match, f"{name} array not found in static/sw.js"
|
||||
return re.findall(r"""['"](/[^'"]+)['"]""", match.group(1))
|
||||
|
||||
|
||||
def _local_path(url):
|
||||
"""Map an app-absolute URL to the file it is served from."""
|
||||
return ROOT / url.split("?", 1)[0].lstrip("/")
|
||||
|
||||
|
||||
def test_every_stylesheet_referenced_by_shipped_html_exists():
|
||||
checked = 0
|
||||
for html_path in sorted((ROOT / "static").glob("*.html")):
|
||||
for href in _stylesheet_hrefs(html_path):
|
||||
if not href.startswith("/"):
|
||||
continue # external or relative-to-page; not ours to resolve
|
||||
assert _local_path(href).is_file(), (
|
||||
f"{html_path.name} links {href}, which does not exist on disk"
|
||||
)
|
||||
checked += 1
|
||||
assert checked, "no app stylesheet links found - the parser or the markup moved"
|
||||
|
||||
|
||||
def test_every_precached_stylesheet_exists():
|
||||
for name in ("PRECACHE", "PANEL_PRECACHE"):
|
||||
for url in _precache_entries(name):
|
||||
if not url.endswith(".css") and ".css?" not in url:
|
||||
continue
|
||||
assert _local_path(url).is_file(), (
|
||||
f"sw.js {name} precaches {url}, which does not exist on disk"
|
||||
)
|
||||
|
||||
|
||||
def test_index_stylesheets_are_precached_with_the_same_cache_bust_string():
|
||||
"""The precache must match the request the browser actually makes.
|
||||
|
||||
A service-worker entry only matches a fetch when the URL is identical,
|
||||
query string included, so a stylesheet whose ``?v=`` differs between the
|
||||
two files is precached under a URL nothing ever requests.
|
||||
"""
|
||||
precached = set(_precache_entries("PRECACHE"))
|
||||
precached_paths = {url.split("?", 1)[0]: url for url in precached}
|
||||
|
||||
for href in _stylesheet_hrefs(INDEX_HTML):
|
||||
if not href.startswith("/static/"):
|
||||
continue
|
||||
path = href.split("?", 1)[0]
|
||||
assert path in precached_paths, (
|
||||
f"index.html loads {href} but sw.js PRECACHE has no entry for {path}; "
|
||||
"the app shell would not be available offline"
|
||||
)
|
||||
assert precached_paths[path] == href, (
|
||||
f"cache-bust mismatch for {path}: index.html requests {href!r}, "
|
||||
f"sw.js precaches {precached_paths[path]!r}"
|
||||
)
|
||||
Reference in New Issue
Block a user