#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Unit tests for the Language Detector """ import unittest from unittest.mock import patch, MagicMock, mock_open import os import sys from pathlib import Path # Add the project root directory to the Python path project_root = Path(__file__).resolve().parent.parent sys.path.insert(0, str(project_root)) from src.core.language_detector import LanguageDetector class TestLanguageDetector(unittest.TestCase): """Test cases for the LanguageDetector class""" def setUp(self): """Set up test fixtures""" self.detector = LanguageDetector() # Create a mock repository structure self.repo_path = "/test/repo" self.mock_files = [ "/test/repo/main.py", "/test/repo/utils.py", "/test/repo/static/script.js", "/test/repo/static/style.css", "/test/repo/src/app.js", "/test/repo/src/components/Button.jsx", "/test/repo/src/components/Form.tsx", "/test/repo/docs/index.html", "/test/repo/README.md", "/test/repo/package.json", "/test/repo/Dockerfile", "/test/repo/.gitignore" ] def test_get_language_from_extension(self): """Test _get_language_from_extension method""" # Test common extensions self.assertEqual(self.detector._get_language_from_extension(".py"), "Python") self.assertEqual(self.detector._get_language_from_extension(".js"), "JavaScript") self.assertEqual(self.detector._get_language_from_extension(".jsx"), "JavaScript") self.assertEqual(self.detector._get_language_from_extension(".ts"), "TypeScript") self.assertEqual(self.detector._get_language_from_extension(".tsx"), "TypeScript") self.assertEqual(self.detector._get_language_from_extension(".java"), "Java") self.assertEqual(self.detector._get_language_from_extension(".go"), "Go") self.assertEqual(self.detector._get_language_from_extension(".rs"), "Rust") self.assertEqual(self.detector._get_language_from_extension(".html"), "HTML") self.assertEqual(self.detector._get_language_from_extension(".css"), "CSS") self.assertEqual(self.detector._get_language_from_extension(".md"), "Markdown") # Test unknown extension self.assertEqual(self.detector._get_language_from_extension(".unknown"), "Other") def test_get_language_from_filename(self): """Test _get_language_from_filename method""" # Test common filenames self.assertEqual(self.detector._get_language_from_filename("Dockerfile"), "Dockerfile") self.assertEqual(self.detector._get_language_from_filename(".gitignore"), "Git") self.assertEqual(self.detector._get_language_from_filename("package.json"), "JSON") self.assertEqual(self.detector._get_language_from_filename("README.md"), "Markdown") # Test unknown filename self.assertEqual(self.detector._get_language_from_filename("unknown"), None) @patch('os.walk') def test_detect_languages(self, mock_walk): """Test detect_languages method""" # Mock os.walk to return our mock files mock_walk.return_value = [ ("/test/repo", ["static", "src", "docs"], ["main.py", "utils.py", "README.md", "package.json", ".gitignore"]), ("/test/repo/static", [], ["script.js", "style.css"]), ("/test/repo/src", ["components"], ["app.js"]), ("/test/repo/src/components", [], ["Button.jsx", "Form.tsx"]), ("/test/repo/docs", [], ["index.html"]), ] # Test the method languages = self.detector.detect_languages(self.repo_path) # Verify the result self.assertIn("Python", languages) self.assertIn("JavaScript", languages) self.assertIn("TypeScript", languages) self.assertIn("HTML", languages) self.assertIn("CSS", languages) self.assertIn("Markdown", languages) self.assertIn("JSON", languages) self.assertIn("Git", languages) @patch('os.walk') @patch('builtins.open', new_callable=mock_open, read_data="line1\nline2\nline3\n") def test_get_language_breakdown(self, mock_file, mock_walk): """Test get_language_breakdown method""" # Mock os.walk to return our mock files mock_walk.return_value = [ ("/test/repo", ["static", "src"], ["main.py", "utils.py", "README.md"]), ("/test/repo/static", [], ["script.js"]), ("/test/repo/src", [], ["app.js"]), ] # Test the method breakdown = self.detector.get_language_breakdown(self.repo_path) # Verify the result self.assertIn("Python", breakdown) self.assertIn("JavaScript", breakdown) self.assertIn("Markdown", breakdown) # Each file has 4 lines (including the newline at the end) self.assertEqual(breakdown["Python"]["files"], 2) self.assertEqual(breakdown["Python"]["lines"], 8) # 2 files * 4 lines self.assertEqual(breakdown["JavaScript"]["files"], 2) self.assertEqual(breakdown["JavaScript"]["lines"], 8) # 2 files * 4 lines self.assertEqual(breakdown["Markdown"]["files"], 1) self.assertEqual(breakdown["Markdown"]["lines"], 4) # 1 file * 4 lines # Check percentages total_lines = 20 # 5 files * 4 lines self.assertEqual(breakdown["Python"]["percentage"], 40) # 8/20 * 100 self.assertEqual(breakdown["JavaScript"]["percentage"], 40) # 8/20 * 100 self.assertEqual(breakdown["Markdown"]["percentage"], 20) # 4/20 * 100 @patch('os.path.isfile') def test_is_binary_file(self, mock_isfile): """Test _is_binary_file method""" # Mock isfile to always return True mock_isfile.return_value = True # Test with text file extensions self.assertFalse(self.detector._is_binary_file("test.py")) self.assertFalse(self.detector._is_binary_file("test.js")) self.assertFalse(self.detector._is_binary_file("test.html")) self.assertFalse(self.detector._is_binary_file("test.css")) self.assertFalse(self.detector._is_binary_file("test.md")) # Test with binary file extensions self.assertTrue(self.detector._is_binary_file("test.png")) self.assertTrue(self.detector._is_binary_file("test.jpg")) self.assertTrue(self.detector._is_binary_file("test.gif")) self.assertTrue(self.detector._is_binary_file("test.pdf")) self.assertTrue(self.detector._is_binary_file("test.zip")) # Test with non-existent file mock_isfile.return_value = False self.assertFalse(self.detector._is_binary_file("nonexistent.py")) @patch('os.path.isdir') def test_should_ignore_directory(self, mock_isdir): """Test _should_ignore_directory method""" # Mock isdir to always return True mock_isdir.return_value = True # Test with common directories to ignore self.assertTrue(self.detector._should_ignore_directory("/test/repo/node_modules")) self.assertTrue(self.detector._should_ignore_directory("/test/repo/.git")) self.assertTrue(self.detector._should_ignore_directory("/test/repo/__pycache__")) self.assertTrue(self.detector._should_ignore_directory("/test/repo/venv")) self.assertTrue(self.detector._should_ignore_directory("/test/repo/.vscode")) # Test with directories not to ignore self.assertFalse(self.detector._should_ignore_directory("/test/repo/src")) self.assertFalse(self.detector._should_ignore_directory("/test/repo/app")) self.assertFalse(self.detector._should_ignore_directory("/test/repo/docs")) # Test with non-existent directory mock_isdir.return_value = False self.assertFalse(self.detector._should_ignore_directory("/test/repo/nonexistent")) def test_should_ignore_file(self): """Test _should_ignore_file method""" # Test with common files to ignore self.assertTrue(self.detector._should_ignore_file("/test/repo/.DS_Store")) self.assertTrue(self.detector._should_ignore_file("/test/repo/Thumbs.db")) self.assertTrue(self.detector._should_ignore_file("/test/repo/.env")) # Test with files not to ignore self.assertFalse(self.detector._should_ignore_file("/test/repo/main.py")) self.assertFalse(self.detector._should_ignore_file("/test/repo/app.js")) self.assertFalse(self.detector._should_ignore_file("/test/repo/README.md")) if __name__ == "__main__": unittest.main()