"""Unit tests for plugin-contributed sidebar nav collection.""" import types from steward.core import plugin_manager as pm def _mod(nav): """A stand-in plugin module; omit get_nav by passing nav=None.""" m = types.SimpleNamespace() if nav is not None: m.get_nav = lambda: nav return m def test_collect_and_get(monkeypatch): monkeypatch.setattr(pm, "_PLUGIN_NAV", []) pm._collect_plugin_nav("docker", _mod([{"label": "Docker", "href": "/plugins/docker/"}])) assert pm.get_plugin_nav() == [ {"plugin": "docker", "label": "Docker", "href": "/plugins/docker/", "section": "Infrastructure"} ] def test_missing_hook_is_noop(monkeypatch): monkeypatch.setattr(pm, "_PLUGIN_NAV", []) pm._collect_plugin_nav("x", _mod(None)) assert pm.get_plugin_nav() == [] def test_reload_replaces_same_plugin_entries(monkeypatch): monkeypatch.setattr(pm, "_PLUGIN_NAV", []) pm._collect_plugin_nav("docker", _mod([{"label": "Docker", "href": "/old"}])) pm._collect_plugin_nav("docker", _mod([{"label": "Docker", "href": "/new"}])) assert [e["href"] for e in pm.get_plugin_nav() if e["plugin"] == "docker"] == ["/new"] def test_malformed_item_skipped(monkeypatch): monkeypatch.setattr(pm, "_PLUGIN_NAV", []) pm._collect_plugin_nav("x", _mod([{"label": "NoHref"}, {"label": "Ok", "href": "/ok"}])) assert [e["href"] for e in pm.get_plugin_nav()] == ["/ok"] def test_raising_hook_skipped(monkeypatch): monkeypatch.setattr(pm, "_PLUGIN_NAV", []) def boom(): raise RuntimeError("nope") pm._collect_plugin_nav("x", types.SimpleNamespace(get_nav=boom)) assert pm.get_plugin_nav() == [] def test_get_plugin_nav_sorted_by_section_then_label(monkeypatch): monkeypatch.setattr(pm, "_PLUGIN_NAV", []) pm._collect_plugin_nav("traefik", _mod([{"label": "Traefik", "href": "/t"}])) pm._collect_plugin_nav("docker", _mod([{"label": "Docker", "href": "/d"}])) # Same default section → sorted by label. assert [e["label"] for e in pm.get_plugin_nav()] == ["Docker", "Traefik"]