mews.page/tests/test_pages.py
randogoth 060d4e00fd refactor: split the repo into self-contained validator, directory, quickstart, spec and site folders
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.
2026-10-13 12:29:23 +03:00

67 lines
2.2 KiB
Python

"""The page emitter, against md2mews.py's.
directory.pages repeats md2mews.page() because md2mews.py is a standalone
script with its own dependencies. This is what keeps the two in step.
"""
import importlib.util
from pathlib import Path
import sys
import pytest
from directory import pages
ROOT = Path(__file__).resolve().parent.parent
def load_md2mews():
"""Import md2mews.py, which is a script rather than part of a package."""
spec = importlib.util.spec_from_file_location(
"md2mews", ROOT / "quickstart" / "md2mews.py"
)
module = importlib.util.module_from_spec(spec)
sys.modules["md2mews"] = module
spec.loader.exec_module(module)
return module
CASES = [
("Plain", [" <p>x</p>"], "en", None, None, None),
("With a variant", [" <p>x</p>"], "en", None, "mews-cool", None),
("Right to left", [" <p>x</p>"], "he", "rtl", None, None),
("Described", [" <p>x</p>"], "en", None, "mews-warm", "A page."),
("An ampersand & a <tag>", [" <p>x</p>"], "en", None, None, None),
]
@pytest.mark.parametrize("case", CASES)
def test_the_two_emitters_agree(case):
"""Same prologue, head order, body attributes and escaping of & and <.
The two differ on quote characters in text, which md2mews.py escapes
because its one escape helper also fills attribute values. Both are
well-formed; mews.pages leaves them alone so prose reads as prose.
"""
md2mews = pytest.importorskip("mistune") and load_md2mews()
title, body, language, direction, variant, description = case
assert pages.page(title, body, language, direction, variant, description) == (
md2mews.page(title, body, language, direction, variant, description)
)
def test_a_message_page_conforms():
from mews.lint import validate_bytes
text = pages.message("Hello", ["One.", "Two."], [("/", "Home")])
assert validate_bytes(text.encode()).conforms
def test_quotes_in_text_are_left_alone():
text = pages.site_page('A "quoted" title', [" <p>x</p>"])
assert '<title>A "quoted" title</title>' in text
def test_an_apostrophe_is_not_escaped():
text = pages.message("Hello", ["It isn't escaped."], [("/", "Home")])
assert "isn't escaped" in text