test_collections.py 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. import uuid
  2. import pytest
  3. from r2r import R2RClient, R2RException
  4. @pytest.fixture(scope="session")
  5. def config():
  6. class TestConfig:
  7. base_url = "http://localhost:7272"
  8. superuser_email = "admin@example.com"
  9. superuser_password = "change_me_immediately"
  10. return TestConfig()
  11. @pytest.fixture(scope="session")
  12. def client(config):
  13. """Create a client instance and log in as a superuser."""
  14. client = R2RClient(config.base_url)
  15. client.users.login(config.superuser_email, config.superuser_password)
  16. return client
  17. @pytest.fixture
  18. def test_document(client):
  19. """Create and yield a test document, then clean up."""
  20. doc_resp = client.documents.create(
  21. raw_text="Test doc for collections", run_with_orchestration=False
  22. )
  23. doc_id = doc_resp["results"]["document_id"]
  24. yield doc_id
  25. # Cleanup: Try deleting the document if it still exists
  26. try:
  27. client.documents.delete(id=doc_id)
  28. except R2RException:
  29. pass
  30. @pytest.fixture
  31. def test_document_2(client):
  32. """Create and yield a test document, then clean up."""
  33. doc_resp = client.documents.create(
  34. raw_text="Another test doc for collections",
  35. run_with_orchestration=False,
  36. )
  37. doc_id = doc_resp["results"]["document_id"]
  38. yield doc_id
  39. # Cleanup: Try deleting the document if it still exists
  40. try:
  41. client.documents.delete(id=doc_id)
  42. except R2RException:
  43. pass
  44. @pytest.fixture
  45. def test_collection(client, test_document):
  46. """Create and yield a test collection, then clean up."""
  47. resp = client.collections.create(
  48. name="Test Collection", description="A sample collection"
  49. )
  50. test_collection_id = resp["results"]["id"]
  51. client.collections.add_document(test_collection_id, test_document)
  52. yield test_collection_id
  53. # Cleanup: Try deleting the collection if it still exists
  54. try:
  55. client.collections.delete(test_collection_id)
  56. except R2RException:
  57. pass
  58. def test_create_collection(client):
  59. resp = client.collections.create(
  60. name="Test Collection Creation", description="Desc"
  61. )
  62. coll_id = resp["results"]["id"]
  63. assert coll_id is not None, "No collection_id returned"
  64. # Cleanup
  65. client.collections.delete(coll_id)
  66. def test_list_collections(client, test_collection):
  67. listed = client.collections.list(limit=10, offset=0)
  68. results = listed["results"]
  69. assert len(results) >= 1, "Expected at least one collection, none found"
  70. def test_retrieve_collection(client, test_collection):
  71. # Retrieve the collection just created
  72. retrieved = client.collections.retrieve(test_collection)["results"]
  73. assert retrieved["id"] == test_collection, "Retrieved wrong collection ID"
  74. def test_update_collection(client, test_collection):
  75. updated_name = "Updated Test Collection"
  76. updated_desc = "Updated description"
  77. updated = client.collections.update(
  78. test_collection, name=updated_name, description=updated_desc
  79. )["results"]
  80. assert updated["name"] == updated_name, "Collection name not updated"
  81. assert (
  82. updated["description"] == updated_desc
  83. ), "Collection description not updated"
  84. def test_add_document_to_collection(client, test_collection, test_document_2):
  85. # Add the test document to the test collection
  86. client.collections.add_document(test_collection, test_document_2)
  87. # Verify by listing documents
  88. docs_in_collection = client.collections.list_documents(test_collection)[
  89. "results"
  90. ]
  91. found = any(doc["id"] == test_document_2 for doc in docs_in_collection)
  92. assert found, "Added document not found in collection"
  93. def test_list_documents_in_collection(client, test_collection, test_document):
  94. # Document should be in the collection already from previous test
  95. docs_in_collection = client.collections.list_documents(test_collection)[
  96. "results"
  97. ]
  98. print("docs_in_collection = ", docs_in_collection)
  99. print("test_document = ", test_document)
  100. found = any(doc["id"] == test_document for doc in docs_in_collection)
  101. assert found, "Expected document not found in collection"
  102. def test_remove_document_from_collection(
  103. client, test_collection, test_document
  104. ):
  105. # Remove the document from the collection
  106. client.collections.remove_document(test_collection, test_document)
  107. docs_in_collection = client.collections.list_documents(test_collection)[
  108. "results"
  109. ]
  110. found = any(doc["id"] == test_document for doc in docs_in_collection)
  111. assert not found, "Document still present in collection after removal"
  112. def test_remove_non_member_user_from_collection(client):
  113. # Create a user and a collection
  114. user_email = f"user_{uuid.uuid4()}@test.com"
  115. password = "pwd123"
  116. client.users.create(user_email, password)
  117. client.users.login(user_email, password)
  118. # Create a collection by the same user
  119. collection_resp = client.collections.create(name="User Owned Collection")[
  120. "results"
  121. ]
  122. collection_id = collection_resp["id"]
  123. client.users.logout()
  124. # Create another user who will not be added to the collection
  125. another_user_email = f"user2_{uuid.uuid4()}@test.com"
  126. client.users.create(another_user_email, password)
  127. client.users.login(another_user_email, password)
  128. another_user_id = client.users.me()["results"]["id"]
  129. client.users.logout()
  130. # Re-login as collection owner
  131. client.users.login(user_email, password)
  132. # Attempt to remove the other user (who was never added)
  133. with pytest.raises(R2RException) as exc_info:
  134. client.collections.remove_user(collection_id, another_user_id)
  135. assert exc_info.value.status_code in [
  136. 400,
  137. 404,
  138. ], "Wrong error code for removing non-member user"
  139. # Cleanup
  140. client.collections.delete(collection_id)
  141. def test_delete_collection(client):
  142. # Create a collection and delete it
  143. coll = client.collections.create(name="Delete Me")["results"]
  144. coll_id = coll["id"]
  145. client.collections.delete(coll_id)
  146. # Verify retrieval fails
  147. with pytest.raises(R2RException) as exc_info:
  148. client.collections.retrieve(coll_id)
  149. assert (
  150. exc_info.value.status_code == 404
  151. ), "Wrong error code retrieving deleted collection"
  152. def test_add_user_to_non_existent_collection(client):
  153. # Create a regular user
  154. user_email = f"test_user_{uuid.uuid4()}@test.com"
  155. user_password = "test_password"
  156. client.users.create(user_email, user_password)
  157. client.users.login(user_email, user_password)
  158. user_id = client.users.me()["results"]["id"]
  159. client.users.logout()
  160. # Re-login as superuser to try adding user to a non-existent collection
  161. # (Assumes superuser credentials are already in the client fixture)
  162. fake_collection_id = str(uuid.uuid4()) # Non-existent collection ID
  163. with pytest.raises(R2RException) as exc_info:
  164. result = client.collections.add_user(fake_collection_id, user_id)
  165. print("result = ", result)
  166. assert (
  167. exc_info.value.status_code == 404
  168. ), "Wrong error code for non-existent collection"
  169. # def test_remove_non_member_user_from_collection_duplicate(client):
  170. # # Similar to the previous non-member removal test but just to ensure coverage.
  171. # owner_email = f"owner_{uuid.uuid4()}@test.com"
  172. # owner_password = "password123"
  173. # client.users.create(owner_email, owner_password)
  174. # client.users.login(owner_email, owner_password)
  175. # # Create a collection by this owner
  176. # coll = client.collections.create(name="Another Non-member Test")["results"]
  177. # collection_id = coll["id"]
  178. # # Create another user who will NOT be added
  179. # other_user_email = f"other_{uuid.uuid4()}@test.com"
  180. # other_password = "password456"
  181. # client.users.create(other_user_email, other_password)
  182. # client.users.login(other_user_email, other_password)
  183. # other_user_id = client.users.me()["results"]["id"]
  184. # client.users.logout()
  185. # # Re-login as collection owner
  186. # client.users.login(owner_email, owner_password)
  187. # # Attempt to remove non-member
  188. # with pytest.raises(R2RException) as exc_info:
  189. # client.collections.remove_user(collection_id, other_user_id)
  190. # assert exc_info.value.status_code in [400, 404], "Wrong error code for removing non-member user"
  191. # # Cleanup
  192. # client.collections.delete(collection_id)
  193. def test_non_owner_delete_collection(client):
  194. # Create owner user
  195. owner_email = f"owner_{uuid.uuid4()}@test.com"
  196. owner_password = "pwd123"
  197. client.users.create(owner_email, owner_password)
  198. client.users.login(owner_email, owner_password)
  199. coll = client.collections.create(name="Owner Collection")["results"]
  200. coll_id = coll["id"]
  201. # Create another user and get their ID
  202. non_owner_email = f"nonowner_{uuid.uuid4()}@test.com"
  203. non_owner_password = "pwd1234"
  204. client.users.logout()
  205. client.users.create(non_owner_email, non_owner_password)
  206. client.users.login(non_owner_email, non_owner_password)
  207. non_owner_id = client.users.me()["results"]["id"]
  208. client.users.logout()
  209. # Owner adds non-owner to collection
  210. client.users.login(owner_email, owner_password)
  211. client.collections.add_user(coll_id, non_owner_id)
  212. client.users.logout()
  213. # Non-owner tries to delete collection
  214. client.users.login(non_owner_email, non_owner_password)
  215. with pytest.raises(R2RException) as exc_info:
  216. result = client.collections.delete(coll_id)
  217. print("result = ", result)
  218. assert (
  219. exc_info.value.status_code == 403
  220. ), "Wrong error code for non-owner deletion attempt"
  221. # Cleanup
  222. client.users.logout()
  223. client.users.login(owner_email, owner_password)
  224. client.collections.delete(coll_id)