File size: 8,840 Bytes
88d205f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#!/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()