File size: 3,315 Bytes
9df97a2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from __future__ import annotations

from types import SimpleNamespace
from unittest.mock import patch

from fastapi.testclient import TestClient

from app.main import app
from app.core.dependencies import get_current_user, get_db
from app.api import matching as matching_module
from app.models.models import Candidate, JobCriteria, User, UserRole


class FakeQuery:
    def __init__(self, rows):
        self.rows = list(rows)

    def filter(self, *args, **kwargs):
        return self

    def order_by(self, *args, **kwargs):
        return self

    def all(self):
        return list(self.rows)

    def first(self):
        return self.rows[0] if self.rows else None


class FakeSession:
    def __init__(self):
        self.recruiter = User(
            id=1,
            email="recruiter@example.com",
            hashed_password="x",
            full_name="Recruiter",
            role=UserRole.recruiter,
        )
        self.criteria = JobCriteria(
            id=1,
            recruiter_id=1,
            title="Senior Python Developer",
            description="Build APIs with FastAPI and SQL",
        )
        self.candidate = Candidate(
            id=10,
            full_name="Alice Smith",
            email="alice@example.com",
            raw_text="Python FastAPI Docker",
        )

    def query(self, model):
        if model is User:
            return FakeQuery([self.recruiter])
        if model is JobCriteria:
            return FakeQuery([self.criteria])
        if model is Candidate:
            return FakeQuery([self.candidate])
        return FakeQuery([])


class FakeUser(SimpleNamespace):
    pass


class TestMatchingGenerationRoutes:
    def setup_method(self):
        self.fake_session = FakeSession()
        app.dependency_overrides[get_db] = lambda: self.fake_session
        app.dependency_overrides[get_current_user] = lambda: FakeUser(id=1, role=UserRole.recruiter)

    def teardown_method(self):
        app.dependency_overrides.clear()

    def test_generate_and_match_route_returns_results(self):
        with patch.object(matching_module, "_generate_profile_payload", return_value={"ideal_skills": [{"name": "Python", "weight": 100}]}), \
             patch.object(matching_module, "calculate_match_score", return_value=(88.0, {"details": "Strong fit"})):
            with TestClient(app) as client:
                response = client.post(
                    "/api/matching/generate-and-match",
                    json={"job_title": "Senior Python Developer", "description": "Looking for Python and FastAPI"},
                )

        assert response.status_code == 200
        payload = response.json()
        assert payload["ideal_profile"]["ideal_skills"]
        assert len(payload["matches"]) == 1
        assert payload["matches"][0]["candidate_id"] == 10
        assert payload["matches"][0]["match_score"] == 88.0

    def test_matching_results_route_handles_numeric_ids(self):
        with patch.object(matching_module, "_score_all_candidates", return_value=[]), \
             patch.object(matching_module, "_persist_match_results", return_value=[]):
            with TestClient(app) as client:
                response = client.post("/api/matching/1/results")

        assert response.status_code == 200
        assert response.json() == []