summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/tests/test_wizard_apps_endpoint.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-node/tests/test_wizard_apps_endpoint.py')
-rw-r--r--packages/meshbay-node/tests/test_wizard_apps_endpoint.py76
1 files changed, 76 insertions, 0 deletions
diff --git a/packages/meshbay-node/tests/test_wizard_apps_endpoint.py b/packages/meshbay-node/tests/test_wizard_apps_endpoint.py
new file mode 100644
index 0000000..10ab489
--- /dev/null
+++ b/packages/meshbay-node/tests/test_wizard_apps_endpoint.py
@@ -0,0 +1,76 @@
+"""
+Create Group wizard: choosing which apps a brand-new group offers, before
+the (potentially long) initial scan — see app.js's CreateGroupWizard. This
+is a loopback-only, operator-authenticated endpoint (11.5.3), same shape as
+the existing member-upload one: a thin adapter over `ops.set_enabled_apps`,
+with only the validation `_do_apps_enabled` (the signed MNP front door)
+already does client-side in the wizard, but worth enforcing at this front
+door too since nothing else would.
+"""
+
+from pathlib import Path
+
+import pytest
+from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
+from fastapi.testclient import TestClient
+
+from conftest import one_root
+from meshbay_node.indexer.group_index import GroupIndex
+from meshbay_node.roster import Roster
+from meshbay_node.ui.app import create_ui_app
+
+pytestmark = pytest.mark.asyncio
+
+
+async def _client(tmp_path: Path):
+ shared = tmp_path / "shared"
+ shared.mkdir(exist_ok=True)
+ index = GroupIndex(group_id="g" * 32, sk_node=Ed25519PrivateKey.generate())
+ roster = Roster(db_path=tmp_path / "roster.db")
+ await roster.open()
+ state = {
+ "status": "running",
+ "groups_ctx": {"g" * 32: {"index": index, "roots": one_root(shared)}},
+ "indexes": {"g" * 32: index},
+ "roster": roster,
+ }
+ app = create_ui_app(state)
+ return TestClient(app), roster
+
+
+async def test_narrowing_the_apps_persists_to_the_roster(tmp_path):
+ client, roster = await _client(tmp_path)
+ try:
+ resp = client.put(f"/api/groups/{'g' * 32}/apps", json={"apps": ["files", "video"]})
+ assert resp.status_code == 200, resp.text
+ assert sorted(resp.json()["apps"]) == ["files", "video"]
+ assert sorted(await roster.enabled_apps("g" * 32)) == ["files", "video"]
+ finally:
+ await roster.close()
+
+
+async def test_empty_apps_list_is_refused(tmp_path):
+ client, roster = await _client(tmp_path)
+ try:
+ resp = client.put(f"/api/groups/{'g' * 32}/apps", json={"apps": []})
+ assert resp.status_code == 400
+ finally:
+ await roster.close()
+
+
+async def test_missing_apps_field_is_refused(tmp_path):
+ client, roster = await _client(tmp_path)
+ try:
+ resp = client.put(f"/api/groups/{'g' * 32}/apps", json={})
+ assert resp.status_code == 400
+ finally:
+ await roster.close()
+
+
+async def test_unhosted_group_is_refused(tmp_path):
+ client, roster = await _client(tmp_path)
+ try:
+ resp = client.put("/api/groups/" + "z" * 32 + "/apps", json={"apps": ["files"]})
+ assert resp.status_code == 404
+ finally:
+ await roster.close()