| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- """Tests for config migration behavior."""
- from __future__ import annotations
- from pathlib import Path
- from unittest.mock import patch
- import yaml
- from cli.core.config.config_manager import (
- DEFAULT_LIBRARY_BRANCH,
- DEFAULT_LIBRARY_DIRECTORY,
- DEFAULT_LIBRARY_NAME,
- DEFAULT_LIBRARY_URL,
- LEGACY_DEFAULT_LIBRARY_URL,
- ConfigManager,
- is_legacy_default_library_url,
- )
- from cli.core.exceptions import ConfigError
- def _write_config(path: Path, data: dict) -> None:
- path.parent.mkdir(parents=True, exist_ok=True)
- path.write_text(yaml.safe_dump(data), encoding="utf-8")
- def test_default_config_uses_new_library_repo(tmp_path: Path) -> None:
- """A fresh config should point at the new default template library."""
- config_path = tmp_path / "config.yaml"
- manager = ConfigManager(config_path=config_path)
- libraries = manager.get_libraries()
- assert len(libraries) == 1
- assert libraries[0]["name"] == DEFAULT_LIBRARY_NAME
- assert libraries[0]["url"] == DEFAULT_LIBRARY_URL
- assert libraries[0]["branch"] == DEFAULT_LIBRARY_BRANCH
- assert libraries[0]["directory"] == DEFAULT_LIBRARY_DIRECTORY
- def test_migrate_legacy_default_library_and_queue_notice(tmp_path: Path) -> None:
- """Legacy christianlempa/boilerplates entries should be rewritten."""
- config_path = tmp_path / "config.yaml"
- ConfigManager.consume_migration_notices()
- _write_config(
- config_path,
- {
- "defaults": {},
- "preferences": {},
- "libraries": [
- {
- "name": DEFAULT_LIBRARY_NAME,
- "type": "git",
- "url": LEGACY_DEFAULT_LIBRARY_URL,
- "branch": "feature/test",
- "directory": "library",
- "enabled": True,
- },
- {
- "name": "custom",
- "type": "git",
- "url": "https://github.com/example/custom-library.git",
- "branch": "dev",
- "directory": "templates",
- "enabled": True,
- },
- ],
- },
- )
- manager = ConfigManager(config_path=config_path)
- libraries = manager.get_libraries()
- notices = ConfigManager.consume_migration_notices()
- assert libraries[0]["name"] == DEFAULT_LIBRARY_NAME
- assert libraries[0]["url"] == DEFAULT_LIBRARY_URL
- assert libraries[0]["branch"] == "feature/test"
- assert libraries[0]["directory"] == DEFAULT_LIBRARY_DIRECTORY
- assert libraries[0]["enabled"] is True
- assert libraries[1]["name"] == "custom"
- assert libraries[1]["url"] == "https://github.com/example/custom-library.git"
- assert libraries[1]["branch"] == "dev"
- assert libraries[1]["directory"] == "templates"
- assert len(notices) == 1
- assert "boilerplates-library" in notices[0].message
- assert "default" in notices[0].message
- # Notices are consumed once.
- assert ConfigManager.consume_migration_notices() == []
- def test_does_not_migrate_custom_non_boilerplates_library(tmp_path: Path) -> None:
- """Non-matching custom library entries should be left untouched."""
- config_path = tmp_path / "config.yaml"
- ConfigManager.consume_migration_notices()
- _write_config(
- config_path,
- {
- "defaults": {},
- "preferences": {},
- "libraries": [
- {
- "name": DEFAULT_LIBRARY_NAME,
- "type": "git",
- "url": "/Users/test/local/boilerplates",
- "branch": "feature/test",
- "directory": ".",
- "enabled": True,
- }
- ],
- },
- )
- manager = ConfigManager(config_path=config_path)
- libraries = manager.get_libraries()
- assert libraries[0]["name"] == DEFAULT_LIBRARY_NAME
- assert libraries[0]["url"] == "/Users/test/local/boilerplates"
- assert libraries[0]["branch"] == "feature/test"
- assert libraries[0]["directory"] == "."
- assert ConfigManager.consume_migration_notices() == []
- def test_migrates_any_library_pointing_to_legacy_boilerplates_repo(tmp_path: Path) -> None:
- """Any library URL pointing to christianlempa/boilerplates should migrate."""
- config_path = tmp_path / "config.yaml"
- ConfigManager.consume_migration_notices()
- _write_config(
- config_path,
- {
- "defaults": {},
- "preferences": {},
- "libraries": [
- {
- "name": "custom",
- "type": "git",
- "url": "git@github.com:ChristianLempa/boilerplates.git",
- "branch": "feature/test",
- "directory": "templates",
- "enabled": True,
- }
- ],
- },
- )
- manager = ConfigManager(config_path=config_path)
- libraries = manager.get_libraries()
- notices = ConfigManager.consume_migration_notices()
- assert libraries[0]["name"] == "custom"
- assert libraries[0]["url"] == DEFAULT_LIBRARY_URL
- assert libraries[0]["branch"] == "feature/test"
- assert libraries[0]["directory"] == DEFAULT_LIBRARY_DIRECTORY
- assert len(notices) == 1
- assert "custom" in notices[0].message
- def test_legacy_library_url_matcher_handles_common_git_url_variants() -> None:
- """Legacy repo detection should match HTTPS and SSH GitHub URL forms."""
- assert is_legacy_default_library_url("https://github.com/christianlempa/boilerplates.git")
- assert is_legacy_default_library_url("https://github.com/ChristianLempa/boilerplates")
- assert is_legacy_default_library_url("git@github.com:ChristianLempa/boilerplates.git")
- assert not is_legacy_default_library_url("https://github.com/christianlempa/boilerplates-library.git")
- def test_migration_write_failure_raises_config_error(tmp_path: Path) -> None:
- """Migration failures should surface as config errors instead of being swallowed."""
- config_path = tmp_path / "config.yaml"
- _write_config(
- config_path,
- {
- "defaults": {},
- "preferences": {},
- "libraries": [
- {
- "name": DEFAULT_LIBRARY_NAME,
- "type": "git",
- "url": LEGACY_DEFAULT_LIBRARY_URL,
- "branch": "main",
- "directory": "library",
- "enabled": True,
- }
- ],
- },
- )
- with patch.object(ConfigManager, "_write_config", side_effect=ConfigError("disk full")):
- try:
- ConfigManager(config_path=config_path)
- except ConfigError as exc:
- assert "disk full" in str(exc)
- else:
- raise AssertionError("Expected ConfigError for failed config migration write")
|