""" Unit tests for artifact repository. Tests SQLiteArtifactRepository implementation. """ import pytest import tempfile from pathlib import Path from markitect.prompts.models import Artifact, ArtifactType, ArtifactMetadata from markitect.prompts.repositories.sqlite import SQLiteArtifactRepository from markitect.prompts.repositories.interfaces import ( ArtifactNotFoundError, DuplicateArtifactError, ) @pytest.fixture def temp_db(): """Create temporary database for testing.""" with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as f: db_path = f.name yield db_path # Cleanup Path(db_path).unlink(missing_ok=True) @pytest.fixture def repository(temp_db): """Create repository instance with temp database.""" return SQLiteArtifactRepository(temp_db) @pytest.fixture def sample_artifact(): """Create sample artifact for testing.""" return Artifact.create( space_id="test-space", name="test-artifact", content="# Test Content\n\nThis is test content.", artifact_type=ArtifactType.CONTENT, ) class TestSQLiteArtifactRepository: """Tests for SQLiteArtifactRepository.""" def test_create_artifact(self, repository, sample_artifact): """Test creating an artifact.""" created = repository.create(sample_artifact) assert created.id == sample_artifact.id assert created.space_id == sample_artifact.space_id assert created.name == sample_artifact.name assert created.content_digest == sample_artifact.content_digest def test_create_duplicate_artifact_raises_error(self, repository, sample_artifact): """Test creating duplicate artifact raises error.""" repository.create(sample_artifact) # Try to create another artifact with same space_id and name duplicate = Artifact.create( space_id="test-space", name="test-artifact", content="Different content", ) with pytest.raises(DuplicateArtifactError, match="already exists"): repository.create(duplicate) def test_get_by_id(self, repository, sample_artifact): """Test retrieving artifact by ID.""" repository.create(sample_artifact) retrieved = repository.get_by_id(sample_artifact.id) assert retrieved is not None assert retrieved.id == sample_artifact.id assert retrieved.name == sample_artifact.name assert retrieved.content_digest == sample_artifact.content_digest def test_get_by_id_not_found(self, repository): """Test get_by_id returns None for non-existent ID.""" result = repository.get_by_id("non-existent-id") assert result is None def test_get_by_name(self, repository, sample_artifact): """Test retrieving artifact by space and name.""" repository.create(sample_artifact) retrieved = repository.get_by_name("test-space", "test-artifact") assert retrieved is not None assert retrieved.id == sample_artifact.id assert retrieved.space_id == "test-space" assert retrieved.name == "test-artifact" def test_get_by_name_not_found(self, repository): """Test get_by_name returns None when not found.""" result = repository.get_by_name("test-space", "non-existent") assert result is None def test_get_by_digest(self, repository): """Test finding artifacts by content digest.""" content = "Shared content" artifact1 = Artifact.create( space_id="space-1", name="artifact-1", content=content, ) artifact2 = Artifact.create( space_id="space-2", name="artifact-2", content=content, # Same content, same digest ) repository.create(artifact1) repository.create(artifact2) results = repository.get_by_digest(artifact1.content_digest) assert len(results) == 2 names = {a.name for a in results} assert names == {"artifact-1", "artifact-2"} def test_list_by_space(self, repository): """Test listing artifacts in a space.""" artifacts = [ Artifact.create( space_id="space-1", name=f"artifact-{i}", content=f"Content {i}", ) for i in range(3) ] for artifact in artifacts: repository.create(artifact) # Add artifact in different space other = Artifact.create( space_id="space-2", name="other", content="Other content", ) repository.create(other) results = repository.list_by_space("space-1") assert len(results) == 3 assert all(a.space_id == "space-1" for a in results) # Should be ordered by name assert [a.name for a in results] == ["artifact-0", "artifact-1", "artifact-2"] def test_list_by_space_with_type_filter(self, repository): """Test listing artifacts filtered by type.""" artifacts = [ Artifact.create( space_id="space-1", name="content-1", content="Content", artifact_type=ArtifactType.CONTENT, ), Artifact.create( space_id="space-1", name="template-1", content="Template", artifact_type=ArtifactType.TEMPLATE, ), Artifact.create( space_id="space-1", name="content-2", content="Content 2", artifact_type=ArtifactType.CONTENT, ), ] for artifact in artifacts: repository.create(artifact) results = repository.list_by_space("space-1", ArtifactType.CONTENT) assert len(results) == 2 assert all(a.artifact_type == ArtifactType.CONTENT for a in results) def test_update_artifact(self, repository, sample_artifact): """Test updating artifact.""" repository.create(sample_artifact) # Update content sample_artifact.update_content("New content") updated = repository.update(sample_artifact) # Retrieve and verify retrieved = repository.get_by_id(sample_artifact.id) assert retrieved.content_digest == updated.content_digest assert retrieved.updated_at >= updated.updated_at def test_update_nonexistent_artifact_raises_error(self, repository): """Test updating non-existent artifact raises error.""" artifact = Artifact.create( space_id="test-space", name="test", content="content", ) with pytest.raises(ArtifactNotFoundError, match="not found"): repository.update(artifact) def test_delete_artifact(self, repository, sample_artifact): """Test deleting artifact.""" repository.create(sample_artifact) result = repository.delete(sample_artifact.id) assert result is True # Verify deleted retrieved = repository.get_by_id(sample_artifact.id) assert retrieved is None def test_delete_nonexistent_artifact(self, repository): """Test deleting non-existent artifact returns False.""" result = repository.delete("non-existent-id") assert result is False def test_exists(self, repository, sample_artifact): """Test checking if artifact exists.""" assert not repository.exists("test-space", "test-artifact") repository.create(sample_artifact) assert repository.exists("test-space", "test-artifact") assert not repository.exists("test-space", "other-artifact") assert not repository.exists("other-space", "test-artifact") def test_artifact_metadata_persistence(self, repository): """Test metadata is persisted correctly.""" metadata = ArtifactMetadata( description="Test description", tags=["tag1", "tag2"], author="test-author", version="1.0.0", custom={"key": "value"}, ) artifact = Artifact.create( space_id="test-space", name="test", content="content", metadata=metadata, ) repository.create(artifact) retrieved = repository.get_by_id(artifact.id) assert retrieved.metadata.description == "Test description" assert retrieved.metadata.tags == ["tag1", "tag2"] assert retrieved.metadata.author == "test-author" assert retrieved.metadata.version == "1.0.0" assert retrieved.metadata.custom == {"key": "value"}