"""Tests for project state detection functionality.""" import os import pytest from ra_aid.project_state import ( DirectoryAccessError, DirectoryNotFoundError, ProjectStateError, is_new_project, ) @pytest.fixture def empty_dir(tmp_path): """Create an empty temporary directory.""" return tmp_path @pytest.fixture def git_only_dir(tmp_path): """Create a directory with only git files.""" git_dir = tmp_path / ".git" git_dir.mkdir(exist_ok=True) gitignore = tmp_path / ".gitignore" gitignore.write_text("*.pyc\n") return tmp_path @pytest.fixture def ra_aid_only_dir(tmp_path): """Create a directory with only a .ra-aid directory.""" ra_aid_dir = tmp_path / ".ra-aid" ra_aid_dir.mkdir(exist_ok=True) return tmp_path @pytest.fixture def mixed_allowed_dir(tmp_path): """Create a directory with all allowed items (.git, .gitignore, and .ra-aid).""" git_dir = tmp_path / ".git" git_dir.mkdir(exist_ok=True) gitignore = tmp_path / ".gitignore" gitignore.write_text("*.pyc\n") ra_aid_dir = tmp_path / ".ra-aid" ra_aid_dir.mkdir(exist_ok=True) return tmp_path @pytest.fixture def project_dir(tmp_path): """Create a directory with some project files.""" (tmp_path / "src").mkdir() (tmp_path / "README.md").write_text("# Test Project") return tmp_path def test_empty_directory(empty_dir): """Test that an empty directory is considered a new project.""" assert is_new_project(str(empty_dir)) is True def test_git_only_directory(git_only_dir): """Test that a directory with only git files is considered a new project.""" assert is_new_project(str(git_only_dir)) is True def test_ra_aid_only_directory(ra_aid_only_dir): """Test that a directory with only a .ra-aid directory is considered a new project.""" assert is_new_project(str(ra_aid_only_dir)) is True def test_mixed_allowed_directory(mixed_allowed_dir): """Test that a directory with all allowed items is considered a new project.""" assert is_new_project(str(mixed_allowed_dir)) is True @pytest.fixture def git_dir_with_contents(tmp_path): """Create a directory with .git containing files and .gitignore.""" git_dir = tmp_path / ".git" git_dir.mkdir() # Add some files inside .git (git_dir / "HEAD").write_text("ref: refs/heads/main") (git_dir / "config").write_text("[core]\n\trepositoryformatversion = 0") (git_dir / "refs").mkdir() # Add .gitignore gitignore = tmp_path / ".gitignore" gitignore.write_text("*.pyc\n") return tmp_path def test_git_directory_with_contents(git_dir_with_contents): """Test that a directory is considered new even with files inside .git.""" assert is_new_project(str(git_dir_with_contents)) is True def test_existing_project_directory(project_dir): """Test that a directory with project files is not considered new.""" assert is_new_project(str(project_dir)) is False def test_nonexistent_directory(): """Test that a non-existent directory raises appropriate error.""" with pytest.raises(DirectoryNotFoundError): is_new_project("/nonexistent/path/123456") def test_file_as_directory(tmp_path): """Test that passing a file instead of directory raises error.""" test_file = tmp_path / "test.txt" test_file.write_text("test") with pytest.raises(ProjectStateError): is_new_project(str(test_file)) @pytest.mark.skipif(os.name == "nt", reason="Permission tests unreliable on Windows") def test_permission_error(tmp_path): """Test handling of permission errors.""" try: # Make directory unreadable os.chmod(tmp_path, 0o000) with pytest.raises(DirectoryAccessError): is_new_project(str(tmp_path)) finally: # Restore permissions to allow cleanup os.chmod(tmp_path, 0o755) def test_verify_fix(tmp_path): """ Verify fix: a project with only .ra-aid directory is considered new, but adding other files makes it recognized as an existing project. """ # Create a .ra-aid directory inside the temporary directory ra_aid_dir = tmp_path / ".ra-aid" ra_aid_dir.mkdir(exist_ok=True) # Check that is_new_project() returns True (only .ra-aid directory) assert is_new_project(str(tmp_path)) is True # Add a README.md file to the directory readme_file = tmp_path / "README.md" readme_file.write_text("# Test Project") # Check that is_new_project() now returns False (has actual content) assert is_new_project(str(tmp_path)) is False