Coverage for tests/test_cli.py: 100%
43 statements
« prev ^ index » next coverage.py v7.17.2, created at 2026-11-09 14:41 +0000
« prev ^ index » next coverage.py v7.17.2, created at 2026-11-09 14:41 +0000
1import io
2import pathlib
3import runpy
4import sys
5import types
6import typing
8import pytest
10from archdocs import cli
11from tests import diagram_rendering
14_SERVICE_NAME: typing.Final = "cli-svc"
15_CLI_ARGUMENTS: typing.Final = (
16 "render",
17 "--root-dir",
18 str(diagram_rendering.LITESTAR_ROOT),
19 "--service-name",
20 _SERVICE_NAME,
21 "--kubernetes-dir",
22 diagram_rendering.WITHOUT_MANIFESTS,
23)
24_USAGE_EXIT_CODE: typing.Final = 2
25_FORMAT_OPTION: typing.Final = "--format"
26_SERVICE_NODE: typing.Final = 'cli_svc{"cli-svc"}'
27_SELF_HOSTED_MERMAID: typing.Final = "/static/mermaid.min.js?v=1&x=2"
28_ALL_FORMAT_CASES: typing.Final = types.MappingProxyType(
29 {
30 "mermaid by default": ((), "graph TB\n", "\n", ("```", "<html")),
31 "markdown": ((_FORMAT_OPTION, "markdown"), "```mermaid\ngraph TB\n", "\n```\n", ("<html",)),
32 "html with self hosted mermaid": (
33 (_FORMAT_OPTION, "html", "--mermaid-script-url", _SELF_HOSTED_MERMAID),
34 "<!DOCTYPE html>",
35 "</html>",
36 ("cdn.jsdelivr.net", _SELF_HOSTED_MERMAID),
37 ),
38 },
39)
42@pytest.mark.parametrize(
43 ("extra_arguments", "expected_start", "expected_end", "forbidden_parts"),
44 _ALL_FORMAT_CASES.values(),
45 ids=_ALL_FORMAT_CASES,
46)
47def test_every_format_is_written_to_a_file(
48 tmp_path: pathlib.Path,
49 extra_arguments: tuple[str, ...],
50 expected_start: str,
51 expected_end: str,
52 forbidden_parts: tuple[str, ...],
53) -> None:
54 output_path: typing.Final = tmp_path / "architecture.out"
56 cli.run_command_line([*_CLI_ARGUMENTS, *extra_arguments, "--output", str(output_path)])
58 rendered_output: typing.Final = output_path.read_text(encoding="utf-8")
59 assert rendered_output.startswith(expected_start)
60 assert rendered_output.endswith(expected_end)
61 assert _SERVICE_NODE in rendered_output
62 for one_forbidden_part in forbidden_parts:
63 assert one_forbidden_part not in rendered_output, one_forbidden_part
66def test_self_hosted_mermaid_is_escaped(tmp_path: pathlib.Path) -> None:
67 output_path: typing.Final = tmp_path / "architecture.html"
69 cli.run_command_line(
70 [
71 *_CLI_ARGUMENTS,
72 _FORMAT_OPTION,
73 "html",
74 "--mermaid-script-url",
75 _SELF_HOSTED_MERMAID,
76 "--output",
77 str(output_path),
78 ],
79 )
81 assert '<script src="/static/mermaid.min.js?v=1&x=2"></script>' in output_path.read_text(encoding="utf-8")
84def test_module_run_prints_the_diagram(monkeypatch: pytest.MonkeyPatch) -> None:
85 printed_output_buffer: typing.Final = io.StringIO()
86 monkeypatch.setattr(sys, "argv", ["archdocs", *_CLI_ARGUMENTS])
87 monkeypatch.setattr(sys, "stdout", printed_output_buffer)
89 runpy.run_module("archdocs", run_name="__main__")
91 printed_output: typing.Final = printed_output_buffer.getvalue()
92 assert printed_output.startswith("graph TB\n")
93 assert _SERVICE_NODE in printed_output
96@pytest.mark.parametrize(
97 "every_argument",
98 [(), ("render",), ("render", "--service-name", _SERVICE_NAME, _FORMAT_OPTION, "pdf")],
99 ids=["no command", "no service name", "unknown format"],
100)
101def test_bad_arguments_exit_with_usage(every_argument: tuple[str, ...]) -> None:
102 with pytest.raises(SystemExit) as exit_info:
103 cli.run_command_line(list(every_argument))
105 assert exit_info.value.code == _USAGE_EXIT_CODE