scholarr/tests/integration/helpers.py
Justin Visser bf04c77aa9 ci: add ruff linting and mypy type checking
Add ruff and mypy to dev dependencies with configuration in pyproject.toml.
Add a lint CI job that runs ruff check, ruff format --check, and mypy.
Auto-fix import sorting and formatting across the codebase. Exclude
alembic/versions from linting (auto-generated migrations). Ignore B008
(FastAPI Depends pattern) and RUF001 (unicode in user-facing strings).

21 ruff lint errors and 50 mypy errors remain for manual review.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 22:11:41 +01:00

56 lines
1.6 KiB
Python

from __future__ import annotations
from fastapi.testclient import TestClient
from sqlalchemy import text
from sqlalchemy.ext.asyncio import AsyncSession
from app.auth.security import PasswordService
def login_user(client: TestClient, *, email: str, password: str) -> None:
bootstrap_response = client.get("/api/v1/auth/csrf")
assert bootstrap_response.status_code == 200
csrf_token = bootstrap_response.json()["data"]["csrf_token"]
assert isinstance(csrf_token, str) and csrf_token
response = client.post(
"/api/v1/auth/login",
json={
"email": email,
"password": password,
},
headers={"X-CSRF-Token": csrf_token},
follow_redirects=False,
)
assert response.status_code == 200
payload = response.json()
assert payload["data"]["authenticated"] is True
async def insert_user(
db_session: AsyncSession,
*,
email: str,
password: str,
is_admin: bool = False,
is_active: bool = True,
) -> int:
password_service = PasswordService()
result = await db_session.execute(
text(
"""
INSERT INTO users (email, password_hash, is_active, is_admin)
VALUES (:email, :password_hash, :is_active, :is_admin)
RETURNING id
"""
),
{
"email": email,
"password_hash": password_service.hash_password(password),
"is_active": is_active,
"is_admin": is_admin,
},
)
user_id = int(result.scalar_one())
await db_session.commit()
return user_id