test_users_cli.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. """
  2. Tests for the user commands in the CLI.
  3. - create
  4. - list
  5. - retrieve
  6. - me
  7. x list-collections
  8. x add-to-collection
  9. x remove-from-collection
  10. """
  11. import json
  12. import uuid
  13. import pytest
  14. from click.testing import CliRunner
  15. from cli.commands.users import (
  16. add_to_collection,
  17. create,
  18. list,
  19. list_collections,
  20. me,
  21. remove_from_collection,
  22. retrieve,
  23. )
  24. from r2r import R2RAsyncClient
  25. from tests.cli.async_invoke import async_invoke
  26. def extract_json_block(output: str) -> dict:
  27. """Extract and parse the first valid JSON object found in the output."""
  28. start = output.find("{")
  29. if start == -1:
  30. raise ValueError("No JSON object start found in output")
  31. brace_count = 0
  32. for i, char in enumerate(output[start:], start=start):
  33. if char == "{":
  34. brace_count += 1
  35. elif char == "}":
  36. brace_count -= 1
  37. if brace_count == 0:
  38. json_str = output[start : i + 1].strip()
  39. return json.loads(json_str)
  40. raise ValueError("No complete JSON object found in output")
  41. @pytest.mark.asyncio
  42. async def test_user_lifecycle():
  43. """Test the complete lifecycle of a user: create, retrieve, list, collections."""
  44. client = R2RAsyncClient(base_url="http://localhost:7272")
  45. runner = CliRunner(mix_stderr=False)
  46. # Create test user with random email
  47. test_email = f"test_{uuid.uuid4()}@example.com"
  48. test_password = "TestPassword123!"
  49. # Create user
  50. create_result = await async_invoke(
  51. runner, create, test_email, test_password, obj=client
  52. )
  53. assert create_result.exit_code == 0, create_result.stdout_bytes.decode()
  54. output = create_result.stdout_bytes.decode()
  55. create_response = extract_json_block(output)
  56. user_id = create_response["results"]["id"]
  57. try:
  58. # List users and verify our new user is included
  59. list_result = await async_invoke(runner, list, obj=client)
  60. assert list_result.exit_code == 0, list_result.stdout_bytes.decode()
  61. list_output = list_result.stdout_bytes.decode()
  62. assert test_email in list_output
  63. # Retrieve specific user
  64. retrieve_result = await async_invoke(
  65. runner, retrieve, user_id, obj=client
  66. )
  67. assert (
  68. retrieve_result.exit_code == 0
  69. ), retrieve_result.stdout_bytes.decode()
  70. retrieve_output = retrieve_result.stdout_bytes.decode()
  71. retrieve_response = extract_json_block(retrieve_output)
  72. assert retrieve_response["results"]["email"] == test_email
  73. # Test me endpoint
  74. me_result = await async_invoke(runner, me, obj=client)
  75. assert me_result.exit_code == 0, me_result.stdout_bytes.decode()
  76. # List collections for user
  77. collections_result = await async_invoke(
  78. runner, list_collections, user_id, obj=client
  79. )
  80. assert (
  81. collections_result.exit_code == 0
  82. ), collections_result.stdout_bytes.decode()
  83. finally:
  84. # We don't delete the user since there's no delete command
  85. pass
  86. # FIXME: This should be returning 'User not found' but returns an empty list instead.
  87. # @pytest.mark.asyncio
  88. # async def test_retrieve_nonexistent_user():
  89. # """Test retrieving a user that doesn't exist."""
  90. # client = R2RAsyncClient(base_url="http://localhost:7272")
  91. # runner = CliRunner(mix_stderr=False)
  92. # nonexistent_id = str(uuid.uuid4())
  93. # result = await async_invoke(runner, retrieve, nonexistent_id, obj=client)
  94. # assert result.exit_code != 0
  95. # error_output = result.stderr_bytes.decode()
  96. # assert "User not found" in error_output
  97. # FIXME: This is returning with a status of 0 but has a 400 on the server side?
  98. # @pytest.mark.asyncio
  99. # async def test_create_duplicate_user():
  100. # """Test creating a user with an email that already exists."""
  101. # client = R2RAsyncClient(base_url="http://localhost:7272")
  102. # runner = CliRunner(mix_stderr=False)
  103. # test_email = f"test_{uuid.uuid4()}@example.com"
  104. # test_password = "TestPassword123!"
  105. # # Create first user
  106. # first_result = await async_invoke(
  107. # runner, create, test_email, test_password, obj=client
  108. # )
  109. # assert first_result.exit_code == 0
  110. # # Try to create second user with same email
  111. # second_result = await async_invoke(
  112. # runner, create, test_email, test_password, obj=client
  113. # )
  114. # print(f"SECOND RESULT: {second_result}")
  115. # assert second_result.exit_code != 0
  116. # error_output = second_result.stderr_bytes.decode()
  117. # assert "already exists" in error_output.lower()