Some checks failed
System Monitoring / Health Checks (push) Has been cancelled
System Monitoring / Performance Monitoring (push) Has been cancelled
System Monitoring / Database Monitoring (push) Has been cancelled
System Monitoring / Cache Monitoring (push) Has been cancelled
System Monitoring / Log Monitoring (push) Has been cancelled
System Monitoring / Resource Monitoring (push) Has been cancelled
System Monitoring / Uptime Monitoring (push) Has been cancelled
System Monitoring / Backup Monitoring (push) Has been cancelled
System Monitoring / Security Monitoring (push) Has been cancelled
System Monitoring / Monitoring Dashboard (push) Has been cancelled
System Monitoring / Alerting (push) Has been cancelled
Security Scanning / Dependency Scanning (push) Has been cancelled
Security Scanning / Code Security Scanning (push) Has been cancelled
Security Scanning / Secrets Scanning (push) Has been cancelled
Security Scanning / Container Security Scanning (push) Has been cancelled
Security Scanning / Compliance Checking (push) Has been cancelled
Security Scanning / Security Dashboard (push) Has been cancelled
Security Scanning / Security Remediation (push) Has been cancelled
251 lines
8.5 KiB
Python
251 lines
8.5 KiB
Python
"""
|
|
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 |