update
Some checks failed
CI/CD Pipeline / Code Quality Checks (push) Failing after 4m49s
CI/CD Pipeline / Security Scanning (push) Successful in 15s
CI/CD Pipeline / Tests (3.11) (push) Successful in 9m41s
CI/CD Pipeline / Tests (3.12) (push) Successful in 9m36s
CI/CD Pipeline / Build Docker Image (push) Has been skipped
Dependency Updates / Update Dependencies (push) Successful in 29s
Some checks failed
CI/CD Pipeline / Code Quality Checks (push) Failing after 4m49s
CI/CD Pipeline / Security Scanning (push) Successful in 15s
CI/CD Pipeline / Tests (3.11) (push) Successful in 9m41s
CI/CD Pipeline / Tests (3.12) (push) Successful in 9m36s
CI/CD Pipeline / Build Docker Image (push) Has been skipped
Dependency Updates / Update Dependencies (push) Successful in 29s
This commit is contained in:
@@ -7,11 +7,11 @@ import sys
|
||||
import tempfile
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
from typing import AsyncGenerator
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy import create_engine, event, text
|
||||
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
|
||||
from sqlalchemy.pool import StaticPool
|
||||
|
||||
@@ -23,7 +23,7 @@ if str(SRC_DIR) not in sys.path:
|
||||
# Import after path setup
|
||||
from guardden.config import Settings
|
||||
from guardden.models.base import Base
|
||||
from guardden.models.guild import Guild, GuildSettings, BannedWord
|
||||
from guardden.models.guild import BannedWord, Guild, GuildSettings
|
||||
from guardden.models.moderation import ModerationLog, Strike, UserNote
|
||||
from guardden.services.database import Database
|
||||
|
||||
@@ -52,6 +52,7 @@ def pytest_pyfunc_call(pyfuncitem: pytest.Function) -> bool | None:
|
||||
# Basic Test Fixtures
|
||||
# ==============================================================================
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_guild_id() -> int:
|
||||
"""Return a sample Discord guild ID."""
|
||||
@@ -80,11 +81,12 @@ def sample_owner_id() -> int:
|
||||
# Configuration Fixtures
|
||||
# ==============================================================================
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_settings() -> Settings:
|
||||
"""Return test configuration settings."""
|
||||
return Settings(
|
||||
discord_token="test_token_12345678901234567890",
|
||||
discord_token="a" * 60,
|
||||
discord_prefix="!test",
|
||||
database_url="sqlite+aiosqlite:///test.db",
|
||||
database_pool_min=1,
|
||||
@@ -101,6 +103,7 @@ def test_settings() -> Settings:
|
||||
# Database Fixtures
|
||||
# ==============================================================================
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def test_database(test_settings: Settings) -> AsyncGenerator[Database, None]:
|
||||
"""Create a test database with in-memory SQLite."""
|
||||
@@ -111,19 +114,26 @@ async def test_database(test_settings: Settings) -> AsyncGenerator[Database, Non
|
||||
poolclass=StaticPool,
|
||||
echo=False,
|
||||
)
|
||||
|
||||
|
||||
@event.listens_for(engine.sync_engine, "connect")
|
||||
def _enable_sqlite_foreign_keys(dbapi_connection, connection_record):
|
||||
cursor = dbapi_connection.cursor()
|
||||
cursor.execute("PRAGMA foreign_keys=ON")
|
||||
cursor.close()
|
||||
|
||||
# Create all tables
|
||||
async with engine.begin() as conn:
|
||||
await conn.execute(text("PRAGMA foreign_keys=ON"))
|
||||
await conn.run_sync(Base.metadata.create_all)
|
||||
|
||||
|
||||
database = Database(test_settings)
|
||||
database._engine = engine
|
||||
database._session_factory = async_sessionmaker(
|
||||
engine, class_=AsyncSession, expire_on_commit=False
|
||||
)
|
||||
|
||||
|
||||
yield database
|
||||
|
||||
|
||||
await engine.dispose()
|
||||
|
||||
|
||||
@@ -138,10 +148,9 @@ async def db_session(test_database: Database) -> AsyncGenerator[AsyncSession, No
|
||||
# Model Fixtures
|
||||
# ==============================================================================
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def test_guild(
|
||||
db_session: AsyncSession, sample_guild_id: int, sample_owner_id: int
|
||||
) -> Guild:
|
||||
async def test_guild(db_session: AsyncSession, sample_guild_id: int, sample_owner_id: int) -> Guild:
|
||||
"""Create a test guild with settings."""
|
||||
guild = Guild(
|
||||
id=sample_guild_id,
|
||||
@@ -150,7 +159,7 @@ async def test_guild(
|
||||
premium=False,
|
||||
)
|
||||
db_session.add(guild)
|
||||
|
||||
|
||||
# Create associated settings
|
||||
settings = GuildSettings(
|
||||
guild_id=sample_guild_id,
|
||||
@@ -160,7 +169,7 @@ async def test_guild(
|
||||
verification_enabled=False,
|
||||
)
|
||||
db_session.add(settings)
|
||||
|
||||
|
||||
await db_session.commit()
|
||||
await db_session.refresh(guild)
|
||||
return guild
|
||||
@@ -187,10 +196,7 @@ async def test_banned_word(
|
||||
|
||||
@pytest.fixture
|
||||
async def test_moderation_log(
|
||||
db_session: AsyncSession,
|
||||
test_guild: Guild,
|
||||
sample_user_id: int,
|
||||
sample_moderator_id: int
|
||||
db_session: AsyncSession, test_guild: Guild, sample_user_id: int, sample_moderator_id: int
|
||||
) -> ModerationLog:
|
||||
"""Create a test moderation log entry."""
|
||||
mod_log = ModerationLog(
|
||||
@@ -211,10 +217,7 @@ async def test_moderation_log(
|
||||
|
||||
@pytest.fixture
|
||||
async def test_strike(
|
||||
db_session: AsyncSession,
|
||||
test_guild: Guild,
|
||||
sample_user_id: int,
|
||||
sample_moderator_id: int
|
||||
db_session: AsyncSession, test_guild: Guild, sample_user_id: int, sample_moderator_id: int
|
||||
) -> Strike:
|
||||
"""Create a test strike."""
|
||||
strike = Strike(
|
||||
@@ -236,6 +239,7 @@ async def test_strike(
|
||||
# Discord Mock Fixtures
|
||||
# ==============================================================================
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_discord_user(sample_user_id: int) -> MagicMock:
|
||||
"""Create a mock Discord user."""
|
||||
@@ -261,7 +265,7 @@ def mock_discord_member(mock_discord_user: MagicMock) -> MagicMock:
|
||||
member.avatar = mock_discord_user.avatar
|
||||
member.bot = mock_discord_user.bot
|
||||
member.send = mock_discord_user.send
|
||||
|
||||
|
||||
# Member-specific attributes
|
||||
member.guild = MagicMock()
|
||||
member.top_role = MagicMock()
|
||||
@@ -271,7 +275,7 @@ def mock_discord_member(mock_discord_user: MagicMock) -> MagicMock:
|
||||
member.kick = AsyncMock()
|
||||
member.ban = AsyncMock()
|
||||
member.timeout = AsyncMock()
|
||||
|
||||
|
||||
return member
|
||||
|
||||
|
||||
@@ -284,14 +288,14 @@ def mock_discord_guild(sample_guild_id: int, sample_owner_id: int) -> MagicMock:
|
||||
guild.owner_id = sample_owner_id
|
||||
guild.member_count = 100
|
||||
guild.premium_tier = 0
|
||||
|
||||
|
||||
# Methods
|
||||
guild.get_member = MagicMock(return_value=None)
|
||||
guild.get_channel = MagicMock(return_value=None)
|
||||
guild.leave = AsyncMock()
|
||||
guild.ban = AsyncMock()
|
||||
guild.unban = AsyncMock()
|
||||
|
||||
|
||||
return guild
|
||||
|
||||
|
||||
@@ -327,9 +331,7 @@ def mock_discord_message(
|
||||
|
||||
@pytest.fixture
|
||||
def mock_discord_context(
|
||||
mock_discord_member: MagicMock,
|
||||
mock_discord_guild: MagicMock,
|
||||
mock_discord_channel: MagicMock
|
||||
mock_discord_member: MagicMock, mock_discord_guild: MagicMock, mock_discord_channel: MagicMock
|
||||
) -> MagicMock:
|
||||
"""Create a mock Discord command context."""
|
||||
ctx = MagicMock()
|
||||
@@ -345,6 +347,7 @@ def mock_discord_context(
|
||||
# Bot and Service Fixtures
|
||||
# ==============================================================================
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_bot(test_database: Database) -> MagicMock:
|
||||
"""Create a mock GuardDen bot."""
|
||||
@@ -363,6 +366,7 @@ def mock_bot(test_database: Database) -> MagicMock:
|
||||
# Test Environment Setup
|
||||
# ==============================================================================
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_test_environment() -> None:
|
||||
"""Set up test environment variables."""
|
||||
|
||||
Reference in New Issue
Block a user