Files
PraisonAIUI/tests/test_feature_chat.py
a433c483c1 fix: document bootstrap entrypoints in examples (fixes #71) (#96)
* feat: standardize bootstrap entrypoint to 'aiui run app.py' across examples

Standardizes platform bootstrap patterns across examples per issue #71:

- Update examples README table to use 'aiui run app.py' consistently
- Update docstrings in examples 10, 12, 19-21 to show 'aiui run' instead of 'python app.py'
- Remove fragmented bootstrap approaches (uvicorn.run, asyncio patterns)
- Enforce single bootstrap SSOT as designed in CLI

Co-authored-by: Mervin Praison <[email protected]>

* feat: consolidate bootstrap entrypoints - auto-detect gateway apps (fixes #71)

- Add bootstrap detection in CLI run command
- Auto-detect gateway pattern (async main + AIUIGateway imports)
- Auto-switch to praisonai backend for gateway apps
- Delegate to user-defined main() when present
- Remove sys.path hacks from example 14
- Update examples README to show unified aiui run entrypoint
- Add BOOTSTRAP.md documentation for migration patterns

Co-authored-by: Mervin Praison <[email protected]>

* fix: resolve critical bootstrap entrypoint issues

- Fix AST parsing bug in gateway auto-detection (cli.py:1419)
- Revert background bots (email-bot, agentmail-bot) to python app.py
- Revert custom UI apps (agent-dashboard) to python app.py
- Update README.md to reflect correct run commands
- Fix import formatting and remove unused imports

These changes ensure that:
1. Gateway auto-detection works correctly by properly checking ast.alias.name
2. Background bots execute their __main__ blocks and don't start unnecessary web servers
3. Custom UI apps register their custom routes in __main__ blocks
4. Documentation matches actual working run commands

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Mervin Praison <[email protected]>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Mervin Praison <[email protected]>
Co-authored-by: Mervin Praison <[email protected]>
Co-authored-by: Cursor <[email protected]>
2026-06-15 16:36:35 +01:00

149 lines
5.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Tests for the chat feature protocol (Gap 1–4).
TDD: These tests define the expected behaviour BEFORE the feature is built.
"""
from __future__ import annotations
import pytest
# ── Unit tests for ChatFeature protocol ──────────────────────────────
class TestChatFeatureProtocol:
"""Verify the chat feature meets BaseFeatureProtocol."""
def test_feature_name(self):
from praisonaiui.features.chat import PraisonAIChat
f = PraisonAIChat()
assert f.name == "chat"
def test_feature_description(self):
from praisonaiui.features.chat import PraisonAIChat
f = PraisonAIChat()
assert "chat" in f.description.lower()
def test_routes_not_empty(self):
from praisonaiui.features.chat import PraisonAIChat
f = PraisonAIChat()
routes = f.routes()
assert len(routes) >= 2 # at minimum: WS + REST send
def test_route_paths(self):
from praisonaiui.features.chat import PraisonAIChat
f = PraisonAIChat()
paths = [r.path for r in f.routes()]
assert "/api/chat/ws" in paths or "/api/chat/send" in paths
@pytest.mark.asyncio
async def test_health(self):
from praisonaiui.features.chat import PraisonAIChat
f = PraisonAIChat()
h = await f.health()
assert h["status"] == "ok"
assert h["feature"] == "chat"
# ── Unit tests for ChatMessage model ─────────────────────────────────
class TestChatMessage:
"""Verify the chat message dataclass."""
def test_chat_message_creation(self):
from praisonaiui.features.chat import ChatMessage
msg = ChatMessage(
role="user",
content="Hello",
session_id="s1",
)
assert msg.role == "user"
assert msg.content == "Hello"
assert msg.session_id == "s1"
assert msg.message_id # auto-generated
def test_chat_message_to_dict(self):
from praisonaiui.features.chat import ChatMessage
msg = ChatMessage(role="assistant", content="Hi!", session_id="s1")
d = msg.to_dict()
assert d["role"] == "assistant"
assert d["content"] == "Hi!"
assert "message_id" in d
assert "timestamp" in d
def test_chat_message_agent_name(self):
from praisonaiui.features.chat import ChatMessage
msg = ChatMessage(
role="assistant",
content="Result",
session_id="s1",
agent_name="Researcher",
)
assert msg.agent_name == "Researcher"
# ── Unit tests for ChatProtocol ──────────────────────────────────────
class TestChatProtocol:
"""Verify the chat protocol interface."""
def test_protocol_has_send(self):
from praisonaiui.features.chat import ChatProtocol
assert hasattr(ChatProtocol, 'send_message')
def test_protocol_has_history(self):
from praisonaiui.features.chat import ChatProtocol
assert hasattr(ChatProtocol, 'get_history')
def test_protocol_has_abort(self):
from praisonaiui.features.chat import ChatProtocol
assert hasattr(ChatProtocol, 'abort_run')
# ── Unit tests for ChatManager ───────────────────────────────────────
class TestChatManager:
"""Verify the chat manager (default implementation of ChatProtocol)."""
@pytest.mark.asyncio
async def test_send_message_returns_message_id(self):
from praisonaiui.features.chat import ChatManager
mgr = ChatManager()
result = await mgr.send_message(
content="Hello",
session_id="test-session",
)
assert "message_id" in result
@pytest.mark.asyncio
async def test_get_history_empty(self):
from praisonaiui.features.chat import ChatManager
mgr = ChatManager()
history = await mgr.get_history("nonexistent")
assert history == []
@pytest.mark.asyncio
async def test_abort_run(self):
from praisonaiui.features.chat import ChatManager
mgr = ChatManager()
# Should not error on non-existent run
result = await mgr.abort_run("fake-run-id")
assert result["status"] in ("aborted", "no_active_run")
# ── Integration: Feature registered in auto_register_defaults ────────
class TestAutoRegistration:
"""Verify chat feature is auto-registered."""
def test_chat_in_features(self):
from praisonaiui.features import auto_register_defaults, get_features
auto_register_defaults()
features = get_features()
assert "chat" in features
def test_chat_routes_mounted(self):
from praisonaiui.features import auto_register_defaults, get_features
auto_register_defaults()
chat = get_features()["chat"]
routes = chat.routes()
assert len(routes) >= 2