test_collections_cli.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. """
  2. Tests for the collection commands in the CLI.
  3. - create
  4. - list
  5. - retrieve
  6. - delete
  7. - list-documents
  8. - list-users
  9. """
  10. import json
  11. import uuid
  12. import pytest
  13. from click.testing import CliRunner
  14. from cli.commands.collections import (
  15. create,
  16. delete,
  17. list,
  18. list_documents,
  19. list_users,
  20. retrieve,
  21. )
  22. from r2r import R2RAsyncClient
  23. from tests.cli.async_invoke import async_invoke
  24. def extract_json_block(output: str) -> dict:
  25. """Extract and parse the first valid JSON object found in the output."""
  26. start = output.find("{")
  27. if start == -1:
  28. raise ValueError("No JSON object start found in output")
  29. brace_count = 0
  30. for i, char in enumerate(output[start:], start=start):
  31. if char == "{":
  32. brace_count += 1
  33. elif char == "}":
  34. brace_count -= 1
  35. if brace_count == 0:
  36. json_str = output[start : i + 1].strip()
  37. return json.loads(json_str)
  38. raise ValueError("No complete JSON object found in output")
  39. @pytest.mark.asyncio
  40. async def test_collection_lifecycle():
  41. """Test the complete lifecycle of a collection: create, retrieve, delete."""
  42. client = R2RAsyncClient(base_url="http://localhost:7272")
  43. runner = CliRunner(mix_stderr=False)
  44. collection_name = f"test-collection-{uuid.uuid4()}"
  45. description = "Test collection description"
  46. # Create collection
  47. create_result = await async_invoke(
  48. runner,
  49. create,
  50. collection_name,
  51. "--description",
  52. description,
  53. obj=client,
  54. )
  55. assert create_result.exit_code == 0, create_result.stdout_bytes.decode()
  56. output = create_result.stdout_bytes.decode()
  57. create_response = extract_json_block(output)
  58. collection_id = create_response["results"]["id"]
  59. try:
  60. # Retrieve collection
  61. retrieve_result = await async_invoke(
  62. runner, retrieve, collection_id, obj=client
  63. )
  64. assert retrieve_result.exit_code == 0
  65. retrieve_output = retrieve_result.stdout_bytes.decode()
  66. assert collection_id in retrieve_output
  67. # List documents in collection
  68. list_docs_result = await async_invoke(
  69. runner, list_documents, collection_id, obj=client
  70. )
  71. assert list_docs_result.exit_code == 0
  72. # List users in collection
  73. list_users_result = await async_invoke(
  74. runner, list_users, collection_id, obj=client
  75. )
  76. assert list_users_result.exit_code == 0
  77. finally:
  78. # Delete collection
  79. delete_result = await async_invoke(
  80. runner, delete, collection_id, obj=client
  81. )
  82. assert delete_result.exit_code == 0
  83. @pytest.mark.asyncio
  84. async def test_list_collections():
  85. """Test listing collections with various parameters."""
  86. client = R2RAsyncClient(base_url="http://localhost:7272")
  87. runner = CliRunner(mix_stderr=False)
  88. # Create test collection first
  89. create_result = await async_invoke(
  90. runner, create, f"test-collection-{uuid.uuid4()}", obj=client
  91. )
  92. response = extract_json_block(create_result.stdout_bytes.decode())
  93. collection_id = response["results"]["id"]
  94. try:
  95. # Test basic list
  96. list_result = await async_invoke(runner, list, obj=client)
  97. assert list_result.exit_code == 0
  98. # Get paginated results just to verify they exist
  99. list_paginated = await async_invoke(
  100. runner, list, "--offset", "0", "--limit", "2", obj=client
  101. )
  102. assert list_paginated.exit_code == 0
  103. finally:
  104. # Cleanup
  105. await async_invoke(runner, delete, collection_id, obj=client)
  106. @pytest.mark.asyncio
  107. async def test_nonexistent_collection():
  108. """Test operations on a nonexistent collection."""
  109. client = R2RAsyncClient(base_url="http://localhost:7272")
  110. runner = CliRunner(mix_stderr=False)
  111. nonexistent_id = str(uuid.uuid4())
  112. # Test retrieve
  113. retrieve_result = await async_invoke(
  114. runner, retrieve, nonexistent_id, obj=client
  115. )
  116. # Updated assertion to match actual error message
  117. assert (
  118. "the specified collection does not exist."
  119. in retrieve_result.stderr_bytes.decode().lower()
  120. )
  121. # Test list_documents
  122. list_docs_result = await async_invoke(
  123. runner, list_documents, nonexistent_id, obj=client
  124. )
  125. assert (
  126. "collection not found"
  127. in list_docs_result.stderr_bytes.decode().lower()
  128. )
  129. # Test list_users
  130. list_users_result = await async_invoke(
  131. runner, list_users, nonexistent_id, obj=client
  132. )
  133. assert (
  134. "collection not found"
  135. in list_users_result.stderr_bytes.decode().lower()
  136. )