Public Access
332 lines
13 KiB
Python
332 lines
13 KiB
Python
"""Unit tests for devx.cli module."""
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import click
|
|
import pytest
|
|
from click.testing import CliRunner
|
|
|
|
from devx.cli import cli
|
|
|
|
|
|
class TestCliGroups:
|
|
def test_cli_help(self) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["--help"])
|
|
assert result.exit_code == 0
|
|
assert "devx" in result.output
|
|
assert "ci" in result.output
|
|
assert "tools" in result.output
|
|
assert "molecule" in result.output
|
|
|
|
def test_ci_group_help(self) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["ci", "--help"])
|
|
assert result.exit_code == 0
|
|
assert "auto-merge" in result.output
|
|
assert "release" in result.output
|
|
assert "publish" in result.output
|
|
|
|
def test_tools_group_help(self) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["tools", "--help"])
|
|
assert result.exit_code == 0
|
|
assert "setup" in result.output
|
|
assert "install-tools" in result.output
|
|
assert "configure-repo" in result.output
|
|
|
|
def test_molecule_group_help(self) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["molecule", "--help"])
|
|
assert result.exit_code == 0
|
|
assert "distribute" in result.output
|
|
assert "all" in result.output
|
|
|
|
|
|
class TestCiCommands:
|
|
@patch("devx.cli._run_module")
|
|
def test_ci_auto_merge(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["ci", "auto-merge", "branch", "title", "repo", "1"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.ci.auto_merge", ["branch", "title", "repo", "1"])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_ci_check_translations(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["ci", "check-translations"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.ci.check_translations", [])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_ci_classify_changes(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["ci", "classify-changes", "positional"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.ci.classify_changes", ["positional"])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_ci_detect_release_commit(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["ci", "detect-release-commit"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.ci.detect_release_commit", [])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_ci_discover_runners(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["ci", "discover-runners", "positional"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.ci.discover_runners", ["positional"])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_ci_doc_coverage(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["ci", "doc-coverage"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.ci.doc_coverage", [])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_ci_lint_docs(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["ci", "lint-docs", "--", "--root", "."])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.ci.lint_docs", ["--root", "."])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_ci_notify_failure(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["ci", "notify-failure", "job1"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.ci.notify_failure", ["job1"])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_ci_post_merge(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["ci", "post-merge", "DEVX-1"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.ci.post_merge", ["DEVX-1"])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_ci_pr_review(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["ci", "pr-review", "42"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.ci.pr_review", ["42"])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_ci_publish(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["ci", "publish", "v1.0.0", "owner/repo"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.ci.publish", ["v1.0.0", "owner/repo"])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_ci_push_badges(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["ci", "push-badges"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.ci.push_badges", [])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_ci_release(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["ci", "release", "positional"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.ci.release", ["positional"])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_ci_sync_wiki(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["ci", "sync-wiki"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.ci.sync_wiki", [])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_ci_validate_commit_msg(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["ci", "validate-commit-msg", "msg"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.ci.validate_commit_msg", ["msg"])
|
|
|
|
|
|
class TestToolsCommands:
|
|
@patch("devx.cli._run_module")
|
|
def test_tools_check_test_speed(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["tools", "check-test-speed"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.tools.check_test_speed", [])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_tools_configure_repo(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["tools", "configure-repo", "myrepo"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.tools.configure_repo", ["myrepo"])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_tools_generate_badges(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["tools", "generate-badges"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.tools.generate_badges", [])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_tools_generate_cliff_config(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["tools", "generate-cliff-config"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.tools.generate_cliff_config", [])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_tools_install_checkmake(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["tools", "install-checkmake"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.tools.install_checkmake", [])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_tools_install_tools(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["tools", "install-tools"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.tools.install_tools", [])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_tools_setup(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["tools", "setup"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.tools.setup", [])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_tools_rebase(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["tools", "rebase", "--", "--no-push"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.tools.rebase", ["--no-push"])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_tools_pr_rebase(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["tools", "pr-rebase", "--", "--pr", "42"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.tools.pr_rebase", ["--pr", "42"])
|
|
|
|
|
|
class TestMoleculeCommands:
|
|
@patch("devx.cli._run_module")
|
|
def test_molecule_distribute(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["molecule", "distribute", "positional"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.molecule.distribute_molecule", ["positional"])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_molecule_discover_runners(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["molecule", "discover-runners"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.molecule.discover_runners", [])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_molecule_all(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["molecule", "all"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.molecule.molecule_all", [])
|
|
|
|
|
|
class TestNewCiCommands:
|
|
@patch("devx.cli._run_module")
|
|
def test_ci_distribute_files(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["ci", "distribute-files", "--", "--pattern", "*.py"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.ci.distribute_files", ["--pattern", "*.py"])
|
|
|
|
@patch("devx.cli._run_module")
|
|
def test_ci_integration_guard(self, mock_run: MagicMock) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["ci", "integration-guard", "--", "-v"])
|
|
assert result.exit_code == 0
|
|
mock_run.assert_called_once_with("devx.ci.integration_guard", ["-v"])
|
|
|
|
|
|
class TestRunModule:
|
|
@patch("importlib.import_module")
|
|
def test_run_module_success(self, mock_import: MagicMock) -> None:
|
|
from devx.cli import _run_module
|
|
|
|
mock_module = MagicMock()
|
|
mock_main = MagicMock()
|
|
mock_module.main = mock_main
|
|
mock_import.return_value = mock_module
|
|
_run_module("devx.ci.release", ["--dry-run"])
|
|
mock_import.assert_called_once_with("devx.ci.release")
|
|
mock_main.assert_called_once()
|
|
|
|
@patch("importlib.import_module")
|
|
def test_run_module_no_main_raises(self, mock_import: MagicMock) -> None:
|
|
from devx.cli import _run_module
|
|
|
|
mock_module = MagicMock()
|
|
mock_module.main = None
|
|
mock_import.return_value = mock_module
|
|
with pytest.raises(SystemExit) as exc_info:
|
|
_run_module("devx.ci.nonexistent", [])
|
|
assert exc_info.value.code == 1
|
|
|
|
@patch("importlib.import_module")
|
|
def test_run_module_click_exception(self, mock_import: MagicMock) -> None:
|
|
from devx.cli import _run_module
|
|
|
|
mock_module = MagicMock()
|
|
mock_main = MagicMock()
|
|
mock_main.side_effect = click.ClickException("test error")
|
|
mock_module.main = mock_main
|
|
mock_import.return_value = mock_module
|
|
with pytest.raises(SystemExit):
|
|
_run_module("devx.ci.release", [])
|
|
|
|
@patch("importlib.import_module")
|
|
def test_run_module_abort(self, mock_import: MagicMock) -> None:
|
|
from devx.cli import _run_module
|
|
|
|
mock_module = MagicMock()
|
|
mock_main = MagicMock()
|
|
mock_main.side_effect = click.exceptions.Abort()
|
|
mock_module.main = mock_main
|
|
mock_import.return_value = mock_module
|
|
with pytest.raises(SystemExit) as exc_info:
|
|
_run_module("devx.ci.release", [])
|
|
assert exc_info.value.code == 1
|
|
|
|
@patch("importlib.import_module")
|
|
def test_run_module_click_command_object(self, mock_import: MagicMock) -> None:
|
|
"""When main is not callable (a click Command), uses .main() method."""
|
|
from devx.cli import _run_module
|
|
|
|
mock_module = MagicMock()
|
|
|
|
# Create a non-callable object with a .main method (like click.Command)
|
|
# callable() returns False only if __call__ is not defined
|
|
class NonCallableMain:
|
|
def __init__(self) -> None:
|
|
self.main = MagicMock()
|
|
|
|
non_callable = NonCallableMain()
|
|
assert not callable(non_callable)
|
|
mock_module.main = non_callable
|
|
mock_import.return_value = mock_module
|
|
_run_module("devx.ci.release", ["arg1"])
|
|
non_callable.main.assert_called_once()
|
|
|
|
|
|
class TestVersionOption:
|
|
def test_version_flag(self) -> None:
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["--version"])
|
|
assert result.exit_code == 0
|