File size: 4,927 Bytes
056e46c
 
 
c2eb49d
 
056e46c
 
 
14b65ae
a79668c
 
 
 
14b65ae
 
 
 
 
056e46c
 
 
 
 
a79668c
 
 
 
 
 
 
 
056e46c
a79668c
 
 
 
056e46c
 
c2eb49d
 
a79668c
c2eb49d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0f31814
c2eb49d
 
bf214ef
 
a79668c
bf214ef
 
 
a79668c
bf214ef
 
 
 
 
 
 
 
 
cf40364
 
 
 
 
bf214ef
cf40364
bf214ef
42c1adb
bf214ef
 
cf40364
bf214ef
 
 
 
 
 
 
 
 
 
a79668c
 
 
bf214ef
 
 
 
 
42c1adb
bf214ef
 
 
 
a79668c
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
from unittest.mock import AsyncMock, patch
import pytest
from app.agents import repo_analysis_agent, bug_detection_agent
from app.models.issue import IssueReport, Bug, Warning, Suggestion
from app.models.repository import RepositoryRequest


@pytest.mark.asyncio
async def test_repo_analysis_agent_returns_metadata(tmp_path):
    with patch(
        "app.agents.repo_analysis_agent.call_llm_for_json",
        new=AsyncMock(return_value={}),
    ):
        result = await repo_analysis_agent.run(
            "https://github.com/test/repo", str(tmp_path)
        )
    assert result.name == "repo"
    assert result.url == "https://github.com/test/repo"


@pytest.mark.asyncio
async def test_bug_detection_agent_returns_report():
    with (
        patch(
            "app.agents.bug_detection_agent.run_full_analysis",
            return_value={"ruff": {"issues": []}, "bandit": {"issues": []}},
        ),
        patch(
            "app.agents.bug_detection_agent.run_tests",
            return_value={"passed": 0, "failed": 0, "errors": 0},
        ),
        patch("app.agents.bug_detection_agent.get_python_files", return_value=[]),
        patch(
            "app.agents.bug_detection_agent.call_llm_for_json",
            new=AsyncMock(return_value={}),
        ),
    ):
        result = await bug_detection_agent.run("/tmp/fake")
    assert result.total_critical == 0


def test_issue_report_totals_computed_automatically():
    report = IssueReport(
        critical=[Bug(description="null ptr", file="main.py")],
        warnings=[Warning(description="unused var", file="utils.py")],
        suggestions=[Suggestion(description="use walrus operator", file="utils.py")],
    )
    assert report.total_critical == 1
    assert report.total_warnings == 1
    assert report.total_suggestions == 1


def test_issue_report_totals_empty():
    report = IssueReport()
    assert report.total_critical == 0
    assert report.total_warnings == 0
    assert report.total_suggestions == 0


def test_repository_request_rejects_invalid_url():
    with pytest.raises(Exception):
        RepositoryRequest(github_url="http://not-github.com/owner/repo")


def test_repository_request_rejects_bare_domain():
    with pytest.raises(Exception):
        RepositoryRequest(github_url="https://github.com")


def test_repository_request_accepts_valid_url():
    req = RepositoryRequest(github_url="https://github.com/owner/repo")
    assert req.github_url == "https://github.com/owner/repo"


@pytest.mark.asyncio
async def test_code_review_agent_no_source_files():
    from app.agents import code_review_agent
    from app.models.repository import RepositoryMetadata

    metadata = RepositoryMetadata(
        url="https://github.com/test/repo",
        name="repo",
        local_path="/tmp/fake",
    )
    with patch("app.tools.file_scanner.get_python_files", return_value=[]):
        result = await code_review_agent.run("/tmp/fake", metadata)
    assert result.overall_score == 0.0
    assert "No source files" in result.summary


@pytest.mark.asyncio
async def test_test_generation_agent_no_source():
    from app.agents import test_generation_agent

    with patch("app.agents.test_generation_agent.get_python_files", return_value=[]):
        result = await test_generation_agent.run("/tmp/fake")
    assert result.total_tests_generated == 0
    assert "No source files" in result.test_code


@pytest.mark.asyncio
async def test_test_generation_agent_with_source(tmp_path):
    from app.agents import test_generation_agent

    # Use a subdirectory without "test_" in the path so the agent doesn't skip it
    src_dir = tmp_path / "src"
    src_dir.mkdir()
    src = src_dir / "sample.py"
    src.write_text("def add(a, b):\n    return a + b\n")

    with patch(
        "app.agents.test_generation_agent.call_llm_routed",
        new=AsyncMock(return_value="def test_add():\n    assert add(1, 2) == 3\n"),
    ):
        result = await test_generation_agent.run(str(src_dir))
    assert result.total_tests_generated >= 1


@pytest.mark.asyncio
async def test_report_generator_agent_returns_report():
    from app.agents import report_generator_agent
    from app.models.repository import RepositoryMetadata
    from app.models.issue import IssueReport
    from app.models.review import ReviewSuggestions, GeneratedTests

    metadata = RepositoryMetadata(
        url="https://github.com/t/r", name="r", local_path="/tmp"
    )
    issues = IssueReport()
    tests = GeneratedTests(test_code="", total_tests_generated=0)
    review = ReviewSuggestions(overall_score=7.0, summary="ok")

    with patch(
        "app.agents.report_generator_agent.call_llm_routed",
        new=AsyncMock(return_value="# Engineering Report\nAll looks good."),
    ):
        result = await report_generator_agent.run(metadata, issues, tests, review)
    assert "Engineering Report" in result.full_report
    assert result.repository.name == "r"