validator/ holds mewslint (lint, css, fetch, DTD/CSS data); directory/ holds the mews.page service (app, db, check, pages, cli) and depends on validator/; quickstart/ holds mews-quickstart and md2mews.py for third parties who want to create Mews content without cloning the repo; spec/ consolidates doc/ and dtd/ with the canonical mews-0.1.css; site/ becomes a Pelican project with the forward-facing pages as Markdown, the check form kept as a raw HTML snippet. Root pyproject.toml is now a virtual uv workspace over validator, directory and quickstart, with cross-cutting tests that span more than one of them staying at the repo root. Makefile and flake.nix updated to match.
78 lines
2.5 KiB
Python
78 lines
2.5 KiB
Python
"""The project's own pages. Every one of them has to follow the spec."""
|
|
|
|
from pathlib import Path
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
|
|
import pytest
|
|
|
|
from mews.lint import validate_file
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
SITE = ROOT / "site"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def built_site():
|
|
"""Build the Pelican site once per test session, and return its output dir."""
|
|
result = subprocess.run(
|
|
[shutil.which("uv"), "run", "pelican", "content", "-o", "output"],
|
|
cwd=SITE,
|
|
capture_output=True,
|
|
text=True,
|
|
check=False,
|
|
)
|
|
assert result.returncode == 0, result.stderr
|
|
return SITE / "output"
|
|
|
|
|
|
@pytest.mark.skipif(shutil.which("uv") is None, reason="uv is not installed")
|
|
@pytest.mark.slow
|
|
def test_the_sites_own_pages_conform(built_site):
|
|
pages = sorted(built_site.glob("*.html"))
|
|
assert pages, "the site build produced no pages"
|
|
for page in pages:
|
|
report = validate_file(str(page))
|
|
assert report.conforms, "\n".join(str(f) for f in report.failures)
|
|
|
|
|
|
@pytest.mark.skipif(shutil.which("uv") is None, reason="uv is not installed")
|
|
@pytest.mark.slow
|
|
def test_the_sites_own_pages_have_no_warnings_either(built_site):
|
|
for page in sorted(built_site.glob("*.html")):
|
|
report = validate_file(str(page))
|
|
assert not report.warnings, "\n".join(str(f) for f in report.warnings)
|
|
|
|
|
|
def test_the_sample_page_conforms():
|
|
report = validate_file(str(ROOT / "sample" / "sample.html"))
|
|
assert report.conforms, "\n".join(str(f) for f in report.failures)
|
|
|
|
|
|
def test_the_sample_page_has_no_warnings_either():
|
|
report = validate_file(str(ROOT / "sample" / "sample.html"))
|
|
assert not report.warnings, "\n".join(str(f) for f in report.warnings)
|
|
|
|
|
|
PLUGIN_PAGES = sorted(
|
|
(ROOT / "pelican-mews" / "tests" / "fixtures").glob("*/expected.xhtml")
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize("page", PLUGIN_PAGES, ids=lambda p: p.parent.name)
|
|
def test_pages_the_pelican_plugin_produces_conform(page):
|
|
"""What the plugin writes has to pass the validator, or it is no use."""
|
|
report = validate_file(str(page))
|
|
assert report.conforms, "\n".join(str(f) for f in report.failures)
|
|
|
|
|
|
def test_the_dtd_still_matches_the_spec():
|
|
"""spec/check_dtd.py is hand-maintained; keep it running in CI."""
|
|
result = subprocess.run(
|
|
[sys.executable, str(ROOT / "spec" / "check_dtd.py")],
|
|
capture_output=True,
|
|
text=True,
|
|
check=False,
|
|
)
|
|
assert result.returncode == 0, result.stderr
|