- #37: Fix stale comment in transaction_freeze.py referencing wrong moveid format - #27: Change config.testing default from True to False (was masking prod behavior) - #25: Replace deprecated asyncio.get_event_loop() with get_running_loop() - #38: Replace naive datetime.now() with timezone-aware datetime.now(UTC) across 7 source files and 4 test files to prevent subtle timezone bugs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
297 lines
9.8 KiB
Python
297 lines
9.8 KiB
Python
"""
|
|
Tests for configuration management
|
|
|
|
Ensures configuration loading, validation, and environment handling work correctly.
|
|
"""
|
|
|
|
import os
|
|
import pytest
|
|
from unittest.mock import patch
|
|
|
|
from config import BotConfig
|
|
|
|
|
|
class TestBotConfig:
|
|
"""Test configuration loading and validation."""
|
|
|
|
def test_config_loads_required_fields(self):
|
|
"""Test that config loads all required fields from environment."""
|
|
with patch.dict(
|
|
os.environ,
|
|
{
|
|
"BOT_TOKEN": "test_bot_token",
|
|
"GUILD_ID": "123456789",
|
|
"API_TOKEN": "test_api_token",
|
|
"DB_URL": "https://api.example.com",
|
|
},
|
|
):
|
|
config = BotConfig()
|
|
assert config.bot_token == "test_bot_token"
|
|
assert config.guild_id == 123456789
|
|
assert config.api_token == "test_api_token"
|
|
assert config.db_url == "https://api.example.com"
|
|
|
|
def test_config_has_default_values(self):
|
|
"""Test that config provides sensible defaults."""
|
|
with patch.dict(
|
|
os.environ,
|
|
{
|
|
"BOT_TOKEN": "test_bot_token",
|
|
"GUILD_ID": "123456789",
|
|
"API_TOKEN": "test_api_token",
|
|
"DB_URL": "https://api.example.com",
|
|
},
|
|
clear=True,
|
|
):
|
|
# Create config with disabled env file to test true defaults
|
|
config = BotConfig(_env_file=None)
|
|
assert config.sba_season == 13
|
|
assert config.pd_season == 10
|
|
assert config.fa_lock_week == 14
|
|
assert config.sba_color == "a6ce39"
|
|
assert config.log_level == "INFO"
|
|
assert config.environment == "development"
|
|
assert config.testing is False
|
|
|
|
def test_config_overrides_defaults_from_env(self):
|
|
"""Test that environment variables override default values."""
|
|
with patch.dict(
|
|
os.environ,
|
|
{
|
|
"BOT_TOKEN": "test_bot_token",
|
|
"GUILD_ID": "123456789",
|
|
"API_TOKEN": "test_api_token",
|
|
"DB_URL": "https://api.example.com",
|
|
"SBA_SEASON": "15",
|
|
"LOG_LEVEL": "DEBUG",
|
|
"ENVIRONMENT": "production",
|
|
"TESTING": "true",
|
|
},
|
|
):
|
|
config = BotConfig()
|
|
assert config.sba_season == 15
|
|
assert config.log_level == "DEBUG"
|
|
assert config.environment == "production"
|
|
assert config.testing is True
|
|
|
|
def test_config_ignores_extra_env_vars(self):
|
|
"""Test that extra environment variables are ignored."""
|
|
with patch.dict(
|
|
os.environ,
|
|
{
|
|
"BOT_TOKEN": "test_bot_token",
|
|
"GUILD_ID": "123456789",
|
|
"API_TOKEN": "test_api_token",
|
|
"DB_URL": "https://api.example.com",
|
|
"RANDOM_EXTRA_VAR": "should_be_ignored",
|
|
"ANOTHER_RANDOM_VAR": "also_ignored",
|
|
},
|
|
):
|
|
# Should not raise validation error
|
|
config = BotConfig()
|
|
assert config.bot_token == "test_bot_token"
|
|
|
|
# Extra vars should not be accessible
|
|
assert not hasattr(config, "random_extra_var")
|
|
assert not hasattr(config, "another_random_var")
|
|
|
|
def test_config_converts_string_to_int(self):
|
|
"""Test that guild_id is properly converted from string to int."""
|
|
with patch.dict(
|
|
os.environ,
|
|
{
|
|
"BOT_TOKEN": "test_bot_token",
|
|
"GUILD_ID": "987654321", # String input
|
|
"API_TOKEN": "test_api_token",
|
|
"DB_URL": "https://api.example.com",
|
|
},
|
|
):
|
|
config = BotConfig()
|
|
assert config.guild_id == 987654321
|
|
assert isinstance(config.guild_id, int)
|
|
|
|
def test_config_converts_string_to_bool(self):
|
|
"""Test that boolean fields are properly converted."""
|
|
with patch.dict(
|
|
os.environ,
|
|
{
|
|
"BOT_TOKEN": "test_bot_token",
|
|
"GUILD_ID": "123456789",
|
|
"API_TOKEN": "test_api_token",
|
|
"DB_URL": "https://api.example.com",
|
|
"TESTING": "false",
|
|
},
|
|
):
|
|
config = BotConfig()
|
|
assert config.testing is False
|
|
assert isinstance(config.testing, bool)
|
|
|
|
with patch.dict(
|
|
os.environ,
|
|
{
|
|
"BOT_TOKEN": "test_bot_token",
|
|
"GUILD_ID": "123456789",
|
|
"API_TOKEN": "test_api_token",
|
|
"DB_URL": "https://api.example.com",
|
|
"TESTING": "1",
|
|
},
|
|
):
|
|
config = BotConfig()
|
|
assert config.testing is True
|
|
|
|
def test_config_case_insensitive(self):
|
|
"""Test that environment variables are case insensitive."""
|
|
with patch.dict(
|
|
os.environ,
|
|
{
|
|
"bot_token": "test_bot_token", # lowercase
|
|
"GUILD_ID": "123456789", # uppercase
|
|
"Api_Token": "test_api_token", # mixed case
|
|
"db_url": "https://api.example.com",
|
|
},
|
|
):
|
|
config = BotConfig()
|
|
assert config.bot_token == "test_bot_token"
|
|
assert config.api_token == "test_api_token"
|
|
assert config.db_url == "https://api.example.com"
|
|
|
|
def test_is_development_property(self):
|
|
"""Test the is_development property."""
|
|
with patch.dict(
|
|
os.environ,
|
|
{
|
|
"BOT_TOKEN": "test_bot_token",
|
|
"GUILD_ID": "123456789",
|
|
"API_TOKEN": "test_api_token",
|
|
"DB_URL": "https://api.example.com",
|
|
"ENVIRONMENT": "development",
|
|
},
|
|
):
|
|
config = BotConfig()
|
|
assert config.is_development is True
|
|
|
|
with patch.dict(
|
|
os.environ,
|
|
{
|
|
"BOT_TOKEN": "test_bot_token",
|
|
"GUILD_ID": "123456789",
|
|
"API_TOKEN": "test_api_token",
|
|
"DB_URL": "https://api.example.com",
|
|
"ENVIRONMENT": "production",
|
|
},
|
|
):
|
|
config = BotConfig()
|
|
assert config.is_development is False
|
|
|
|
def test_is_testing_property(self):
|
|
"""Test the is_testing property."""
|
|
with patch.dict(
|
|
os.environ,
|
|
{
|
|
"BOT_TOKEN": "test_bot_token",
|
|
"GUILD_ID": "123456789",
|
|
"API_TOKEN": "test_api_token",
|
|
"DB_URL": "https://api.example.com",
|
|
"TESTING": "true",
|
|
},
|
|
):
|
|
config = BotConfig()
|
|
assert config.is_testing is True
|
|
|
|
with patch.dict(
|
|
os.environ,
|
|
{
|
|
"BOT_TOKEN": "test_bot_token",
|
|
"GUILD_ID": "123456789",
|
|
"API_TOKEN": "test_api_token",
|
|
"DB_URL": "https://api.example.com",
|
|
"TESTING": "false",
|
|
},
|
|
):
|
|
config = BotConfig()
|
|
assert config.is_testing is False
|
|
|
|
|
|
class TestConfigValidation:
|
|
"""Test configuration validation and error handling."""
|
|
|
|
def test_missing_required_field_raises_error(self):
|
|
"""Test that missing required fields raise validation errors."""
|
|
# Missing BOT_TOKEN
|
|
with patch.dict(
|
|
os.environ,
|
|
{
|
|
"GUILD_ID": "123456789",
|
|
"API_TOKEN": "test_api_token",
|
|
"DB_URL": "https://api.example.com",
|
|
},
|
|
clear=True,
|
|
):
|
|
with pytest.raises(Exception): # Pydantic ValidationError
|
|
BotConfig(_env_file=None)
|
|
|
|
# Missing GUILD_ID
|
|
with patch.dict(
|
|
os.environ,
|
|
{
|
|
"BOT_TOKEN": "test_bot_token",
|
|
"API_TOKEN": "test_api_token",
|
|
"DB_URL": "https://api.example.com",
|
|
},
|
|
clear=True,
|
|
):
|
|
with pytest.raises(Exception): # Pydantic ValidationError
|
|
BotConfig(_env_file=None)
|
|
|
|
def test_invalid_guild_id_raises_error(self):
|
|
"""Test that invalid guild_id values raise validation errors."""
|
|
with patch.dict(
|
|
os.environ,
|
|
{
|
|
"BOT_TOKEN": "test_bot_token",
|
|
"GUILD_ID": "not_a_number",
|
|
"API_TOKEN": "test_api_token",
|
|
"DB_URL": "https://api.example.com",
|
|
},
|
|
):
|
|
with pytest.raises(Exception): # Pydantic ValidationError
|
|
BotConfig()
|
|
|
|
def test_empty_required_field_is_allowed(self):
|
|
"""Test that empty required fields are allowed (Pydantic default behavior)."""
|
|
with patch.dict(
|
|
os.environ,
|
|
{
|
|
"BOT_TOKEN": "", # Empty string
|
|
"GUILD_ID": "123456789",
|
|
"API_TOKEN": "test_api_token",
|
|
"DB_URL": "https://api.example.com",
|
|
},
|
|
):
|
|
# Should not raise - Pydantic allows empty strings by default
|
|
config = BotConfig()
|
|
assert config.bot_token == ""
|
|
|
|
|
|
@pytest.fixture
|
|
def valid_config():
|
|
"""Provide a valid configuration for testing."""
|
|
with patch.dict(
|
|
os.environ,
|
|
{
|
|
"BOT_TOKEN": "test_bot_token",
|
|
"GUILD_ID": "123456789",
|
|
"API_TOKEN": "test_api_token",
|
|
"DB_URL": "https://api.example.com",
|
|
},
|
|
):
|
|
return BotConfig()
|
|
|
|
|
|
def test_config_fixture(valid_config):
|
|
"""Test that the valid_config fixture works correctly."""
|
|
assert valid_config.bot_token == "test_bot_token"
|
|
assert valid_config.guild_id == 123456789
|
|
assert valid_config.api_token == "test_api_token"
|
|
assert valid_config.db_url == "https://api.example.com"
|