Coverage for tests/test_extension.py: 98.68%
62 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-14 19:41 +0100
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-14 19:41 +0100
1"""Tests for the extension module."""
3from __future__ import annotations
5import re
6import sys
7from textwrap import dedent
8from typing import TYPE_CHECKING
10import pytest
12if TYPE_CHECKING:
13 from markdown import Markdown
15 from mkdocstrings.plugin import MkdocstringsPlugin
18@pytest.mark.parametrize("ext_markdown", [{"markdown_extensions": [{"footnotes": {}}]}], indirect=["ext_markdown"])
19def test_multiple_footnotes(ext_markdown: Markdown) -> None:
20 """Assert footnotes don't get added to subsequent docstrings."""
21 output = ext_markdown.convert(
22 dedent(
23 """
24 Top.[^aaa]
26 ::: tests.fixtures.footnotes.func_a
28 ::: tests.fixtures.footnotes.func_b
30 ::: tests.fixtures.footnotes.func_c
32 [^aaa]: Top footnote
33 """,
34 ),
35 )
36 assert output.count("Footnote A") == 1
37 assert output.count("Footnote B") == 1
38 assert output.count("Top footnote") == 1
41def test_markdown_heading_level(ext_markdown: Markdown) -> None:
42 """Assert that Markdown headings' level doesn't exceed heading_level."""
43 output = ext_markdown.convert("::: tests.fixtures.headings\n options:\n show_root_heading: true")
44 assert ">Foo</h3>" in output
45 assert ">Bar</h5>" in output
46 assert ">Baz</h6>" in output
49def test_keeps_preceding_text(ext_markdown: Markdown) -> None:
50 """Assert that autodoc is recognized in the middle of a block and preceding text is kept."""
51 output = ext_markdown.convert("**preceding**\n::: tests.fixtures.headings")
52 assert "<strong>preceding</strong>" in output
53 assert ">Foo</h2>" in output
54 assert ":::" not in output
57def test_reference_inside_autodoc(ext_markdown: Markdown) -> None:
58 """Assert cross-reference Markdown extension works correctly."""
59 output = ext_markdown.convert("::: tests.fixtures.cross_reference")
60 assert re.search(r"Link to <.*something\.Else.*>something\.Else<.*>\.", output)
63@pytest.mark.skipif(sys.version_info < (3, 8), reason="typing.Literal requires Python 3.8")
64def test_quote_inside_annotation(ext_markdown: Markdown) -> None:
65 """Assert that inline highlighting doesn't double-escape HTML."""
66 output = ext_markdown.convert("::: tests.fixtures.string_annotation.Foo")
67 assert ";hi&" in output
68 assert "&" not in output
71def test_html_inside_heading(ext_markdown: Markdown) -> None:
72 """Assert that headings don't double-escape HTML."""
73 output = ext_markdown.convert("::: tests.fixtures.html_tokens")
74 assert "'<" in output
75 assert "&" not in output
78@pytest.mark.parametrize(
79 ("ext_markdown", "expect_permalink"),
80 [
81 ({"markdown_extensions": [{"toc": {"permalink": "@@@"}}]}, "@@@"),
82 ({"markdown_extensions": [{"toc": {"permalink": "TeSt"}}]}, "TeSt"),
83 ({"markdown_extensions": [{"toc": {"permalink": True}}]}, "¶"),
84 ],
85 indirect=["ext_markdown"],
86)
87def test_no_double_toc(ext_markdown: Markdown, expect_permalink: str) -> None:
88 """Assert that the 'toc' extension doesn't apply its modification twice."""
89 output = ext_markdown.convert(
90 dedent(
91 """
92 # aa
94 ::: tests.fixtures.headings
95 options:
96 show_root_toc_entry: false
98 # bb
99 """,
100 ),
101 )
102 assert output.count(expect_permalink) == 5
103 assert 'id="tests.fixtures.headings--foo"' in output
104 assert ext_markdown.toc_tokens == [ # type: ignore[attr-defined] # the member gets populated only with 'toc' extension
105 {
106 "level": 1,
107 "id": "aa",
108 "name": "aa",
109 "children": [
110 {
111 "level": 2,
112 "id": "tests.fixtures.headings--foo",
113 "name": "Foo",
114 "children": [
115 {
116 "level": 4,
117 "id": "tests.fixtures.headings--bar",
118 "name": "Bar",
119 "children": [
120 {"level": 6, "id": "tests.fixtures.headings--baz", "name": "Baz", "children": []},
121 ],
122 },
123 ],
124 },
125 ],
126 },
127 {"level": 1, "id": "bb", "name": "bb", "children": []},
128 ]
131def test_use_custom_handler(ext_markdown: Markdown) -> None:
132 """Assert that we use the custom handler declared in an individual autodoc instruction."""
133 with pytest.raises(ModuleNotFoundError):
134 ext_markdown.convert("::: tests.fixtures.headings\n handler: not_here")
137def test_dont_register_every_identifier_as_anchor(plugin: MkdocstringsPlugin, ext_markdown: Markdown) -> None:
138 """Assert that we don't preemptively register all identifiers of a rendered object."""
139 handler = plugin._handlers.get_handler("python") # type: ignore[union-attr]
140 ids = ("id1", "id2", "id3")
141 handler.get_anchors = lambda _: ids # type: ignore[method-assign] 141 ↛ exitline 141 didn't run the lambda on line 141
142 ext_markdown.convert("::: tests.fixtures.headings")
143 autorefs = ext_markdown.parser.blockprocessors["mkdocstrings"]._autorefs # type: ignore[attr-defined]
144 for identifier in ids:
145 assert identifier not in autorefs._url_map
146 assert identifier not in autorefs._abs_url_map
149def test_use_options_yaml_key(ext_markdown: Markdown) -> None:
150 """Check that using the 'options' YAML key works as expected."""
151 assert "h1" in ext_markdown.convert("::: tests.fixtures.headings\n options:\n heading_level: 1")
152 assert "h1" not in ext_markdown.convert("::: tests.fixtures.headings\n options:\n heading_level: 2")
155@pytest.mark.parametrize("ext_markdown", [{"markdown_extensions": [{"admonition": {}}]}], indirect=["ext_markdown"])
156def test_removing_duplicated_headings(ext_markdown: Markdown) -> None:
157 """Assert duplicated headings are removed from the output."""
158 output = ext_markdown.convert(
159 dedent(
160 """
161 ::: tests.fixtures.headings_many.heading_1
163 !!! note
165 ::: tests.fixtures.headings_many.heading_2
167 ::: tests.fixtures.headings_many.heading_3
168 """,
169 ),
170 )
171 assert output.count(">Heading one<") == 1
172 assert output.count(">Heading two<") == 1
173 assert output.count(">Heading three<") == 1
174 assert output.count('class="mkdocstrings') == 0