Files
local-transcription/client/tests/test_config.py
Developer 5a674ed199
Some checks failed
Release / Bump version and tag (push) Successful in 4s
Sidecar Release / Bump sidecar version and tag (push) Failing after 3s
Tests / Python Backend Tests (push) Failing after 3s
Tests / Frontend Tests (push) Successful in 8s
Tests / Rust Sidecar Tests (push) Successful in 3m10s
Add test suite (63 tests) and CI workflow, fix Settings API bugs
Test suite covering all three layers:

Python backend (25 tests):
- AppController: state machine, start/stop, callbacks, settings reload
- API server: REST endpoints, config CRUD, status, devices
- Config: dot-notation get/set, persistence, nested paths
- Main headless: ready event port format validation

Svelte frontend (14 tests via Vitest):
- Backend store: exported properties/methods, port derivation, URLs
- Config store: method names (fetchConfig not loadConfig), defaults
- Transcriptions store: add/clear/plaintext
- File extension regression: ensures $state runes only in .svelte.ts

Rust sidecar (24 tests via cargo test):
- Platform/arch detection, asset name construction
- Ready event deserialization (with extra fields tolerance)
- Path construction, version read/write, old version cleanup
- Zip extraction, SidecarManager lifecycle

CI workflow (.gitea/workflows/test.yml):
- Runs on push to main and PRs
- Three parallel jobs: Python, Frontend, Rust

Also fixes three bugs found during test planning:
- Settings: /api/check-updates -> GET /api/check-update
- Settings: /api/remote/login -> /api/login
- Settings: /api/remote/register -> /api/register

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 07:48:36 -07:00

79 lines
2.7 KiB
Python

"""Tests for client.config.Config."""
import sys
from pathlib import Path
import pytest
# Ensure project root is on path
project_root = Path(__file__).resolve().parent.parent.parent
sys.path.insert(0, str(project_root))
from client.config import Config
@pytest.fixture
def cfg(tmp_path):
"""A Config backed by a temp file so we never touch the real user config."""
return Config(config_path=str(tmp_path / "test_config.yaml"))
# ── dot-notation get ────────────────────────────────────────────────
def test_dot_notation_get(cfg):
"""Config.get should traverse nested dicts using dot-separated keys."""
cfg.config = {"audio": {"sample_rate": 16000}}
assert cfg.get("audio.sample_rate") == 16000
# ── dot-notation set ────────────────────────────────────────────────
def test_dot_notation_set(cfg):
"""Config.set should create/update nested values via dot-separated keys."""
cfg.set("audio.sample_rate", 44100)
assert cfg.config["audio"]["sample_rate"] == 44100
# Also readable via .get
assert cfg.get("audio.sample_rate") == 44100
# ── missing key returns default ─────────────────────────────────────
def test_missing_key_returns_default(cfg):
"""Accessing a nonexistent key should return the supplied default."""
assert cfg.get("nonexistent.path", "fallback") == "fallback"
assert cfg.get("also.missing") is None # default default is None
# ── nested set creates intermediate dicts ───────────────────────────
def test_nested_set_creates_path(cfg):
"""Setting a deeply nested key should create all intermediate dicts."""
cfg.config = {}
cfg.set("a.b.c.d", 42)
assert cfg.config["a"]["b"]["c"]["d"] == 42
assert cfg.get("a.b.c.d") == 42
# ── save and reload round-trip ──────────────────────────────────────
def test_save_and_reload(tmp_path):
"""Values persisted via save() should survive a fresh Config load."""
config_file = str(tmp_path / "roundtrip.yaml")
# Create and populate
cfg1 = Config(config_path=config_file)
cfg1.set("user.name", "TestUser")
cfg1.set("transcription.model", "tiny.en")
# Load a fresh instance from the same file
cfg2 = Config(config_path=config_file)
assert cfg2.get("user.name") == "TestUser"
assert cfg2.get("transcription.model") == "tiny.en"