summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/tests/test_cli_dispatch.py
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-24 17:42:10 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-24 17:58:08 +0200
commitef942b93d1e9bfc28bf607dfaf501cc7d9685e7b (patch)
tree644ffc1884d506036a279f7f19a2d302f45d9064 /packages/meshbay-node/tests/test_cli_dispatch.py
parentdf6fafa76b0eec167fa1fa18a40632c2e95181ff (diff)
downloadmeshbay-ef942b93d1e9bfc28bf607dfaf501cc7d9685e7b.tar.gz
test(node): read the daemon's source wherever it is split
Tests that read daemon.py now take their text from node_source (daemon.py, NodeDaemon's bases, the cli package once it exists). The CLI tests that sliced main() run the CLI instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-node/tests/test_cli_dispatch.py')
-rw-r--r--packages/meshbay-node/tests/test_cli_dispatch.py51
1 files changed, 32 insertions, 19 deletions
diff --git a/packages/meshbay-node/tests/test_cli_dispatch.py b/packages/meshbay-node/tests/test_cli_dispatch.py
index a0b2a64..d73dfcf 100644
--- a/packages/meshbay-node/tests/test_cli_dispatch.py
+++ b/packages/meshbay-node/tests/test_cli_dispatch.py
@@ -13,10 +13,12 @@ is tested in `test_ops.py` and `test_roster_pairing.py`. What this catches is a
branch nobody ever ran.
"""
+import re
import sys
import pytest
from meshbay_node import daemon as daemon_mod
+from node_source import cli_source
# Each verb, with the arguments that reach its branch. `--yes` where the command
# would otherwise stop for a confirmation nobody can type in a test.
@@ -151,18 +153,22 @@ def test_every_verb_reaches_its_branch(argv, stub_daemon, monkeypatch, capsys):
assert out.out or out.err, f"{' '.join(argv)} printed nothing at all"
-def test_the_verb_list_here_matches_the_parser():
+def test_the_verb_list_here_matches_the_parser(monkeypatch, capsys):
"""
A verb added to the parser and not to this file would go untested, which is
exactly how `reload` shipped broken.
- """
- import inspect
- source = inspect.getsource(daemon_mod.main)
- start = source.index('choices=[') + len('choices=[')
- end = source.index(']', start)
- declared = {c.strip().strip('"\'') for c in source[start:end].split(',')
- if c.strip()}
+ The verbs are read from what `--help` prints, not from the source, so this
+ holds wherever the parser is built.
+ """
+ monkeypatch.setattr(sys, "argv", ["meshbay-node", "--help"])
+ with pytest.raises(SystemExit):
+ daemon_mod.main()
+ usage = capsys.readouterr().out
+ groups = [g for g in re.findall(r"\{([\w,-]+)\}", usage)
+ if "status" in g.split(",")]
+ assert groups, "--help no longer lists the verbs as {a,b,…}"
+ declared = set(groups[0].split(","))
exercised = {argv[0] for argv in VERBS}
# `init` writes a config file and `calibrate-argon2` burns CPU for seconds;
@@ -262,7 +268,7 @@ def test_a_bare_invocation_with_no_config_yet_exits_cleanly(monkeypatch, tmp_pat
"a fresh, unprovisioned start must not create anything on disk")
-def test_a_removed_verb_says_what_replaced_it():
+def test_a_removed_verb_says_what_replaced_it(stub_daemon, monkeypatch, capsys):
"""
`member upload` used to set a group-wide switch that no longer exists. It
reached the usage line for the *other* member verbs — "usage: meshbay-node
@@ -272,20 +278,20 @@ def test_a_removed_verb_says_what_replaced_it():
Naming it costs three lines and is the difference between an operator
finding `root set --writable` and concluding the CLI is broken.
"""
- import inspect
- source = inspect.getsource(daemon_mod.main)
- start = source.index('if args.command == "member":')
- block = source[start:source.index('if args.command == "group":', start)]
+ monkeypatch.setattr(sys, "argv", ["meshbay-node", "member", "upload"])
+ with pytest.raises(SystemExit) as exc:
+ daemon_mod.main()
+ assert exc.value.code == 1
+ guidance = capsys.readouterr().out
- assert 'sub == "upload"' in block, (
+ assert "usage: meshbay-node member upload" not in guidance, (
"`member upload` falls through to the generic usage line")
- guidance = block[block.index('sub == "upload"'):]
- guidance = guidance[:guidance.index("sys.exit")]
assert "root set" in guidance and "--writable" in guidance, (
"the message does not name what replaced it")
-def test_there_is_no_way_to_create_a_group_in_the_old_shape():
+def test_there_is_no_way_to_create_a_group_in_the_old_shape(
+ stub_daemon, monkeypatch, capsys):
"""
`--upload-dir` is gone, and documenting it as deprecated was the wrong
answer — which is what it got at first.
@@ -301,9 +307,16 @@ def test_there_is_no_way_to_create_a_group_in_the_old_shape():
only legitimate use. Writing it does not.
"""
import inspect
- source = inspect.getsource(daemon_mod.main)
- assert "--upload-dir" not in source, (
+ assert "--upload-dir" not in cli_source(), (
"the CLI can still create a group in the pre-RO/RW shape")
+ # With the daemon stubbed: a parser that accepted the flag would otherwise
+ # go on and add the group on whatever node answers the loopback API.
+ monkeypatch.setattr(sys, "argv", ["meshbay-node", "group", "add", "g",
+ "--dir", "/tmp/a", "--upload-dir", "/tmp/b"])
+ with pytest.raises(SystemExit) as exc:
+ daemon_mod.main()
+ assert exc.value.code == 2, "the parser accepts --upload-dir"
+ assert "--upload-dir" in capsys.readouterr().err
from meshbay_node import ops
params = inspect.signature(ops.attach_group).parameters