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
85 lines
1.9 KiB
Python
85 lines
1.9 KiB
Python
"""
|
|
LinkSyncServer - Test Configuration
|
|
"""
|
|
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
from sqlalchemy import create_engine
|
|
from sqlalchemy.orm import sessionmaker
|
|
|
|
from models.base import Base, get_engine
|
|
|
|
|
|
SQLALCHEMY_DATABASE_URL = "sqlite:///test_linksync.db"
|
|
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
|
|
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def test_engine():
|
|
Base.metadata.create_all(bind=engine)
|
|
yield engine
|
|
Base.metadata.drop_all(bind=engine)
|
|
|
|
|
|
@pytest.fixture
|
|
def db_session(test_engine):
|
|
connection = test_engine.connect()
|
|
transaction = connection.begin()
|
|
session = TestingSessionLocal(bind=connection)
|
|
|
|
yield session
|
|
|
|
session.close()
|
|
transaction.rollback()
|
|
connection.close()
|
|
|
|
|
|
@pytest.fixture
|
|
def client():
|
|
from app import app
|
|
with TestClient(app) as c:
|
|
yield c
|
|
|
|
|
|
@pytest.fixture
|
|
def admin_token(client):
|
|
response = client.post(
|
|
"/api/auth/login",
|
|
data={"username": "admin", "password": "admin123"},
|
|
)
|
|
assert response.status_code == 200
|
|
return response.json()["access_token"]
|
|
|
|
|
|
@pytest.fixture
|
|
def auth_headers(admin_token):
|
|
return {"Authorization": f"Bearer {admin_token}"}
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_bookmark_data():
|
|
return {
|
|
"url": "https://example.com",
|
|
"title": "Example Site",
|
|
"description": "An example website",
|
|
"notes": "Test notes",
|
|
"tags": ["test", "example"],
|
|
"favicon_url": "https://example.com/favicon.ico",
|
|
"path": "/Test",
|
|
"visit_count": 0,
|
|
"is_bookmarked": True,
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_collection_data():
|
|
return {
|
|
"name": "Test Collection",
|
|
"description": "A test collection",
|
|
"query_type": "static",
|
|
"query_expression": None,
|
|
"is_public": False,
|
|
"link_ids": [],
|
|
}
|