Files
hermes-agent/tests/hermes_cli/test_update_channel_stable.py
ethernet 0533b03268 test: update flows resolve their channel locally; desktop checks get real deps
Every unflagged `hermes update` resolves its channel through R2 now, so the
mocked update harnesses reached the network (and 404 today). An autouse
fixture in tests/hermes_cli defaults every channel to a source-branch record
through the documented `_resolve_channel` seam; archive/transport tests keep
the real reader via the `real_release_channels` marker. The stable-identity
test pins the channel's commit through that seam instead of the retired
release-candidates pointer, and the completion-process fixture ships
source_completion.py in its NEW tree.

Desktop: js-tests installs the dev extra (the electron contracts drive real
hermes_cli/pm code through HERMES_PYTHON); the source-backend fixture runs PM's
worker on PM's staged runtime; async canImportHermesCli is awaited; the
feature-flag test pins the platform rule; a mocked profile store exports what
settings-scope reads; the peer-device e2e imports the mock-provider helpers
from tests-js like its siblings.
2026-09-19 03:28:27 -04:00

69 lines
2.7 KiB
Python

"""Source-update channel selection policy."""
import json
from unittest.mock import patch
import pytest
from hermes_cli.update_cmd import _source_update_channel
class _Args:
def __init__(self, branch=None, channel=None):
self.branch = branch
self.channel = channel
class TestSourceUpdateChannel:
def test_explicit_branch_always_wins(self):
"""--branch means main-style behavior regardless of channel config."""
assert _source_update_channel(_Args(branch="bb/gui", channel="stable")) == "main"
assert _source_update_channel(channel="canary", branch_explicit=True) == "main"
def test_transient_channel_flag_wins(self):
"""--channel is the per-invocation override (--set-channel persists);
no config read happens when it is present."""
with patch("hermes_cli.config.require_readable_config_before_write") as load_config:
for channel in ("stable", "main", "canary"):
assert _source_update_channel(_Args(channel=channel)) == channel
assert _source_update_channel(channel=channel) == channel
load_config.assert_not_called()
def test_per_install_record_activates(self, tmp_path, monkeypatch):
from hermes_cli.update_channel import install_id
root = tmp_path / "install"
root.mkdir()
(root / "install-stamp.json").write_text(
'{"schemaVersion": 2, "updateMechanism": "self"}'
)
config = {
"update": {"installs": {install_id(root): {"path": str(root), "channel": "stable"}}}
}
import hermes_cli.update_cmd as update_cmd
monkeypatch.setattr(update_cmd._m(), "PROJECT_ROOT", root)
home = tmp_path / "home"
home.mkdir()
monkeypatch.setenv("HERMES_HOME", str(home))
(home / "config.yaml").write_text(json.dumps(config), encoding="utf-8")
assert _source_update_channel(_Args()) == "stable"
def test_no_record_stays_main(self, tmp_path, monkeypatch):
root = tmp_path / "install"
root.mkdir()
(root / "install-stamp.json").write_text(
'{"schemaVersion": 2, "updateMechanism": "self"}'
)
import hermes_cli.update_cmd as update_cmd
monkeypatch.setattr(update_cmd._m(), "PROJECT_ROOT", root)
monkeypatch.setenv("HERMES_HOME", str(tmp_path / "home"))
assert _source_update_channel(_Args()) == "main"
def test_config_failure_never_changes_the_subscription(self, tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
(tmp_path / "config.yaml").write_text("update: [broken", encoding="utf-8")
with pytest.raises(RuntimeError, match="formatting error"):
_source_update_channel(_Args())