X-Internal-Key 헤더 검증 dependency (insta-lab 동일 패턴). Windows music-render webhook 수신 endpoint — update_task + 옵션 add_track. Plan-B-Music Phase 1 (수신부). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
104 lines
3.3 KiB
Python
104 lines
3.3 KiB
Python
"""POST /api/internal/music/update — Windows music-render webhook."""
|
|
import pytest
|
|
from fastapi import FastAPI
|
|
from fastapi.testclient import TestClient
|
|
from app.internal_router import router
|
|
from app import db
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _set_key(monkeypatch):
|
|
monkeypatch.setenv("INTERNAL_API_KEY", "test-secret")
|
|
|
|
|
|
@pytest.fixture
|
|
def client(tmp_path, monkeypatch):
|
|
monkeypatch.setenv("MUSIC_DATA_DIR", str(tmp_path))
|
|
monkeypatch.setattr(db, "DB_PATH", str(tmp_path / "test_music.db"))
|
|
db.init_db()
|
|
app = FastAPI()
|
|
app.include_router(router)
|
|
return TestClient(app)
|
|
|
|
|
|
def _make_task():
|
|
tid = "test-task-1"
|
|
db.create_task(tid, {"provider": "suno", "title": "T"}, provider="suno")
|
|
return tid
|
|
|
|
|
|
def test_update_with_valid_key_updates_db(client):
|
|
tid = _make_task()
|
|
r = client.post(
|
|
"/api/internal/music/update",
|
|
headers={"X-Internal-Key": "test-secret"},
|
|
json={"task_id": tid, "status": "processing", "progress": 30, "message": "downloading"},
|
|
)
|
|
assert r.status_code == 200
|
|
task = db.get_task(tid)
|
|
assert task["status"] == "processing"
|
|
assert task["progress"] == 30
|
|
|
|
|
|
def test_update_with_invalid_key_returns_401(client):
|
|
tid = _make_task()
|
|
r = client.post(
|
|
"/api/internal/music/update",
|
|
headers={"X-Internal-Key": "wrong"},
|
|
json={"task_id": tid, "status": "processing", "progress": 30},
|
|
)
|
|
assert r.status_code == 401
|
|
|
|
|
|
def test_update_succeeded_with_audio_url(client):
|
|
tid = _make_task()
|
|
r = client.post(
|
|
"/api/internal/music/update",
|
|
headers={"X-Internal-Key": "test-secret"},
|
|
json={
|
|
"task_id": tid, "status": "succeeded", "progress": 100,
|
|
"message": "완료", "audio_url": "/media/music/test-task-1.mp3",
|
|
},
|
|
)
|
|
assert r.status_code == 200
|
|
task = db.get_task(tid)
|
|
assert task["status"] == "succeeded"
|
|
assert task["audio_url"] == "/media/music/test-task-1.mp3"
|
|
|
|
|
|
def test_update_failed_records_error(client):
|
|
tid = _make_task()
|
|
r = client.post(
|
|
"/api/internal/music/update",
|
|
headers={"X-Internal-Key": "test-secret"},
|
|
json={"task_id": tid, "status": "failed", "progress": 0, "error": "Suno API rate limit"},
|
|
)
|
|
assert r.status_code == 200
|
|
task = db.get_task(tid)
|
|
assert task["status"] == "failed"
|
|
assert "Suno" in (task.get("error") or "")
|
|
|
|
|
|
def test_add_track_action_inserts_library(client):
|
|
tid = _make_task()
|
|
r = client.post(
|
|
"/api/internal/music/update",
|
|
headers={"X-Internal-Key": "test-secret"},
|
|
json={
|
|
"task_id": tid, "status": "succeeded", "progress": 100,
|
|
"message": "ok",
|
|
"track": {
|
|
"title": "My Song", "genre": "lofi", "moods": ["chill"],
|
|
"instruments": [], "duration_sec": 180, "bpm": 80,
|
|
"key": "C", "scale": "major", "prompt": "",
|
|
"audio_url": "/media/music/test-task-1.mp3",
|
|
"file_path": "/app/data/test-task-1.mp3",
|
|
"task_id": tid, "provider": "suno",
|
|
"lyrics": "", "image_url": "", "suno_id": "suno-abc",
|
|
},
|
|
},
|
|
)
|
|
assert r.status_code == 200
|
|
tracks = db.get_all_tracks()
|
|
assert any(t["title"] == "My Song" for t in tracks)
|