feat: add web UI with login, CRUD, admin, and API key management
- Add login page with JWT authentication - Add dashboard with stats and quick actions - Add links management page (full CRUD with search) - Add collections management page - Add API key management page with copy-to-clipboard - Add admin user management page (admin only) - Fix UUID type mismatches across all endpoints - Add updated_at column to api_keys and audit_log in schema.sql - Fix DB_PASSWORD default in docker-compose.yml - Add PyJWT to requirements.txt - Fix API docs URL (/docs instead of /api/docs) - Improve JS error handling (show actual messages) - Rewrite conftest.py with proper DB lifecycle management - Add 42 new integration tests (84 total, all passing) - test_admin.py: 15 tests for admin endpoints - test_auth_extended.py: 9 tests for API key CRUD - test_tags.py: 12 tests for tag endpoints - test_sync.py: 6 tests for sync endpoints
This commit is contained in:
93
LinkSyncServer/tests/test_sync.py
Normal file
93
LinkSyncServer/tests/test_sync.py
Normal file
@@ -0,0 +1,93 @@
|
||||
"""
|
||||
LinkSyncServer - Sync API Tests
|
||||
"""
|
||||
|
||||
import uuid
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
class TestSync:
|
||||
def test_sync_list_collections(self, client: TestClient):
|
||||
response = client.get("/api/sync/collections")
|
||||
assert response.status_code == 200
|
||||
assert isinstance(response.json(), list)
|
||||
|
||||
def test_sync_get_collection_not_found(self, client: TestClient, auth_headers: dict):
|
||||
response = client.get(
|
||||
"/api/sync/collections/00000000-0000-0000-0000-000000000000",
|
||||
headers=auth_headers,
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_sync_create_collection_and_get(self, client: TestClient, auth_headers: dict):
|
||||
col_name = f"Sync Get Test {uuid.uuid4().hex[:8]}"
|
||||
create_resp = client.post(
|
||||
"/api/collections/",
|
||||
json={
|
||||
"name": col_name,
|
||||
"description": "Test",
|
||||
"query_type": "static",
|
||||
"is_public": False,
|
||||
"link_ids": [],
|
||||
},
|
||||
headers=auth_headers,
|
||||
)
|
||||
collection_id = create_resp.json()["id"]
|
||||
response = client.get(
|
||||
f"/api/sync/collections/{collection_id}",
|
||||
headers=auth_headers,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json()["name"] == col_name
|
||||
|
||||
def test_sync_add_links(self, client: TestClient, auth_headers: dict, sample_bookmark_data: dict):
|
||||
bm_data = sample_bookmark_data.copy()
|
||||
bm_data["url"] = f"https://sync-test-{uuid.uuid4().hex[:8]}.com"
|
||||
bm_data["title"] = f"Sync Test {uuid.uuid4().hex[:8]}"
|
||||
bm_resp = client.post("/api/links/", json=bm_data, headers=auth_headers)
|
||||
bookmark_id = bm_resp.json()["id"]
|
||||
|
||||
col_name = f"Sync Add Links {uuid.uuid4().hex[:8]}"
|
||||
col_resp = client.post(
|
||||
"/api/collections/",
|
||||
json={
|
||||
"name": col_name,
|
||||
"query_type": "static",
|
||||
"is_public": False,
|
||||
"link_ids": [],
|
||||
},
|
||||
headers=auth_headers,
|
||||
)
|
||||
collection_id = col_resp.json()["id"]
|
||||
|
||||
response = client.post(
|
||||
f"/api/sync/collections/{collection_id}/add-links",
|
||||
json=[bookmark_id],
|
||||
headers=auth_headers,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_sync_delete_collection(self, client: TestClient, auth_headers: dict):
|
||||
col_name = f"Sync Delete {uuid.uuid4().hex[:8]}"
|
||||
create_resp = client.post(
|
||||
"/api/collections/",
|
||||
json={
|
||||
"name": col_name,
|
||||
"query_type": "static",
|
||||
"is_public": False,
|
||||
"link_ids": [],
|
||||
},
|
||||
headers=auth_headers,
|
||||
)
|
||||
collection_id = create_resp.json()["id"]
|
||||
|
||||
response = client.delete(
|
||||
f"/api/sync/collections/{collection_id}",
|
||||
headers=auth_headers,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_sync_list_collections_no_auth(self, client: TestClient):
|
||||
response = client.get("/api/sync/collections")
|
||||
assert response.status_code == 200
|
||||
Reference in New Issue
Block a user