This repository has been archived on 2026-03-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Timmy-time-dashboard/tests/functional/test_activity_feed_e2e.py
Alexander Payne d8d976aa60 feat: complete Event Log, Ledger, Memory, Cascade Router, Upgrade Queue, Activity Feed
This commit implements six major features:

1. Event Log System (src/swarm/event_log.py)
   - SQLite-based audit trail for all swarm events
   - Task lifecycle tracking (created, assigned, completed, failed)
   - Agent lifecycle tracking (joined, left, status changes)
   - Integrated with coordinator for automatic logging
   - Dashboard page at /swarm/events

2. Lightning Ledger (src/lightning/ledger.py)
   - Transaction tracking for Lightning Network payments
   - Balance calculations (incoming, outgoing, net, available)
   - Integrated with payment_handler for automatic logging
   - Dashboard page at /lightning/ledger

3. Semantic Memory / Vector Store (src/memory/vector_store.py)
   - Embedding-based similarity search for Echo agent
   - Fallback to keyword matching if sentence-transformers unavailable
   - Personal facts storage and retrieval
   - Dashboard page at /memory

4. Cascade Router Integration (src/timmy/cascade_adapter.py)
   - Automatic LLM failover between providers (Ollama → AirLLM → API)
   - Circuit breaker pattern for failing providers
   - Metrics tracking per provider (latency, error rates)
   - Dashboard status page at /router/status

5. Self-Upgrade Approval Queue (src/upgrades/)
   - State machine for self-modifications: proposed → approved/rejected → applied/failed
   - Human approval required before applying changes
   - Git integration for branch management
   - Dashboard queue at /self-modify/queue

6. Real-Time Activity Feed (src/events/broadcaster.py)
   - WebSocket-based live activity streaming
   - Bridges event_log to dashboard clients
   - Activity panel on /swarm/live

Tests:
- 101 unit tests passing
- 4 new E2E test files for Selenium testing
- Run with: SELENIUM_UI=1 pytest tests/functional/ -v --headed

Documentation:
- 6 ADRs (017-022) documenting architecture decisions
- Implementation summary in docs/IMPLEMENTATION_SUMMARY.md
- Architecture diagram in docs/architecture-v2.md
2026-02-26 08:01:01 -05:00

212 lines
7.0 KiB
Python

"""E2E tests for Real-Time Activity Feed.
RUN: pytest tests/functional/test_activity_feed_e2e.py -v --headed
"""
import os
import time
import pytest
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
import httpx
from .conftest import DASHBOARD_URL
@pytest.fixture
def driver():
"""Non-headless Chrome so you can watch."""
opts = Options()
opts.add_argument("--no-sandbox")
opts.add_argument("--disable-dev-shm-usage")
opts.add_argument("--window-size=1400,900")
d = webdriver.Chrome(options=opts)
d.implicitly_wait(5)
yield d
d.quit()
class TestActivityFeedUI:
"""Real-time activity feed on dashboard."""
def test_activity_feed_exists_on_swarm_live(self, driver):
"""Swarm live page has activity feed panel."""
driver.get(f"{DASHBOARD_URL}/swarm/live")
# Look for activity feed
feed = driver.find_elements(
By.CSS_SELECTOR, ".activity-feed, .live-feed, .events-feed"
)
# Or look for activity header
headers = driver.find_elements(
By.XPATH, "//*[contains(text(), 'Activity') or contains(text(), 'Live')]"
)
assert feed or headers, "Should have activity feed panel"
def test_activity_feed_shows_events(self, driver):
"""Activity feed displays events."""
driver.get(f"{DASHBOARD_URL}/swarm/live")
time.sleep(2) # Let feed load
# Look for event items
events = driver.find_elements(By.CSS_SELECTOR, ".event-item, .activity-item")
# Or empty state
empty = driver.find_elements(By.XPATH, "//*[contains(text(), 'No activity')]")
assert events or empty, "Should show events or empty state"
def test_activity_feed_updates_in_realtime(self, driver):
"""Creating a task shows up in activity feed immediately.
This tests the WebSocket real-time update.
"""
driver.get(f"{DASHBOARD_URL}/swarm/live")
# Get initial event count
initial = len(driver.find_elements(By.CSS_SELECTOR, ".event-item"))
# Create a task via API (this should trigger event)
task_desc = f"Activity test {time.time()}"
try:
httpx.post(
f"{DASHBOARD_URL}/swarm/tasks",
data={"description": task_desc},
timeout=5
)
except Exception:
pass # Task may not complete, but event should still fire
# Wait for WebSocket update
time.sleep(3)
# Check for new event
current = len(driver.find_elements(By.CSS_SELECTOR, ".event-item"))
# Or check for task-related text
page_text = driver.find_element(By.TAG_NAME, "body").text.lower()
has_task_event = "task" in page_text and "created" in page_text
assert current > initial or has_task_event, "Should see new activity"
def test_activity_feed_shows_task_events(self, driver):
"""Task lifecycle events appear in feed."""
driver.get(f"{DASHBOARD_URL}/swarm/live")
time.sleep(2)
page_text = driver.find_element(By.TAG_NAME, "body").text.lower()
# Should see task-related events if any exist
task_related = any(x in page_text for x in [
"task.created", "task assigned", "task completed", "new task"
])
# Not a failure if no tasks exist, just check the feed is there
feed_exists = driver.find_elements(By.CSS_SELECTOR, ".activity-feed")
assert feed_exists, "Activity feed should exist"
def test_activity_feed_shows_agent_events(self, driver):
"""Agent join/leave events appear in feed."""
driver.get(f"{DASHBOARD_URL}/swarm/live")
time.sleep(2)
page_text = driver.find_element(By.TAG_NAME, "body").text.lower()
# Should see agent-related events if any exist
agent_related = any(x in page_text for x in [
"agent joined", "agent left", "agent status"
])
# Feed should exist regardless
feed = driver.find_elements(By.CSS_SELECTOR, ".activity-feed, .live-feed")
def test_activity_feed_shows_bid_events(self, driver):
"""Bid events appear in feed."""
driver.get(f"{DASHBOARD_URL}/swarm/live")
time.sleep(2)
page_text = driver.find_element(By.TAG_NAME, "body").text.lower()
# Look for bid-related text
bid_related = any(x in page_text for x in [
"bid", "sats", "auction"
])
def test_activity_feed_timestamps(self, driver):
"""Events show timestamps."""
driver.get(f"{DASHBOARD_URL}/swarm/live")
time.sleep(2)
# Look for time patterns
page_text = driver.find_element(By.TAG_NAME, "body").text
# Should have timestamps (HH:MM format)
import re
time_pattern = re.search(r'\d{1,2}:\d{2}', page_text)
# If there are events, they should have timestamps
events = driver.find_elements(By.CSS_SELECTOR, ".event-item")
if events:
assert time_pattern, "Events should have timestamps"
def test_activity_feed_icons(self, driver):
"""Different event types have different icons."""
driver.get(f"{DASHBOARD_URL}/swarm/live")
time.sleep(2)
# Look for icons or visual indicators
icons = driver.find_elements(By.CSS_SELECTOR, ".event-icon, .activity-icon, .icon")
# Not required but nice to have
class TestActivityFeedIntegration:
"""Activity feed integration with other features."""
def test_activity_appears_in_event_log(self, driver):
"""Activity feed events are also in event log page."""
# Create a task
try:
httpx.post(
f"{DASHBOARD_URL}/swarm/tasks",
data={"description": "Integration test task"},
timeout=5
)
except Exception:
pass
time.sleep(2)
# Check event log
driver.get(f"{DASHBOARD_URL}/swarm/events")
page_text = driver.find_element(By.TAG_NAME, "body").text.lower()
assert "task" in page_text, "Event log should show task events"
def test_nav_to_swarm_live(self, driver):
"""Can navigate to swarm live page."""
driver.get(DASHBOARD_URL)
# Look for swarm/live link
live_link = driver.find_elements(
By.XPATH, "//a[contains(@href, '/swarm/live') or contains(text(), 'Live')]"
)
if live_link:
live_link[0].click()
time.sleep(1)
assert "/swarm/live" in driver.current_url