feat(clean-release): complete compliance redesign phases and polish tasks T047-T052
This commit is contained in:
97
backend/tests/scripts/test_clean_release_tui_v2.py
Normal file
97
backend/tests/scripts/test_clean_release_tui_v2.py
Normal file
@@ -0,0 +1,97 @@
|
||||
# [DEF:test_clean_release_tui_v2:Module]
|
||||
# @TIER: STANDARD
|
||||
# @PURPOSE: Smoke tests for thin-client TUI action dispatch and blocked transition behavior.
|
||||
# @LAYER: Domain
|
||||
# @RELATION: TESTS -> backend.src.scripts.clean_release_tui
|
||||
|
||||
"""Smoke tests for the redesigned clean release TUI."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import curses
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from backend.src.models.clean_release import CheckFinalStatus
|
||||
from backend.src.scripts.clean_release_tui import CleanReleaseTUI, main
|
||||
|
||||
|
||||
def _build_mock_stdscr() -> MagicMock:
|
||||
stdscr = MagicMock()
|
||||
stdscr.getmaxyx.return_value = (40, 120)
|
||||
stdscr.getch.return_value = curses.KEY_F10
|
||||
return stdscr
|
||||
|
||||
|
||||
@patch("backend.src.scripts.clean_release_tui.curses")
|
||||
def test_tui_f5_dispatches_run_action(mock_curses_module: MagicMock) -> None:
|
||||
"""F5 should dispatch run action from TUI loop."""
|
||||
mock_curses_module.KEY_F10 = curses.KEY_F10
|
||||
mock_curses_module.KEY_F5 = curses.KEY_F5
|
||||
mock_curses_module.color_pair.side_effect = lambda value: value
|
||||
mock_curses_module.A_BOLD = 0
|
||||
|
||||
stdscr = _build_mock_stdscr()
|
||||
app = CleanReleaseTUI(stdscr)
|
||||
|
||||
stdscr.getch.side_effect = [curses.KEY_F5, curses.KEY_F10]
|
||||
with patch.object(app, "run_checks", autospec=True) as run_checks_mock:
|
||||
app.loop()
|
||||
|
||||
run_checks_mock.assert_called_once_with()
|
||||
|
||||
|
||||
@patch("backend.src.scripts.clean_release_tui.curses")
|
||||
def test_tui_f5_run_smoke_reports_blocked_state(mock_curses_module: MagicMock) -> None:
|
||||
"""F5 smoke test should expose blocked outcome state after run action."""
|
||||
mock_curses_module.KEY_F10 = curses.KEY_F10
|
||||
mock_curses_module.KEY_F5 = curses.KEY_F5
|
||||
mock_curses_module.color_pair.side_effect = lambda value: value
|
||||
mock_curses_module.A_BOLD = 0
|
||||
|
||||
stdscr = _build_mock_stdscr()
|
||||
app = CleanReleaseTUI(stdscr)
|
||||
stdscr.getch.side_effect = [curses.KEY_F5, curses.KEY_F10]
|
||||
|
||||
def _set_blocked_state() -> None:
|
||||
app.status = CheckFinalStatus.BLOCKED
|
||||
app.report_id = "CCR-smoke-blocked"
|
||||
app.violations_list = [object()]
|
||||
|
||||
with patch.object(app, "run_checks", side_effect=_set_blocked_state, autospec=True):
|
||||
app.loop()
|
||||
|
||||
assert app.status == CheckFinalStatus.BLOCKED
|
||||
assert app.report_id == "CCR-smoke-blocked"
|
||||
assert app.violations_list
|
||||
|
||||
|
||||
def test_tui_non_tty_refuses_startup(capsys) -> None:
|
||||
"""Non-TTY startup must refuse TUI mode and redirect operator to CLI/API flow."""
|
||||
with patch("sys.stdout.isatty", return_value=False):
|
||||
exit_code = main()
|
||||
|
||||
captured = capsys.readouterr()
|
||||
assert exit_code == 2
|
||||
assert "TTY is required for TUI mode" in captured.err
|
||||
assert "Use CLI/API workflow instead" in captured.err
|
||||
|
||||
|
||||
@patch("backend.src.scripts.clean_release_tui.curses")
|
||||
def test_tui_f8_blocked_without_facade_binding(mock_curses_module: MagicMock) -> None:
|
||||
"""F8 should not perform hidden state mutation when facade action is not bound."""
|
||||
mock_curses_module.KEY_F10 = curses.KEY_F10
|
||||
mock_curses_module.KEY_F8 = curses.KEY_F8
|
||||
mock_curses_module.color_pair.side_effect = lambda value: value
|
||||
mock_curses_module.A_BOLD = 0
|
||||
|
||||
stdscr = _build_mock_stdscr()
|
||||
app = CleanReleaseTUI(stdscr)
|
||||
stdscr.getch.side_effect = [curses.KEY_F8, curses.KEY_F10]
|
||||
|
||||
app.loop()
|
||||
|
||||
assert app.last_error is not None
|
||||
assert "F8 disabled" in app.last_error
|
||||
|
||||
|
||||
# [/DEF:test_clean_release_tui_v2:Module]
|
||||
Reference in New Issue
Block a user