feat: Add new tools and configurations for Castle platform
- Introduced `uv.lock` for dependency management with various packages including `pytest`, `colorama`, and `pluggy`. - Added `pyrightconfig.json` for Python type checking configuration. - Expanded `recommendations.md` with detailed scaling recommendations and project management strategies. - Created shared `ruff.toml` for consistent linting across projects. - Developed `Castle Tools` with various utilities including Android backup, browser automation, document conversion, and search tools. - Implemented `backup-collect` and `schedule` tools for system administration tasks. - Enhanced `search` functionality with indexing and querying capabilities using Tantivy. - Added comprehensive documentation for each tool, including usage examples and installation instructions.
This commit is contained in:
0
event-bus/tests/__init__.py
Normal file
0
event-bus/tests/__init__.py
Normal file
28
event-bus/tests/conftest.py
Normal file
28
event-bus/tests/conftest.py
Normal file
@@ -0,0 +1,28 @@
|
||||
"""Test fixtures for event-bus."""
|
||||
|
||||
from collections.abc import Generator
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from event_bus.config import settings
|
||||
from event_bus.main import app
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def temp_data_dir(tmp_path: Path) -> Generator[Path, None, None]:
|
||||
"""Create a temporary data directory for tests."""
|
||||
data_dir = tmp_path / "data"
|
||||
data_dir.mkdir()
|
||||
original = settings.data_dir
|
||||
settings.data_dir = data_dir
|
||||
yield data_dir
|
||||
settings.data_dir = original
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def client(temp_data_dir: Path) -> Generator[TestClient, None, None]:
|
||||
"""Create a test client with isolated data directory."""
|
||||
with TestClient(app) as client:
|
||||
yield client
|
||||
139
event-bus/tests/test_bus.py
Normal file
139
event-bus/tests/test_bus.py
Normal file
@@ -0,0 +1,139 @@
|
||||
"""Tests for event bus publish/subscribe functionality."""
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from event_bus.bus import EventBus
|
||||
|
||||
|
||||
class TestSubscribe:
|
||||
"""Subscription management tests."""
|
||||
|
||||
def test_subscribe(self, client: TestClient) -> None:
|
||||
"""Subscribe to a topic."""
|
||||
response = client.post(
|
||||
"/subscribe",
|
||||
json={
|
||||
"topic": "test.event",
|
||||
"callback_url": "http://localhost:9999/hook",
|
||||
"subscriber": "test-service",
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["status"] == "subscribed"
|
||||
assert data["topic"] == "test.event"
|
||||
|
||||
def test_subscribe_deduplicates(self, client: TestClient) -> None:
|
||||
"""Same callback URL for same topic is not duplicated."""
|
||||
for _ in range(3):
|
||||
client.post(
|
||||
"/subscribe",
|
||||
json={
|
||||
"topic": "test.event",
|
||||
"callback_url": "http://localhost:9999/hook",
|
||||
},
|
||||
)
|
||||
|
||||
response = client.get("/topics")
|
||||
topics = response.json()["topics"]
|
||||
assert len(topics.get("test.event", [])) == 1
|
||||
|
||||
def test_unsubscribe(self, client: TestClient) -> None:
|
||||
"""Unsubscribe removes the subscription."""
|
||||
client.post(
|
||||
"/subscribe",
|
||||
json={
|
||||
"topic": "test.event",
|
||||
"callback_url": "http://localhost:9999/hook",
|
||||
},
|
||||
)
|
||||
|
||||
response = client.post(
|
||||
"/unsubscribe",
|
||||
json={
|
||||
"topic": "test.event",
|
||||
"callback_url": "http://localhost:9999/hook",
|
||||
},
|
||||
)
|
||||
assert response.json()["status"] == "unsubscribed"
|
||||
|
||||
response = client.get("/topics")
|
||||
assert "test.event" not in response.json()["topics"]
|
||||
|
||||
def test_unsubscribe_not_found(self, client: TestClient) -> None:
|
||||
"""Unsubscribing from non-existent subscription returns not_found."""
|
||||
response = client.post(
|
||||
"/unsubscribe",
|
||||
json={
|
||||
"topic": "nonexistent",
|
||||
"callback_url": "http://localhost:9999/hook",
|
||||
},
|
||||
)
|
||||
assert response.json()["status"] == "not_found"
|
||||
|
||||
|
||||
class TestPublish:
|
||||
"""Event publishing tests."""
|
||||
|
||||
def test_publish_no_subscribers(self, client: TestClient) -> None:
|
||||
"""Publishing to a topic with no subscribers returns 0."""
|
||||
response = client.post(
|
||||
"/publish",
|
||||
json={"topic": "empty.topic", "payload": {"msg": "hello"}},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json()["subscribers_notified"] == 0
|
||||
|
||||
|
||||
class TestTopics:
|
||||
"""Topic listing tests."""
|
||||
|
||||
def test_list_topics_empty(self, client: TestClient) -> None:
|
||||
"""Empty bus returns empty topics."""
|
||||
response = client.get("/topics")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"topics": {}}
|
||||
|
||||
def test_list_topics_with_subscriptions(self, client: TestClient) -> None:
|
||||
"""Topics list shows all subscriptions."""
|
||||
client.post(
|
||||
"/subscribe",
|
||||
json={
|
||||
"topic": "a.event",
|
||||
"callback_url": "http://localhost:9999/a",
|
||||
"subscriber": "svc-a",
|
||||
},
|
||||
)
|
||||
client.post(
|
||||
"/subscribe",
|
||||
json={
|
||||
"topic": "b.event",
|
||||
"callback_url": "http://localhost:9999/b",
|
||||
"subscriber": "svc-b",
|
||||
},
|
||||
)
|
||||
|
||||
response = client.get("/topics")
|
||||
topics = response.json()["topics"]
|
||||
assert "a.event" in topics
|
||||
assert "b.event" in topics
|
||||
assert topics["a.event"][0]["subscriber"] == "svc-a"
|
||||
|
||||
|
||||
class TestEventBusUnit:
|
||||
"""Unit tests for the EventBus class."""
|
||||
|
||||
def test_subscribe_and_list(self) -> None:
|
||||
"""Subscribe adds to subscription table."""
|
||||
eb = EventBus()
|
||||
eb.subscribe("test", "http://localhost/hook", "test-svc")
|
||||
topics = eb.list_topics()
|
||||
assert "test" in topics
|
||||
assert topics["test"][0]["callback_url"] == "http://localhost/hook"
|
||||
|
||||
def test_unsubscribe_cleans_empty_topic(self) -> None:
|
||||
"""Unsubscribing the last subscriber removes the topic."""
|
||||
eb = EventBus()
|
||||
eb.subscribe("test", "http://localhost/hook")
|
||||
eb.unsubscribe("test", "http://localhost/hook")
|
||||
assert "test" not in eb.list_topics()
|
||||
13
event-bus/tests/test_health.py
Normal file
13
event-bus/tests/test_health.py
Normal file
@@ -0,0 +1,13 @@
|
||||
"""Tests for event-bus health endpoint."""
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
class TestHealth:
|
||||
"""Health endpoint tests."""
|
||||
|
||||
def test_health(self, client: TestClient) -> None:
|
||||
"""Health endpoint returns ok."""
|
||||
response = client.get("/health")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"status": "ok"}
|
||||
Reference in New Issue
Block a user