from pathlib import Path from app.signals import analyze_dependencies, detect_test_signals def test_dependency_analysis_handles_multiple_ecosystems(tmp_path: Path) -> None: package = tmp_path / "package.json" package.write_text('{"dependencies":{"react":"latest"}}', encoding="utf-8") requirements = tmp_path / "requirements.txt" requirements.write_text("fastapi>=0.100\n", encoding="utf-8") lock = tmp_path / "package-lock.json" lock.write_text("{}", encoding="utf-8") signals, findings = analyze_dependencies( tmp_path, { "package.json": [package], "requirements.txt": [requirements], "package-lock.json": [lock], }, ) assert signals.declared_dependencies == 2 assert signals.unbounded_dependencies == 2 assert signals.unpinned_dependencies == 0 assert "package-lock.json" in signals.lockfiles assert any(item.code == "dependency.unbounded" for item in findings) def test_python_dependency_ranges_only_flag_truly_unbounded_declarations(tmp_path: Path) -> None: pyproject = tmp_path / "pyproject.toml" pyproject.write_text( """ [project] dependencies = [ "exact==1.2.3", "compatible~=2.0", "bounded>=3.0,<4.0", "open>=5.0", ] optional-dependencies.dev = ["pytest~=8.0"] """.strip(), encoding="utf-8", ) signals, findings = analyze_dependencies(tmp_path, {"pyproject.toml": [pyproject]}) assert signals.declared_dependencies == 5 assert signals.unbounded_dependencies == 1 assert [finding.code for finding in findings] == ["dependency.python-unbounded"] def test_test_signals_detect_ci_coverage_and_frameworks() -> None: text_by_path = { "package.json": '{"devDependencies":{"vitest":"^3.0.0","@playwright/test":"^1.0.0"}}', } signals = detect_test_signals( ["src/app.ts", "src/app.test.ts", ".gitea/workflows/ci.yml", "coverage/lcov.info"], source_files=2, test_files=1, text_by_path=text_by_path, ) assert "Vitest" in signals.frameworks assert "Playwright" in signals.frameworks assert signals.ci_workflows == [".gitea/workflows/ci.yml"] assert signals.coverage_artifacts == ["coverage/lcov.info"] assert signals.test_source_ratio == 50.0 def test_test_signals_distinguish_validation_from_deploy_only_workflows() -> None: signals = detect_test_signals( [".gitea/workflows/validate.yml", ".gitea/workflows/deploy.yml"], source_files=1, test_files=1, text_by_path={ ".gitea/workflows/validate.yml": "steps:\n - run: pytest --cov\n - run: npm run build\n", ".gitea/workflows/deploy.yml": "steps:\n - run: deploy production\n", }, ) assert signals.ci_validation_workflows == [".gitea/workflows/validate.yml"] assert signals.ci_build_workflows == [".gitea/workflows/validate.yml"] assert signals.ci_deploy_only_workflows == [".gitea/workflows/deploy.yml"] assert signals.coverage_evidence == [".gitea/workflows/validate.yml"] def test_dependency_analysis_follows_local_requirements_includes_and_workspace_locks(tmp_path: Path) -> None: packages = tmp_path / "packages" / "web" packages.mkdir(parents=True) package = packages / "package.json" package.write_text('{"dependencies":{"shared":"workspace:*"}}', encoding="utf-8") lock = tmp_path / "pnpm-lock.yaml" lock.write_text("lockfileVersion: '9.0'\n", encoding="utf-8") requirements = tmp_path / "requirements.txt" included = tmp_path / "requirements-prod.txt" requirements.write_text("-r requirements-prod.txt\n", encoding="utf-8") included.write_text("fastapi==0.116.0\n", encoding="utf-8") signals, findings = analyze_dependencies( tmp_path, { "package.json": [package], "pnpm-lock.yaml": [lock], "requirements.txt": [requirements], "requirements-prod.txt": [included], }, ) assert signals.unbounded_dependencies == 0 assert signals.included_requirements == ["requirements-prod.txt"] assert signals.declared_dependencies == 2 assert not any(item.code == "dependency.no-lockfile" for item in findings)