Files
volumen/tests/conftest.py
T
petrbalvin 3b8ed31f67
Test / test (push) Successful in 1m7s
Release / release (push) Successful in 1m11s
chore: prepare release v0.4.0
2026-07-26 18:15:29 +02:00

126 lines
3.7 KiB
Python

"""Shared fixtures for the volumen test suite."""
from __future__ import annotations
import tempfile
from collections.abc import Generator
from pathlib import Path
import pytest
from fastapi.testclient import TestClient
from volumen import reset_login_attempts
from volumen.config import Config
from volumen.password import hash_password as hash_pw
from volumen.store import Store
from volumen.users import Users
@pytest.fixture(autouse=True)
def _reset_login_attempts() -> Generator[None]:
"""Reset the global login-attempts tracker before every test."""
reset_login_attempts()
yield
@pytest.fixture
def tmp_dir() -> Generator[Path]:
"""Create a temporary directory that is cleaned up after the test."""
with tempfile.TemporaryDirectory() as d:
yield Path(d)
@pytest.fixture
def tmp_content_dir(tmp_path: Path) -> Path:
"""Temporary content directory with sample posts."""
content = tmp_path / "posts"
content.mkdir()
(content / "hello.md").write_text(
'+++\ntitle = "Hello"\ntags = ["intro"]\n+++\n\nHello **world**.\n'
)
(content / "draft.md").write_text('+++\ntitle = "Draft"\ndraft = true\n+++\n\nSecret.\n')
return content
@pytest.fixture
def config(tmp_content_dir: Path, tmp_path: Path) -> Config:
"""Test Config instance pointing at a temp content directory."""
users_file = str(tmp_path / "users.toml")
return Config.load(
path="/nonexistent/volumen.toml",
overrides={"content": str(tmp_content_dir), "users_file": users_file},
)
@pytest.fixture
def store(tmp_content_dir: Path) -> Store:
"""Test Store instance backed by a temp content directory."""
return Store(str(tmp_content_dir), default_lang="en")
@pytest.fixture
def users_path(tmp_path: Path) -> str:
"""Path for a temporary users.toml file."""
return str(tmp_path / "users.toml")
@pytest.fixture
def bootstrap_hash() -> str:
"""A pre-hashed password for bootstrap tests."""
return hash_pw("volumen-test-password")
@pytest.fixture
def users(users_path: str, bootstrap_hash: str) -> Users:
"""Test Users instance with bootstrap admin user."""
return Users(path=users_path, bootstrap_hash=bootstrap_hash)
@pytest.fixture
def client(config: Config, store: Store) -> TestClient:
"""FastAPI TestClient for public API tests."""
from volumen.app import create_app
app = create_app(config, store)
return TestClient(app)
@pytest.fixture
def admin_config_dir(tmp_path: Path) -> Path:
"""Create a directory with config and posts for admin tests."""
posts_dir = tmp_path / "posts"
posts_dir.mkdir()
users_path = tmp_path / "users.toml"
config_path = tmp_path / "config.toml"
pw_hash = hash_pw("volumen-test-password")
config_path.write_text(
f'content_dir = "{posts_dir}"\n'
f'users_file = "{users_path}"\n\n'
"[admin]\n"
f'password_hash = "{pw_hash}"\n'
)
return tmp_path
@pytest.fixture
def admin_client(admin_config_dir: Path) -> TestClient:
"""FastAPI TestClient for admin tests with bootstrap admin."""
from volumen.app import create_app
from volumen.config import Config
from volumen.store import Store
config = Config.load(path=str(admin_config_dir / "config.toml"))
store = Store(config.content_dir, default_lang="en")
app = create_app(config, store)
return TestClient(app)
@pytest.fixture
def sample_post_md() -> str:
"""Sample post in Markdown with TOML frontmatter."""
return (
'+++\ntitle = "Test Post"\nslug = "test-post"\nlang = "en"\n'
'tags = ["python", "blog"]\ndate = 2026-01-15\ndraft = false\n+++\n\n'
"This is the **body** of the post.\n\nSecond paragraph."
)