Files
javis_bot/tests/test_mcp_catalogue.py
javis-bot c4abf63f38
Some checks failed
Release / semantic-release (push) Successful in 59s
tests / Unit tests (Linux, Python 3.11) (push) Successful in 13m45s
Release / build-linux (push) Failing after 7m47s
Release / build-windows (push) Has been cancelled
Release / build-macos (arm64, macos-latest) (push) Has been cancelled
Release / build-macos (x64, macos-15-intel) (push) Has been cancelled
Release / release-main (push) Has been cancelled
Release / release-develop (push) Has been cancelled
Add Discord-native hybrid front-end for Jarvis (bot + bridge)
Transform isair/jarvis into a Discord-controlled voice assistant running on
the Ubuntu VNC desktop, keeping the mature ~39k-line Python brain intact.

- bot/ (Node + bun, discord.js): /자비스 slash commands (ephemeral),
  voice channel join + voice receive/playback, pluggable VNC screen broadcast
  (selfbot live / noVNC / screenshot)
- bridge/ (Python, Flask): wraps jarvis STT + run_reply_engine + Piper TTS
  behind a thin localhost HTTP API
- .env.example, scripts/ (start_bridge/start_bot/dev), README rewrite,
  docs/language-comparison.md and docs/vnc-xfce-setup.md

Language decision: hybrid (Python brain + Node/bun Discord layer) because
Discord blocks bot video; native screen broadcast only works via a Node
selfbot library.
2026-06-09 14:51:05 +09:00

111 lines
3.8 KiB
Python

"""
Tests for the MCP server catalogue.
Verifies catalogue integrity, entry conversion, and wizard filtering.
"""
from desktop_app.mcp_catalogue import (
CATALOGUE,
CATALOGUE_BY_NAME,
MCPEntry,
get_wizard_entries,
)
class TestCatalogueIntegrity:
"""Tests for catalogue data integrity."""
def test_no_duplicate_names(self):
"""Every catalogue entry must have a unique name."""
names = [e.name for e in CATALOGUE]
assert len(names) == len(set(names)), (
f"Duplicate names: {[n for n in names if names.count(n) > 1]}"
)
def test_all_entries_have_required_fields(self):
"""Every entry needs name, display_name, description, command."""
for e in CATALOGUE:
assert e.name.strip(), f"Entry missing name"
assert e.display_name.strip(), f"Entry '{e.name}' missing display_name"
assert e.description.strip(), f"Entry '{e.name}' missing description"
assert e.command.strip(), f"Entry '{e.name}' missing command"
def test_api_key_entries_have_env_var(self):
"""Entries that need an API key must specify the env var name."""
for e in CATALOGUE:
if e.needs_api_key:
assert e.api_key_env_var, (
f"Entry '{e.name}' needs API key but has no api_key_env_var"
)
def test_by_name_matches_catalogue(self):
"""CATALOGUE_BY_NAME should contain exactly the same entries."""
assert len(CATALOGUE_BY_NAME) == len(CATALOGUE)
for e in CATALOGUE:
assert e.name in CATALOGUE_BY_NAME
assert CATALOGUE_BY_NAME[e.name] is e
class TestMCPEntryToConfig:
"""Tests for MCPEntry.to_config() conversion."""
def test_basic_entry(self):
entry = MCPEntry(
name="test",
display_name="Test",
description="A test server",
command="npx",
args=["-y", "@test/server"],
)
cfg = entry.to_config()
assert cfg["transport"] == "stdio"
assert cfg["command"] == "npx"
assert cfg["args"] == ["-y", "@test/server"]
assert "env" not in cfg
def test_entry_with_env(self):
entry = MCPEntry(
name="test",
display_name="Test",
description="A test server",
command="npx",
args=[],
env={"API_KEY": "secret"},
)
cfg = entry.to_config()
assert cfg["env"] == {"API_KEY": "secret"}
def test_to_config_returns_independent_copy(self):
"""Calling to_config twice should return separate dicts."""
entry = CATALOGUE[0]
a = entry.to_config()
b = entry.to_config()
assert a == b
a["args"].append("extra")
assert a != b # mutating one shouldn't affect the other
class TestWizardEntries:
"""Tests for get_wizard_entries() filtering."""
def test_only_returns_featured(self):
"""get_wizard_entries() should only return wizard_featured entries."""
entries = get_wizard_entries()
assert len(entries) > 0
for e in entries:
assert e.wizard_featured is True
def test_no_api_key_required(self):
"""Wizard entries should not require API keys (they're meant for quick setup)."""
for e in get_wizard_entries():
assert not e.needs_api_key, (
f"Wizard entry '{e.name}' requires an API key — "
"wizard entries should be zero-config"
)
def test_wizard_entries_are_subset_of_catalogue(self):
"""Every wizard entry must also exist in the full catalogue."""
wizard_names = {e.name for e in get_wizard_entries()}
catalogue_names = {e.name for e in CATALOGUE}
assert wizard_names.issubset(catalogue_names)