Files
markitect-main/tests/unit/prompts/test_artifact_repository.py
tegwick 706981c39f fix(prompts): fix three infrastructure bugs in prompt dependency resolution
- ContentMacro: add __post_init__ to auto-derive raw_text when built
  programmatically, preventing str.replace("", X) corruption
- MacroParser: add @{target} shorthand syntax support mapped to REQUIRED kind,
  updating parse, has_macros, count_macros, and find_macro_positions
- Artifact: store content in model and SQLite DB, replace resolver placeholder
  with actual artifact content, add migration for existing databases

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:53:02 +01:00

291 lines
9.5 KiB
Python

"""
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"}
def test_content_round_trip(self, repository):
"""Test that artifact content survives store and retrieve."""
original_content = "# Test Content\n\nThis is the full content."
artifact = Artifact.create(
space_id="test-space",
name="content-test",
content=original_content,
)
repository.create(artifact)
retrieved = repository.get_by_id(artifact.id)
assert retrieved.content == original_content
def test_content_persisted_after_update(self, repository):
"""Test that updated content is persisted."""
artifact = Artifact.create(
space_id="test-space",
name="update-test",
content="Original content",
)
repository.create(artifact)
artifact.update_content("Updated content")
repository.update(artifact)
retrieved = repository.get_by_id(artifact.id)
assert retrieved.content == "Updated content"