|
| 1 | +"""Man page + version surface: guard the roff generator and `dow --version`. |
| 2 | +
|
| 3 | +Regression coverage for two defects found during a v2.0.2 install verification: |
| 4 | +
|
| 5 | +1. A wrapped doc line beginning with ``'`` or ``.`` is a roff control line, so |
| 6 | + troff silently dropped it (e.g. init.txt's "'dow commit' to capture v1 ..." |
| 7 | + sentence vanished from `man dow`). `_roff` now protects such lines with a |
| 8 | + leading zero-width ``\\&``. |
| 9 | +2. There was no ``dow --version`` flag even though the version feeds the man |
| 10 | + page header; it is now a top-level eager option. |
| 11 | +""" |
| 12 | +from typer.testing import CliRunner |
| 13 | + |
| 14 | +from dow.cli import _dow_version, _render_manpage, _roff, app |
| 15 | + |
| 16 | +runner = CliRunner() |
| 17 | + |
| 18 | + |
| 19 | +def test_roff_protects_leading_control_characters(): |
| 20 | + # Lines that begin with a roff control char get a zero-width guard. |
| 21 | + assert _roff("'dow commit' to capture v1").startswith("\\&'") |
| 22 | + assert _roff(".PP is not a real macro here").startswith("\\&.") |
| 23 | + # Ordinary prose is untouched (apart from hyphen/backslash escaping). |
| 24 | + assert _roff("ordinary line") == "ordinary line" |
| 25 | + # Multi-line text is guarded line by line. |
| 26 | + out = _roff("first line\n'second starts with quote") |
| 27 | + assert out.splitlines()[1].startswith("\\&'") |
| 28 | + |
| 29 | + |
| 30 | +def test_manpage_has_no_unprotected_control_line_from_prose(): |
| 31 | + page = _render_manpage() |
| 32 | + # The init sentence that troff used to swallow must survive, guarded. |
| 33 | + assert "'dow commit' to capture v1" in page |
| 34 | + assert "\\&'dow commit' to capture v1" in page |
| 35 | + # No line may start with an apostrophe followed by a letter (that is the |
| 36 | + # exact shape troff misreads as an undefined macro call). |
| 37 | + for line in page.splitlines(): |
| 38 | + assert not (line[:1] == "'" and line[1:2].isalpha()), line |
| 39 | + |
| 40 | + |
| 41 | +def test_version_flag_prints_version(): |
| 42 | + for flag in ("--version", "-V"): |
| 43 | + result = runner.invoke(app, [flag]) |
| 44 | + assert result.exit_code == 0 |
| 45 | + assert _dow_version() in result.stdout |
0 commit comments