test_collections.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. import pytest
  2. import uuid
  3. from uuid import UUID
  4. from core.base.api.models import CollectionResponse
  5. from core.base import R2RException
  6. @pytest.mark.asyncio
  7. async def test_create_collection(collections_handler):
  8. owner_id = uuid.uuid4()
  9. resp = await collections_handler.create_collection(
  10. owner_id=owner_id,
  11. name="Test Collection",
  12. description="A test collection",
  13. )
  14. assert isinstance(resp, CollectionResponse)
  15. assert resp.name == "Test Collection"
  16. assert resp.owner_id == owner_id
  17. assert resp.description == "A test collection"
  18. @pytest.mark.asyncio
  19. async def test_create_collection_default_name(collections_handler):
  20. owner_id = uuid.uuid4()
  21. # If no name provided, should use default_collection_name from config
  22. resp = await collections_handler.create_collection(owner_id=owner_id)
  23. assert isinstance(resp, CollectionResponse)
  24. assert resp.name is not None # default collection name should be set
  25. assert resp.owner_id == owner_id
  26. @pytest.mark.asyncio
  27. async def test_update_collection(collections_handler):
  28. owner_id = uuid.uuid4()
  29. coll = await collections_handler.create_collection(
  30. owner_id=owner_id, name="Original Name", description="Original Desc"
  31. )
  32. updated = await collections_handler.update_collection(
  33. collection_id=coll.id,
  34. name="Updated Name",
  35. description="New Description",
  36. )
  37. assert updated.name == "Updated Name"
  38. assert updated.description == "New Description"
  39. # user_count and document_count should be integers
  40. assert isinstance(updated.user_count, int)
  41. assert isinstance(updated.document_count, int)
  42. @pytest.mark.asyncio
  43. async def test_update_collection_no_fields(collections_handler):
  44. owner_id = uuid.uuid4()
  45. coll = await collections_handler.create_collection(
  46. owner_id=owner_id, name="NoUpdate", description="No Update"
  47. )
  48. with pytest.raises(R2RException) as exc:
  49. await collections_handler.update_collection(collection_id=coll.id)
  50. assert exc.value.status_code == 400
  51. @pytest.mark.asyncio
  52. async def test_delete_collection_relational(collections_handler):
  53. owner_id = uuid.uuid4()
  54. coll = await collections_handler.create_collection(
  55. owner_id=owner_id, name="ToDelete"
  56. )
  57. # Confirm existence
  58. exists = await collections_handler.collection_exists(coll.id)
  59. assert exists is True
  60. await collections_handler.delete_collection_relational(coll.id)
  61. exists = await collections_handler.collection_exists(coll.id)
  62. assert exists is False
  63. @pytest.mark.asyncio
  64. async def test_collection_exists(collections_handler):
  65. owner_id = uuid.uuid4()
  66. coll = await collections_handler.create_collection(owner_id=owner_id)
  67. assert await collections_handler.collection_exists(coll.id) is True
  68. @pytest.mark.asyncio
  69. async def test_documents_in_collection(collections_handler, db_provider):
  70. # Create a collection
  71. owner_id = uuid.uuid4()
  72. coll = await collections_handler.create_collection(
  73. owner_id=owner_id, name="DocCollection"
  74. )
  75. # Insert some documents related to this collection
  76. # We'll directly insert into the documents table for simplicity
  77. doc_id = uuid.uuid4()
  78. insert_doc_query = f"""
  79. INSERT INTO {db_provider.project_name}.documents (id, collection_ids, owner_id, type, metadata, title, version, size_in_bytes, ingestion_status, extraction_status)
  80. VALUES ($1, $2, $3, 'txt', '{{}}', 'Test Doc', 'v1', 1234, 'pending', 'pending')
  81. """
  82. await db_provider.connection_manager.execute_query(
  83. insert_doc_query, [doc_id, [coll.id], owner_id]
  84. )
  85. # Now fetch documents in collection
  86. res = await collections_handler.documents_in_collection(
  87. coll.id, offset=0, limit=10
  88. )
  89. assert len(res["results"]) == 1
  90. assert res["total_entries"] == 1
  91. assert res["results"][0].id == doc_id
  92. assert res["results"][0].title == "Test Doc"
  93. @pytest.mark.asyncio
  94. async def test_get_collections_overview(collections_handler, db_provider):
  95. owner_id = uuid.uuid4()
  96. coll1 = await collections_handler.create_collection(
  97. owner_id=owner_id, name="Overview1"
  98. )
  99. coll2 = await collections_handler.create_collection(
  100. owner_id=owner_id, name="Overview2"
  101. )
  102. overview = await collections_handler.get_collections_overview(
  103. offset=0, limit=10
  104. )
  105. # There should be at least these two
  106. ids = [c.id for c in overview["results"]]
  107. assert coll1.id in ids
  108. assert coll2.id in ids
  109. @pytest.mark.asyncio
  110. async def test_assign_document_to_collection_relational(
  111. collections_handler, db_provider
  112. ):
  113. owner_id = uuid.uuid4()
  114. coll = await collections_handler.create_collection(
  115. owner_id=owner_id, name="Assign"
  116. )
  117. # Insert a doc
  118. doc_id = uuid.uuid4()
  119. insert_doc_query = f"""
  120. INSERT INTO {db_provider.project_name}.documents (id, owner_id, type, metadata, title, version, size_in_bytes, ingestion_status, extraction_status, collection_ids)
  121. VALUES ($1, $2, 'txt', '{{}}', 'Standalone Doc', 'v1', 10, 'pending', 'pending', ARRAY[]::uuid[])
  122. """
  123. await db_provider.connection_manager.execute_query(
  124. insert_doc_query, [doc_id, owner_id]
  125. )
  126. # Assign this doc to the collection
  127. await collections_handler.assign_document_to_collection_relational(
  128. doc_id, coll.id
  129. )
  130. # Verify doc is now in collection
  131. docs = await collections_handler.documents_in_collection(
  132. coll.id, offset=0, limit=10
  133. )
  134. assert len(docs["results"]) == 1
  135. assert docs["results"][0].id == doc_id
  136. @pytest.mark.asyncio
  137. async def test_remove_document_from_collection_relational(
  138. collections_handler, db_provider
  139. ):
  140. owner_id = uuid.uuid4()
  141. coll = await collections_handler.create_collection(
  142. owner_id=owner_id, name="RemoveDoc"
  143. )
  144. # Insert a doc already in collection
  145. doc_id = uuid.uuid4()
  146. insert_doc_query = f"""
  147. INSERT INTO {db_provider.project_name}.documents
  148. (id, owner_id, type, metadata, title, version, size_in_bytes, ingestion_status, extraction_status, collection_ids)
  149. VALUES ($1, $2, 'txt', '{{}}'::jsonb, 'Another Doc', 'v1', 10, 'pending', 'pending', $3)
  150. """
  151. await db_provider.connection_manager.execute_query(
  152. insert_doc_query, [doc_id, owner_id, [coll.id]]
  153. )
  154. # Remove it
  155. await collections_handler.remove_document_from_collection_relational(
  156. doc_id, coll.id
  157. )
  158. docs = await collections_handler.documents_in_collection(
  159. coll.id, offset=0, limit=10
  160. )
  161. assert len(docs["results"]) == 0
  162. @pytest.mark.asyncio
  163. async def test_delete_nonexistent_collection(collections_handler):
  164. non_existent_id = uuid.uuid4()
  165. with pytest.raises(R2RException) as exc:
  166. await collections_handler.delete_collection_relational(non_existent_id)
  167. assert (
  168. exc.value.status_code == 404
  169. ), "Should raise 404 for non-existing collection"