diff --git a/tests/unit/test_parsers.py b/tests/unit/test_parsers.py new file mode 100644 index 0000000..1888b87 --- /dev/null +++ b/tests/unit/test_parsers.py @@ -0,0 +1,208 @@ +import pytest +from pathlib import Path +from src.parsers.base import BaseParser, Entity, EntityType, ParserResult +from src.parsers.python import PythonParser +from src.parsers.javascript import JavaScriptParser +from src.parsers.go import GoParser +from src.parsers.rust import RustParser + + +class TestBaseParser: + def test_entity_creation(self): + entity = Entity( + name="test_func", + entity_type=EntityType.FUNCTION, + file_path=Path("/test/file.py"), + start_line=1, + end_line=10, + code="def test_func(): pass", + ) + assert entity.name == "test_func" + assert entity.entity_type == EntityType.FUNCTION + assert entity.start_line == 1 + assert entity.end_line == 10 + + def test_parser_result(self): + result = ParserResult( + file_path=Path("/test/file.py"), + language="python", + ) + assert result.file_path == Path("/test/file.py") + assert result.language == "python" + assert result.entities == [] + assert result.imports == [] + + +class TestPythonParser: + def setup_method(self): + self.parser = PythonParser() + + def test_parse_simple_function(self): + code = """ +def hello(): + print("Hello, World!") +""" + result = self.parser.parse(Path("/test.py"), code) + assert result.language == "python" + assert len(result.entities) >= 1 + + def test_parse_class_with_methods(self): + code = """ +class MyClass: + def method1(self): + pass + + def method2(self): + pass +""" + result = self.parser.parse(Path("/test.py"), code) + assert result.language == "python" + class_entities = [e for e in result.entities if e.entity_type == EntityType.CLASS] + assert len(class_entities) == 1 + + def test_extract_imports(self): + code = """ +import os +import sys +from pathlib import Path +""" + result = self.parser.parse(Path("/test.py"), code) + assert "os" in result.imports + assert "sys" in result.imports + + def test_can_parse_py_file(self): + assert self.parser.can_parse(Path("/test.py")) + assert self.parser.can_parse(Path("/test.pyi")) + assert not self.parser.can_parse(Path("/test.js")) + + +class TestJavaScriptParser: + def setup_method(self): + self.parser = JavaScriptParser() + + def test_parse_function(self): + code = """ +function hello() { + console.log("Hello"); +} +""" + result = self.parser.parse(Path("/test.js"), code) + assert result.language == "javascript" + assert len(result.entities) >= 1 + + def test_parse_arrow_function(self): + code = """ +const add = (a, b) => a + b; +""" + result = self.parser.parse(Path("/test.js"), code) + assert result.language == "javascript" + + def test_parse_class(self): + code = """ +class MyClass { + constructor() {} + + method1() {} +} +""" + result = self.parser.parse(Path("/test.js"), code) + class_entities = [e for e in result.entities if e.entity_type == EntityType.CLASS] + assert len(class_entities) == 1 + + def test_can_parse_js_file(self): + assert self.parser.can_parse(Path("/test.js")) + assert self.parser.can_parse(Path("/test.jsx")) + assert not self.parser.can_parse(Path("/test.py")) + + +class TestGoParser: + def setup_method(self): + self.parser = GoParser() + + def test_parse_function(self): + code = """ +func hello() { + fmt.Println("Hello") +} +""" + result = self.parser.parse(Path("/test.go"), code) + assert result.language == "go" + assert len(result.entities) >= 1 + + def test_parse_struct(self): + code = """ +type Person struct { + Name string + Age int +} +""" + result = self.parser.parse(Path("/test.go"), code) + assert result.language == "go" + + def test_can_parse_go_file(self): + assert self.parser.can_parse(Path("/test.go")) + assert not self.parser.can_parse(Path("/test.py")) + + +class TestRustParser: + def setup_method(self): + self.parser = RustParser() + + def test_parse_function(self): + code = """ +fn hello() { + println!("Hello"); +} +""" + result = self.parser.parse(Path("/test.rs"), code) + assert result.language == "rust" + assert len(result.entities) >= 1 + + def test_parse_struct(self): + code = """ +struct Person { + name: String, + age: u32, +} +""" + result = self.parser.parse(Path("/test.rs"), code) + assert result.language == "rust" + + def test_parse_trait(self): + code = """ +trait Drawable { + fn draw(&self); +} +""" + result = self.parser.parse(Path("/test.rs"), code) + assert result.language == "rust" + + def test_can_parse_rs_file(self): + assert self.parser.can_parse(Path("/test.rs")) + assert not self.parser.can_parse(Path("/test.py")) + + +class TestParserFactory: + def test_get_parser_for_python_file(self): + parser = BaseParser.get_parser_for_file(Path("/test.py")) + assert parser is not None + assert isinstance(parser, PythonParser) + + def test_get_parser_for_js_file(self): + parser = BaseParser.get_parser_for_file(Path("/test.js")) + assert parser is not None + assert isinstance(parser, JavaScriptParser) + + def test_get_parser_for_go_file(self): + parser = BaseParser.get_parser_for_file(Path("/test.go")) + assert parser is not None + assert isinstance(parser, GoParser) + + def test_get_parser_for_rs_file(self): + parser = BaseParser.get_parser_for_file(Path("/test.rs")) + assert parser is not None + assert isinstance(parser, RustParser) + + def test_get_parser_returns_none_for_unknown(self): + parser = BaseParser.get_parser_for_file(Path("/test.xyz")) + assert parser is None