from __future__ import annotations import base64 import pytest from pyxray.libs.nodes import NodeManager, NodeStore, parse_node_link def test_node_store_saves_nodes_and_selected_id_as_toml(tmp_path) -> None: manager = NodeManager(NodeStore(tmp_path / "nodes.toml")) result = manager.add_link(_ss_link("secret", "ss-node")) selected = manager.select_node(result.node.id) reloaded = NodeManager(NodeStore(tmp_path / "nodes.toml")) assert selected.id == result.node.id assert reloaded.selected_id() == result.node.id assert reloaded.get_selected_node() is not None assert reloaded.get_selected_node().name == "ss-node" assert "selected_id" in (tmp_path / "nodes.toml").read_text(encoding="utf-8") assert "[[nodes]]" in (tmp_path / "nodes.toml").read_text(encoding="utf-8") def test_node_manager_updates_existing_node_by_id_and_keeps_created_at(tmp_path) -> None: manager = NodeManager(NodeStore(tmp_path / "nodes.toml")) node = parse_node_link(_ss_link("secret", "first-name")) created = manager.add_node(node) same_node = parse_node_link(_ss_link("secret", "second-name")) updated = manager.add_node(same_node) nodes = manager.list_nodes() assert created.created is True assert updated.created is False assert len(nodes) == 1 assert nodes[0].name == "second-name" assert nodes[0].created_at == created.node.created_at assert nodes[0].updated_at >= nodes[0].created_at def test_node_manager_removes_selected_node_and_clears_selection(tmp_path) -> None: manager = NodeManager(NodeStore(tmp_path / "nodes.toml")) result = manager.add_link(_ss_link("secret", "ss-node")) manager.select_node(result.node.id) assert manager.remove_node(result.node.id) is True assert manager.list_nodes() == [] assert manager.selected_id() == "" assert manager.get_selected_node() is None def test_node_manager_rejects_unknown_selection(tmp_path) -> None: manager = NodeManager(NodeStore(tmp_path / "nodes.toml")) with pytest.raises(ValueError, match="node does not exist"): manager.select_node("missing") def test_node_manager_imports_valid_links_and_returns_invalid_results(tmp_path) -> None: manager = NodeManager(NodeStore(tmp_path / "nodes.toml")) results = manager.import_links(f"bad://example\n{_ss_link('secret', 'ss-node')}\n") assert [result.ok for result in results] == [False, True] assert len(manager.list_nodes()) == 1 assert manager.list_nodes()[0].name == "ss-node" def _ss_link(password: str, name: str) -> str: user = base64.urlsafe_b64encode(f"chacha20-ietf-poly1305:{password}".encode()).decode().rstrip("=") return f"ss://{user}@ss.example.net:8388#{name}"