feat(server): /fetch and /jobs endpoints with async download jobs
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
81
tests/test_api.py
Normal file
81
tests/test_api.py
Normal file
@@ -0,0 +1,81 @@
|
||||
import time
|
||||
import pytest
|
||||
from server import mf, jobs as jobs_mod
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _clear_jobs():
|
||||
jobs_mod.JOBS.clear()
|
||||
yield
|
||||
jobs_mod.JOBS.clear()
|
||||
|
||||
|
||||
def _yt_hit():
|
||||
return mf.Hit(source="youtube", kind="track", title="Together",
|
||||
artist="Avril Lavigne", album="Under My Skin", year="2004",
|
||||
payload={"videoId": "abc"})
|
||||
|
||||
|
||||
def test_fetch_returns_job_and_message(client, auth, monkeypatch):
|
||||
hit = _yt_hit()
|
||||
monkeypatch.setattr("server.app.mf.build_combined_hits",
|
||||
lambda q, limit, yt_first, lidarr_only, yt_only: [hit])
|
||||
monkeypatch.setattr("server.app.mf.pick",
|
||||
lambda hits, q, noninteractive, yt_first: hits[0])
|
||||
monkeypatch.setattr("server.app.actions.perform_fetch",
|
||||
lambda chosen, hits, quality, root: {"path": "/media/music/x", "lidarr_album_id": None})
|
||||
|
||||
r = client.post("/fetch", params={"q": "Under My Skin"}, headers=auth)
|
||||
assert r.status_code == 200
|
||||
body = r.json()
|
||||
assert body["status"] == "queued"
|
||||
assert "Under My Skin" in body["message"] or "Together" in body["message"]
|
||||
assert body["hit"]["artist"] == "Avril Lavigne"
|
||||
assert body["job_id"]
|
||||
|
||||
|
||||
def test_fetch_no_hits_returns_404(client, auth, monkeypatch):
|
||||
monkeypatch.setattr("server.app.mf.build_combined_hits",
|
||||
lambda q, limit, yt_first, lidarr_only, yt_only: [])
|
||||
r = client.post("/fetch", params={"q": "zzzz"}, headers=auth)
|
||||
assert r.status_code == 404
|
||||
assert "zzzz" in r.json()["message"]
|
||||
|
||||
|
||||
def test_fetch_missing_q_returns_422(client, auth):
|
||||
r = client.post("/fetch", headers=auth)
|
||||
assert r.status_code == 422
|
||||
|
||||
|
||||
def test_job_lifecycle_done(client, auth, monkeypatch):
|
||||
hit = _yt_hit()
|
||||
monkeypatch.setattr("server.app.mf.build_combined_hits",
|
||||
lambda q, limit, yt_first, lidarr_only, yt_only: [hit])
|
||||
monkeypatch.setattr("server.app.mf.pick",
|
||||
lambda hits, q, noninteractive, yt_first: hits[0])
|
||||
monkeypatch.setattr("server.app.actions.perform_fetch",
|
||||
lambda chosen, hits, quality, root: {"path": "/media/music/x", "lidarr_album_id": None})
|
||||
job_id = client.post("/fetch", params={"q": "x"}, headers=auth).json()["job_id"]
|
||||
|
||||
end = time.time() + 2
|
||||
status = None
|
||||
while time.time() < end:
|
||||
body = client.get(f"/jobs/{job_id}", headers=auth).json()
|
||||
status = body["status"]
|
||||
if status == "done":
|
||||
break
|
||||
time.sleep(0.01)
|
||||
assert status == "done"
|
||||
assert body["result"]["path"] == "/media/music/x"
|
||||
assert "Finished" in body["message"]
|
||||
|
||||
|
||||
def test_unknown_job_404(client, auth):
|
||||
r = client.get("/jobs/deadbeef", headers=auth)
|
||||
assert r.status_code == 404
|
||||
assert "message" in r.json()
|
||||
|
||||
|
||||
def test_jobs_requires_key(client):
|
||||
r = client.get("/jobs/whatever")
|
||||
assert r.status_code == 401
|
||||
Reference in New Issue
Block a user