AIstudioProxyAPI / tests /gui /test_config.py
peijun1's picture
Deploy AI Studio Proxy API to Hugging Face Spaces
a5784e9
Raw
History Blame Contribute Delete
10.2 kB
"""Tests for gui/config.py module."""
import re
class TestConfigPaths:
"""Tests for path configurations."""
def test_project_root_exists(self):
"""PROJECT_ROOT should point to valid directory."""
from gui.config import PROJECT_ROOT
assert PROJECT_ROOT.exists()
assert PROJECT_ROOT.is_dir()
def test_gui_dir_exists(self):
"""GUI_DIR should point to the gui module directory."""
from gui.config import GUI_DIR
assert GUI_DIR.exists()
assert GUI_DIR.is_dir()
assert GUI_DIR.name == "gui"
def test_auth_profiles_dir_structure(self):
"""AUTH_PROFILES_DIR should be under PROJECT_ROOT."""
from gui.config import AUTH_PROFILES_DIR, PROJECT_ROOT
assert AUTH_PROFILES_DIR == PROJECT_ROOT / "auth_profiles"
def test_saved_auth_dir_structure(self):
"""SAVED_AUTH_DIR should be under AUTH_PROFILES_DIR."""
from gui.config import AUTH_PROFILES_DIR, SAVED_AUTH_DIR
assert SAVED_AUTH_DIR == AUTH_PROFILES_DIR / "saved"
def test_active_auth_dir_structure(self):
"""ACTIVE_AUTH_DIR should be under AUTH_PROFILES_DIR."""
from gui.config import ACTIVE_AUTH_DIR, AUTH_PROFILES_DIR
assert ACTIVE_AUTH_DIR == AUTH_PROFILES_DIR / "active"
def test_launch_script_path(self):
"""LAUNCH_SCRIPT should point to launch_camoufox.py."""
from gui.config import LAUNCH_SCRIPT, PROJECT_ROOT
assert LAUNCH_SCRIPT == PROJECT_ROOT / "launch_camoufox.py"
assert LAUNCH_SCRIPT.exists()
def test_config_file_path(self):
"""CONFIG_FILE should be in GUI_DIR."""
from gui.config import CONFIG_FILE, GUI_DIR
assert CONFIG_FILE == GUI_DIR / "user_config.json"
def test_log_file_path(self):
"""LOG_FILE should be in PROJECT_ROOT/logs."""
from gui.config import LOG_FILE, PROJECT_ROOT
assert LOG_FILE == PROJECT_ROOT / "logs" / "gui_launcher.log"
class TestConfigVersion:
"""Tests for version string."""
def test_version_format(self):
"""VERSION should be a valid semver string."""
from gui.config import VERSION
assert isinstance(VERSION, str)
parts = VERSION.split(".")
assert len(parts) >= 2
assert all(p.isdigit() for p in parts[:2])
class TestDefaultConfig:
"""Tests for DEFAULT_CONFIG dictionary."""
def test_default_config_has_required_keys(self):
"""DEFAULT_CONFIG should have all required keys."""
from gui.config import DEFAULT_CONFIG
required_keys = [
"fastapi_port",
"camoufox_port",
"stream_port",
"proxy_address",
"proxy_enabled",
"last_account",
"appearance_mode",
"minimize_to_tray",
"language",
]
for key in required_keys:
assert key in DEFAULT_CONFIG, f"Missing key: {key}"
def test_default_ports_are_valid(self):
"""Default ports should be in valid range."""
from gui.config import DEFAULT_CONFIG
assert 1 <= DEFAULT_CONFIG["fastapi_port"] <= 65535
assert 1 <= DEFAULT_CONFIG["camoufox_port"] <= 65535
assert 1 <= DEFAULT_CONFIG["stream_port"] <= 65535
def test_default_ports_are_different(self):
"""Default ports should not conflict."""
from gui.config import DEFAULT_CONFIG
ports = [
DEFAULT_CONFIG["fastapi_port"],
DEFAULT_CONFIG["camoufox_port"],
DEFAULT_CONFIG["stream_port"],
]
assert len(set(ports)) == 3, "Ports should be unique"
def test_default_language_is_valid(self):
"""Default language should be 'en' or 'zh'."""
from gui.config import DEFAULT_CONFIG
assert DEFAULT_CONFIG["language"] in ("en", "zh")
def test_default_booleans(self):
"""Boolean defaults should be booleans."""
from gui.config import DEFAULT_CONFIG
assert isinstance(DEFAULT_CONFIG["proxy_enabled"], bool)
assert isinstance(DEFAULT_CONFIG["minimize_to_tray"], bool)
# appearance_mode is a string, not a bool
assert isinstance(DEFAULT_CONFIG["appearance_mode"], str)
assert DEFAULT_CONFIG["appearance_mode"] in ("dark", "light", "system")
class TestCustomTkinterSettings:
"""Tests for CustomTkinter theme settings."""
def test_ctk_appearance_mode(self):
"""CTK_APPEARANCE_MODE should be valid."""
from gui.config import CTK_APPEARANCE_MODE
assert CTK_APPEARANCE_MODE in ("dark", "light", "system")
def test_ctk_color_theme(self):
"""CTK_COLOR_THEME should be valid."""
from gui.config import CTK_COLOR_THEME
valid_themes = ("blue", "dark-blue", "green")
assert CTK_COLOR_THEME in valid_themes
class TestColors:
"""Tests for COLORS dictionary."""
def test_colors_has_required_keys(self):
"""COLORS should have all required color keys."""
from gui.config import COLORS
required_keys = [
"bg_dark",
"bg_medium",
"bg_light",
"accent",
"accent_hover",
"success",
"warning",
"error",
"text_primary",
"text_secondary",
"border",
]
for key in required_keys:
assert key in COLORS, f"Missing color: {key}"
def test_colors_are_valid_hex_or_special(self):
"""Colors should be valid hex codes, tuples of hex codes, or special values."""
from gui.config import COLORS
hex_pattern = re.compile(r"^#[0-9A-Fa-f]{6}$")
special_values = {"transparent"}
def is_valid_color(color):
"""Check if a single color value is valid."""
return hex_pattern.match(color) or color in special_values
for name, color in COLORS.items():
if isinstance(color, tuple):
# CustomTkinter tuple format: (light_color, dark_color)
assert len(color) == 2, f"Color tuple {name} should have 2 values"
for c in color:
assert is_valid_color(c), f"Invalid color in tuple for {name}: {c}"
else:
# Single color value
assert is_valid_color(color), f"Invalid color for {name}: {color}"
def test_has_semantic_colors(self):
"""Should have semantic color variants."""
from gui.config import COLORS
# Success colors
assert "success" in COLORS
assert "success_hover" in COLORS
# Error colors
assert "error" in COLORS
assert "error_hover" in COLORS
class TestFonts:
"""Tests for FONTS configuration."""
def test_fonts_has_required_keys(self):
"""FONTS should have all required keys."""
from gui.config import FONTS
required_keys = [
"family",
"family_mono",
"size_small",
"size_normal",
"size_large",
"size_header",
]
for key in required_keys:
assert key in FONTS, f"Missing font key: {key}"
def test_font_sizes_are_positive(self):
"""Font sizes should be positive integers."""
from gui.config import FONTS
size_keys = [k for k in FONTS if k.startswith("size_")]
for key in size_keys:
assert isinstance(FONTS[key], int)
assert FONTS[key] > 0
class TestDimensions:
"""Tests for DIMENSIONS configuration."""
def test_dimensions_has_corner_radius(self):
"""DIMENSIONS should have corner radius values."""
from gui.config import DIMENSIONS
assert "corner_radius" in DIMENSIONS
assert "corner_radius_small" in DIMENSIONS
def test_dimensions_are_positive(self):
"""Dimension values should be positive."""
from gui.config import DIMENSIONS
for key, value in DIMENSIONS.items():
assert isinstance(value, int)
assert value > 0
class TestUrls:
"""Tests for URL constants."""
def test_github_url_format(self):
"""GITHUB_URL should be a valid GitHub URL."""
from gui.config import GITHUB_URL
assert GITHUB_URL.startswith("https://github.com/")
def test_docs_url_references_github(self):
"""DOCS_URL should reference the GitHub README."""
from gui.config import DOCS_URL, GITHUB_URL
assert DOCS_URL.startswith(GITHUB_URL)
assert "#readme" in DOCS_URL
class TestColorUtilityFunctions:
"""Tests for color utility functions."""
def test_get_color_returns_dark_mode_by_default(self):
"""get_color should return dark mode color by default."""
from gui.config import get_color
# Test with accent color (same in both modes)
assert get_color("accent") == "#e94560"
def test_get_color_returns_light_mode(self):
"""get_color should return light mode color when specified."""
from gui.config import get_color
# bg_dark is different in light vs dark mode
light_color = get_color("bg_dark", "light")
dark_color = get_color("bg_dark", "dark")
assert light_color == "#e8e8e8"
assert dark_color == "#1a1a2e"
assert light_color != dark_color
def test_get_color_with_plain_string(self):
"""get_color should handle plain string colors."""
from gui.config import get_color
# text_on_color is a plain string, not a tuple
result = get_color("text_on_color")
assert result == "#ffffff"
def test_get_color_with_unknown_key(self):
"""get_color should return default for unknown keys."""
from gui.config import get_color
result = get_color("nonexistent_color")
assert result == "#ffffff" # default fallback
def test_get_current_color_function_exists(self):
"""get_current_color function should exist."""
from gui.config import get_current_color
# Just verify it can be called (it uses ctk which may not be set up)
assert callable(get_current_color)