test_storage.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. """
  2. Tests for the person storage layer.
  3. """
  4. from __future__ import annotations
  5. import asyncio
  6. import os
  7. import tempfile
  8. from pathlib import Path
  9. import pytest
  10. from src.astro_mcp import storage
  11. @pytest.fixture
  12. def tmp_db(tmp_path, monkeypatch):
  13. """Use a temporary database for each test."""
  14. db_path = tmp_path / "test_astro.sqlite3"
  15. monkeypatch.setattr(storage, "DB_PATH", db_path)
  16. storage._initialized = False # Reset init state
  17. yield db_path
  18. storage._initialized = False # Cleanup
  19. class TestAddPerson:
  20. def test_add_person(self, tmp_db):
  21. result = asyncio.run(storage.add_person(
  22. name="Test Person",
  23. birth_datetime="2000-01-01T12:00:00Z",
  24. latitude=47.0,
  25. longitude=8.0,
  26. ))
  27. assert result["name"] == "Test Person"
  28. assert result["birth_datetime"] == "2000-01-01T12:00:00Z"
  29. assert result["latitude"] == 47.0
  30. assert result["longitude"] == 8.0
  31. assert result["elevation"] == 0.0
  32. assert "id" in result
  33. assert "created_at" in result
  34. def test_add_person_with_nickname(self, tmp_db):
  35. result = asyncio.run(storage.add_person(
  36. name="Test Person",
  37. birth_datetime="2000-01-01T12:00:00Z",
  38. latitude=47.0,
  39. longitude=8.0,
  40. nickname="testy",
  41. ))
  42. assert result["nickname"] == "testy"
  43. def test_add_person_with_elevation(self, tmp_db):
  44. result = asyncio.run(storage.add_person(
  45. name="Test Person",
  46. birth_datetime="2000-01-01T12:00:00Z",
  47. latitude=47.0,
  48. longitude=8.0,
  49. elevation=500.0,
  50. ))
  51. assert result["elevation"] == 500.0
  52. class TestGetPerson:
  53. def test_get_by_id(self, tmp_db):
  54. added = asyncio.run(storage.add_person(
  55. name="Test Person",
  56. birth_datetime="2000-01-01T12:00:00Z",
  57. latitude=47.0,
  58. longitude=8.0,
  59. ))
  60. fetched = asyncio.run(storage.get_person(person_id=added["id"]))
  61. assert fetched is not None
  62. assert fetched["id"] == added["id"]
  63. assert fetched["name"] == "Test Person"
  64. def test_get_by_nickname(self, tmp_db):
  65. asyncio.run(storage.add_person(
  66. name="Test Person",
  67. birth_datetime="2000-01-01T12:00:00Z",
  68. latitude=47.0,
  69. longitude=8.0,
  70. nickname="testy",
  71. ))
  72. fetched = asyncio.run(storage.get_person(nickname="testy"))
  73. assert fetched is not None
  74. assert fetched["nickname"] == "testy"
  75. def test_get_not_found(self, tmp_db):
  76. result = asyncio.run(storage.get_person(person_id="nonexistent"))
  77. assert result is None
  78. def test_get_no_params(self, tmp_db):
  79. result = asyncio.run(storage.get_person())
  80. assert result is None
  81. class TestListPersons:
  82. def test_empty_list(self, tmp_db):
  83. result = asyncio.run(storage.list_persons())
  84. assert result == []
  85. def test_list_persons(self, tmp_db):
  86. for i in range(3):
  87. asyncio.run(storage.add_person(
  88. name=f"Person {i}",
  89. birth_datetime="2000-01-01T12:00:00Z",
  90. latitude=47.0,
  91. longitude=8.0,
  92. ))
  93. result = asyncio.run(storage.list_persons())
  94. assert len(result) == 3
  95. def test_list_ordered_newest_first(self, tmp_db):
  96. for i in range(3):
  97. asyncio.run(storage.add_person(
  98. name=f"Person {i}",
  99. birth_datetime="2000-01-01T12:00:00Z",
  100. latitude=47.0,
  101. longitude=8.0,
  102. ))
  103. result = asyncio.run(storage.list_persons())
  104. # Newest first
  105. assert result[0]["name"] == "Person 2"
  106. assert result[-1]["name"] == "Person 0"
  107. class TestUpdatePerson:
  108. def test_update_name(self, tmp_db):
  109. added = asyncio.run(storage.add_person(
  110. name="Original",
  111. birth_datetime="2000-01-01T12:00:00Z",
  112. latitude=47.0,
  113. longitude=8.0,
  114. ))
  115. updated = asyncio.run(storage.update_person(
  116. person_id=added["id"],
  117. name="Updated",
  118. ))
  119. assert updated is not None
  120. assert updated["name"] == "Updated"
  121. assert updated["updated_at"] is not None
  122. def test_update_birth_data(self, tmp_db):
  123. added = asyncio.run(storage.add_person(
  124. name="Test",
  125. birth_datetime="2000-01-01T12:00:00Z",
  126. latitude=47.0,
  127. longitude=8.0,
  128. ))
  129. updated = asyncio.run(storage.update_person(
  130. person_id=added["id"],
  131. birth_datetime="1995-06-15T08:30:00Z",
  132. latitude=52.0,
  133. longitude=13.0,
  134. ))
  135. assert updated["birth_datetime"] == "1995-06-15T08:30:00Z"
  136. assert updated["latitude"] == 52.0
  137. assert updated["longitude"] == 13.0
  138. def test_update_not_found(self, tmp_db):
  139. result = asyncio.run(storage.update_person(
  140. person_id="nonexistent",
  141. name="Updated",
  142. ))
  143. assert result is None
  144. def test_update_no_fields_returns_unchanged(self, tmp_db):
  145. added = asyncio.run(storage.add_person(
  146. name="Test",
  147. birth_datetime="2000-01-01T12:00:00Z",
  148. latitude=47.0,
  149. longitude=8.0,
  150. ))
  151. updated = asyncio.run(storage.update_person(person_id=added["id"]))
  152. assert updated is not None
  153. assert updated["name"] == "Test" # Unchanged
  154. class TestDeletePerson:
  155. def test_delete_person(self, tmp_db):
  156. added = asyncio.run(storage.add_person(
  157. name="Test",
  158. birth_datetime="2000-01-01T12:00:00Z",
  159. latitude=47.0,
  160. longitude=8.0,
  161. ))
  162. deleted = asyncio.run(storage.delete_person(added["id"]))
  163. assert deleted is True
  164. # Verify it's gone
  165. fetched = asyncio.run(storage.get_person(person_id=added["id"]))
  166. assert fetched is None
  167. def test_delete_not_found(self, tmp_db):
  168. result = asyncio.run(storage.delete_person("nonexistent"))
  169. assert result is False