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

1"""Tests for the extension module.""" 

2 

3from __future__ import annotations 

4 

5import re 

6import sys 

7from textwrap import dedent 

8from typing import TYPE_CHECKING 

9 

10import pytest 

11 

12if TYPE_CHECKING: 

13 from markdown import Markdown 

14 

15 from mkdocstrings.plugin import MkdocstringsPlugin 

16 

17 

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] 

25 

26 ::: tests.fixtures.footnotes.func_a 

27 

28 ::: tests.fixtures.footnotes.func_b 

29 

30 ::: tests.fixtures.footnotes.func_c 

31 

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 

39 

40 

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 

47 

48 

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 

55 

56 

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) 

61 

62 

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 "&amp;" not in output 

69 

70 

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 "&#39;&lt;" in output 

75 assert "&amp;" not in output 

76 

77 

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}}]}, "&para;"), 

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 

93 

94 ::: tests.fixtures.headings 

95 options: 

96 show_root_toc_entry: false 

97 

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 ] 

129 

130 

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") 

135 

136 

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 

147 

148 

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") 

153 

154 

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 

162 

163 !!! note 

164 

165 ::: tests.fixtures.headings_many.heading_2 

166 

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