Files
wehub-resource-sync 0418dc5cf9
CI / Python tests (3.10) (push) Has been cancelled
CI / Python tests (3.11) (push) Has been cancelled
CI / Python quality (push) Has been cancelled
CI / Frontend typecheck (push) Has been cancelled
Autopilot Pages / deploy (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:45:00 +08:00

263 lines
11 KiB
Python

import json
import logging
from pathlib import Path
from typer.testing import CliRunner
from ohmo.cli import _build_gateway_logging_handlers, app
def test_ohmo_help():
runner = CliRunner()
result = runner.invoke(app, ["--help"])
assert result.exit_code == 0
assert "personal-agent app" in result.output
assert "config" in result.output
def test_ohmo_init_and_doctor(tmp_path: Path):
runner = CliRunner()
workspace = tmp_path / ".ohmo-home"
result = runner.invoke(app, ["init", "--workspace", str(workspace), "--no-interactive"])
assert result.exit_code == 0
assert str(workspace) in result.output
doctor = runner.invoke(app, ["doctor", "--cwd", str(tmp_path), "--workspace", str(workspace)])
assert doctor.exit_code == 0
assert "ohmo doctor:" in doctor.output
assert "workspace: ok" in doctor.output
def test_ohmo_init_existing_workspace_points_to_config(tmp_path: Path):
runner = CliRunner()
workspace = tmp_path / ".ohmo-home"
first = runner.invoke(app, ["init", "--workspace", str(workspace), "--no-interactive"])
assert first.exit_code == 0
second = runner.invoke(app, ["init", "--workspace", str(workspace), "--no-interactive"])
assert second.exit_code == 0
assert "ohmo workspace already exists." in second.output
assert "Use `ohmo config`" in second.output
def test_ohmo_init_noninteractive_defaults_to_deny_all_remote_access(tmp_path: Path):
runner = CliRunner()
workspace = tmp_path / ".ohmo-home"
result = runner.invoke(app, ["init", "--workspace", str(workspace), "--no-interactive"])
assert result.exit_code == 0
config = json.loads((workspace / "gateway.json").read_text(encoding="utf-8"))
assert config["channel_configs"] == {}
def test_gateway_logging_handlers_write_gateway_log_file(tmp_path: Path):
workspace = tmp_path / ".ohmo-home"
runner = CliRunner()
result = runner.invoke(app, ["init", "--workspace", str(workspace), "--no-interactive"])
assert result.exit_code == 0
handlers = _build_gateway_logging_handlers(workspace, console=True, log_file=True)
try:
file_handlers = [handler for handler in handlers if isinstance(handler, logging.FileHandler)]
console_handlers = [
handler
for handler in handlers
if isinstance(handler, logging.StreamHandler) and not isinstance(handler, logging.FileHandler)
]
assert len(file_handlers) == 1
assert len(console_handlers) == 1
record = logging.LogRecord(
name="ohmo.gateway.test",
level=logging.INFO,
pathname=__file__,
lineno=1,
msg="GATEWAY_LOG_OK",
args=(),
exc_info=None,
)
file_handlers[0].emit(record)
file_handlers[0].flush()
log_path = workspace / "logs" / "gateway.log"
assert "GATEWAY_LOG_OK" in log_path.read_text(encoding="utf-8")
finally:
for handler in handlers:
handler.close()
def test_ohmo_init_interactive_writes_gateway_config(tmp_path: Path, monkeypatch):
runner = CliRunner()
workspace = tmp_path / ".ohmo-home"
monkeypatch.setattr("sys.stdin.isatty", lambda: True)
monkeypatch.setattr("sys.stdout.isatty", lambda: True)
user_input = "\n".join(
[
"1", # provider profile
"y", # enable telegram
"123456", # allow_from
"telegram-token",
"y", # reply_to_message
"n", # slack
"n", # discord
"n", # feishu
"y", # send_progress
"y", # send_tool_hints
"n", # allow_remote_admin_commands
]
)
result = runner.invoke(app, ["init", "--workspace", str(workspace)], input=user_input)
assert result.exit_code == 0
config = json.loads((workspace / "gateway.json").read_text(encoding="utf-8"))
assert config["enabled_channels"] == ["telegram"]
assert config["channel_configs"]["telegram"]["token"] == "telegram-token"
assert config["channel_configs"]["telegram"]["allow_from"] == ["123456"]
def test_ohmo_init_interactive_allows_blank_allow_from_for_secure_default(tmp_path: Path, monkeypatch):
runner = CliRunner()
workspace = tmp_path / ".ohmo-home"
monkeypatch.setattr("sys.stdin.isatty", lambda: True)
monkeypatch.setattr("sys.stdout.isatty", lambda: True)
user_input = "\n".join(
[
"1", # provider profile
"y", # enable telegram
"", # allow_from -> deny all until explicitly configured
"telegram-token",
"y", # reply_to_message
"n", # slack
"n", # discord
"n", # feishu
"y", # send_progress
"y", # send_tool_hints
"n", # allow_remote_admin_commands
]
)
result = runner.invoke(app, ["init", "--workspace", str(workspace)], input=user_input)
assert result.exit_code == 0
config = json.loads((workspace / "gateway.json").read_text(encoding="utf-8"))
assert config["channel_configs"]["telegram"]["allow_from"] == []
assert "Remote access denied until allow_from is configured for: telegram" in result.output
def test_ohmo_init_interactive_writes_feishu_gateway_config(tmp_path: Path, monkeypatch):
runner = CliRunner()
workspace = tmp_path / ".ohmo-home"
monkeypatch.setattr("sys.stdin.isatty", lambda: True)
monkeypatch.setattr("sys.stdout.isatty", lambda: True)
user_input = "\n".join(
[
"1", # provider profile
"n", # telegram
"n", # slack
"n", # discord
"y", # feishu
"feishu-user-1", # allow_from
"1", # domain -> Feishu (China)
"cli_app", # app_id
"cli_secret",# app_secret
"enc_key", # encrypt_key
"verify_me", # verification_token
"OK", # react_emoji
"1", # group_policy -> managed_or_mention
"ohmo,openclaw", # bot_names
"", # bot_open_id
"y", # send_progress
"n", # send_tool_hints
"n", # allow_remote_admin_commands
]
)
result = runner.invoke(app, ["init", "--workspace", str(workspace)], input=user_input)
assert result.exit_code == 0
config = json.loads((workspace / "gateway.json").read_text(encoding="utf-8"))
assert config["enabled_channels"] == ["feishu"]
assert config["channel_configs"]["feishu"]["domain"] == "https://open.feishu.cn"
assert config["channel_configs"]["feishu"]["app_id"] == "cli_app"
assert config["channel_configs"]["feishu"]["app_secret"] == "cli_secret"
assert config["channel_configs"]["feishu"]["encrypt_key"] == "enc_key"
assert config["channel_configs"]["feishu"]["verification_token"] == "verify_me"
assert config["channel_configs"]["feishu"]["react_emoji"] == "OK"
assert config["channel_configs"]["feishu"]["group_policy"] == "managed_or_mention"
assert config["channel_configs"]["feishu"]["bot_names"] == ["ohmo", "openclaw"]
def test_ohmo_config_interactive_can_restart_gateway(tmp_path: Path, monkeypatch):
runner = CliRunner()
workspace = tmp_path / ".ohmo-home"
runner.invoke(app, ["init", "--workspace", str(workspace), "--no-interactive"])
monkeypatch.setattr("sys.stdin.isatty", lambda: True)
monkeypatch.setattr("sys.stdout.isatty", lambda: True)
monkeypatch.setattr("ohmo.cli.gateway_status", lambda cwd, workspace: type("State", (), {"running": True})())
monkeypatch.setattr("ohmo.cli.stop_gateway_process", lambda cwd, workspace: True)
monkeypatch.setattr("ohmo.cli.start_gateway_process", lambda cwd, workspace: 4321)
user_input = "\n".join(
[
"4", # provider profile -> codex
"n", # telegram
"n", # slack
"n", # discord
"y", # feishu
"feishu-user-1", # allow_from
"2", # domain -> Lark (International)
"cli_app", # app_id
"cli_secret", # app_secret
"", # encrypt_key
"verify_me", # verification_token
"OK", # react_emoji
"1", # group_policy -> managed_or_mention
"ohmo,openclaw", # bot_names
"", # bot_open_id
"y", # send_progress
"y", # send_tool_hints
"n", # allow_remote_admin_commands
"y", # restart gateway
]
)
result = runner.invoke(app, ["config", "--workspace", str(workspace)], input=user_input)
assert result.exit_code == 0
assert "ohmo gateway restarted (pid=4321)" in result.output
config = json.loads((workspace / "gateway.json").read_text(encoding="utf-8"))
assert config["provider_profile"] == "codex"
assert config["enabled_channels"] == ["feishu"]
assert config["channel_configs"]["feishu"]["domain"] == "https://open.larksuite.com"
def test_ohmo_config_keeps_existing_channel_when_not_reconfigured(tmp_path: Path, monkeypatch):
runner = CliRunner()
workspace = tmp_path / ".ohmo-home"
runner.invoke(app, ["init", "--workspace", str(workspace), "--no-interactive"])
gateway_path = workspace / "gateway.json"
config = json.loads(gateway_path.read_text(encoding="utf-8"))
config["enabled_channels"] = ["feishu"]
config["channel_configs"]["feishu"] = {
"allow_from": ["feishu-user-1"],
"app_id": "old_app",
"app_secret": "old_secret",
"encrypt_key": "",
"verification_token": "old_verify",
"react_emoji": "OK",
}
gateway_path.write_text(json.dumps(config, indent=2) + "\n", encoding="utf-8")
monkeypatch.setattr("sys.stdin.isatty", lambda: True)
monkeypatch.setattr("sys.stdout.isatty", lambda: True)
monkeypatch.setattr("ohmo.cli.gateway_status", lambda cwd, workspace: type("State", (), {"running": False})())
user_input = "\n".join(
[
"4", # provider profile -> codex
"n", # telegram
"n", # slack
"n", # discord
"n", # reconfigure feishu? keep existing
"y", # send_progress
"y", # send_tool_hints
"n", # allow_remote_admin_commands
]
)
result = runner.invoke(app, ["config", "--workspace", str(workspace)], input=user_input)
assert result.exit_code == 0
updated = json.loads(gateway_path.read_text(encoding="utf-8"))
assert updated["enabled_channels"] == ["feishu"]
assert updated["channel_configs"]["feishu"]["app_id"] == "old_app"
assert updated["channel_configs"]["feishu"]["app_secret"] == "old_secret"