LinkSyncServer: - Fix app.py imports, add CORS middleware, lifespan events - Create api/routes.py router aggregator - Create config/settings.py for centralized configuration - Rewrite models/base.py with proper relationships and serialization - Rewrite all API endpoints with real DB integration (auth, links, collections, sync, queries, tags) - Add admin endpoints (user management, stats, audit log) - Complete query parser with recursive descent and proper precedence - Complete query executor with set operations and field filters - Set up Alembic migrations with initial schema - Create web interface (templates, CSS, JS) - Add 42 passing tests (auth, links, collections, queries) - Add deploy.ps1 and deploy.sh scripts - Update README with deployment workflow LinkSyncExtension: - Create utils/api.js (REST client with retries, auth, error handling) - Create utils/sync.js (3 sync modes + conflict detection) - Create utils/collection.js (collection management) - Create utils/query-engine.js (client-side query parser) - Rewrite background.js (sync loop, bookmark events, message routing) - Rewrite popup.js (tabs, settings modal, notifications, CRUD) - Update popup.html (tabbed interface, query builder, modal) - Update popup.css (full redesign) - Create content/content.js (page metadata extraction) - Create options.html/js (dedicated settings page) - Generate icons (48x48, 96x96) - Update manifest.json (host permissions, content scripts, options) - Create AGENTS.md
84 lines
3.8 KiB
Python
84 lines
3.8 KiB
Python
"""
|
|
LinkSyncServer - Collection API Tests
|
|
"""
|
|
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
|
|
|
|
class TestCollections:
|
|
def test_create_collection(self, client: TestClient, auth_headers: dict, sample_collection_data: dict):
|
|
response = client.post("/api/collections/", json=sample_collection_data, headers=auth_headers)
|
|
assert response.status_code == 201
|
|
data = response.json()
|
|
assert data["name"] == sample_collection_data["name"]
|
|
assert data["query_type"] == "static"
|
|
|
|
def test_list_collections(self, client: TestClient, auth_headers: dict, sample_collection_data: dict):
|
|
client.post("/api/collections/", json=sample_collection_data, headers=auth_headers)
|
|
response = client.get("/api/collections/", headers=auth_headers)
|
|
assert response.status_code == 200
|
|
assert isinstance(response.json(), list)
|
|
|
|
def test_get_collection(self, client: TestClient, auth_headers: dict, sample_collection_data: dict):
|
|
create_resp = client.post("/api/collections/", json=sample_collection_data, headers=auth_headers)
|
|
collection_id = create_resp.json()["id"]
|
|
response = client.get(f"/api/collections/{collection_id}", headers=auth_headers)
|
|
assert response.status_code == 200
|
|
assert response.json()["id"] == collection_id
|
|
|
|
def test_update_collection(self, client: TestClient, auth_headers: dict, sample_collection_data: dict):
|
|
create_resp = client.post("/api/collections/", json=sample_collection_data, headers=auth_headers)
|
|
collection_id = create_resp.json()["id"]
|
|
response = client.put(
|
|
f"/api/collections/{collection_id}",
|
|
json={"name": "Updated Name"},
|
|
headers=auth_headers,
|
|
)
|
|
assert response.status_code == 200
|
|
assert response.json()["name"] == "Updated Name"
|
|
|
|
def test_delete_collection(self, client: TestClient, auth_headers: dict, sample_collection_data: dict):
|
|
create_resp = client.post("/api/collections/", json=sample_collection_data, headers=auth_headers)
|
|
collection_id = create_resp.json()["id"]
|
|
response = client.delete(f"/api/collections/{collection_id}", headers=auth_headers)
|
|
assert response.status_code == 200
|
|
assert response.json()["deleted_id"] == collection_id
|
|
|
|
def test_add_links_to_collection(
|
|
self, client: TestClient, auth_headers: dict, sample_bookmark_data: dict, sample_collection_data: dict
|
|
):
|
|
bm_resp = client.post("/api/links/", json=sample_bookmark_data, headers=auth_headers)
|
|
bookmark_id = bm_resp.json()["id"]
|
|
|
|
col_resp = client.post("/api/collections/", json=sample_collection_data, headers=auth_headers)
|
|
collection_id = col_resp.json()["id"]
|
|
|
|
response = client.post(
|
|
f"/api/collections/{collection_id}/add-links",
|
|
json=[bookmark_id],
|
|
headers=auth_headers,
|
|
)
|
|
assert response.status_code == 200
|
|
assert response.json()["added_count"] == 1
|
|
|
|
def test_remove_links_from_collection(
|
|
self, client: TestClient, auth_headers: dict, sample_bookmark_data: dict, sample_collection_data: dict
|
|
):
|
|
bm_resp = client.post("/api/links/", json=sample_bookmark_data, headers=auth_headers)
|
|
bookmark_id = bm_resp.json()["id"]
|
|
|
|
col_data = sample_collection_data.copy()
|
|
col_data["link_ids"] = [bookmark_id]
|
|
col_resp = client.post("/api/collections/", json=col_data, headers=auth_headers)
|
|
collection_id = col_resp.json()["id"]
|
|
|
|
response = client.request(
|
|
"DELETE",
|
|
f"/api/collections/{collection_id}/remove-links",
|
|
json=[bookmark_id],
|
|
headers=auth_headers,
|
|
)
|
|
assert response.status_code == 200
|
|
assert response.json()["removed_count"] == 1
|