Coverage for tests/test_plugin.py: 100.00%

61 statements  

« prev     ^ index     » next       coverage.py v7.6.10, created at 2025-01-10 16:33 +0100

1"""Tests for the plugin module.""" 

2 

3from __future__ import annotations 

4import functools 

5 

6import pytest 

7 

8from mkdocs_autorefs.plugin import AutorefsPlugin, AutorefsConfig 

9from mkdocs_autorefs.references import fix_refs 

10 

11 

12def test_url_registration() -> None: 

13 """Check that URLs can be registered, then obtained.""" 

14 plugin = AutorefsPlugin() 

15 plugin.register_anchor(identifier="foo", page="foo1.html", primary=True) 

16 plugin.register_url(identifier="bar", url="https://example.org/bar.html") 

17 

18 assert plugin.get_item_url("foo") == "foo1.html#foo" 

19 assert plugin.get_item_url("bar") == "https://example.org/bar.html" 

20 with pytest.raises(KeyError): 

21 plugin.get_item_url("baz") 

22 

23 

24def test_url_registration_with_from_url() -> None: 

25 """Check that URLs can be registered, then obtained, relative to a page.""" 

26 plugin = AutorefsPlugin() 

27 plugin.register_anchor(identifier="foo", page="foo1.html", primary=True) 

28 plugin.register_url(identifier="bar", url="https://example.org/bar.html") 

29 

30 assert plugin.get_item_url("foo", from_url="a/b.html") == "../foo1.html#foo" 

31 assert plugin.get_item_url("bar", from_url="a/b.html") == "https://example.org/bar.html" 

32 with pytest.raises(KeyError): 

33 plugin.get_item_url("baz", from_url="a/b.html") 

34 

35 

36def test_url_registration_with_fallback() -> None: 

37 """Check that URLs can be registered, then obtained through a fallback.""" 

38 plugin = AutorefsPlugin() 

39 plugin.register_anchor(identifier="foo", page="foo1.html", primary=True) 

40 plugin.register_url(identifier="bar", url="https://example.org/bar.html") 

41 

42 # URL map will be updated with baz -> foo1.html#foo 

43 assert plugin.get_item_url("baz", fallback=lambda _: ("foo",)) == "foo1.html#foo" 

44 # as expected, baz is now known as foo1.html#foo 

45 assert plugin.get_item_url("baz", fallback=lambda _: ("bar",)) == "foo1.html#foo" 

46 # unknown identifiers correctly fallback: qux -> https://example.org/bar.html 

47 assert plugin.get_item_url("qux", fallback=lambda _: ("bar",)) == "https://example.org/bar.html" 

48 

49 with pytest.raises(KeyError): 

50 plugin.get_item_url("foobar", fallback=lambda _: ("baaaa",)) 

51 with pytest.raises(KeyError): 

52 plugin.get_item_url("foobar", fallback=lambda _: ()) 

53 

54 

55def test_dont_make_relative_urls_relative_again() -> None: 

56 """Check that URLs are not made relative more than once.""" 

57 plugin = AutorefsPlugin() 

58 plugin.register_anchor(identifier="foo.bar.baz", page="foo/bar/baz.html", primary=True) 

59 

60 for _ in range(2): 

61 assert ( 

62 plugin.get_item_url("hello", from_url="baz/bar/foo.html", fallback=lambda _: ("foo.bar.baz",)) 

63 == "../../foo/bar/baz.html#foo.bar.baz" 

64 ) 

65 

66 

67@pytest.mark.parametrize( 

68 ("base", "urls", "expected"), 

69 [ 

70 # One URL is closest. 

71 ("", ["x/#b", "#b"], "#b"), 

72 # Several URLs are equally close. 

73 ("a/b", ["x/#e", "a/c/#e", "a/d/#e"], "a/c/#e"), 

74 ("a/b/", ["x/#e", "a/d/#e", "a/c/#e"], "a/d/#e"), 

75 # Two close URLs, one is shorter (closer). 

76 ("a/b", ["x/#e", "a/c/#e", "a/c/d/#e"], "a/c/#e"), 

77 ("a/b/", ["x/#e", "a/c/d/#e", "a/c/#e"], "a/c/#e"), 

78 # Deeper-nested URLs. 

79 ("a/b/c", ["x/#e", "a/#e", "a/b/#e", "a/b/c/#e", "a/b/c/d/#e"], "a/b/c/#e"), 

80 ("a/b/c/", ["x/#e", "a/#e", "a/b/#e", "a/b/c/d/#e", "a/b/c/#e"], "a/b/c/#e"), 

81 # No closest URL, use first one even if longer distance. 

82 ("a", ["b/c/#d", "c/#d"], "b/c/#d"), 

83 ("a/", ["c/#d", "b/c/#d"], "c/#d"), 

84 ], 

85) 

86def test_find_closest_url(base: str, urls: list[str], expected: str) -> None: 

87 """Find closest URLs given a list of URLs.""" 

88 assert AutorefsPlugin._get_closest_url(base, urls, "test") == expected 

89 

90 

91def test_register_secondary_url() -> None: 

92 """Test registering secondary URLs.""" 

93 plugin = AutorefsPlugin() 

94 plugin.register_anchor(identifier="foo", page="foo.html", primary=False) 

95 assert plugin._secondary_url_map == {"foo": ["foo.html#foo"]} 

96 

97 

98def test_warn_multiple_urls(caplog: pytest.LogCaptureFixture) -> None: 

99 """Warn when multiple URLs are found for the same identifier.""" 

100 plugin = AutorefsPlugin() 

101 plugin.config = AutorefsConfig() 

102 plugin.register_anchor(identifier="foo", page="foo.html", primary=True) 

103 plugin.register_anchor(identifier="foo", page="bar.html", primary=True) 

104 url_mapper = functools.partial(plugin.get_item_url, from_url="/hello") 

105 fix_refs('<autoref identifier="foo">Foo</autoref>', url_mapper, _legacy_refs=False) 

106 assert "Multiple primary URLs found for 'foo': ['foo.html#foo', 'bar.html#foo']" in caplog.text 

107 

108 

109def test_use_closest_url(caplog: pytest.LogCaptureFixture) -> None: 

110 """Use the closest URL when multiple URLs are found for the same identifier.""" 

111 plugin = AutorefsPlugin() 

112 plugin.config = AutorefsConfig() 

113 plugin.config.resolve_closest = True 

114 plugin.register_anchor(identifier="foo", page="foo.html", primary=True) 

115 plugin.register_anchor(identifier="foo", page="bar.html", primary=True) 

116 url_mapper = functools.partial(plugin.get_item_url, from_url="/hello") 

117 fix_refs('<autoref identifier="foo">Foo</autoref>', url_mapper, _legacy_refs=False) 

118 assert "Multiple primary URLs found for 'foo': ['foo.html#foo', 'bar.html#foo']" not in caplog.text