""" Tests for JSON file storage layer. Tests the new json_store module that replaced SQLite. """ import pytest import json import tempfile import shutil from pathlib import Path from datetime import datetime # Temporarily override DATA_DIR for tests import tools.storage.json_store as json_store @pytest.fixture def temp_storage(tmp_path): """Create temporary storage directory for tests.""" # Save original paths original_data_dir = json_store.DATA_DIR original_system_dir = json_store.SYSTEM_DIR original_projects_dir = json_store.PROJECTS_DIR original_teams_dir = json_store.TEAMS_DIR # Override with temp paths json_store.DATA_DIR = tmp_path / "data" json_store.SYSTEM_DIR = json_store.DATA_DIR / "_system" json_store.PROJECTS_DIR = json_store.DATA_DIR / "projects" json_store.TEAMS_DIR = json_store.DATA_DIR / "teams" json_store.Cache.CACHE_DIR = json_store.SYSTEM_DIR / "cache" # Initialize directories json_store.init_storage() yield tmp_path # Restore original paths json_store.DATA_DIR = original_data_dir json_store.SYSTEM_DIR = original_system_dir json_store.PROJECTS_DIR = original_projects_dir json_store.TEAMS_DIR = original_teams_dir json_store.Cache.CACHE_DIR = original_system_dir / "cache" class TestCache: """Tests for TTL-based cache.""" def test_cache_set_and_get(self, temp_storage): """Test basic cache operations.""" json_store.Cache.set("test_key", {"foo": "bar"}, ttl=60) result = json_store.Cache.get("test_key") assert result == {"foo": "bar"} def test_cache_expiry(self, temp_storage): """Test that expired cache returns None.""" import time json_store.Cache.set("expired_key", "value", ttl=1) time.sleep(1.1) # Wait for expiry result = json_store.Cache.get("expired_key") assert result is None def test_cache_delete(self, temp_storage): """Test cache deletion.""" json_store.Cache.set("delete_me", "value") json_store.Cache.delete("delete_me") result = json_store.Cache.get("delete_me") assert result is None def test_cache_clear_all(self, temp_storage): """Test clearing all cache.""" json_store.Cache.set("key1", "value1") json_store.Cache.set("key2", "value2") json_store.Cache.clear_all() assert json_store.Cache.get("key1") is None assert json_store.Cache.get("key2") is None class TestProjects: """Tests for project operations.""" def test_create_project(self, temp_storage): """Test project creation.""" project = json_store.Projects.create( id="test-project", name="Test Project", description="A test project" ) assert project["id"] == "test-project" assert project["name"] == "Test Project" assert project["status"] == "active" def test_get_project(self, temp_storage): """Test project retrieval.""" json_store.Projects.create(id="get-test", name="Get Test") project = json_store.Projects.get("get-test") assert project is not None assert project["name"] == "Get Test" def test_list_projects(self, temp_storage): """Test listing projects.""" json_store.Projects.create(id="proj1", name="Project 1") json_store.Projects.create(id="proj2", name="Project 2") projects = json_store.Projects.list() assert len(projects) == 2 def test_update_project(self, temp_storage): """Test project update.""" json_store.Projects.create(id="update-test", name="Original") updated = json_store.Projects.update("update-test", name="Updated") assert updated["name"] == "Updated" def test_delete_project(self, temp_storage): """Test project deletion (archives).""" json_store.Projects.create(id="delete-test", name="Delete Me") result = json_store.Projects.delete("delete-test") assert result is True assert json_store.Projects.get("delete-test") is None def test_project_creates_token_structure(self, temp_storage): """Test that project creation initializes token folders.""" json_store.Projects.create(id="token-test", name="Token Test") tokens_dir = json_store.PROJECTS_DIR / "token-test" / "tokens" assert tokens_dir.exists() assert (tokens_dir / "colors.json").exists() assert (tokens_dir / "spacing.json").exists() class TestTokens: """Tests for token operations.""" def test_get_all_tokens(self, temp_storage): """Test getting all tokens for a project.""" json_store.Projects.create(id="tokens-proj", name="Tokens Project") tokens = json_store.Tokens.get_all("tokens-proj") assert "colors" in tokens assert "spacing" in tokens assert "typography" in tokens def test_set_and_get_tokens(self, temp_storage): """Test setting and getting tokens by type.""" json_store.Projects.create(id="set-tokens", name="Set Tokens") json_store.Tokens.set_by_type("set-tokens", "colors", { "primary": "#3B82F6", "secondary": "#10B981" }) colors = json_store.Tokens.get_by_type("set-tokens", "colors") assert colors["primary"] == "#3B82F6" assert colors["secondary"] == "#10B981" def test_merge_tokens_last_strategy(self, temp_storage): """Test merging tokens with LAST strategy.""" json_store.Projects.create(id="merge-test", name="Merge Test") json_store.Tokens.set_by_type("merge-test", "colors", { "primary": "#old", "secondary": "#keep" }) merged = json_store.Tokens.merge("merge-test", "colors", { "primary": "#new", "tertiary": "#added" }, strategy="LAST") assert merged["primary"] == "#new" assert merged["secondary"] == "#keep" assert merged["tertiary"] == "#added" class TestComponents: """Tests for component operations.""" def test_upsert_components(self, temp_storage): """Test bulk component upsert.""" json_store.Projects.create(id="comp-proj", name="Component Project") count = json_store.Components.upsert("comp-proj", [ {"name": "Button", "properties": {"variant": "primary"}}, {"name": "Card", "properties": {"shadow": "md"}} ]) assert count == 2 def test_list_components(self, temp_storage): """Test listing components.""" json_store.Projects.create(id="list-comp", name="List Components") json_store.Components.upsert("list-comp", [ {"name": "Button"}, {"name": "Input"} ]) components = json_store.Components.list("list-comp") assert len(components) == 2 names = [c["name"] for c in components] assert "Button" in names assert "Input" in names class TestActivityLog: """Tests for activity logging.""" def test_log_activity(self, temp_storage): """Test logging an activity.""" json_store.ActivityLog.log( action="test_action", entity_type="test", entity_name="Test Entity", project_id="test-proj" ) recent = json_store.ActivityLog.recent(limit=1) assert len(recent) == 1 assert recent[0]["action"] == "test_action" def test_activity_auto_category(self, temp_storage): """Test that activity auto-detects category.""" json_store.ActivityLog.log(action="extract_tokens") recent = json_store.ActivityLog.recent(limit=1) assert recent[0]["category"] == "design_system" class TestTeams: """Tests for team operations.""" def test_create_team(self, temp_storage): """Test team creation.""" team = json_store.Teams.create( id="test-team", name="Test Team", description="A test team" ) assert team["id"] == "test-team" assert team["name"] == "Test Team" def test_add_member(self, temp_storage): """Test adding team member.""" json_store.Teams.create(id="member-team", name="Member Team") json_store.Teams.add_member("member-team", "user-123", "DEVELOPER") members = json_store.Teams.get_members("member-team") assert len(members) == 1 assert members[0]["user_id"] == "user-123" assert members[0]["role"] == "DEVELOPER" def test_get_user_role(self, temp_storage): """Test getting user role in team.""" json_store.Teams.create(id="role-team", name="Role Team") json_store.Teams.add_member("role-team", "admin-user", "SUPER_ADMIN") role = json_store.Teams.get_user_role("role-team", "admin-user") assert role == "SUPER_ADMIN" class TestSyncHistory: """Tests for sync history.""" def test_sync_lifecycle(self, temp_storage): """Test sync start and complete.""" json_store.Projects.create(id="sync-proj", name="Sync Project") sync_id = json_store.SyncHistory.start("sync-proj", "tokens") json_store.SyncHistory.complete("sync-proj", sync_id, "success", items_synced=10) recent = json_store.SyncHistory.recent("sync-proj", limit=5) # Should have both start and complete records completed = [r for r in recent if r.get("status") == "success"] assert len(completed) >= 1 class TestStats: """Tests for storage statistics.""" def test_get_stats(self, temp_storage): """Test getting storage stats.""" json_store.Projects.create(id="stats-proj", name="Stats Project") json_store.Teams.create(id="stats-team", name="Stats Team") stats = json_store.get_stats() # Stats count directories, verify basic structure assert "projects" in stats assert "teams" in stats assert "total_size_mb" in stats assert stats["total_size_mb"] >= 0