""" Contract test for POST /users endpoint. This test MUST fail before implementation. """ import pytest from django.test import TestCase from django.urls import reverse from rest_framework.test import APIClient from rest_framework import status import json class UsersPostContractTest(TestCase): def setUp(self): self.client = APIClient() self.users_url = '/api/v1/users/' # Admin authentication header self.admin_auth = {'HTTP_AUTHORIZATION': 'Bearer admin_token'} # Tenant admin authentication header self.tenant_admin_auth = {'HTTP_AUTHORIZATION': 'Bearer tenant_admin_token'} # Valid user data self.user_data = { 'email': 'john.doe@example.com', 'name': 'John Doe', 'password': 'SecurePassword123!', 'role': 'STAFF', 'department': 'Operations', 'phone': '+60123456789', 'profile': { 'position': 'Manager', 'skills': ['leadership', 'operations'], 'experience_years': 5 } } def test_create_user_success_admin(self): """Test successful user creation by super admin.""" response = self.client.post( self.users_url, data=json.dumps(self.user_data), content_type='application/json', **self.admin_auth ) # This should fail before implementation assert response.status_code == status.HTTP_201_CREATED data = response.json() assert 'id' in data assert data['email'] == self.user_data['email'] assert data['name'] == self.user_data['name'] assert data['role'] == self.user_data['role'] assert data['status'] == 'PENDING' # Default status for new users assert data['department'] == self.user_data['department'] assert data['phone'] == self.user_data['phone'] # Should have generated tenant_id from context assert 'tenant_id' in data # Should have timestamps assert 'created_at' in data assert 'updated_at' in data # Password should not be returned assert 'password' not in data def test_create_user_success_tenant_admin(self): """Test successful user creation by tenant admin.""" response = self.client.post( self.users_url, data=json.dumps(self.user_data), content_type='application/json', **self.tenant_admin_auth ) # This should fail before implementation assert response.status_code == status.HTTP_201_CREATED data = response.json() assert 'id' in data assert data['email'] == self.user_data['email'] assert data['name'] == self.user_data['name'] # Tenant admin cannot create SUPER_ADMIN users # This will be validated once implementation exists def test_create_user_unauthorized(self): """Test user creation without authentication.""" response = self.client.post( self.users_url, data=json.dumps(self.user_data), content_type='application/json' ) assert response.status_code == status.HTTP_401_UNAUTHORIZED def test_create_user_forbidden(self): """Test user creation by regular user (no permissions).""" user_auth = {'HTTP_AUTHORIZATION': 'Bearer user_token'} response = self.client.post( self.users_url, data=json.dumps(self.user_data), content_type='application/json', **user_auth ) assert response.status_code == status.HTTP_403_FORBIDDEN def test_create_user_missing_required_fields(self): """Test user creation with missing required fields.""" incomplete_data = self.user_data.copy() del incomplete_data['email'] response = self.client.post( self.users_url, data=json.dumps(incomplete_data), content_type='application/json', **self.admin_auth ) assert response.status_code == status.HTTP_400_BAD_REQUEST data = response.json() assert 'email' in data.get('errors', {}) def test_create_user_invalid_email(self): """Test user creation with invalid email format.""" invalid_data = self.user_data.copy() invalid_data['email'] = 'invalid-email' response = self.client.post( self.users_url, data=json.dumps(invalid_data), content_type='application/json', **self.admin_auth ) assert response.status_code == status.HTTP_400_BAD_REQUEST def test_create_user_weak_password(self): """Test user creation with weak password.""" invalid_data = self.user_data.copy() invalid_data['password'] = '123' response = self.client.post( self.users_url, data=json.dumps(invalid_data), content_type='application/json', **self.admin_auth ) assert response.status_code == status.HTTP_400_BAD_REQUEST def test_create_user_invalid_role(self): """Test user creation with invalid role.""" invalid_data = self.user_data.copy() invalid_data['role'] = 'INVALID_ROLE' response = self.client.post( self.users_url, data=json.dumps(invalid_data), content_type='application/json', **self.admin_auth ) assert response.status_code == status.HTTP_400_BAD_REQUEST def test_create_user_duplicate_email(self): """Test user creation with duplicate email.""" # First request should succeed (if implemented) first_response = self.client.post( self.users_url, data=json.dumps(self.user_data), content_type='application/json', **self.admin_auth ) if first_response.status_code == status.HTTP_201_CREATED: # Second request with same email should fail second_response = self.client.post( self.users_url, data=json.dumps(self.user_data), content_type='application/json', **self.admin_auth ) assert second_response.status_code == status.HTTP_400_BAD_REQUEST def test_create_user_tenant_admin_cannot_create_super_admin(self): """Test that tenant admin cannot create super admin users.""" super_admin_data = self.user_data.copy() super_admin_data['role'] = 'SUPER_ADMIN' response = self.client.post( self.users_url, data=json.dumps(super_admin_data), content_type='application/json', **self.tenant_admin_auth ) assert response.status_code == status.HTTP_403_FORBIDDEN def test_create_user_with_profile_data(self): """Test user creation with profile information.""" response = self.client.post( self.users_url, data=json.dumps(self.user_data), content_type='application/json', **self.admin_auth ) if response.status_code == status.HTTP_201_CREATED: data = response.json() assert 'profile' in data profile = data['profile'] assert profile['position'] == self.user_data['profile']['position'] assert profile['skills'] == self.user_data['profile']['skills'] assert profile['experience_years'] == self.user_data['profile']['experience_years'] def test_create_user_malformed_profile(self): """Test user creation with malformed profile JSON.""" invalid_data = self.user_data.copy() invalid_data['profile'] = 'invalid profile format' response = self.client.post( self.users_url, data=json.dumps(invalid_data), content_type='application/json', **self.admin_auth ) assert response.status_code == status.HTTP_400_BAD_REQUEST def test_create_user_tenant_isolation(self): """Test that user creation respects tenant isolation.""" response = self.client.post( self.users_url, data=json.dumps(self.user_data), content_type='application/json', **self.tenant_admin_auth ) if response.status_code == status.HTTP_201_CREATED: data = response.json() # User should be created in the tenant admin's tenant # This will be validated once implementation exists assert 'tenant_id' in data