108 lines
5.5 KiB
Python
108 lines
5.5 KiB
Python
from fastapi.testclient import TestClient
|
|
import pytest
|
|
|
|
from test_app import load_app_module
|
|
|
|
|
|
def test_cv_evaluation_has_structured_semantic_rules_and_requirements_only_context(monkeypatch):
|
|
module = load_app_module(monkeypatch, ollama_model="qwen2.5:7b", service_token="local-proof-token")
|
|
expected = {"verdict": "supported", "coverageComplete": True, "claims": [
|
|
{"text": "Utviklet API-er.", "verdict": "supported", "sourceQuotes": ["Built APIs."]}]}
|
|
|
|
def evaluate(prompt):
|
|
assert "faithful paraphrases, shortening" in prompt
|
|
assert "English/Bokmal translations" in prompt
|
|
assert "Job/context text describes requirements ONLY" in prompt
|
|
assert "Candidate source is the ONLY evidence" in prompt
|
|
assert "Assess ALL factual claims" in prompt
|
|
assert "coverage is complete and every entry is supported" in prompt
|
|
assert "Employer requires Kubernetes." in prompt
|
|
assert module._ai_task_type.get() == "cv-rewrite"
|
|
return expected
|
|
|
|
monkeypatch.setattr(module, "_ollama_generate_json", evaluate)
|
|
client = TestClient(module.app)
|
|
body = {"candidate_source": "Built APIs.", "proposal": "Utviklet API-er.", "context_only": "Employer requires Kubernetes."}
|
|
assert client.post("/cv/evaluate-rewrite", json=body).status_code == 401
|
|
response = client.post("/cv/evaluate-rewrite", json=body, headers={"X-Ai-Service-Token": "local-proof-token"})
|
|
assert response.status_code == 200
|
|
assert response.json() == {"assessment": expected}
|
|
|
|
|
|
@pytest.mark.parametrize("source,proposal,context", [
|
|
("", "Built APIs.", ""), (" ", "Built APIs.", ""), ("Built APIs.", "", ""),
|
|
("x" * 20000, "New proposal.", ""), ("Built APIs.", "Proposal.", "x" * 6001),
|
|
])
|
|
def test_cv_evaluation_rejects_empty_or_oversized_inputs_before_generation(monkeypatch, source, proposal, context):
|
|
module = load_app_module(monkeypatch)
|
|
monkeypatch.setattr(module, "_ollama_generate_json", lambda _: pytest.fail("Invalid input must not generate"))
|
|
response = TestClient(module.app).post("/cv/evaluate-rewrite", json={"candidate_source": source, "proposal": proposal, "context_only": context})
|
|
assert response.status_code == 422
|
|
|
|
|
|
def test_cv_evaluation_uses_existing_local_first_privacy_gate(monkeypatch):
|
|
monkeypatch.setenv("AI_PROVIDER", "groq")
|
|
monkeypatch.setenv("GROQ_API_KEY", "synthetic-test-key")
|
|
module = load_app_module(monkeypatch, ollama_model="qwen2.5:7b", external_ai_enabled=True)
|
|
providers = []
|
|
|
|
def generate(provider, prompt, **kwargs):
|
|
providers.append(provider)
|
|
assert kwargs["json_mode"] is True
|
|
if provider == "ollama":
|
|
raise module._ProviderFailure(provider, "provider_unavailable", 503)
|
|
return '{"verdict":"unknown","coverageComplete":false,"claims":[]}'
|
|
|
|
monkeypatch.setattr(module, "_generate_from_provider", generate)
|
|
client = TestClient(module.app)
|
|
body = {"candidate_source": "Built APIs.", "proposal": "Led engineers."}
|
|
assert client.post("/cv/evaluate-rewrite", json=body).status_code == 503
|
|
assert providers == ["ollama"]
|
|
providers.clear()
|
|
response = client.post("/cv/evaluate-rewrite", json=body, headers={"X-Ai-External-Allowed": "true"})
|
|
assert response.status_code == 200
|
|
assert providers == ["ollama", "groq"]
|
|
assert response.json()["assessment"]["verdict"] == "unknown"
|
|
|
|
|
|
def test_cv_evaluation_rejects_non_object_provider_assessment(monkeypatch):
|
|
module = load_app_module(monkeypatch)
|
|
monkeypatch.setattr(module, "_ollama_generate_json", lambda _: [])
|
|
response = TestClient(module.app).post("/cv/evaluate-rewrite", json={"candidate_source": "Built APIs.", "proposal": "Developed APIs."})
|
|
assert response.status_code == 502
|
|
|
|
|
|
@pytest.mark.parametrize("output_mode", [None, "text", "cv_blocks_json"])
|
|
def test_cv_rewrite_typed_format_preserves_legacy_text_and_document_json(monkeypatch, output_mode):
|
|
module = load_app_module(monkeypatch)
|
|
result = '[{"id":"section:summary","title":"Profile","items":["Developed APIs."]}]' if output_mode == "cv_blocks_json" else "Developed APIs."
|
|
|
|
def generate(prompt):
|
|
if output_mode == "cv_blocks_json":
|
|
assert "Return ONLY a valid JSON array" in prompt
|
|
assert "Preserve every original block id exactly once" in prompt
|
|
assert "same title, subtitle and items fields/types" in prompt
|
|
assert "No JSON." not in prompt
|
|
assert "Preferred whole-CV structure" not in prompt
|
|
assert "sensible headings and bullets" not in prompt
|
|
else:
|
|
assert "Return ONLY the final CV text" in prompt
|
|
assert "No JSON." in prompt
|
|
assert module._ai_task_type.get() == "cv-rewrite"
|
|
return result
|
|
|
|
monkeypatch.setattr(module, "_ollama_generate_text", generate)
|
|
body = {"instruction": "Improve clarity.", "text": "Built APIs."}
|
|
if output_mode is not None:
|
|
body["output_mode"] = output_mode
|
|
response = TestClient(module.app).post("/cv/rewrite", json=body)
|
|
assert response.status_code == 200
|
|
assert response.json() == {"rewritten_text": result}
|
|
|
|
|
|
def test_cv_rewrite_rejects_unknown_typed_output_mode_before_generation(monkeypatch):
|
|
module = load_app_module(monkeypatch)
|
|
monkeypatch.setattr(module, "_ollama_generate_text", lambda _: pytest.fail("Unknown mode must not generate"))
|
|
response = TestClient(module.app).post("/cv/rewrite", json={"instruction": "Improve", "text": "Built APIs.", "output_mode": "untrusted-mode"})
|
|
assert response.status_code == 422
|