summaryrefslogtreecommitdiff
path: root/tools/tests/test_check_docs.py
blob: 67404c93224882393b67b26ca36a105099138002 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
"""Tests for tools/check_docs.py, the offline Markdown link checker."""

from __future__ import annotations

import re
from pathlib import Path

import check_docs as cd
import pytest
from conftest import PROJECT_ROOT
from hypothesis import given
from hypothesis import strategies as st


@pytest.mark.parametrize(
    ("heading", "anchor"),
    [
        ("12.4 How each symbology is proven scannable", "124-how-each-symbology-is-proven-scannable"),
        ("3e. Writing values back: unknown", "3e-writing-values-back-unknown"),
        ("1. Scope", "1-scope"),
        ("`make sim` and noVNC", "make-sim-and-novnc"),
        ("A — B", "a--b"),
        ("[Link](x.md) text", "link-text"),
    ],
)
def test_slugify_matches_github(heading: str, anchor: str) -> None:
    assert cd.slugify(heading) == anchor


@given(st.text())
def test_slugify_output_is_anchor_safe(heading: str) -> None:
    assert re.fullmatch(r"[\w\-]*", cd.slugify(heading))


def write(tmp_path: Path, name: str, text: str) -> Path:
    path = tmp_path / name
    path.write_text(text, encoding="utf-8")
    return path


def test_repeated_headings_get_numbered_anchors(tmp_path: Path) -> None:
    doc = write(tmp_path, "a.md", "# Notes\n\n## Notes\n\n```\n# not a heading\n```\n")
    assert cd.anchors_of(doc) == {"notes", "notes-1"}


def test_broken_links_are_reported(tmp_path: Path) -> None:
    write(tmp_path, "other.md", "# Present\n")
    doc = write(
        tmp_path,
        "a.md",
        "# Top\n"
        "[ok](#top) [ok2](other.md#present) [web](https://example.com/x)\n"
        "[missing file](nope.md)\n"
        "[missing anchor](other.md#absent)\n"
        "`[inline code](ignored.md)`\n"
        "```\n[fenced](ignored.md)\n```\n",
    )
    problems = cd.check_file(doc, tmp_path, {})
    assert [(p.line, p.message) for p in problems] == [
        (3, "missing file 'nope.md'"),
        (4, "no heading for anchor '#absent' in other.md"),
    ]


def test_project_docs_have_no_broken_links() -> None:
    cache: dict[Path, set[str]] = {}
    problems = [p for f in cd.markdown_files(PROJECT_ROOT) for p in cd.check_file(f, PROJECT_ROOT, cache)]
    assert problems == [], "\n".join(map(str, problems))