import pytest from pathlib import Path from src.presets import PresetManager from src.models import Preset def test_load_all_merged(tmp_path, monkeypatch): """Tests that load_all correctly merges global and project presets.""" global_file = tmp_path / "global_presets.toml" project_root = tmp_path / "project" project_root.mkdir() project_file = project_root / "project_presets.toml" # Setup global presets global_file.write_text(""" [presets.global_only] system_prompt = "global prompt" temperature = 0.5 [presets.override_me] system_prompt = "original prompt" """, encoding="utf-8") # Setup project presets project_file.write_text(""" [presets.project_only] system_prompt = "project prompt" max_output_tokens = 100 [presets.override_me] system_prompt = "overridden prompt" """, encoding="utf-8") monkeypatch.setattr("src.presets.get_global_presets_path", lambda: global_file) monkeypatch.setattr("src.presets.get_project_presets_path", lambda p: project_file) pm = PresetManager(project_root=project_root) presets = pm.load_all() assert len(presets) == 3 assert presets["global_only"].system_prompt == "global prompt" assert presets["global_only"].temperature == 0.5 assert presets["project_only"].system_prompt == "project prompt" assert presets["project_only"].max_output_tokens == 100 assert presets["override_me"].system_prompt == "overridden prompt" def test_save_preset_global(tmp_path, monkeypatch): """Tests saving a preset to the global scope.""" global_file = tmp_path / "global_presets.toml" monkeypatch.setattr("src.presets.get_global_presets_path", lambda: global_file) pm = PresetManager() preset = Preset(name="new_global", system_prompt="new global prompt", temperature=0.7) pm.save_preset(preset, scope="global") assert global_file.exists() loaded_presets = pm.load_all() assert "new_global" in loaded_presets assert loaded_presets["new_global"].system_prompt == "new global prompt" assert loaded_presets["new_global"].temperature == 0.7 def test_save_preset_project(tmp_path, monkeypatch): """Tests saving a preset to the project scope.""" project_root = tmp_path / "project" project_root.mkdir() project_file = project_root / "project_presets.toml" global_file = tmp_path / "global_presets.toml" monkeypatch.setattr("src.presets.get_global_presets_path", lambda: global_file) monkeypatch.setattr("src.presets.get_project_presets_path", lambda p: project_file) pm = PresetManager(project_root=project_root) preset = Preset(name="new_project", system_prompt="new project prompt", max_output_tokens=500) pm.save_preset(preset, scope="project") assert project_file.exists() # Global file should NOT have been created/modified assert not global_file.exists() loaded_presets = pm.load_all() assert "new_project" in loaded_presets assert loaded_presets["new_project"].system_prompt == "new project prompt" assert loaded_presets["new_project"].max_output_tokens == 500 def test_save_preset_project_no_root(): """Tests that saving to project scope fails if no project root is provided.""" pm = PresetManager(project_root=None) preset = Preset(name="fail", system_prompt="fail") with pytest.raises(ValueError, match="Project scope requested but no project_root provided"): pm.save_preset(preset, scope="project") def test_delete_preset(tmp_path, monkeypatch): """Tests deleting a preset from both scopes.""" global_file = tmp_path / "global_presets.toml" project_root = tmp_path / "project" project_root.mkdir() project_file = project_root / "project_presets.toml" global_file.write_text(""" [presets.global1] system_prompt = "g1" [presets.both] system_prompt = "both_g" """, encoding="utf-8") project_file.write_text(""" [presets.project1] system_prompt = "p1" [presets.both] system_prompt = "both_p" """, encoding="utf-8") monkeypatch.setattr("src.presets.get_global_presets_path", lambda: global_file) monkeypatch.setattr("src.presets.get_project_presets_path", lambda p: project_file) pm = PresetManager(project_root=project_root) # Delete from project pm.delete_preset("both", scope="project") presets = pm.load_all() assert "project1" in presets # "both" should now show the global version because project override is gone assert presets["both"].system_prompt == "both_g" # Delete from global pm.delete_preset("global1", scope="global") presets = pm.load_all() assert "global1" not in presets assert "both" in presets # Delete last project preset pm.delete_preset("project1", scope="project") presets = pm.load_all() assert "project1" not in presets assert "both" in presets # still in global