"""Tests for clickup_runner.config.""" import os from pathlib import Path import pytest import yaml from clickup_runner.config import Config, load_config @pytest.fixture def yaml_config(tmp_path): """Write a config YAML file and return its path.""" cfg = { "clickup": { "space_id": "space_from_yaml", "delegate_field_name": "Run It", "ai_working_status": "bot working", }, "runner": { "poll_interval_seconds": 300, "claude_timeout_seconds": 1800, }, "autocora": { "jobs_dir": "/tmp/autocora/jobs", "xlsx_dir": "/tmp/autocora/xlsx", }, } p = tmp_path / "clickup_runner.yaml" p.write_text(yaml.dump(cfg)) return p def test_defaults(): """Config defaults are sensible without any YAML or env vars.""" cfg = Config() assert cfg.clickup.delegate_field_name == "Delegate to Claude" assert cfg.clickup.stage_field_name == "Stage" assert cfg.clickup.error_field_name == "Error" assert cfg.clickup.ai_working_status == "ai working" assert cfg.runner.poll_interval_seconds == 720 assert cfg.runner.claude_timeout_seconds == 2700 assert cfg.autocora.poll_interval_seconds == 120 def test_yaml_overrides(yaml_config, monkeypatch): """YAML values override defaults.""" monkeypatch.delenv("CLICKUP_SPACE_ID", raising=False) monkeypatch.delenv("CLICKUP_API_TOKEN", raising=False) cfg = load_config(yaml_path=yaml_config) assert cfg.clickup.space_id == "space_from_yaml" assert cfg.clickup.delegate_field_name == "Run It" assert cfg.clickup.ai_working_status == "bot working" assert cfg.runner.poll_interval_seconds == 300 assert cfg.runner.claude_timeout_seconds == 1800 assert cfg.autocora.jobs_dir == "/tmp/autocora/jobs" assert cfg.autocora.xlsx_dir == "/tmp/autocora/xlsx" def test_env_overrides_yaml(yaml_config, monkeypatch): """Env vars take precedence over YAML.""" monkeypatch.setenv("CLICKUP_API_TOKEN", "pk_env_token") monkeypatch.setenv("CLICKUP_SPACE_ID", "space_from_env") cfg = load_config(yaml_path=yaml_config) assert cfg.clickup.api_token == "pk_env_token" # Env var overrides YAML assert cfg.clickup.space_id == "space_from_env" def test_missing_yaml_uses_defaults(tmp_path): """If YAML doesn't exist, all defaults are used.""" nonexistent = tmp_path / "nope.yaml" cfg = load_config(yaml_path=nonexistent) assert cfg.clickup.delegate_field_name == "Delegate to Claude" assert cfg.runner.poll_interval_seconds == 720 def test_unknown_yaml_keys_ignored(tmp_path, monkeypatch): """Unknown keys in YAML don't cause errors.""" monkeypatch.delenv("CLICKUP_SPACE_ID", raising=False) monkeypatch.delenv("CLICKUP_API_TOKEN", raising=False) p = tmp_path / "clickup_runner.yaml" p.write_text(yaml.dump({ "clickup": {"space_id": "test", "bogus_key": "whatever"}, "totally_unknown_section": {"foo": "bar"}, })) cfg = load_config(yaml_path=p) assert cfg.clickup.space_id == "test" assert not hasattr(cfg.clickup, "bogus_key") def test_db_path_parent_created(tmp_path, monkeypatch): """load_config ensures the DB parent directory exists.""" # Patch ROOT_DIR so db_path points inside tmp_path import clickup_runner.config as config_mod fake_root = tmp_path / "project" fake_root.mkdir() monkeypatch.setattr(config_mod, "ROOT_DIR", fake_root) cfg = load_config(yaml_path=tmp_path / "nope.yaml") # The default db_path parent should have been created assert cfg.db_path.parent.exists()