- 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.
140 lines
4.5 KiB
Python
140 lines
4.5 KiB
Python
"""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()
|