Coverage for tests/test_served_page.py: 100%

43 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-18 22:03 +0000

1import typing 

2 

3import hypothesis 

4import pytest 

5from hypothesis import strategies as st 

6 

7from archdocs import settings 

8from tests import served_page 

9from tests.diagram_rendering import build_named_settings 

10 

11 

12# Minifying the template by joining on "" used to glue attributes onto their tags, turning the 

13# mermaid script tag into `<scriptsrc=...>`: the served document is the only proof there is. 

14_SERVICE_NAME: typing.Final = "page-svc" 

15# A quote in the name closes the node label early and takes the whole render down with it, so 

16# it may not reach the page at all — the markup characters around it have to survive escaped. 

17_MARKED_UP_SERVICE_NAME: typing.Final = 'svc<b>&"x' 

18# The template ships a demo diagram inside its `<pre>`: the page has to replace that slot, not 

19# grow a second one next to it. 

20_TEMPLATE_DEMO_MARK: typing.Final = "Example Start Node" 

21_RENDERER_ARGUMENT: typing.Final = "render_page" 

22_HYPOTHESIS_EXAMPLES: typing.Final = 20 

23_TEMPLATE_WITHOUT_A_SLOT: typing.Final = "<!DOCTYPE html><html lang='en'><body>no room here</body></html>" 

24_REQUIRED_PAGE_TAGS: typing.Final = ( 

25 "<!DOCTYPE html>", 

26 '<html lang="en">', 

27 '<script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js">', 

28 '<pre class="archdoc__diagram">', 

29 "graph TB", 

30) 

31_NAME_ALPHABET: typing.Final = st.characters(whitelist_categories=["Ll", "Lu"], whitelist_characters=["_", "-"]) 

32_NAME_STRATEGY: typing.Final = st.text(min_size=1, max_size=10, alphabet=_NAME_ALPHABET) 

33 

34 

35@pytest.mark.parametrize(_RENDERER_ARGUMENT, served_page.ALL_PAGE_RENDERERS, ids=served_page.FRAMEWORK_IDS) 

36def test_default_route_serves_a_whole_document(render_page: served_page.PageRenderer) -> None: 

37 page_html: typing.Final = render_page(build_named_settings(_SERVICE_NAME), None) 

38 

39 for one_required_tag in _REQUIRED_PAGE_TAGS: 

40 assert page_html.count(one_required_tag) == 1, one_required_tag 

41 assert _SERVICE_NAME in page_html 

42 assert _TEMPLATE_DEMO_MARK not in page_html 

43 

44 

45# Without settings the scan starts from the working directory, which under pytest is the 

46# repository itself: the page has to name the default service and draw its node. 

47@pytest.mark.parametrize(_RENDERER_ARGUMENT, served_page.ALL_PAGE_RENDERERS, ids=served_page.FRAMEWORK_IDS) 

48def test_omitted_settings_draw_the_default(render_page: served_page.PageRenderer) -> None: 

49 page_html: typing.Final = render_page(None, None) 

50 

51 assert 'example_service{"example-service' in page_html 

52 

53 

54# A template shipped without a `<pre>` slot has nowhere to put the diagram: the page still has 

55# to be a page. 

56@pytest.mark.parametrize(_RENDERER_ARGUMENT, served_page.ALL_PAGE_RENDERERS, ids=served_page.FRAMEWORK_IDS) 

57def test_template_without_a_slot_is_served_whole( 

58 render_page: served_page.PageRenderer, 

59 monkeypatch: pytest.MonkeyPatch, 

60) -> None: 

61 monkeypatch.setattr(settings, "UI_HTML_TEMPLATE", _TEMPLATE_WITHOUT_A_SLOT) 

62 

63 page_html: typing.Final = render_page(build_named_settings(_SERVICE_NAME), None) 

64 

65 assert page_html == _TEMPLATE_WITHOUT_A_SLOT 

66 

67 

68@pytest.mark.parametrize(_RENDERER_ARGUMENT, served_page.ALL_PAGE_RENDERERS, ids=served_page.FRAMEWORK_IDS) 

69def test_markup_characters_are_escaped(render_page: served_page.PageRenderer) -> None: 

70 page_html: typing.Final = render_page(build_named_settings(_MARKED_UP_SERVICE_NAME), None) 

71 

72 assert 'svc&lt;b>&amp;x"}' in page_html 

73 assert "svc<b>" not in page_html 

74 

75 

76@pytest.mark.parametrize(_RENDERER_ARGUMENT, served_page.ALL_PAGE_RENDERERS, ids=served_page.FRAMEWORK_IDS) 

77@hypothesis.settings(deadline=None, max_examples=_HYPOTHESIS_EXAMPLES) 

78@hypothesis.given(service_name=_NAME_STRATEGY, route_value=_NAME_STRATEGY) 

79def test_any_service_name_and_route_are_served( 

80 render_page: served_page.PageRenderer, 

81 service_name: str, 

82 route_value: str, 

83) -> None: 

84 page_html: typing.Final = render_page(build_named_settings(service_name), f"/{route_value}") 

85 

86 assert service_name in page_html