test: add tests for shortest_path and path_explanation
This commit is contained in:
106
nexus/mnemosyne/tests/test_path.py
Normal file
106
nexus/mnemosyne/tests/test_path.py
Normal file
@@ -0,0 +1,106 @@
|
||||
"""Tests for MnemosyneArchive.shortest_path and path_explanation."""
|
||||
|
||||
from nexus.mnemosyne.archive import MnemosyneArchive
|
||||
from nexus.mnemosyne.entry import ArchiveEntry
|
||||
|
||||
|
||||
def _make_archive(tmp_path):
|
||||
archive = MnemosyneArchive(str(tmp_path / "test_archive.json"))
|
||||
return archive
|
||||
|
||||
|
||||
class TestShortestPath:
|
||||
def test_direct_connection(self, tmp_path):
|
||||
archive = _make_archive(tmp_path)
|
||||
a = archive.add("Alpha", "first entry", topics=["start"])
|
||||
b = archive.add("Beta", "second entry", topics=["end"])
|
||||
# Manually link
|
||||
a.links.append(b.id)
|
||||
b.links.append(a.id)
|
||||
archive._entries[a.id] = a
|
||||
archive._entries[b.id] = b
|
||||
archive._save()
|
||||
|
||||
path = archive.shortest_path(a.id, b.id)
|
||||
assert path == [a.id, b.id]
|
||||
|
||||
def test_multi_hop_path(self, tmp_path):
|
||||
archive = _make_archive(tmp_path)
|
||||
a = archive.add("A", "alpha", topics=["x"])
|
||||
b = archive.add("B", "beta", topics=["y"])
|
||||
c = archive.add("C", "gamma", topics=["z"])
|
||||
# Chain: A -> B -> C
|
||||
a.links.append(b.id)
|
||||
b.links.extend([a.id, c.id])
|
||||
c.links.append(b.id)
|
||||
archive._entries[a.id] = a
|
||||
archive._entries[b.id] = b
|
||||
archive._entries[c.id] = c
|
||||
archive._save()
|
||||
|
||||
path = archive.shortest_path(a.id, c.id)
|
||||
assert path == [a.id, b.id, c.id]
|
||||
|
||||
def test_no_path(self, tmp_path):
|
||||
archive = _make_archive(tmp_path)
|
||||
a = archive.add("A", "isolated", topics=[])
|
||||
b = archive.add("B", "also isolated", topics=[])
|
||||
path = archive.shortest_path(a.id, b.id)
|
||||
assert path is None
|
||||
|
||||
def test_same_entry(self, tmp_path):
|
||||
archive = _make_archive(tmp_path)
|
||||
a = archive.add("A", "lonely", topics=[])
|
||||
path = archive.shortest_path(a.id, a.id)
|
||||
assert path == [a.id]
|
||||
|
||||
def test_nonexistent_entry(self, tmp_path):
|
||||
archive = _make_archive(tmp_path)
|
||||
a = archive.add("A", "exists", topics=[])
|
||||
path = archive.shortest_path("fake-id", a.id)
|
||||
assert path is None
|
||||
|
||||
def test_shortest_of_multiple(self, tmp_path):
|
||||
"""When multiple paths exist, BFS returns shortest."""
|
||||
archive = _make_archive(tmp_path)
|
||||
a = archive.add("A", "a", topics=[])
|
||||
b = archive.add("B", "b", topics=[])
|
||||
c = archive.add("C", "c", topics=[])
|
||||
d = archive.add("D", "d", topics=[])
|
||||
# A -> B -> D (short)
|
||||
# A -> C -> B -> D (long)
|
||||
a.links.extend([b.id, c.id])
|
||||
b.links.extend([a.id, d.id, c.id])
|
||||
c.links.extend([a.id, b.id])
|
||||
d.links.append(b.id)
|
||||
for e in [a, b, c, d]:
|
||||
archive._entries[e.id] = e
|
||||
archive._save()
|
||||
|
||||
path = archive.shortest_path(a.id, d.id)
|
||||
assert len(path) == 3 # A -> B -> D, not A -> C -> B -> D
|
||||
|
||||
|
||||
class TestPathExplanation:
|
||||
def test_returns_step_details(self, tmp_path):
|
||||
archive = _make_archive(tmp_path)
|
||||
a = archive.add("Alpha", "the beginning", topics=["origin"])
|
||||
b = archive.add("Beta", "the middle", topics=["process"])
|
||||
a.links.append(b.id)
|
||||
b.links.append(a.id)
|
||||
archive._entries[a.id] = a
|
||||
archive._entries[b.id] = b
|
||||
archive._save()
|
||||
|
||||
path = [a.id, b.id]
|
||||
steps = archive.path_explanation(path)
|
||||
assert len(steps) == 2
|
||||
assert steps[0]["title"] == "Alpha"
|
||||
assert steps[1]["title"] == "Beta"
|
||||
assert "origin" in steps[0]["topics"]
|
||||
|
||||
def test_content_preview_truncation(self, tmp_path):
|
||||
archive = _make_archive(tmp_path)
|
||||
a = archive.add("A", "x" * 200, topics=[])
|
||||
steps = archive.path_explanation([a.id])
|
||||
assert len(steps[0]["content_preview"]) <= 123 # 120 + "..."
|
||||
Reference in New Issue
Block a user