import pytest import requests from unittest.mock import patch, MagicMock from gitignore_generator import api from gitignore_generator.api import ( get_patterns, get_patterns_batch, get_list, get_local_template, get_local_list, GitignoreIOError ) class TestGetPatterns: """Tests for get_patterns function.""" def test_get_patterns_from_api(self): """Test fetching patterns from API.""" mock_response = MagicMock() mock_response.text = "__pycache__/\n*.pyc\n" mock_response.raise_for_status = MagicMock() with patch('gitignore_generator.api.requests.get') as mock_get: mock_get.return_value = mock_response result = get_patterns('python', force_refresh=True) assert '__pycache__' in result assert '*.pyc' in result def test_get_patterns_from_cache(self, tmp_path): """Test using cached patterns.""" cache_file = tmp_path / "python.txt" cache_file.write_text("cached content") with patch('gitignore_generator.api.CACHE_DIR', tmp_path): result = get_patterns('python', force_refresh=False) assert result == "cached content" def test_get_patterns_fallback_to_local(self, tmp_path): """Test fallback to local template when API fails.""" template_file = tmp_path / "python.gitignore" template_file.write_text("local template content") with patch('gitignore_generator.api.CACHE_DIR', tmp_path): with patch('gitignore_generator.api.TEMPLATES_DIR', tmp_path): with patch('gitignore_generator.api.requests.get') as mock_get: def raise_error(*args, **kwargs): raise requests.RequestException("Network error") mock_get.side_effect = raise_error result = get_patterns('python') assert result == "local template content" def test_get_patterns_case_insensitive(self): """Test that technology names are case insensitive.""" mock_response = MagicMock() mock_response.text = "__pycache__/\n" mock_response.raise_for_status = MagicMock() with patch('gitignore_generator.api.requests.get') as mock_get: mock_get.return_value = mock_response result = get_patterns('PYTHON') assert '__pycache__' in result def test_get_patterns_raises_error_on_failure(self, tmp_path): """Test error is raised when both API and local fail.""" with patch('gitignore_generator.api.CACHE_DIR', tmp_path): with patch('gitignore_generator.api.TEMPLATES_DIR', tmp_path): with patch('gitignore_generator.api.requests.get') as mock_get: def raise_error(*args, **kwargs): raise requests.RequestException("Network error") mock_get.side_effect = raise_error with pytest.raises(GitignoreIOError): get_patterns('nonexistent_xyz_123') class TestGetPatternsBatch: """Tests for get_patterns_batch function.""" def test_get_patterns_batch_multiple_techs(self): """Test fetching patterns for multiple technologies.""" def mock_get(url, **kwargs): response = MagicMock() if 'node' in url: response.text = "node_modules/" elif 'python' in url: response.text = "__pycache__/" response.raise_for_status = MagicMock() return response with patch.object(api.requests, 'get', side_effect=mock_get): result = get_patterns_batch(['node', 'python'], force_refresh=True) assert 'node' in result assert 'python' in result assert 'node_modules' in result['node'] assert '__pycache__' in result['python'] def test_get_patterns_batch_handles_errors(self): """Test batch fetch continues on individual errors.""" def mock_get(url, **kwargs): response = MagicMock() if 'unknown' in url: raise requests.RequestException("Network error") response.text = "content" response.raise_for_status = MagicMock() return response with patch.object(api.requests, 'get', side_effect=mock_get): result = get_patterns_batch(['python', 'unknown_xyz_123']) assert 'python' in result assert 'unknown_xyz_123' in result assert result['unknown_xyz_123'] == "" class TestGetList: """Tests for get_list function.""" def test_get_list_from_api(self): """Test fetching list from API.""" mock_response = MagicMock() mock_response.text = "python\nnode\ndjango\nflask\n" mock_response.raise_for_status = MagicMock() with patch('gitignore_generator.api.requests.get') as mock_get: mock_get.return_value = mock_response result = get_list(force_refresh=True) assert 'python' in result assert 'node' in result assert 'django' in result assert 'flask' in result def test_get_list_from_cache(self, tmp_path): """Test using cached list.""" cache_file = tmp_path / "list.txt" cache_file.write_text("python\nnode\ndjango") with patch('gitignore_generator.api.CACHE_DIR', tmp_path): result = get_list(force_refresh=False) assert 'python' in result assert 'node' in result def test_get_list_fallback_to_local(self, tmp_path): """Test fallback to local list when API fails.""" local_list = tmp_path / "list.txt" local_list.write_text("python\nnode") with patch('gitignore_generator.api.CACHE_DIR', tmp_path): with patch('gitignore_generator.api.TEMPLATES_DIR', tmp_path): with patch('gitignore_generator.api.requests.get') as mock_get: mock_get.side_effect = Exception("Network error") result = get_list() assert 'python' in result class TestLocalTemplates: """Tests for local template functions.""" def test_get_local_template_exists(self, tmp_path): """Test getting existing local template.""" template_file = tmp_path / "python.gitignore" template_file.write_text("local template") with patch('gitignore_generator.api.TEMPLATES_DIR', tmp_path): result = get_local_template('python') assert result == "local template" def test_get_local_template_not_exists(self, tmp_path): """Test getting non-existent local template.""" with patch('gitignore_generator.api.TEMPLATES_DIR', tmp_path): result = get_local_template('nonexistent_xyz_123') assert result is None def test_get_local_list(self, tmp_path): """Test getting local list.""" list_file = tmp_path / "list.txt" list_file.write_text("python\nnode\ndjango") with patch('gitignore_generator.api.TEMPLATES_DIR', tmp_path): result = get_local_list() assert 'python' in result assert 'node' in result assert 'django' in result