- Formatted 103 files to comply with ruff format requirements - No code logic changes, only formatting/whitespace - Fixes CI formatting check failures
287 lines
9.5 KiB
Python
287 lines
9.5 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Integration tests for ChromaDB and Weaviate upload functionality.
|
|
|
|
Tests real upload capabilities for vector databases.
|
|
"""
|
|
|
|
import json
|
|
import pytest
|
|
|
|
# Import adaptors
|
|
from skill_seekers.cli.adaptors import get_adaptor
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_chroma_package(tmp_path):
|
|
"""Create a sample ChromaDB package for testing."""
|
|
package_data = {
|
|
"collection_name": "test_collection",
|
|
"documents": ["Test doc 1", "Test doc 2", "Test doc 3"],
|
|
"metadatas": [
|
|
{"source": "test", "category": "overview", "file": "SKILL.md"},
|
|
{"source": "test", "category": "api", "file": "API.md"},
|
|
{"source": "test", "category": "guide", "file": "GUIDE.md"},
|
|
],
|
|
"ids": ["id1", "id2", "id3"],
|
|
}
|
|
|
|
package_path = tmp_path / "test-chroma.json"
|
|
package_path.write_text(json.dumps(package_data))
|
|
return package_path
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_weaviate_package(tmp_path):
|
|
"""Create a sample Weaviate package for testing."""
|
|
package_data = {
|
|
"class_name": "TestSkill",
|
|
"schema": {
|
|
"class": "TestSkill",
|
|
"description": "Test skill documentation",
|
|
"vectorizer": "none",
|
|
"properties": [
|
|
{"name": "content", "dataType": ["text"]},
|
|
{"name": "source", "dataType": ["string"]},
|
|
{"name": "category", "dataType": ["string"]},
|
|
],
|
|
},
|
|
"objects": [
|
|
{
|
|
"id": "00000000-0000-0000-0000-000000000001",
|
|
"properties": {
|
|
"content": "Test content 1",
|
|
"source": "test",
|
|
"category": "overview",
|
|
},
|
|
},
|
|
{
|
|
"id": "00000000-0000-0000-0000-000000000002",
|
|
"properties": {"content": "Test content 2", "source": "test", "category": "api"},
|
|
},
|
|
],
|
|
}
|
|
|
|
package_path = tmp_path / "test-weaviate.json"
|
|
package_path.write_text(json.dumps(package_data))
|
|
return package_path
|
|
|
|
|
|
class TestChromaUploadBasics:
|
|
"""Test ChromaDB upload basic functionality."""
|
|
|
|
def test_chroma_adaptor_exists(self):
|
|
"""Test that ChromaDB adaptor can be loaded."""
|
|
adaptor = get_adaptor("chroma")
|
|
assert adaptor is not None
|
|
assert adaptor.PLATFORM == "chroma"
|
|
|
|
def test_chroma_upload_without_chromadb_installed(self, sample_chroma_package):
|
|
"""Test upload fails gracefully without chromadb installed."""
|
|
adaptor = get_adaptor("chroma")
|
|
|
|
# Temporarily remove chromadb if it exists
|
|
import sys
|
|
|
|
chromadb_backup = sys.modules.get("chromadb")
|
|
if "chromadb" in sys.modules:
|
|
del sys.modules["chromadb"]
|
|
|
|
try:
|
|
result = adaptor.upload(sample_chroma_package)
|
|
|
|
assert result["success"] is False
|
|
assert "chromadb not installed" in result["message"]
|
|
assert "pip install chromadb" in result["message"]
|
|
finally:
|
|
if chromadb_backup:
|
|
sys.modules["chromadb"] = chromadb_backup
|
|
|
|
def test_chroma_upload_api_signature(self, sample_chroma_package):
|
|
"""Test ChromaDB upload has correct API signature."""
|
|
adaptor = get_adaptor("chroma")
|
|
|
|
# Verify upload method exists and accepts kwargs
|
|
assert hasattr(adaptor, "upload")
|
|
assert callable(adaptor.upload)
|
|
|
|
# Verify adaptor methods exist
|
|
assert hasattr(adaptor, "_generate_openai_embeddings")
|
|
|
|
|
|
class TestWeaviateUploadBasics:
|
|
"""Test Weaviate upload basic functionality."""
|
|
|
|
def test_weaviate_adaptor_exists(self):
|
|
"""Test that Weaviate adaptor can be loaded."""
|
|
adaptor = get_adaptor("weaviate")
|
|
assert adaptor is not None
|
|
assert adaptor.PLATFORM == "weaviate"
|
|
|
|
def test_weaviate_upload_without_weaviate_installed(self, sample_weaviate_package):
|
|
"""Test upload fails gracefully without weaviate-client installed."""
|
|
adaptor = get_adaptor("weaviate")
|
|
|
|
# Temporarily remove weaviate if it exists
|
|
import sys
|
|
|
|
weaviate_backup = sys.modules.get("weaviate")
|
|
if "weaviate" in sys.modules:
|
|
del sys.modules["weaviate"]
|
|
|
|
try:
|
|
result = adaptor.upload(sample_weaviate_package)
|
|
|
|
assert result["success"] is False
|
|
assert "weaviate-client not installed" in result["message"]
|
|
assert "pip install weaviate-client" in result["message"]
|
|
finally:
|
|
if weaviate_backup:
|
|
sys.modules["weaviate"] = weaviate_backup
|
|
|
|
def test_weaviate_upload_api_signature(self, sample_weaviate_package):
|
|
"""Test Weaviate upload has correct API signature."""
|
|
adaptor = get_adaptor("weaviate")
|
|
|
|
# Verify upload method exists and accepts kwargs
|
|
assert hasattr(adaptor, "upload")
|
|
assert callable(adaptor.upload)
|
|
|
|
# Verify adaptor methods exist
|
|
assert hasattr(adaptor, "_generate_openai_embeddings")
|
|
|
|
|
|
class TestPackageStructure:
|
|
"""Test that packages are correctly structured for upload."""
|
|
|
|
def test_chroma_package_structure(self, sample_chroma_package):
|
|
"""Test ChromaDB package has required fields."""
|
|
with open(sample_chroma_package) as f:
|
|
data = json.load(f)
|
|
|
|
assert "collection_name" in data
|
|
assert "documents" in data
|
|
assert "metadatas" in data
|
|
assert "ids" in data
|
|
assert len(data["documents"]) == len(data["metadatas"]) == len(data["ids"])
|
|
|
|
def test_weaviate_package_structure(self, sample_weaviate_package):
|
|
"""Test Weaviate package has required fields."""
|
|
with open(sample_weaviate_package) as f:
|
|
data = json.load(f)
|
|
|
|
assert "class_name" in data
|
|
assert "schema" in data
|
|
assert "objects" in data
|
|
assert len(data["objects"]) == 2
|
|
|
|
# Verify schema structure
|
|
assert "class" in data["schema"]
|
|
assert "properties" in data["schema"]
|
|
|
|
# Verify object structure
|
|
for obj in data["objects"]:
|
|
assert "id" in obj
|
|
assert "properties" in obj
|
|
|
|
|
|
class TestUploadCommandIntegration:
|
|
"""Test upload command integration."""
|
|
|
|
def test_upload_skill_api_signature(self):
|
|
"""Test upload_skill_api has correct signature."""
|
|
from skill_seekers.cli.upload_skill import upload_skill_api
|
|
|
|
# Verify function exists
|
|
assert callable(upload_skill_api)
|
|
|
|
# Verify it accepts kwargs for vector DBs
|
|
import inspect
|
|
|
|
sig = inspect.signature(upload_skill_api)
|
|
params = list(sig.parameters.keys())
|
|
assert "package_path" in params
|
|
assert "target" in params
|
|
assert "api_key" in params
|
|
assert "kwargs" in params # For platform-specific options
|
|
|
|
def test_upload_command_supports_chroma(self):
|
|
"""Test upload command recognizes chroma as target."""
|
|
|
|
# This should not raise ValueError
|
|
adaptor = get_adaptor("chroma")
|
|
assert adaptor is not None
|
|
|
|
def test_upload_command_supports_weaviate(self):
|
|
"""Test upload command recognizes weaviate as target."""
|
|
|
|
# This should not raise ValueError
|
|
adaptor = get_adaptor("weaviate")
|
|
assert adaptor is not None
|
|
|
|
|
|
class TestErrorHandling:
|
|
"""Test error handling in upload functionality."""
|
|
|
|
def test_chroma_handles_missing_file(self, tmp_path):
|
|
"""Test ChromaDB upload handles missing files gracefully."""
|
|
adaptor = get_adaptor("chroma")
|
|
|
|
missing_file = tmp_path / "nonexistent.json"
|
|
|
|
# Should raise FileNotFoundError or return error dict
|
|
try:
|
|
result = adaptor.upload(missing_file)
|
|
# If it returns a dict, it should indicate failure
|
|
assert result["success"] is False
|
|
except FileNotFoundError:
|
|
# This is also acceptable
|
|
pass
|
|
|
|
def test_weaviate_handles_missing_file(self, tmp_path):
|
|
"""Test Weaviate upload handles missing files gracefully."""
|
|
adaptor = get_adaptor("weaviate")
|
|
|
|
missing_file = tmp_path / "nonexistent.json"
|
|
|
|
# Should raise FileNotFoundError or return error dict
|
|
try:
|
|
result = adaptor.upload(missing_file)
|
|
# If it returns a dict, it should indicate failure
|
|
assert result["success"] is False
|
|
except FileNotFoundError:
|
|
# This is also acceptable
|
|
pass
|
|
|
|
def test_chroma_handles_invalid_json(self, tmp_path):
|
|
"""Test ChromaDB upload handles invalid JSON gracefully."""
|
|
adaptor = get_adaptor("chroma")
|
|
|
|
invalid_file = tmp_path / "invalid.json"
|
|
invalid_file.write_text("not valid json{")
|
|
|
|
# Should raise JSONDecodeError or return error dict
|
|
try:
|
|
result = adaptor.upload(invalid_file)
|
|
# If it returns a dict, it should indicate failure
|
|
assert result["success"] is False
|
|
except json.JSONDecodeError:
|
|
# This is also acceptable
|
|
pass
|
|
|
|
def test_weaviate_handles_invalid_json(self, tmp_path):
|
|
"""Test Weaviate upload handles invalid JSON gracefully."""
|
|
adaptor = get_adaptor("weaviate")
|
|
|
|
invalid_file = tmp_path / "invalid.json"
|
|
invalid_file.write_text("not valid json{")
|
|
|
|
# Should raise JSONDecodeError or return error dict
|
|
try:
|
|
result = adaptor.upload(invalid_file)
|
|
# If it returns a dict, it should indicate failure
|
|
assert result["success"] is False
|
|
except json.JSONDecodeError:
|
|
# This is also acceptable
|
|
pass
|