"""present(): the boundary where a bin/ tool's plain output gets the house style. The tools print flush-left ASCII so they stay greppable and pipe-friendly when run directly; presentation belongs to the CLI. That split is only safe if the boundary is exact, which is what these assert. Colour constants are empty unless stdout is a terminal, so each test that cares about colour substitutes sentinels for them. """ import pytest import nexa @pytest.fixture() def tint(monkeypatch): """Sentinel colours, so a test can assert which one was chosen.""" for name, value in (("GREEN", ""), ("RED", ""), ("AMBER", ""), ("GREY", ""), ("WHITE", ""), ("DIM", ""), ("RESET", "<0>")): monkeypatch.setattr(nexa, name, value) monkeypatch.setattr(nexa, "HBAR", "-") monkeypatch.setattr(nexa, "TICK", "+") monkeypatch.setattr(nexa, "CROSS", "x") monkeypatch.setattr(nexa, "BANG", "!") def test_blank_lines_collapse_to_empty(): assert nexa.present("") == "" assert nexa.present(" \t ") == "" def test_body_is_indented_under_the_banner(): assert nexa.present("32 rules").startswith(" ") def test_relative_indentation_is_preserved(): """A tool's own nesting still has to read as nesting after the shift.""" outer = nexa.present("Decided by an AST pass:") inner = nexa.present(" [critical] odoo.prefer-sql-constraint") assert len(inner) - len(inner.lstrip()) > len(outer) - len(outer.lstrip()) def test_a_line_that_already_has_escapes_is_untouched(): """Otherwise the CLI would restyle its own already-styled output.""" line = "\033[38;5;51mstyled by the tool itself\033[0m" assert nexa.present(line) == line def test_ascii_separator_becomes_the_house_rule(tint): out = nexa.present("----------------------------------------") assert out == " " + "-" * 66 + "<0>" def test_short_dashes_are_not_a_separator(tint): """A hyphenated word is not a horizontal rule.""" assert "-" * 66 not in nexa.present("a - b") @pytest.mark.parametrize("line,expected", [ ("PASS: 32 rules valid", ""), ("OK everything", ""), ("FAIL: 2 problems", ""), ("ERROR: broken", ""), ("WARN: something", ""), ("Rules retrieved:", ""), ("Findings", ""), (" 0.586 [high] odoo.prefer-sql-constraint", ""), ]) def test_colour_selection(tint, line, expected): assert nexa.present(line).startswith(" " + expected) def test_severity_tags_are_tinted_inside_a_grey_line(tint): out = nexa.present(" [critical] odoo.prefer-sql-constraint") assert "[critical]<0>" in out # ------------------------------------------------------------- code fences def test_fence_markers_are_dimmed(tint): assert nexa.present("```python").startswith(" ") def test_code_inside_a_fence_is_white(tint): assert nexa.present(" rec.qty = 1", in_code=True).startswith(" ") def test_a_def_inside_a_fence_is_not_a_heading(tint): """It ends with a colon at the margin, which is the prose heading rule. Inside a fence that rule must not apply, or every function signature in every answer turns amber.""" assert nexa.present("def _check_quantity(self):", in_code=True).startswith(" ") def test_a_def_outside_a_fence_is_not_treated_as_a_heading_either(tint): """The heading rule requires no colon anywhere, or a trailing colon on a short line; a signature has parentheses and is long.""" out = nexa.present("def _check_quantity(self):") assert out.startswith(" ") or out.startswith(" ") def test_severity_tags_are_left_alone_inside_code(tint): """Code is code. Rewriting a bracketed word inside a fenced block would corrupt the answer being displayed.""" out = nexa.present("x = data['[critical]']", in_code=True) assert "" not in out