Skip to content

Commit 12df697

Browse files
authored
test: cover the redirect stubs the build writes (#60)
1 parent 6ccfd2f commit 12df697

1 file changed

Lines changed: 120 additions & 0 deletions

File tree

‎tests/mkdocs_hooks_test.py‎

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
"""Tests for the redirect stubs ``scripts/mkdocs_hooks.py`` writes after a build.
2+
3+
Run them with the rest of the suite::
4+
5+
pytest tests/
6+
"""
7+
8+
from __future__ import annotations
9+
10+
import importlib.util
11+
from pathlib import Path
12+
13+
import pytest
14+
15+
HOOKS_PATH = Path(__file__).parent.parent / "scripts" / "mkdocs_hooks.py"
16+
17+
# ``scripts/`` is not a package: MkDocs loads the hook by path, and so does this.
18+
_spec = importlib.util.spec_from_file_location("mkdocs_hooks", HOOKS_PATH)
19+
assert _spec is not None and _spec.loader is not None
20+
hooks = importlib.util.module_from_spec(_spec)
21+
_spec.loader.exec_module(hooks)
22+
23+
24+
def _build(tmp_path: Path, site_url: str | None) -> Path:
25+
site = tmp_path / "site"
26+
site.mkdir()
27+
hooks.on_post_build({"site_dir": str(site), "site_url": site_url})
28+
return site
29+
30+
31+
def _target(stub: Path) -> str:
32+
"""The URL a stub sends the browser to."""
33+
text = stub.read_text(encoding="utf-8")
34+
start = text.index('var target = "') + len('var target = "')
35+
return text[start : text.index('"', start)]
36+
37+
38+
@pytest.fixture
39+
def not_netlify(monkeypatch):
40+
monkeypatch.delenv("NETLIFY", raising=False)
41+
42+
43+
def test_every_retired_and_legacy_url_gets_a_stub(tmp_path, not_netlify):
44+
site = _build(tmp_path, "https://commit-check.com/")
45+
46+
for old, target in hooks.MOVED_URLS.items():
47+
assert (
48+
_target(site / old / "index.html") == f"https://commit-check.com/{target}"
49+
)
50+
for legacy, target in hooks.LEGACY_URLS.items():
51+
assert _target(site / f"{legacy}.html") == f"https://commit-check.com/{target}"
52+
53+
54+
def test_a_stub_redirects_three_ways_and_keeps_the_fragment(tmp_path, not_netlify):
55+
site = _build(tmp_path, "https://commit-check.com/")
56+
text = (site / "rules.html").read_text(encoding="utf-8")
57+
58+
url = "https://commit-check.com/rules/"
59+
assert f'<link rel="canonical" href="{url}">' in text
60+
assert f'<meta http-equiv="refresh" content="0; url={url}">' in text
61+
# The script, not the meta refresh, is what carries ``#cc003`` across.
62+
assert "location.replace(target + location.hash)" in text
63+
assert f'<a href="{url}">{url}</a>' in text
64+
65+
66+
def test_a_site_url_without_a_trailing_slash_still_joins(tmp_path, not_netlify):
67+
# Deploy previews pass their own URL in, sometimes without the slash.
68+
site = _build(tmp_path, "https://deploy-preview-7--commit-check.netlify.app")
69+
70+
assert _target(site / "rules.html") == (
71+
"https://deploy-preview-7--commit-check.netlify.app/rules/"
72+
)
73+
74+
75+
def test_without_a_site_url_the_targets_are_root_relative(tmp_path, not_netlify):
76+
site = _build(tmp_path, None)
77+
78+
assert _target(site / "rules.html") == "/rules/"
79+
assert _target(site / "projects" / "index.html") == "/"
80+
81+
82+
def test_on_netlify_only_the_retired_pages_get_stubs(tmp_path, monkeypatch):
83+
# netlify.toml redirects the .html URLs; a stub there would shadow
84+
# rules/index.html and loop.
85+
monkeypatch.setenv("NETLIFY", "true")
86+
site = _build(tmp_path, "https://commit-check.com/")
87+
88+
for old in hooks.MOVED_URLS:
89+
assert (site / old / "index.html").is_file()
90+
assert not any(site.glob("*.html"))
91+
92+
93+
def test_a_stub_never_overwrites_a_page_the_build_wrote(tmp_path, not_netlify):
94+
# The stubs run after the build, so a retired URL that became a real page
95+
# again would be replaced by a redirect away from itself.
96+
site = tmp_path / "site"
97+
site.mkdir()
98+
page = site / "guides" / "pre-commit" / "index.html"
99+
page.parent.mkdir(parents=True)
100+
page.write_text("real page", encoding="utf-8")
101+
102+
hooks.on_post_build(
103+
{"site_dir": str(site), "site_url": "https://commit-check.com/"}
104+
)
105+
106+
assert page.read_text(encoding="utf-8") == "real page"
107+
108+
109+
def test_no_stub_redirects_to_another_stub():
110+
# A chain would cost a second hop, and a cycle would never end.
111+
retired = {f"{old}/" for old in hooks.MOVED_URLS}
112+
for target in [*hooks.MOVED_URLS.values(), *hooks.LEGACY_URLS.values()]:
113+
assert target not in retired, target
114+
115+
116+
def test_the_pages_the_cli_links_to_never_move():
117+
# Every released commit-check prints commit-check.com/rules/#ccNNN, and
118+
# links to configuration/; those two pages must stay where they are.
119+
assert "rules" not in hooks.MOVED_URLS
120+
assert "configuration" not in hooks.MOVED_URLS

0 commit comments

Comments
 (0)