"""Tests for string scanner.""" import pytest from i18n_guardian.scanners.string_scanner import StringScanner, ScanResult class TestStringScanner: """Tests for StringScanner.""" def test_scan_python_file(self, sample_python_file): """Test scanning a Python file.""" scanner = StringScanner(min_length=3) result = scanner.scan(sample_python_file.parent) assert result.files_scanned >= 1 assert result.strings_found > 0 assert isinstance(result, ScanResult) def test_scan_js_file(self, sample_js_file): """Test scanning a JavaScript file.""" scanner = StringScanner(min_length=3) result = scanner.scan(sample_js_file.parent) assert result.files_scanned >= 1 def test_min_length_filter(self, temp_dir): """Test minimum length filter.""" py_file = temp_dir / "test.py" py_file.write_text('a = "x"\nb = "longer string here"', encoding="utf-8") scanner = StringScanner(min_length=5) result = scanner.scan(temp_dir) assert result.strings_found >= 1 def test_url_exclusion(self, temp_dir): """Test that URLs are excluded.""" py_file = temp_dir / "test.py" py_file.write_text('url = "https://example.com/path"', encoding="utf-8") scanner = StringScanner(min_length=3) result = scanner.scan(temp_dir) violations = [v for v in result.violations if "https://" in v.literal.value] assert len(violations) == 0 def test_email_exclusion(self, temp_dir): """Test that emails are excluded.""" py_file = temp_dir / "test.py" py_file.write_text('email = "test@example.com"', encoding="utf-8") scanner = StringScanner(min_length=3) result = scanner.scan(temp_dir) violations = [v for v in result.violations if "test@example.com" in v.literal.value] assert len(violations) == 0 def test_regex_exclusion(self, temp_dir): """Test that regex patterns are excluded.""" py_file = temp_dir / "test.py" py_file.write_text('pattern = r"^test\\d+$"', encoding="utf-8") scanner = StringScanner(min_length=3) result = scanner.scan(temp_dir) assert result.violations_count == 0 def test_exclude_patterns(self, temp_dir): """Test exclusion patterns.""" node_modules = temp_dir / "node_modules" node_modules.mkdir() test_file = node_modules / "test.js" test_file.write_text('message = "Hardcoded string"', encoding="utf-8") src_dir = temp_dir / "src" src_dir.mkdir() src_file = src_dir / "test.js" src_file.write_text('message = "Hardcoded string"', encoding="utf-8") scanner = StringScanner( min_length=3, exclude_patterns=["**/node_modules/**"], ) result = scanner.scan(temp_dir) for violation in result.violations: assert "node_modules" not in str(violation.literal.file_path) def test_i18n_function_exclusion(self, sample_js_file): """Test that i18n function calls are excluded.""" scanner = StringScanner( min_length=3, i18n_functions=["t", "formatMessage"], ) result = scanner.scan(sample_js_file.parent) for violation in result.violations: if violation.literal.value.startswith("t("): pytest.skip("Function call detected") def test_key_generation(self, sample_python_file): """Test that keys are generated for violations.""" scanner = StringScanner(min_length=3) result = scanner.scan(sample_python_file.parent) for violation in result.violations: assert violation.suggested_key is not None assert len(violation.suggested_key) > 0 def test_scan_result_structure(self, sample_python_file): """Test ScanResult has correct structure.""" scanner = StringScanner(min_length=3) result = scanner.scan(sample_python_file.parent) assert hasattr(result, "violations") assert hasattr(result, "files_scanned") assert hasattr(result, "strings_found") assert hasattr(result, "violations_count") assert isinstance(result.violations, list) def test_violation_structure(self, sample_python_file): """Test Violation has correct structure.""" scanner = StringScanner(min_length=3) result = scanner.scan(sample_python_file.parent) if result.violations: violation = result.violations[0] assert hasattr(violation, "literal") assert hasattr(violation, "suggested_key") assert hasattr(violation, "reason")