import pytest from docslib.components import H1, Image, List, LocalLink, LocLink, P, RawHTML from docslib.hooks import Component, Page from docslib.registry import registry def test_components_escape_text_and_raw_html_is_explicit(): assert H1("") == "

<hello>

" assert P('a & b') == "

a & b

" assert List([""]) == "" assert RawHTML("trusted") == "trusted" def test_custom_component_must_return_string(): @Component def Broken(): return 123 with pytest.raises(TypeError, match="must return str"): Broken() def test_page_registration_normalises_number_and_rejects_arguments(): @Page("1.", "Home") def home(): return H1("Home") assert registry.pages()[0].number == "1" with pytest.raises(TypeError, match="must not accept arguments"): @Page("2", "Broken") def broken(value): return value def test_image_rejects_parent_traversal(): with pytest.raises(ValueError, match="relative path"): Image("../secret.png") def test_local_link_resolves_number_title_section_and_function(): @Page("1", "Introduction") def introduction(): return "" @Page("1.1", "Install") def install_one(): return "" @Page("2.1", "Install") def install_two(): return "" assert 'href="#/page/1"' in LocalLink("Intro", "1.") assert 'href="#/page/1.1"' in LocalLink("Install", "Install", section="1") assert 'href="#/page/2.1"' in LocalLink("Other install", install_two) assert LocLink is LocalLink with pytest.raises(ValueError, match="ambiguous"): LocalLink("Install", "Install") with pytest.raises(ValueError, match="No @Page"): LocalLink("Unknown", lambda: None)