chore: import upstream snapshot with attribution
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,198 @@
|
||||
"""Tests for authentication-related database models."""
|
||||
|
||||
from datetime import datetime, timezone
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from local_deep_research.database.models import Base, User
|
||||
|
||||
|
||||
class TestUserModel:
|
||||
"""Test suite for the User model."""
|
||||
|
||||
@pytest.fixture
|
||||
def engine(self):
|
||||
"""Create an in-memory SQLite database for testing."""
|
||||
engine = create_engine("sqlite:///:memory:")
|
||||
Base.metadata.create_all(engine)
|
||||
yield engine
|
||||
engine.dispose()
|
||||
|
||||
@pytest.fixture
|
||||
def session(self, engine):
|
||||
"""Create a database session for testing."""
|
||||
Session = sessionmaker(bind=engine)
|
||||
session = Session()
|
||||
yield session
|
||||
session.close()
|
||||
|
||||
def test_create_user(self, session):
|
||||
"""Test creating a new user."""
|
||||
user = User(username="testuser")
|
||||
|
||||
session.add(user)
|
||||
session.commit()
|
||||
|
||||
# Retrieve the user
|
||||
saved_user = session.query(User).filter_by(username="testuser").first()
|
||||
assert saved_user is not None
|
||||
assert saved_user.username == "testuser"
|
||||
assert saved_user.created_at is not None
|
||||
assert saved_user.database_version == 1
|
||||
|
||||
def test_unique_username_constraint(self, session):
|
||||
"""Test that usernames must be unique."""
|
||||
user1 = User(username="testuser")
|
||||
session.add(user1)
|
||||
session.commit()
|
||||
|
||||
# Try to create another user with the same username
|
||||
user2 = User(username="testuser")
|
||||
session.add(user2)
|
||||
|
||||
with pytest.raises(IntegrityError):
|
||||
session.commit()
|
||||
|
||||
def test_user_timestamps(self, session):
|
||||
"""Test that created_at is set correctly."""
|
||||
user = User(username="testuser")
|
||||
|
||||
# Before saving, created_at should be None
|
||||
assert user.created_at is None
|
||||
|
||||
session.add(user)
|
||||
session.commit()
|
||||
|
||||
# After saving, created_at should be set
|
||||
assert user.created_at is not None
|
||||
assert isinstance(user.created_at, datetime)
|
||||
|
||||
# Update last_login
|
||||
user.last_login = datetime.now(timezone.utc)
|
||||
session.commit()
|
||||
|
||||
# Verify last_login is set
|
||||
assert user.last_login is not None
|
||||
assert user.last_login >= user.created_at
|
||||
|
||||
def test_user_last_login(self, session):
|
||||
"""Test last_login timestamp."""
|
||||
user = User(username="testuser")
|
||||
|
||||
session.add(user)
|
||||
session.commit()
|
||||
|
||||
# Initially last_login should be None
|
||||
assert user.last_login is None
|
||||
|
||||
# Update last_login
|
||||
login_time = datetime.now(timezone.utc)
|
||||
user.last_login = login_time
|
||||
session.commit()
|
||||
|
||||
# Verify last_login is set
|
||||
saved_user = session.query(User).filter_by(username="testuser").first()
|
||||
assert saved_user.last_login is not None
|
||||
assert abs((saved_user.last_login - login_time).total_seconds()) < 1
|
||||
|
||||
def test_user_representation(self):
|
||||
"""Test string representation of User model."""
|
||||
user = User(username="testuser")
|
||||
|
||||
# Should have a meaningful string representation
|
||||
assert repr(user) == "<User testuser>"
|
||||
|
||||
def test_database_path_property(self):
|
||||
"""Test the database_path property generates consistent paths."""
|
||||
user1 = User(username="testuser")
|
||||
user2 = User(username="testuser")
|
||||
user3 = User(username="different")
|
||||
|
||||
# Same username should generate same path
|
||||
assert user1.database_path == user2.database_path
|
||||
|
||||
# Different username should generate different path
|
||||
assert user1.database_path != user3.database_path
|
||||
|
||||
# Path should have expected format
|
||||
assert user1.database_path.startswith("ldr_user_")
|
||||
assert user1.database_path.endswith(".db")
|
||||
|
||||
def test_database_version_default(self, session):
|
||||
"""Test that database_version defaults to 1."""
|
||||
user = User(username="testuser")
|
||||
|
||||
session.add(user)
|
||||
session.commit()
|
||||
|
||||
assert user.database_version == 1
|
||||
|
||||
# Can update version
|
||||
user.database_version = 2
|
||||
session.commit()
|
||||
|
||||
saved_user = session.query(User).filter_by(username="testuser").first()
|
||||
assert saved_user.database_version == 2
|
||||
|
||||
def test_username_with_special_characters(self, session):
|
||||
"""Test usernames with special characters."""
|
||||
special_users = [
|
||||
"user@email.com",
|
||||
"user-with-dashes",
|
||||
"user_with_underscores",
|
||||
"user.with.dots",
|
||||
"user123",
|
||||
"UPPERCASE",
|
||||
"مستخدم", # Arabic
|
||||
"用户", # Chinese
|
||||
"🎉user", # Emoji
|
||||
]
|
||||
|
||||
for username in special_users:
|
||||
user = User(username=username)
|
||||
session.add(user)
|
||||
|
||||
session.commit()
|
||||
|
||||
# All should be saved successfully
|
||||
assert session.query(User).count() == len(special_users)
|
||||
|
||||
# Each should have a valid database path
|
||||
for username in special_users:
|
||||
user = session.query(User).filter_by(username=username).first()
|
||||
assert user is not None
|
||||
assert user.database_path.startswith("ldr_user_")
|
||||
assert user.database_path.endswith(".db")
|
||||
# Path should be filesystem-safe (no special chars)
|
||||
assert all(c.isalnum() or c in "_." for c in user.database_path)
|
||||
|
||||
def test_user_query_operations(self, session):
|
||||
"""Test various query operations on User model."""
|
||||
# Create multiple users
|
||||
users = []
|
||||
for i in range(5):
|
||||
user = User(username=f"user{i}")
|
||||
users.append(user)
|
||||
session.add(user)
|
||||
|
||||
session.commit()
|
||||
|
||||
# Query all users
|
||||
all_users = session.query(User).all()
|
||||
assert len(all_users) == 5
|
||||
|
||||
# Query by username
|
||||
user2 = session.query(User).filter_by(username="user2").first()
|
||||
assert user2 is not None
|
||||
assert user2.username == "user2"
|
||||
|
||||
# Query ordered by created_at
|
||||
ordered_users = session.query(User).order_by(User.created_at).all()
|
||||
assert len(ordered_users) == 5
|
||||
|
||||
# Query with limit
|
||||
limited_users = session.query(User).limit(3).all()
|
||||
assert len(limited_users) == 3
|
||||
Reference in New Issue
Block a user