feat(webui): add guided setup flows
* feat(channels): add guided setup flows * test(channels): preserve setup config values * fix(channels): reflect saved setup state * refactor(channels): simplify setup state metadata * fix(channels): harden setup lifecycle * refactor(channels): centralize setup contracts * fix(channels): route setup actions through webui shim * fix(channels): adapt settings for compact screens * fix(models): preserve default preset display * feat(models): add curated Codex catalog * fix(webui): stop attached gateway on interrupt * fix(webui): simplify apps catalog * docs(webui): clarify apps and runtime features * feat(settings): add guided capability setup * fix(webui): harden setup and managed services * test: keep managed runtime checks portable * test: scope POSIX runtime coverage * fix(webui): simplify file settings * feat(files): bundle document reading * fix(webui): harden setup request boundaries * fix(webui): prevent channel setup status squeeze * fix(settings): group provider compatibility aliases * refactor(settings): remove redundant setup surfaces * fix(webui): harden guided setup lifecycle * fix(webui): preserve channel setup compatibility
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
from nanobot.channels._setup import channel_setup_spec
|
||||
|
||||
|
||||
def test_channel_setup_spec_derives_route_and_secret_metadata() -> None:
|
||||
slack = channel_setup_spec("slack")
|
||||
|
||||
assert slack is not None
|
||||
assert slack.secrets == {"appToken", "botToken"}
|
||||
assert slack.route_field_types == {
|
||||
"appToken": "secret",
|
||||
"botToken": "secret",
|
||||
"groupPolicy": ("enum", {"mention", "open", "allowlist"}),
|
||||
}
|
||||
assert slack.simple_required_fields == ("appToken", "botToken")
|
||||
|
||||
|
||||
def test_matrix_setup_requires_one_complete_login_method() -> None:
|
||||
matrix = channel_setup_spec("matrix")
|
||||
|
||||
assert matrix is not None
|
||||
base = {
|
||||
"homeserver": "https://matrix.example",
|
||||
"userId": "@nanobot:matrix.example",
|
||||
}
|
||||
assert matrix.is_configured(base | {"password": "secret"})
|
||||
assert matrix.is_configured(base | {"accessToken": "token", "deviceId": "DEVICE"})
|
||||
assert not matrix.is_configured(base | {"accessToken": "token"})
|
||||
|
||||
|
||||
def test_channel_setup_spec_separates_writable_and_snapshot_fields() -> None:
|
||||
matrix = channel_setup_spec("matrix")
|
||||
discord = channel_setup_spec("discord")
|
||||
|
||||
assert matrix is not None
|
||||
assert discord is not None
|
||||
assert "allowFrom" not in matrix.route_field_types
|
||||
assert "allowFrom" in matrix.snapshot_fields
|
||||
assert "allowFrom" in discord.route_field_types
|
||||
assert "allowFrom" not in discord.snapshot_fields
|
||||
|
||||
|
||||
def test_webui_forms_have_writable_mattermost_and_whatsapp_contracts() -> None:
|
||||
mattermost = channel_setup_spec("mattermost")
|
||||
whatsapp = channel_setup_spec("whatsapp")
|
||||
|
||||
assert mattermost is not None
|
||||
assert whatsapp is not None
|
||||
assert mattermost.route_field_types["serverUrl"] == "string"
|
||||
assert mattermost.route_field_types["token"] == "secret"
|
||||
assert whatsapp.route_field_types["allowFrom"] == "list"
|
||||
assert whatsapp.route_field_types["groupPolicy"] == (
|
||||
"enum",
|
||||
{"mention", "open"},
|
||||
)
|
||||
Reference in New Issue
Block a user