import os import json import pytest from fastapi.testclient import TestClient from unittest.mock import patch, MagicMock from app.main import app from app.core.vst_engine import HAS_PEDALBOARD, HAS_PYFLUIDSYNTH client = TestClient(app) def get_admin_token(): resp = client.post("/api/v1/auth/login", json={"username": "admin", "password": "admin123"}) if resp.status_code == 200: return resp.json()["access_token"] return None class TestPluginAPI: def test_list_plugins_requires_auth(self): resp = client.get("/api/v1/plugins/available") assert resp.status_code in (401, 403) def test_list_plugins_authenticated(self): token = get_admin_token() if not token: pytest.skip("Cannot get admin token") resp = client.get("/api/v1/plugins/available", headers={"Authorization": f"Bearer {token}"}) assert resp.status_code == 200 data = resp.json() assert "vst_instruments" in data assert "soundfonts" in data def test_list_default_soundfonts(self): resp = client.get("/api/v1/plugins/default-soundfonts") assert resp.status_code == 200 data = resp.json() assert isinstance(data, list) def test_render_project_invalid_json(self): token = get_admin_token() if not token: pytest.skip("Cannot get admin token") resp = client.post("/api/v1/plugins/render", headers={"Authorization": f"Bearer {token}"}, json={"project_json": {}}) # Should fail because project is empty, but API should return 500 or error assert resp.status_code in (400, 422, 500) def test_upload_soundfont_requires_auth(self): resp = client.post("/api/v1/plugins/upload-soundfont") assert resp.status_code in (401, 403, 422) def test_upload_soundfont_invalid_magic(self): token = get_admin_token() if not token: pytest.skip("Cannot get admin token") # Upload a file with invalid magic bytes fake_content = b'XXXX\x00\x00\x00\x00YYYY' * 100 resp = client.post( "/api/v1/plugins/upload-soundfont", headers={"Authorization": f"Bearer {token}"}, files={"file": ("fake.sf2", fake_content, "application/octet-stream")} ) assert resp.status_code == 400 assert "Invalid SoundFont" in resp.json().get("detail", "") def test_upload_soundfont_valid_magic(self): token = get_admin_token() if not token: pytest.skip("Cannot get admin token") # Upload a file with valid RIFF + sfbk magic valid_content = b'RIFF\x00\x00\x00\x00sfbk' + b'\x00' * 200 resp = client.post( "/api/v1/plugins/upload-soundfont", headers={"Authorization": f"Bearer {token}"}, files={"file": ("test.sf2", valid_content, "application/octet-stream")} ) # Should succeed (200) unless auth/permission issues if resp.status_code == 200: data = resp.json() assert "id" in data assert "size_bytes" in data assert data["size_bytes"] == len(valid_content) elif resp.status_code == 403: pytest.skip("Permission denied for admin user")