163 lines
5.8 KiB
Python
163 lines
5.8 KiB
Python
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"
|