from unittest.mock import MagicMock import pytest from tht.adapters.vector.thoth_http import ThothHttpVectorStore from tht.ports.vector import ( VectorHit, VectorRecord, VectorStore, VectorWriteUnavailable, ) def test_http_store_reports_reader_without_writer(): reader = MagicMock() store = ThothHttpVectorStore(reader=reader, writer=None) assert store.capabilities.search is True assert store.capabilities.upsert is False with pytest.raises(VectorWriteUnavailable): store.upsert("memory", []) def test_http_store_keeps_reader_and_writer_operations_separate(): reader = MagicMock() reader.search_similar.return_value = [ { "similarity": 0.75, "metadata": { "record_key": "m1", "kind": "memory", "ref": "session:s1", "title": "Choice", "content": "Use the curated table", }, } ] writer = MagicMock() writer.existing_hashes.return_value = {"m1": "abc"} writer.upsert_records.return_value = 1 store = ThothHttpVectorStore(reader=reader, writer=writer) hits = store.search(["memory"], [0.1, 0.2], limit=3, kinds=["memory"]) assert hits == [ VectorHit( id="m1", kind="memory", ref="session:s1", title="Choice", content="Use the curated table", metadata={ "record_key": "m1", "kind": "memory", "ref": "session:s1", "title": "Choice", "content": "Use the curated table", }, similarity=0.75, ) ] reader.search_similar.assert_called_once_with( "memory", [0.1, 0.2], 3, kinds=["memory"] ) writer.search_similar.assert_not_called() assert store.existing_hashes("memory", ["memory"]) == {"m1": "abc"} writer.existing_hashes.assert_called_once_with("memory", ["memory"]) records = [ VectorRecord( id="m1", kind="memory", ref="session:s1", title="Choice", content="Use the curated table", metadata={"embedding": [0.1, 0.2], "content_hash": "abc"}, ) ] assert store.upsert("memory", records) == 1 writer.upsert_records.assert_called_once() reader.upsert_records.assert_not_called() def test_http_store_is_runtime_vector_store(): store = ThothHttpVectorStore(reader=MagicMock(), writer=None) assert isinstance(store, VectorStore) def test_http_health_uses_reader_list_tables_and_reports_failure(): reader = MagicMock() store = ThothHttpVectorStore(reader=reader, writer=None) assert store.health().ok is True reader.list_tables.side_effect = RuntimeError("offline") health = store.health() assert health.ok is False assert health.detail == "offline"