|
4 | 4 | """ |
5 | 5 |
|
6 | 6 | import uuid |
| 7 | +from unittest.mock import AsyncMock, patch |
7 | 8 |
|
8 | 9 | import pytest |
9 | 10 |
|
| 11 | +from permit import Permit, PermitConfig |
10 | 12 | from permit.api.models import ElementsUserInviteApprove, ElementsUserInviteRead, UserInviteStatus |
11 | | -from permit.api.users import UsersApi |
| 13 | +from permit.api.user_invites import UserInvitesApi |
12 | 14 |
|
13 | 15 |
|
14 | 16 | class TestUserInviteApproveSimple: |
15 | 17 | """Simple test suite for user invite approve functionality.""" |
16 | 18 |
|
17 | 19 | def test_approve_method_exists(self): |
18 | | - """Test that the approve method exists in UsersApi.""" |
19 | | - assert hasattr(UsersApi, "approve") |
20 | | - assert callable(UsersApi.approve) |
| 20 | + """Test that the approve method exists in UserInvitesApi.""" |
| 21 | + assert hasattr(UserInvitesApi, "approve") |
| 22 | + assert callable(UserInvitesApi.approve) |
21 | 23 |
|
22 | 24 | def test_approve_method_signature(self): |
23 | 25 | """Test that the approve method has the correct signature.""" |
24 | 26 | import inspect |
25 | 27 |
|
26 | | - method = UsersApi.approve |
| 28 | + method = UserInvitesApi.approve |
27 | 29 | signature = inspect.signature(method) |
28 | 30 |
|
29 | 31 | # Check parameter names |
@@ -57,8 +59,8 @@ def test_approve_data_model_key_validation(self): |
57 | 59 | with pytest.raises(ValueError): |
58 | 60 | ElementsUserInviteApprove( |
59 | 61 | email="test@example.com", |
60 | | - key="invalid key with spaces", # Should fail regex validation |
61 | | - attributes={}, |
| 62 | + key="invalid key with spaces", |
| 63 | + attributes={}, # Should fail regex validation |
62 | 64 | ) |
63 | 65 |
|
64 | 66 | def test_approve_data_model_with_complex_attributes(self): |
@@ -121,7 +123,7 @@ def test_approve_parameter_types(self): |
121 | 123 | """Test that the approve method parameters have correct types.""" |
122 | 124 | from typing import get_type_hints |
123 | 125 |
|
124 | | - method = UsersApi.approve |
| 126 | + method = UserInvitesApi.approve |
125 | 127 | type_hints = get_type_hints(method) |
126 | 128 |
|
127 | 129 | # Check parameter types |
@@ -158,3 +160,131 @@ def test_approve_data_serialization(self): |
158 | 160 | parsed_data = json.loads(json_str) |
159 | 161 | assert parsed_data["email"] == "test@example.com" |
160 | 162 | assert parsed_data["key"] == "test-key-123" |
| 163 | + |
| 164 | + def test_permit_instance_has_user_invites_api(self): |
| 165 | + """Test that Permit instance exposes user_invites API correctly.""" |
| 166 | + # Create a Permit instance with mock configuration |
| 167 | + config = PermitConfig(token="test-token-123", api_url="http://localhost:8000", pdp="http://localhost:7766") |
| 168 | + permit = Permit(config) |
| 169 | + |
| 170 | + # Test that user_invites API is accessible |
| 171 | + assert hasattr(permit.api, "user_invites") |
| 172 | + assert permit.api.user_invites is not None |
| 173 | + |
| 174 | + # Test that the approve method is available |
| 175 | + assert hasattr(permit.api.user_invites, "approve") |
| 176 | + assert callable(permit.api.user_invites.approve) |
| 177 | + |
| 178 | + @pytest.mark.asyncio |
| 179 | + async def test_permit_user_invites_approve_usage_pattern(self): |
| 180 | + """ |
| 181 | + Test the actual usage pattern: permit.api.user_invites.approve() |
| 182 | + This test mimics how users will actually use the function. |
| 183 | + """ |
| 184 | + # Create a Permit instance with mock configuration |
| 185 | + config = PermitConfig(token="test-token-123", api_url="http://localhost:8000", pdp="http://localhost:7766") |
| 186 | + permit = Permit(config) |
| 187 | + |
| 188 | + # Create test data - this is how users will use it |
| 189 | + user_invite_id = "test-invite-uuid-123" |
| 190 | + approve_data = ElementsUserInviteApprove( |
| 191 | + email="newuser@company.com", |
| 192 | + key="new-user-invite-key", |
| 193 | + attributes={ |
| 194 | + "department": "Engineering", |
| 195 | + "role": "Developer", |
| 196 | + "start_date": "2024-01-15", |
| 197 | + "manager": "manager@company.com", |
| 198 | + }, |
| 199 | + ) |
| 200 | + |
| 201 | + # Mock the entire approve method to avoid HTTP calls |
| 202 | + mock_response = ElementsUserInviteRead( |
| 203 | + id=uuid.uuid4(), |
| 204 | + organization_id=uuid.uuid4(), |
| 205 | + project_id=uuid.uuid4(), |
| 206 | + environment_id=uuid.uuid4(), |
| 207 | + key="new-user-invite-key", |
| 208 | + status=UserInviteStatus.approved, |
| 209 | + email="newuser@company.com", |
| 210 | + first_name="New", |
| 211 | + last_name="User", |
| 212 | + role_id=uuid.uuid4(), |
| 213 | + tenant_id=uuid.uuid4(), |
| 214 | + created_at="2024-01-01T00:00:00Z", |
| 215 | + updated_at="2024-01-01T01:00:00Z", |
| 216 | + ) |
| 217 | + |
| 218 | + # Mock just the approve method |
| 219 | + with patch.object(permit.api.user_invites, "approve", new_callable=AsyncMock) as mock_approve: |
| 220 | + mock_approve.return_value = mock_response |
| 221 | + |
| 222 | + # This is the actual usage pattern that users will use! |
| 223 | + result = await permit.api.user_invites.approve(user_invite_id, approve_data) |
| 224 | + |
| 225 | + # Verify the result |
| 226 | + assert isinstance(result, ElementsUserInviteRead) |
| 227 | + assert result.status == UserInviteStatus.approved |
| 228 | + assert result.email == "newuser@company.com" |
| 229 | + assert result.key == "new-user-invite-key" |
| 230 | + |
| 231 | + # Verify the method was called with correct parameters |
| 232 | + mock_approve.assert_called_once_with(user_invite_id, approve_data) |
| 233 | + |
| 234 | + def test_user_invites_api_integration_in_permit_client(self): |
| 235 | + """Test that the UserInvitesApi is properly integrated into the Permit client.""" |
| 236 | + config = PermitConfig(token="test-token-123", api_url="http://localhost:8000", pdp="http://localhost:7766") |
| 237 | + permit = Permit(config) |
| 238 | + |
| 239 | + # Test the complete integration |
| 240 | + assert hasattr(permit, "api") |
| 241 | + assert hasattr(permit.api, "user_invites") |
| 242 | + assert isinstance(permit.api.user_invites, UserInvitesApi) |
| 243 | + |
| 244 | + # Test that it's different from users API |
| 245 | + assert hasattr(permit.api, "users") |
| 246 | + assert permit.api.user_invites is not permit.api.users |
| 247 | + assert type(permit.api.user_invites).__name__ == "UserInvitesApi" |
| 248 | + assert type(permit.api.users).__name__ == "UsersApi" |
| 249 | + |
| 250 | + def test_actual_usage_pattern_structure(self): |
| 251 | + """ |
| 252 | + Test that the actual usage pattern permit.api.user_invites.approve() is available. |
| 253 | + This verifies the complete structure that users will interact with. |
| 254 | + """ |
| 255 | + # Create a real Permit instance (no mocking) |
| 256 | + config = PermitConfig(token="test-token-123", api_url="http://localhost:8000", pdp="http://localhost:7766") |
| 257 | + permit = Permit(config) |
| 258 | + |
| 259 | + # Create real test data as users would |
| 260 | + approve_data = ElementsUserInviteApprove( |
| 261 | + email="newuser@company.com", |
| 262 | + key="new-user-invite-key", |
| 263 | + attributes={"department": "Engineering", "role": "Developer", "start_date": "2024-01-15"}, |
| 264 | + ) |
| 265 | + |
| 266 | + # Verify the complete call chain exists (this is what users will use) |
| 267 | + assert hasattr(permit, "api"), "permit.api should exist" |
| 268 | + assert hasattr(permit.api, "user_invites"), "permit.api.user_invites should exist" |
| 269 | + assert hasattr(permit.api.user_invites, "approve"), "permit.api.user_invites.approve should exist" |
| 270 | + assert callable(permit.api.user_invites.approve), "permit.api.user_invites.approve should be callable" |
| 271 | + |
| 272 | + # Verify the method signature matches what users expect |
| 273 | + import inspect |
| 274 | + |
| 275 | + method = permit.api.user_invites.approve |
| 276 | + signature = inspect.signature(method) |
| 277 | + params = list(signature.parameters.keys()) |
| 278 | + |
| 279 | + assert "user_invite_id" in params, "Method should accept user_invite_id parameter" |
| 280 | + assert "approve_data" in params, "Method should accept approve_data parameter" |
| 281 | + |
| 282 | + # Verify the approve_data can be created with user's data |
| 283 | + assert approve_data.email == "newuser@company.com" |
| 284 | + assert approve_data.key == "new-user-invite-key" |
| 285 | + assert approve_data.attributes["department"] == "Engineering" |
| 286 | + |
| 287 | + |
| 288 | +if __name__ == "__main__": |
| 289 | + # Run with: python -m pytest tests/test_user_invite_approve_simple.py -v |
| 290 | + pass |
0 commit comments