"""Tests for cli.autofmt module.""" from __future__ import annotations from pathlib import Path from unittest.mock import MagicMock, patch from pyflowx.ops import autofmt as dev # ---------------------------------------------------------------------- # # format_with_ruff # ---------------------------------------------------------------------- # class TestFormatWithRuff: """Test format_with_ruff function.""" def test_format_with_ruff(self, tmp_path: Path) -> None: """Should format with ruff.""" with patch("subprocess.run") as mock_run: mock_run.return_value = MagicMock(returncode=0) dev.format_with_ruff(tmp_path, fix=True) assert mock_run.called def test_format_with_ruff_no_fix(self, tmp_path: Path) -> None: """Should format with ruff without fix.""" with patch("subprocess.run") as mock_run: mock_run.return_value = MagicMock(returncode=0) dev.format_with_ruff(tmp_path, fix=False) # Should not include --fix flag call_args = mock_run.call_args[0][0] assert "--fix" not in call_args # ---------------------------------------------------------------------- # # lint_with_ruff # ---------------------------------------------------------------------- # class TestLintWithRuff: """Test lint_with_ruff function.""" def test_lint_with_ruff(self, tmp_path: Path) -> None: """Should lint with ruff.""" with patch("subprocess.run") as mock_run: mock_run.return_value = MagicMock(returncode=0) dev.lint_with_ruff(tmp_path, fix=True) assert mock_run.called def test_lint_with_ruff_no_fix(self, tmp_path: Path) -> None: """Should lint with ruff without fix.""" with patch("subprocess.run") as mock_run: mock_run.return_value = MagicMock(returncode=0) dev.lint_with_ruff(tmp_path, fix=False) # Should not include --fix flag call_args = mock_run.call_args[0][0] assert "--fix" not in call_args # ---------------------------------------------------------------------- # # add_docstring # ---------------------------------------------------------------------- # class TestAddDocstring: """Test add_docstring function.""" def test_add_docstring_to_file(self, tmp_path: Path) -> None: """Should add docstring to file.""" py_file = tmp_path / "test.py" py_file.write_text("def test():\n pass\n") result = dev.add_docstring(py_file, '"""Test module."""') assert result is True def test_add_docstring_skips_files_with_docstring(self, tmp_path: Path) -> None: """Should skip files that already have docstring.""" py_file = tmp_path / "test.py" py_file.write_text('"""Existing docstring."""\ndef test():\n pass\n') result = dev.add_docstring(py_file, '"""New docstring."""') assert result is False def test_add_docstring_empty_file(self, tmp_path: Path) -> None: """Should handle empty file.""" py_file = tmp_path / "test.py" py_file.write_text("") result = dev.add_docstring(py_file, '"""Test module."""') # Should handle empty file assert result is True # ---------------------------------------------------------------------- # # generate_module_docstring # ---------------------------------------------------------------------- # class TestGenerateModuleDocstring: """Test generate_module_docstring function.""" def test_generate_module_docstring_basic(self, tmp_path: Path) -> None: """Should generate basic docstring.""" py_file = tmp_path / "test.py" py_file.write_text("def test():\n pass\n") result = dev.generate_module_docstring(py_file) # Should contain "Tests for" since stem contains "test" assert "Tests for" in result def test_generate_module_docstring_with_package(self, tmp_path: Path) -> None: """Should generate docstring for package.""" py_file = tmp_path / "mypackage" / "test.py" py_file.parent.mkdir(parents=True) py_file.write_text("def test():\n pass\n") result = dev.generate_module_docstring(py_file) assert "mypackage" in result def test_generate_module_docstring_cli(self, tmp_path: Path) -> None: """Should generate docstring for CLI module.""" py_file = tmp_path / "cli.py" py_file.write_text("def test():\n pass\n") result = dev.generate_module_docstring(py_file) assert "Command-line interface" in result def test_generate_module_docstring_util(self, tmp_path: Path) -> None: """Should generate docstring for utility module.""" py_file = tmp_path / "utils.py" py_file.write_text("def test():\n pass\n") result = dev.generate_module_docstring(py_file) assert "Utility functions" in result # ---------------------------------------------------------------------- # # auto_add_docstrings # ---------------------------------------------------------------------- # class TestAutoAddDocstrings: """Test auto_add_docstrings function.""" def test_auto_add_docstrings(self, tmp_path: Path) -> None: """Should auto add docstrings.""" py_file = tmp_path / "test.py" py_file.write_text("def test():\n pass\n") with patch.object(dev, "add_docstring", return_value=True): count = dev.auto_add_docstrings(tmp_path) assert count >= 0 def test_auto_add_docstrings_skips_ignored(self, tmp_path: Path) -> None: """Should skip ignored directories.""" py_file = tmp_path / "__pycache__" / "test.py" py_file.parent.mkdir() py_file.write_text("def test():\n pass\n") count = dev.auto_add_docstrings(tmp_path) # Should skip __pycache__ assert count == 0 def test_auto_add_docstrings_no_files(self, tmp_path: Path) -> None: """Should handle no Python files.""" txt_file = tmp_path / "test.txt" txt_file.write_text("test content") count = dev.auto_add_docstrings(tmp_path) assert count == 0 # ---------------------------------------------------------------------- # # sync_pyproject_config # ---------------------------------------------------------------------- # class TestSyncPyprojectConfig: """Test sync_pyproject_config function.""" def test_sync_pyproject_config_creates_file(self, tmp_path: Path) -> None: """Should sync pyproject.toml config.""" main_toml = tmp_path / "pyproject.toml" main_toml.write_text("[tool.ruff]\n") sub_dir = tmp_path / "subproject" sub_dir.mkdir() sub_toml = sub_dir / "pyproject.toml" sub_toml.write_text("[tool.ruff]\n") with patch("subprocess.run") as mock_run: mock_run.return_value = MagicMock(returncode=0) dev.sync_pyproject_config(tmp_path) assert mock_run.called def test_sync_pyproject_config_updates_file(self, tmp_path: Path) -> None: """Should update existing pyproject.toml.""" main_toml = tmp_path / "pyproject.toml" main_toml.write_text("[tool.ruff]\n") sub_dir = tmp_path / "subproject" sub_dir.mkdir() sub_toml = sub_dir / "pyproject.toml" sub_toml.write_text("[tool.ruff]\n") with patch("subprocess.run") as mock_run: mock_run.return_value = MagicMock(returncode=0) dev.sync_pyproject_config(tmp_path) assert mock_run.called # ---------------------------------------------------------------------- # # format_all # ---------------------------------------------------------------------- # class TestFormatAll: """Test format_all function.""" def test_format_all_runs_ruff_format(self, tmp_path: Path) -> None: """Should run ruff format.""" with patch("subprocess.run") as mock_run: mock_run.return_value = MagicMock(returncode=0) dev.format_all(tmp_path) assert mock_run.called def test_format_all_runs_ruff_check(self, tmp_path: Path) -> None: """Should run ruff check.""" with patch("subprocess.run") as mock_run: mock_run.return_value = MagicMock(returncode=0) dev.format_all(tmp_path) # Should call ruff format and ruff check assert mock_run.call_count == 2