"""Unit tests for devx.utils.json_registry.""" from __future__ import annotations from pathlib import Path import pytest from devx.utils.json_registry import JsonRegistry class TestJsonRegistry: def test_add_and_get(self, tmp_path: Path) -> None: reg = JsonRegistry(tmp_path / "state.json") reg.add("item1", host="10.0.0.1", user="deploy") info = reg.get("item1") assert info is not None assert info["host"] == "10.0.0.1" assert info["user"] == "deploy" assert "created_at" in info def test_get_nonexistent(self, tmp_path: Path) -> None: reg = JsonRegistry(tmp_path / "state.json") assert reg.get("nope") is None def test_remove(self, tmp_path: Path) -> None: reg = JsonRegistry(tmp_path / "state.json") reg.add("item1", host="10.0.0.1") reg.remove("item1") assert reg.get("item1") is None def test_remove_nonexistent_is_noop(self, tmp_path: Path) -> None: reg = JsonRegistry(tmp_path / "state.json") reg.remove("nonexistent") # should not raise def test_list(self, tmp_path: Path) -> None: reg = JsonRegistry(tmp_path / "state.json") reg.add("a", host="1.1.1.1") reg.add("b", host="2.2.2.2") items = reg.list() assert set(items.keys()) == {"a", "b"} assert items["a"]["host"] == "1.1.1.1" def test_list_empty(self, tmp_path: Path) -> None: reg = JsonRegistry(tmp_path / "state.json") assert reg.list() == {} def test_update_existing(self, tmp_path: Path) -> None: reg = JsonRegistry(tmp_path / "state.json") reg.add("item", host="1.1.1.1", status="active") reg.update("item", status="inactive") info = reg.get("item") assert info["status"] == "inactive" assert info["host"] == "1.1.1.1" # unchanged def test_update_nonexistent_raises(self, tmp_path: Path) -> None: reg = JsonRegistry(tmp_path / "state.json") with pytest.raises(KeyError): reg.update("nonexistent", host="1.1.1.1") def test_update_skips_none_values(self, tmp_path: Path) -> None: reg = JsonRegistry(tmp_path / "state.json") reg.add("item", host="1.1.1.1") reg.update("item", host=None, status="active") info = reg.get("item") assert info["host"] == "1.1.1.1" # not overwritten by None assert info["status"] == "active" def test_persistence_across_instances(self, tmp_path: Path) -> None: path = tmp_path / "state.json" reg1 = JsonRegistry(path) reg1.add("item", host="10.0.0.1") reg2 = JsonRegistry(path) info = reg2.get("item") assert info is not None assert info["host"] == "10.0.0.1" def test_overwrite_existing(self, tmp_path: Path) -> None: reg = JsonRegistry(tmp_path / "state.json") reg.add("item", host="1.1.1.1") reg.add("item", host="2.2.2.2") info = reg.get("item") assert info["host"] == "2.2.2.2" def test_corrupt_json_returns_empty(self, tmp_path: Path) -> None: path = tmp_path / "state.json" path.write_text("{invalid json") reg = JsonRegistry(path) assert reg.list() == {} def test_nonexistent_file_returns_empty(self, tmp_path: Path) -> None: reg = JsonRegistry(tmp_path / "nonexistent.json") assert reg.list() == {} def test_creates_parent_dirs(self, tmp_path: Path) -> None: path = tmp_path / "subdir" / "deeper" / "state.json" reg = JsonRegistry(path) reg.add("item", host="1.1.1.1") assert path.exists() def test_get_returns_copy(self, tmp_path: Path) -> None: reg = JsonRegistry(tmp_path / "state.json") reg.add("item", host="1.1.1.1", tags=["a", "b"]) info = reg.get("item") assert info is not None info["tags"].append("c") # Original should be unchanged info2 = reg.get("item") assert info2 is not None assert info2["tags"] == ["a", "b"]