import json import pytest from backend.app import create_app @pytest.fixture def client(): """ Creates a Flask test client from your create_app function. """ app = create_app() app.config["TESTING"] = True with app.test_client() as client: yield client @pytest.fixture def auth_headers(client): """ Registers and logs in a test user, returning an authorization header. """ import uuid unique_suffix = str(uuid.uuid4())[:8] username = f"apilistuser_{unique_suffix}" email = f"{username}@example.com" reg_payload = { "username": username, "email": email, "password": "TestPassword123" } reg_resp = client.post("/api/register", data=json.dumps(reg_payload), content_type="application/json") assert reg_resp.status_code == 201, f"Registration failed: {reg_resp.data.decode()}" data = json.loads(reg_resp.data) token = data["token"] return {"Authorization": f"Bearer {token}"} def test_list_api_keys_empty(client, auth_headers): """ Initially, the user has no API keys. GET /api/api_list should return empty array. """ resp = client.get("/api/api_list", headers=auth_headers) assert resp.status_code == 200, f"List keys failed: {resp.data.decode()}" data = json.loads(resp.data) assert "api_keys" in data assert len(data["api_keys"]) == 0 def test_create_api_key(client, auth_headers): """ Test creating an API key for e.g. 'Gemini'. """ payload = { "name": "Gemini", "key": "gemini-secret-key", "selected": True } create_resp = client.post("/api/api_list", data=json.dumps(payload), content_type="application/json", headers=auth_headers) assert create_resp.status_code == 201, f"Create API key failed: {create_resp.data.decode()}" data = json.loads(create_resp.data) assert "api_id" in data # Now list and verify we see the new key list_resp = client.get("/api/api_list", headers=auth_headers) assert list_resp.status_code == 200 list_data = json.loads(list_resp.data) keys = list_data.get("api_keys", []) assert len(keys) == 1 api_entry = keys[0] assert api_entry["name"] == "Gemini" assert api_entry["key"] == "gemini-secret-key" assert api_entry["selected"] is True def test_create_api_key_duplicate(client, auth_headers): """ By default, the code returns 400 if the user already has an API key for the same 'name'. """ # Create first payload1 = { "name": "Chatgpt", "key": "chatgpt-key1", "selected": False } resp1 = client.post("/api/api_list", data=json.dumps(payload1), content_type="application/json", headers=auth_headers) assert resp1.status_code == 201 # Try creating second with same 'name' => should fail with 400 payload2 = { "name": "Chatgpt", "key": "chatgpt-key2", "selected": True } resp2 = client.post("/api/api_list", data=json.dumps(payload2), content_type="application/json", headers=auth_headers) assert resp2.status_code == 400, f"Expected 400 on duplicate provider, got {resp2.status_code}" def test_create_api_key_invalid_name(client, auth_headers): """ If 'name' is not in ['Gemini','Deepseek','Chatgpt'], the code should fail with 400. """ invalid_payload = { "name": "InvalidProvider", "key": "some-key", "selected": False } resp = client.post("/api/api_list", data=json.dumps(invalid_payload), content_type="application/json", headers=auth_headers) assert resp.status_code == 400, f"Expected 400 on invalid 'name', got {resp.status_code}" def test_update_api_key(client, auth_headers): """ Test updating an existing API key fields: 'key', 'selected', or 'name'. """ # Create payload = { "name": "Deepseek", "key": "deepseek-initial", "selected": False } create_resp = client.post("/api/api_list", data=json.dumps(payload), content_type="application/json", headers=auth_headers) assert create_resp.status_code == 201 api_id = json.loads(create_resp.data)["api_id"] # Now update update_payload = {"key": "deepseek-updated", "selected": True} update_resp = client.put(f"/api/api_list/{api_id}", data=json.dumps(update_payload), content_type="application/json", headers=auth_headers) assert update_resp.status_code == 200, f"Update failed: {update_resp.data.decode()}" # List and confirm list_resp = client.get("/api/api_list", headers=auth_headers) data = json.loads(list_resp.data) updated_entry = next((k for k in data["api_keys"] if k["_id"] == api_id), None) assert updated_entry is not None, "Updated key not found in list" assert updated_entry["key"] == "deepseek-updated" assert updated_entry["selected"] is True def test_delete_api_key(client, auth_headers): """ Test deleting an API key by _id. """ payload = { "name": "Gemini", "key": "gemini-key2", "selected": False } create_resp = client.post("/api/api_list", data=json.dumps(payload), content_type="application/json", headers=auth_headers) assert create_resp.status_code == 201 api_id = json.loads(create_resp.data)["api_id"] # Delete delete_resp = client.delete(f"/api/api_list/{api_id}", headers=auth_headers) assert delete_resp.status_code == 200, f"Deletion failed: {delete_resp.data.decode()}" # Confirm it's gone list_resp = client.get("/api/api_list", headers=auth_headers) data = json.loads(list_resp.data) keys_left = [k for k in data["api_keys"] if k["_id"] == api_id] assert len(keys_left) == 0, "API key was not deleted properly"