Asset and structural tests

tests/test_assets_structure.py checks rendered assets and theme controls that Sphinx does not validate. It has a fast offline check and a slow, advisory check of external resources. Both use representative pages, not a whole-site crawl.

Fast: local assets and structure

  • Local linked stylesheets, scripts and images resolve to files relative to each generated page. The home page, both syntax cheat sheets, a nested code-heading page and search are representative fixtures.

  • Core Ulwazi CSS and JS are linked; no page loads the same stylesheet or script twice. Search loads its breadcrumb script exactly once, and other pages do not load it.

  • Side-navigation expanders’ checkbox IDs match their labels and theme data attributes. Local-TOC fragments target the same page’s article.

  • Theme tab/control IDs are unique, and notifications do not have empty IDs.

The test_assets_structure_fast case checks these contracts without network access. It also uses mocked responses to check the slow probe’s URL discovery, retry, redirect safety, and warning messages. It does not re-check Sphinx’s source-reference warnings, sitemap/SEO, or extension-specific output such as structured-TOC navigation.

Slow: remote availability

The test_assets_structure_slow case checks statically referenced external assets on the same pages: stylesheets, scripts, images (including srcset), Open Graph preview images, and remote fonts and backgrounds referenced by linked local CSS. It probes each distinct URL once, with bounded timeouts and at most one retry for transient problems. The current sample assets use assets.ubuntu.com; probes are restricted to reviewed public asset hosts.

If a resource cannot be confirmed available, the case passes with a pytest warning listing the URL, HTTP reason, and the originating source file and line number when the URL occurs literally in docs/conf.py, a sampled MyST or RST source page, or a checked-in theme stylesheet. A URL emitted by a template or third-party extension without an identifiable source is reported as rendered <page>/index.html:<line> instead. For example:

tests/test_assets_structure.py: RemoteAssetWarning: Assets and structure [slow]:
  remote availability is advisory; fallback not verified:
  - https://assets.ubuntu.com/v1/example.png (HTTP 404; referenced by docs/content/myst-cheat-sheet.md:439 img[src])

Read the warnings summary even when pytest reports PASSED: a green result means the check ran, not that every remote asset was healthy. The slow tier is scheduled and can also be run manually. Ordinary hyperlinks, resources loaded only by runtime JavaScript (such as analytics), disabled optional menus, and resources imported by remote stylesheets are outside this check. It is a snapshot of availability, not uptime monitoring or a rendering test.

No CDN-to-local asset failover is currently configured. System-font choices and path-based search breadcrumbs are not evidence that a replacement asset loaded. The slow check therefore reports an unavailable primary with “fallback not verified”; it never claims a fallback was used. If an asset failover is added, it needs a separate browser test that blocks the primary and observes the secondary loading successfully.

How it is tested

The checks parse a fresh dirhtml build with Beautiful Soup. Run the fast case with make test, or the slow advisory with make test-slow (which also runs other slow tests). To run either case alone, use uv run --group docs pytest -m 'not slow' tests/test_assets_structure.py or uv run --group docs pytest -m slow tests/test_assets_structure.py.

The fast assertion collects every broken local resource or control under Assets and structure [fast] checks failed, for example:

Assets and structure [fast] checks failed:
- [content/myst-cheat-sheet] script[src] '../../_static/js/nav-toggle.js': missing /tmp/.../html/_static/js/nav-toggle.js
- [search] breadcrumb script: expected 1, got 2

When green, the category recap groups these tests with other asset/structure checks on one line, with separate fast and slow statuses. Use -vv to see individual test IDs.