import os, json, time import pytest from fastapi.testclient import TestClient from app.main import app from app.config import settings from app.core.auth import create_token client = TestClient(app) TEST_DATA_FILE = os.path.join(settings.PROCESSED_DIR, "ai_presets.json") if os.path.exists(TEST_DATA_FILE): os.remove(TEST_DATA_FILE) def _auth_header(): token = create_token("test_user_presets", "testuser", "standard", False) return {"Authorization": f"Bearer {token}"} def test_list_presets_defaults(): res = client.get("/api/v1/ai/presets") assert res.status_code == 200 data = res.json() assert data["success"] is True assert len(data["presets"]) == 3 names = [p["name"] for p in data["presets"]] assert "Epic Orchestra Intro (8 Bars)" in names assert "Pop Piano Chords (4 Bars)" in names assert "Cyberpunk Synthwave (8 Bars)" in names def test_create_user_preset(): preset = { "id": "preset_test_my_beat", "name": "My Beat (4 Bars)", "keywords": ["my beat", "custom beat", "beat của tôi"], "category": "Hip Hop / Beat", "default_bars": 4, "default_bpm": 100, "default_scale": "A Minor", "system_instruction_template": "Generate a 4-bar hip hop beat with kick, snare, hi-hat.", "is_user_defined": True, "is_favorite": False, "created_at": "2026-07-28T00:00:00Z" } res = client.post("/api/v1/ai/presets", json=preset, headers=_auth_header()) assert res.status_code == 200, res.text data = res.json() assert data["success"] is True assert data["preset"]["id"] == "preset_test_my_beat" # Verify it appears in listing res2 = client.get("/api/v1/ai/presets", headers=_auth_header()) assert res2.status_code == 200 names = [p["name"] for p in res2.json()["presets"]] assert "My Beat (4 Bars)" in names assert len(res2.json()["presets"]) == 4 # 3 defaults + 1 user def test_update_user_preset(): preset = { "id": "preset_test_my_beat", "name": "My Beat Updated (8 Bars)", "keywords": ["my beat", "custom beat"], "category": "Hip Hop / Beat", "default_bars": 8, "default_bpm": 110, "default_scale": "C Minor", "system_instruction_template": "Generate an 8-bar hip hop beat.", "is_user_defined": True, "is_favorite": True, "created_at": "2026-07-28T00:00:00Z" } res = client.post("/api/v1/ai/presets", json=preset, headers=_auth_header()) assert res.status_code == 200 data = res.json() assert data["preset"]["name"] == "My Beat Updated (8 Bars)" assert data["preset"]["is_favorite"] is True assert data["preset"]["default_bars"] == 8 def test_delete_user_preset(): res = client.delete("/api/v1/ai/presets/preset_test_my_beat", headers=_auth_header()) assert res.status_code == 200 data = res.json() assert data["success"] is True res2 = client.get("/api/v1/ai/presets", headers=_auth_header()) assert res2.status_code == 200 names = [p["name"] for p in res2.json()["presets"]] assert "My Beat Updated (8 Bars)" not in names def test_delete_nonexistent_preset(): res = client.delete("/api/v1/ai/presets/nonexistent_id", headers=_auth_header()) assert res.status_code == 404 def test_presets_anonymous_cannot_save(): preset = { "id": "preset_anon", "name": "Anon Preset", "keywords": ["anon"], "category": "General", "default_bars": 4, "default_bpm": 120, "default_scale": "C Major", "system_instruction_template": "Test", "is_user_defined": True, "is_favorite": False } res = client.post("/api/v1/ai/presets", json=preset) assert res.status_code == 401 res2 = client.delete("/api/v1/ai/presets/preset_anon") assert res2.status_code == 401 def test_presets_isolation_between_users(): token_a = create_token("user_a", "usera", "standard", False) token_b = create_token("user_b", "userb", "standard", False) preset_a = { "id": "preset_user_a_only", "name": "User A Preset", "keywords": ["user a"], "category": "General", "default_bars": 4, "default_bpm": 120, "default_scale": "C Major", "system_instruction_template": "User A specific", "is_user_defined": True, "is_favorite": False } res = client.post("/api/v1/ai/presets", json=preset_a, headers={"Authorization": f"Bearer {token_a}"}) assert res.status_code == 200 # User B shouldn't see User A's presets res_b = client.get("/api/v1/ai/presets", headers={"Authorization": f"Bearer {token_b}"}) assert res_b.status_code == 200 names_b = [p["name"] for p in res_b.json()["presets"]] assert "User A Preset" not in names_b assert "Epic Orchestra Intro (8 Bars)" in names_b