From 7b95a48bc326943c5b105b2ce7bf635b5fc21e57 Mon Sep 17 00:00:00 2001 From: andrew Date: Wed, 2 Sep 2026 16:45:47 +0300 Subject: [PATCH] Add tests/test_cli.py --- tests/test_cli.py | 120 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 tests/test_cli.py diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 0000000..37bc2f9 --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,120 @@ +"""Базовые тесты CLI.""" + +from __future__ import annotations + +import subprocess +import sys + +from click.testing import CliRunner + +from selectel_ml_tui import __version__ +from selectel_ml_tui.cli import main +from selectel_ml_tui.config import load_credentials, load_settings + + +def test_version() -> None: + runner = CliRunner() + result = runner.invoke(main, ["--version"]) + assert result.exit_code == 0 + assert __version__ in result.output + + +def test_main_module_help() -> None: + result = subprocess.run( + [sys.executable, "-m", "selectel_ml_tui", "--help"], + capture_output=True, + text=True, + check=False, + ) + assert result.returncode == 0 + assert "doctor" in result.stdout + assert "run" in result.stdout + + +def test_config_paths(tmp_path, monkeypatch) -> None: + monkeypatch.setattr("selectel_ml_tui.config.config_dir", lambda: tmp_path) + monkeypatch.setattr("selectel_ml_tui.cli.config_dir", lambda: tmp_path) + runner = CliRunner() + result = runner.invoke(main, ["config", "--path"]) + assert result.exit_code == 0 + assert str(tmp_path) in result.output + + +def test_config_show_masks_secrets(tmp_path, monkeypatch) -> None: + monkeypatch.setattr("selectel_ml_tui.config.config_dir", lambda: tmp_path) + monkeypatch.setattr("selectel_ml_tui.cli.config_dir", lambda: tmp_path) + runner = CliRunner() + result = runner.invoke(main, ["config", "--show"]) + assert result.exit_code == 0 + assert "Static token" in result.output + assert "секрет" not in result.output.lower() + + +def test_config_wizard_saves(tmp_path, monkeypatch) -> None: + monkeypatch.setattr("selectel_ml_tui.config.config_dir", lambda: tmp_path) + monkeypatch.setattr("selectel_ml_tui.cli.config_dir", lambda: tmp_path) + input_data = "\n".join( + [ + "https://api.example.test", # API base URL + "30", # интервал обновления + "gw-test", # ID роутера + "ru-3", # регион + "svc-user", # сервисный пользователь + "239633", # домен (аккаунт) + "7bf2d2a328494e25b13d05a1926ca75a", # project id + "secret-pass", # пароль + "secret-token", # статический токен + ] + ) + runner = CliRunner() + result = runner.invoke(main, ["config"], input=input_data) + assert result.exit_code == 0, result.output + assert "Сохранено" in result.output + + settings = load_settings() + assert settings.router_id == "gw-test" + assert settings.refresh_interval == 30 + assert settings.api_base_url == "https://api.example.test" + assert settings.region == "ru-3" + + creds = load_credentials() + assert creds.service_user == "svc-user" + assert creds.domain_id == "239633" + assert creds.project_id == "7bf2d2a328494e25b13d05a1926ca75a" + assert creds.password == "secret-pass" + assert creds.static_token == "secret-token" + + +def test_run_requires_credentials(tmp_path, monkeypatch) -> None: + monkeypatch.setattr("selectel_ml_tui.config.config_dir", lambda: tmp_path) + monkeypatch.setattr("selectel_ml_tui.cli.config_dir", lambda: tmp_path) + runner = CliRunner() + result = runner.invoke(main, ["run"]) + assert result.exit_code == 1 + assert "не настроены" in result.output + + +def test_config_wizard_rejects_small_interval(tmp_path, monkeypatch) -> None: + monkeypatch.setattr("selectel_ml_tui.config.config_dir", lambda: tmp_path) + monkeypatch.setattr("selectel_ml_tui.cli.config_dir", lambda: tmp_path) + input_data = "\n".join( + [ + "https://api.example.test", # API base URL + "5", # интервал < 10 — будет отклонён + "30", # повторный ввод, валидный + "gw-test", # ID роутера + "", # регион (оставить) + "", # сервисный пользователь (оставить) + "", # домен (оставить) + "", # project id (оставить) + "", # пароль (оставить) + "", # статический токен (оставить) + "", # хвостовая строка (CliRunner отбрасывает последний пустой элемент) + ] + ) + runner = CliRunner() + result = runner.invoke(main, ["config"], input=input_data) + assert result.exit_code == 0, result.output + assert "не может быть меньше 10" in result.output + settings = load_settings() + assert settings.refresh_interval == 30