jobhunt-platform/apps/api/tests/test_cv_import.py
hermes 3035e4eac9 W2: api v1 features (CV import, AF fetch, batch scoring, today/nudges, interview prep, SMTP+clipboard transports, scheduler, 90 tests)
Implements docs/api-contract-v2.md. Migration 002 adds follow-up fields.
EchoTransport replaced by SMTP->Clipboard selection behind unchanged approval gate.
Scheduler (APScheduler) daily 07:00 fetch+score, env-gated, default off.
Test image installs workspace packages; build context moved to repo root.
Recovered and committed by integration lead after W2 worker hit iteration limit.
2026-07-30 18:29:17 +00:00

162 lines
No EOL
5.1 KiB
Python

"""Tests for v1 CV import endpoints (mock LLM mode)."""
from __future__ import annotations
import base64
import pytest
from fastapi.testclient import TestClient
@pytest.fixture()
def client():
from app.main import app
return TestClient(app)
class TestCvImport:
def test_import_txt_file(self, client):
"""POST /cv/import with a .txt file returns drafts."""
content = b"John Doe\nSoftware Engineer at TechCorp\n5 years experience with Python"
resp = client.post(
"/api/cv/import",
json={
"filename": "my_cv.txt",
"content_base64": base64.b64encode(content).decode(),
},
)
assert resp.status_code == 200
data = resp.json()
assert "drafts" in data
assert len(data["drafts"]) > 0
def test_import_empty_file_422(self, client):
"""Empty file -> 422."""
content = b""
resp = client.post(
"/api/cv/import",
json={
"filename": "empty.txt",
"content_base64": base64.b64encode(content).decode(),
},
)
assert resp.status_code == 422
assert "empty" in resp.text.lower()
def test_import_whitespace_only_file_422(self, client):
"""File with only whitespace -> 422."""
content = b" \n\n\t "
resp = client.post(
"/api/cv/import",
json={
"filename": "blank.txt",
"content_base64": base64.b64encode(content).decode(),
},
)
assert resp.status_code == 422
assert "empty" in resp.text.lower()
def test_import_unsupported_format_422(self, client):
"""Unsupported file format -> 422."""
content = b"some data"
resp = client.post(
"/api/cv/import",
json={
"filename": "file.xyz",
"content_base64": base64.b64encode(content).decode(),
},
)
assert resp.status_code == 422
assert "unsupported" in resp.text.lower()
def test_import_invalid_base64_422(self, client):
"""Invalid base64 -> 422."""
resp = client.post(
"/api/cv/import",
json={
"filename": "file.txt",
"content_base64": "!!!not-base64!!!",
},
)
assert resp.status_code == 422
def test_import_md_file(self, client):
"""POST /cv/import with a .md file returns drafts."""
content = b"# Jane Doe\n\n## Experience\nSenior Developer at Acme"
resp = client.post(
"/api/cv/import",
json={
"filename": "cv.md",
"content_base64": base64.b64encode(content).decode(),
},
)
assert resp.status_code == 200
assert "drafts" in resp.json()
def test_import_creates_telemetry(self, client):
"""CV import should create a task_run entry."""
content = b"Some CV text with experience"
client.post(
"/api/cv/import",
json={
"filename": "cv.txt",
"content_base64": base64.b64encode(content).decode(),
},
)
resp = client.get("/api/telemetry/tasks")
tasks = resp.json()
assert any(t["task"] == "cv_extract" for t in tasks)
class TestCvImportConfirm:
def test_confirm_creates_sections(self, client):
"""POST /cv/import/confirm creates cv_section rows."""
client.get("/api/profile")
resp = client.post(
"/api/cv/import/confirm",
json={
"drafts": [
{
"kind": "experience",
"title": "Dev",
"org": "Corp",
"bullets": ["did stuff"],
"tags": ["python"],
},
{
"kind": "education",
"title": "MSc",
"org": "Uni",
},
]
},
)
assert resp.status_code == 201
data = resp.json()
assert data["created"] == 2
assert len(data["sections"]) == 2
def test_confirm_empty_drafts(self, client):
"""Empty drafts list creates zero sections."""
client.get("/api/profile")
resp = client.post(
"/api/cv/import/confirm",
json={"drafts": []},
)
assert resp.status_code == 201
assert resp.json()["created"] == 0
def test_confirm_sections_appear_in_list(self, client):
"""Confirmed sections appear in GET /profile/sections."""
client.get("/api/profile")
client.post(
"/api/cv/import/confirm",
json={
"drafts": [
{"kind": "skills", "title": "Python Dev", "bullets": ["FastAPI"]},
]
},
)
resp = client.get("/api/profile/sections")
assert resp.status_code == 200
assert any(s["title"] == "Python Dev" for s in resp.json())