feat: implement Instagram clone SocialPhoto API

- FastAPI backend with SQLite database
- JWT authentication (register, login)
- User profiles with follow/unfollow
- Posts with image upload and likes/dislikes
- Comments with likes
- Global and personalized feed
- Comprehensive pytest test suite (37 tests)

TASK-ID: 758f4029-702
This commit is contained in:
OpenClaw Agent
2026-04-16 03:20:48 +00:00
parent 8cbc4000ac
commit a3eca3b7da
95 changed files with 2767 additions and 1 deletions

129
tests/conftest.py Normal file
View File

@@ -0,0 +1,129 @@
"""Pytest fixtures for SocialPhoto tests."""
import os
import sqlite3
from pathlib import Path
from typing import Generator
import pytest
from fastapi.testclient import TestClient
# Set test database path before importing app
TEST_DB = Path(__file__).parent / "test_socialphoto.db"
def override_db_path():
"""Override database path for tests."""
return TEST_DB
@pytest.fixture(scope="function")
def db() -> Generator[sqlite3.Connection, None, None]:
"""Create a fresh database for each test."""
# Remove existing test database
if TEST_DB.exists():
TEST_DB.unlink()
# Patch the database path before importing
import app.database as db_module
original_path = db_module.DATABASE_PATH
db_module.DATABASE_PATH = TEST_DB
# Initialize database with new path
db_module.init_db()
conn = db_module.get_db_connection()
conn.row_factory = sqlite3.Row
yield conn
conn.close()
db_module.DATABASE_PATH = original_path
if TEST_DB.exists():
TEST_DB.unlink()
@pytest.fixture(scope="function")
def client(db: sqlite3.Connection) -> Generator[TestClient, None, None]:
"""Create a test client."""
from app.main import app
from app.database import get_db
# Override database dependency
def override_get_db():
yield db
app.dependency_overrides[get_db] = override_get_db
with TestClient(app) as test_client:
yield test_client
app.dependency_overrides.clear()
def get_user_id_from_token(token: str) -> int:
"""Extract user ID from JWT token (for test fixtures only)."""
from jose import jwt
from app.auth import SECRET_KEY, ALGORITHM
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
return int(payload["sub"])
@pytest.fixture
def registered_user(client: TestClient) -> dict:
"""Register a test user and return user data with token."""
response = client.post(
"/auth/register",
json={
"username": "testuser",
"email": "test@example.com",
"password": "testpass123",
},
)
assert response.status_code == 201
data = response.json()
token = data["access_token"]
user_id = get_user_id_from_token(token)
return {
"id": user_id,
"username": "testuser",
"email": "test@example.com",
"password": "testpass123",
"token": token,
}
@pytest.fixture
def two_users(client: TestClient) -> dict:
"""Create two test users."""
# User 1
response = client.post(
"/auth/register",
json={
"username": "user1",
"email": "user1@example.com",
"password": "password123",
},
)
assert response.status_code == 201
token1 = response.json()["access_token"]
# User 2
response = client.post(
"/auth/register",
json={
"username": "user2",
"email": "user2@example.com",
"password": "password123",
},
)
assert response.status_code == 201
token2 = response.json()["access_token"]
return {
"user1_id": get_user_id_from_token(token1),
"user2_id": get_user_id_from_token(token2),
"user1_token": token1,
"user2_token": token2,
"user1_username": "user1",
"user2_username": "user2",
}