114 lines
4.1 KiB
Python
114 lines
4.1 KiB
Python
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)
|