nanobot/tests/cli/test_extensions.py
2026-07-26 21:19:29 +08:00

119 lines
3.7 KiB
Python

from __future__ import annotations
from io import StringIO
from rich.console import Console
from typer.testing import CliRunner
from nanobot.cli.extensions import create_extensions_app
class _Service:
def __init__(self) -> None:
self.calls: list[tuple[str, object]] = []
async def status(self):
self.calls.append(("status", None))
return {
"extensions": [
{
"id": "sample",
"name": "Sample",
"version": "1.0.0",
"runtime": "pi",
"scope": "user",
"description": "Example extension",
"enabled": True,
"trusted": False,
"active": False,
"contributions": [],
"dependencies": [],
"permissions": [{"name": "network", "reason": "Fetch data"}],
"granted_permissions": [],
}
],
"diagnostics": [],
}
async def search(self, query, *, ecosystem, limit):
self.calls.append(("search", (query, ecosystem, limit)))
return {"packages": []}
async def install(self, source, *, kind, ref, trusted):
self.calls.append(("install", (source, kind, ref, trusted)))
return {
"record": {
"id": "sample",
"version": "1.0.0",
"trusted": trusted,
}
}
async def set_enabled(self, extension_id, enabled):
self.calls.append(("enabled", (extension_id, enabled)))
return {"record": {"id": extension_id}}
async def set_trusted(self, extension_id, trusted):
self.calls.append(("trusted", (extension_id, trusted)))
return {"record": {"id": extension_id}}
async def set_permissions(self, extension_id, permissions):
self.calls.append(("permissions", (extension_id, permissions)))
return {
"record": {
"id": extension_id,
"granted_permissions": sorted(permissions),
}
}
async def uninstall(self, extension_id):
self.calls.append(("uninstall", extension_id))
return {"removed": extension_id}
def _runner(service: _Service):
output = StringIO()
app = create_extensions_app(
console=Console(file=output, force_terminal=False),
service_factory=lambda: service,
)
return CliRunner(), app, output
def test_extension_cli_inspects_and_searches() -> None:
service = _Service()
runner, app, output = _runner(service)
inspected = runner.invoke(app, ["inspect", "sample"])
searched = runner.invoke(app, ["search", "web", "--ecosystem", "pi", "--limit", "7"])
assert inspected.exit_code == 0
assert searched.exit_code == 0
assert "Sample" in output.getvalue()
assert service.calls == [
("status", None),
("search", ("web", "pi", 7)),
]
def test_extension_cli_install_and_policy_commands() -> None:
service = _Service()
runner, app, _output = _runner(service)
assert runner.invoke(app, ["install", "pi-example"]).exit_code == 0
assert runner.invoke(app, ["trust", "sample"]).exit_code == 0
assert runner.invoke(app, ["disable", "sample"]).exit_code == 0
assert runner.invoke(
app,
["permissions", "sample", "network", "filesystem.read"],
).exit_code == 0
assert runner.invoke(app, ["uninstall", "sample", "--yes"]).exit_code == 0
assert service.calls == [
("install", ("pi-example", "npm", "", False)),
("trusted", ("sample", True)),
("enabled", ("sample", False)),
("permissions", ("sample", {"network", "filesystem.read"})),
("uninstall", "sample"),
]