diff --git a/tests/test_parsers.py b/tests/test_parsers.py new file mode 100644 index 0000000..eb08f15 --- /dev/null +++ b/tests/test_parsers.py @@ -0,0 +1,174 @@ +import pytest +from pathlib import Path +import tempfile +import os + +from config_auditor.discovery import ConfigDiscovery +from config_auditor.parsers import ParserFactory, JsonParser, YamlParser, TomlParser +from config_auditor.rules import ( + RuleRegistry, + DeprecatedPackageRule, + OutdatedVersionRule, + MissingTypeCheckingRule, + SecurityVulnerabilityRule, + MissingScriptsRule, + PythonProjectMetaRule, +) + + +class TestConfigDiscovery: + def test_discover_json_files(self): + with tempfile.TemporaryDirectory() as tmpdir: + (Path(tmpdir) / "package.json").write_text('{"name": "test"}') + (Path(tmpdir) / "tsconfig.json").write_text('{"compilerOptions": {}}') + + discovery = ConfigDiscovery(max_depth=2) + configs = discovery.discover(Path(tmpdir)) + + assert len(configs) >= 2 + + def test_discover_nested_files(self): + with tempfile.TemporaryDirectory() as tmpdir: + nested = Path(tmpdir) / "src" + nested.mkdir() + (nested / "tsconfig.json").write_text('{"compilerOptions": {}}') + + discovery = ConfigDiscovery(max_depth=3) + configs = discovery.discover(Path(tmpdir)) + + assert len(configs) == 1 + + def test_no_files_found(self): + with tempfile.TemporaryDirectory() as tmpdir: + discovery = ConfigDiscovery(max_depth=2) + configs = discovery.discover(Path(tmpdir)) + + assert len(configs) == 0 + + +class TestParsers: + def test_json_parse_valid(self): + parser = JsonParser() + content = '{"name": "test", "version": "1.0.0"}' + result = parser.parse(content) + + assert result is not None + assert result["name"] == "test" + assert result["version"] == "1.0.0" + + def test_json_parse_invalid(self): + parser = JsonParser() + content = "not valid json" + result = parser.parse(content) + + assert result is None + + def test_yaml_parse_valid(self): + parser = YamlParser() + content = "key: value\nlist:\n - item1\n - item2" + result = parser.parse(content) + + assert result is not None + assert result["key"] == "value" + assert len(result["list"]) == 2 + + def test_toml_parse_valid(self): + parser = TomlParser() + content = 'name = "test"\nversion = "1.0.0"' + result = parser.parse(content) + + assert result is not None + assert result["name"] == "test" + + def test_parser_factory(self): + factory = ParserFactory() + + json_result = factory.parse("json", '{"test": true}') + assert json_result is not None + + yaml_result = factory.parse("yaml", "test: value") + assert yaml_result is not None + + toml_result = factory.parse("toml", 'test = true') + assert toml_result is not None + + +class TestRules: + def test_deprecated_package_rule(self): + rule = DeprecatedPackageRule() + data = {"dependencies": {"request": "^2.0.0"}} + result = rule.evaluate(data, Path("package.json")) + + assert result.passed is False + assert "deprecated" in result.message.lower() + + def test_no_deprecated_packages(self): + rule = DeprecatedPackageRule() + data = {"dependencies": {"express": "^4.0.0"}} + result = rule.evaluate(data, Path("package.json")) + + assert result.passed is True + + def test_outdated_version_rule(self): + rule = OutdatedVersionRule() + data = {"dependencies": {"express": "^0.1.0"}} + result = rule.evaluate(data, Path("package.json")) + + assert result.passed is False + + def test_missing_type_checking_rule(self): + rule = MissingTypeCheckingRule() + data = {"compilerOptions": {"strict": False}} + result = rule.evaluate(data, Path("tsconfig.json")) + + assert result.passed is False + + def test_strict_mode_enabled(self): + rule = MissingTypeCheckingRule() + data = {"compilerOptions": {"strict": True}} + result = rule.evaluate(data, Path("tsconfig.json")) + + assert result.passed is True + + def test_missing_scripts_rule(self): + rule = MissingScriptsRule() + data = {"scripts": {}} + result = rule.evaluate(data, Path("package.json")) + + assert result.passed is False + + def test_all_scripts_present(self): + rule = MissingScriptsRule() + data = {"scripts": {"test": "jest", "build": "tsc"}} + result = rule.evaluate(data, Path("package.json")) + + assert result.passed is True + + def test_python_project_meta_rule(self): + rule = PythonProjectMetaRule() + data = {"tool": {"poetry": {"name": "test", "version": "1.0.0"}}} + result = rule.evaluate(data, Path("pyproject.toml")) + + assert result.passed is True + + +class TestRuleRegistry: + def test_evaluate_json_config(self): + registry = RuleRegistry() + data = { + "dependencies": {"request": "^2.0.0"}, + "scripts": {} + } + issues = registry.evaluate("json", data, Path("package.json")) + + issue_categories = [i.category for i in issues] + assert "deprecated-package" in issue_categories + assert "missing-scripts" in issue_categories + + def test_empty_config_has_warnings(self): + registry = RuleRegistry() + issues = registry.evaluate("json", {}, Path("package.json")) + + assert len(issues) > 0 + categories = [i.category for i in issues] + assert "missing-scripts" in categories