project initialization
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

This commit is contained in:
2025-10-05 02:37:33 +08:00
parent 2cbb6d5fa1
commit b3fff546e9
226 changed files with 97805 additions and 35 deletions

View File

View File

@@ -0,0 +1,638 @@
"""
Unit tests for Core Services
Tests for all core services:
- TenantService
- UserService
- SubscriptionService
- ModuleService
- PaymentService
Author: Claude
"""
import pytest
from unittest.mock import Mock, patch, MagicMock
from django.test import TestCase
from django.contrib.auth import get_user_model
from django.utils import timezone
from decimal import Decimal
from datetime import date, timedelta
from backend.src.core.models.tenant import Tenant
from backend.src.core.models.user import User
from backend.src.core.models.subscription import Subscription
from backend.src.core.models.module import Module
from backend.src.core.models.payment import PaymentTransaction
from backend.src.core.services.tenant_service import TenantService
from backend.src.core.services.user_service import UserService
from backend.src.core.services.subscription_service import SubscriptionService
from backend.src.core.services.module_service import ModuleService
from backend.src.core.services.payment_service import PaymentService
User = get_user_model()
class TenantServiceTest(TestCase):
"""Test cases for TenantService"""
def setUp(self):
self.service = TenantService()
self.tenant_data = {
'name': 'Test Business Sdn Bhd',
'schema_name': 'test_business',
'domain': 'testbusiness.com',
'business_type': 'retail',
'registration_number': '202401000001',
'tax_id': 'MY123456789',
'contact_email': 'contact@testbusiness.com',
'contact_phone': '+60123456789',
'address': '123 Test Street',
'city': 'Kuala Lumpur',
'state': 'KUL',
'postal_code': '50000'
}
def test_create_tenant_success(self):
"""Test successful tenant creation"""
tenant = self.service.create_tenant(self.tenant_data)
self.assertEqual(tenant.name, self.tenant_data['name'])
self.assertEqual(tenant.schema_name, self.tenant_data['schema_name'])
self.assertTrue(tenant.is_active)
self.assertEqual(tenant.subscription_tier, 'free')
def test_create_tenant_invalid_data(self):
"""Test tenant creation with invalid data"""
invalid_data = self.tenant_data.copy()
invalid_data['name'] = '' # Empty name
with self.assertRaises(Exception):
self.service.create_tenant(invalid_data)
def test_get_tenant_by_id(self):
"""Test getting tenant by ID"""
tenant = self.service.create_tenant(self.tenant_data)
retrieved_tenant = self.service.get_tenant_by_id(tenant.id)
self.assertEqual(retrieved_tenant, tenant)
def test_get_tenant_by_schema_name(self):
"""Test getting tenant by schema name"""
tenant = self.service.create_tenant(self.tenant_data)
retrieved_tenant = self.service.get_tenant_by_schema_name(tenant.schema_name)
self.assertEqual(retrieved_tenant, tenant)
def test_update_tenant(self):
"""Test updating tenant information"""
tenant = self.service.create_tenant(self.tenant_data)
update_data = {'name': 'Updated Business Name'}
updated_tenant = self.service.update_tenant(tenant.id, update_data)
self.assertEqual(updated_tenant.name, 'Updated Business Name')
def test_activate_tenant(self):
"""Test tenant activation"""
tenant = self.service.create_tenant(self.tenant_data)
tenant.is_active = False
tenant.save()
activated_tenant = self.service.activate_tenant(tenant.id)
self.assertTrue(activated_tenant.is_active)
def test_deactivate_tenant(self):
"""Test tenant deactivation"""
tenant = self.service.create_tenant(self.tenant_data)
deactivated_tenant = self.service.deactivate_tenant(tenant.id)
self.assertFalse(deactivated_tenant.is_active)
def test_get_tenant_statistics(self):
"""Test getting tenant statistics"""
tenant = self.service.create_tenant(self.tenant_data)
stats = self.service.get_tenant_statistics(tenant.id)
self.assertIn('total_users', stats)
self.assertIn('active_subscriptions', stats)
self.assertIn('total_modules', stats)
class UserServiceTest(TestCase):
"""Test cases for UserService"""
def setUp(self):
self.service = UserService()
self.tenant = Tenant.objects.create(
name='Test Business Sdn Bhd',
schema_name='test_business',
domain='testbusiness.com',
business_type='retail'
)
def test_create_user_success(self):
"""Test successful user creation"""
user_data = {
'username': 'testuser',
'email': 'user@test.com',
'password': 'test123',
'first_name': 'Test',
'last_name': 'User',
'phone': '+60123456789',
'tenant': self.tenant,
'role': 'staff'
}
user = self.service.create_user(user_data)
self.assertEqual(user.username, user_data['username'])
self.assertEqual(user.email, user_data['email'])
self.assertEqual(user.tenant, self.tenant)
self.assertTrue(user.check_password('test123'))
def test_create_superuser(self):
"""Test superuser creation"""
user_data = {
'username': 'admin',
'email': 'admin@test.com',
'password': 'admin123',
'first_name': 'Admin',
'last_name': 'User'
}
user = self.service.create_superuser(user_data)
self.assertTrue(user.is_staff)
self.assertTrue(user.is_superuser)
self.assertEqual(user.role, 'admin')
def test_authenticate_user_success(self):
"""Test successful user authentication"""
user_data = {
'username': 'testuser',
'email': 'user@test.com',
'password': 'test123',
'tenant': self.tenant,
'role': 'staff'
}
self.service.create_user(user_data)
authenticated_user = self.service.authenticate_user(
user_data['username'],
user_data['password']
)
self.assertIsNotNone(authenticated_user)
self.assertEqual(authenticated_user.username, user_data['username'])
def test_authenticate_user_failure(self):
"""Test failed user authentication"""
user_data = {
'username': 'testuser',
'email': 'user@test.com',
'password': 'test123',
'tenant': self.tenant,
'role': 'staff'
}
self.service.create_user(user_data)
authenticated_user = self.service.authenticate_user(
user_data['username'],
'wrongpassword'
)
self.assertIsNone(authenticated_user)
def test_update_user_profile(self):
"""Test updating user profile"""
user_data = {
'username': 'testuser',
'email': 'user@test.com',
'password': 'test123',
'tenant': self.tenant,
'role': 'staff'
}
user = self.service.create_user(user_data)
update_data = {'first_name': 'Updated', 'last_name': 'Name'}
updated_user = self.service.update_user(user.id, update_data)
self.assertEqual(updated_user.first_name, 'Updated')
self.assertEqual(updated_user.last_name, 'Name')
def test_change_password(self):
"""Test changing user password"""
user_data = {
'username': 'testuser',
'email': 'user@test.com',
'password': 'test123',
'tenant': self.tenant,
'role': 'staff'
}
user = self.service.create_user(user_data)
success = self.service.change_password(user.id, 'newpassword123')
self.assertTrue(success)
self.assertTrue(user.check_password('newpassword123'))
def test_deactivate_user(self):
"""Test user deactivation"""
user_data = {
'username': 'testuser',
'email': 'user@test.com',
'password': 'test123',
'tenant': self.tenant,
'role': 'staff'
}
user = self.service.create_user(user_data)
deactivated_user = self.service.deactivate_user(user.id)
self.assertFalse(deactivated_user.is_active)
def test_get_users_by_tenant(self):
"""Test getting users by tenant"""
user_data = {
'username': 'testuser',
'email': 'user@test.com',
'password': 'test123',
'tenant': self.tenant,
'role': 'staff'
}
self.service.create_user(user_data)
users = self.service.get_users_by_tenant(self.tenant.id)
self.assertEqual(len(users), 1)
self.assertEqual(users[0].username, user_data['username'])
class SubscriptionServiceTest(TestCase):
"""Test cases for SubscriptionService"""
def setUp(self):
self.service = SubscriptionService()
self.tenant = Tenant.objects.create(
name='Test Business Sdn Bhd',
schema_name='test_business',
domain='testbusiness.com',
business_type='retail'
)
def test_create_subscription_success(self):
"""Test successful subscription creation"""
subscription_data = {
'tenant': self.tenant,
'plan': 'premium',
'amount': Decimal('299.00'),
'currency': 'MYR',
'billing_cycle': 'monthly',
'start_date': date.today(),
'end_date': date.today() + timedelta(days=30)
}
subscription = self.service.create_subscription(subscription_data)
self.assertEqual(subscription.tenant, self.tenant)
self.assertEqual(subscription.plan, 'premium')
self.assertEqual(subscription.status, 'active')
def test_upgrade_subscription(self):
"""Test subscription upgrade"""
subscription_data = {
'tenant': self.tenant,
'plan': 'basic',
'amount': Decimal('99.00'),
'currency': 'MYR',
'billing_cycle': 'monthly',
'start_date': date.today(),
'end_date': date.today() + timedelta(days=30)
}
subscription = self.service.create_subscription(subscription_data)
upgraded_subscription = self.service.upgrade_subscription(
subscription.id,
'premium',
Decimal('299.00')
)
self.assertEqual(upgraded_subscription.plan, 'premium')
self.assertEqual(upgraded_subscription.amount, Decimal('299.00'))
def test_cancel_subscription(self):
"""Test subscription cancellation"""
subscription_data = {
'tenant': self.tenant,
'plan': 'premium',
'amount': Decimal('299.00'),
'currency': 'MYR',
'billing_cycle': 'monthly',
'start_date': date.today(),
'end_date': date.today() + timedelta(days=30)
}
subscription = self.service.create_subscription(subscription_data)
cancelled_subscription = self.service.cancel_subscription(subscription.id)
self.assertEqual(cancelled_subscription.status, 'cancelled')
def test_renew_subscription(self):
"""Test subscription renewal"""
subscription_data = {
'tenant': self.tenant,
'plan': 'premium',
'amount': Decimal('299.00'),
'currency': 'MYR',
'billing_cycle': 'monthly',
'start_date': date.today() - timedelta(days=29),
'end_date': date.today() + timedelta(days=1)
}
subscription = self.service.create_subscription(subscription_data)
renewed_subscription = self.service.renew_subscription(subscription.id)
self.assertEqual(renewed_subscription.status, 'active')
self.assertGreater(renewed_subscription.end_date, subscription.end_date)
def test_check_subscription_status(self):
"""Test subscription status check"""
subscription_data = {
'tenant': self.tenant,
'plan': 'premium',
'amount': Decimal('299.00'),
'currency': 'MYR',
'billing_cycle': 'monthly',
'start_date': date.today(),
'end_date': date.today() + timedelta(days=30)
}
subscription = self.service.create_subscription(subscription_data)
status = self.service.check_subscription_status(self.tenant.id)
self.assertTrue(status['is_active'])
self.assertEqual(status['plan'], 'premium')
def test_get_subscription_history(self):
"""Test getting subscription history"""
subscription_data = {
'tenant': self.tenant,
'plan': 'premium',
'amount': Decimal('299.00'),
'currency': 'MYR',
'billing_cycle': 'monthly',
'start_date': date.today(),
'end_date': date.today() + timedelta(days=30)
}
self.service.create_subscription(subscription_data)
history = self.service.get_subscription_history(self.tenant.id)
self.assertEqual(len(history), 1)
self.assertEqual(history[0]['plan'], 'premium')
class ModuleServiceTest(TestCase):
"""Test cases for ModuleService"""
def setUp(self):
self.service = ModuleService()
def test_create_module_success(self):
"""Test successful module creation"""
module_data = {
'name': 'Test Module',
'code': 'test',
'description': 'A test module',
'category': 'industry',
'version': '1.0.0',
'is_active': True,
'config_schema': {'features': ['test']},
'pricing_tier': 'premium'
}
module = self.service.create_module(module_data)
self.assertEqual(module.name, module_data['name'])
self.assertEqual(module.code, module_data['code'])
self.assertTrue(module.is_active)
def test_get_module_by_code(self):
"""Test getting module by code"""
module_data = {
'name': 'Test Module',
'code': 'test',
'description': 'A test module',
'category': 'industry',
'version': '1.0.0',
'is_active': True,
'config_schema': {'features': ['test']},
'pricing_tier': 'premium'
}
module = self.service.create_module(module_data)
retrieved_module = self.service.get_module_by_code('test')
self.assertEqual(retrieved_module, module)
def test_get_modules_by_category(self):
"""Test getting modules by category"""
module_data = {
'name': 'Test Module',
'code': 'test',
'description': 'A test module',
'category': 'industry',
'version': '1.0.0',
'is_active': True,
'config_schema': {'features': ['test']},
'pricing_tier': 'premium'
}
self.service.create_module(module_data)
modules = self.service.get_modules_by_category('industry')
self.assertEqual(len(modules), 1)
self.assertEqual(modules[0].code, 'test')
def test_activate_module(self):
"""Test module activation"""
module_data = {
'name': 'Test Module',
'code': 'test',
'description': 'A test module',
'category': 'industry',
'version': '1.0.0',
'is_active': False,
'config_schema': {'features': ['test']},
'pricing_tier': 'premium'
}
module = self.service.create_module(module_data)
activated_module = self.service.activate_module(module.id)
self.assertTrue(activated_module.is_active)
def test_deactivate_module(self):
"""Test module deactivation"""
module_data = {
'name': 'Test Module',
'code': 'test',
'description': 'A test module',
'category': 'industry',
'version': '1.0.0',
'is_active': True,
'config_schema': {'features': ['test']},
'pricing_tier': 'premium'
}
module = self.service.create_module(module_data)
deactivated_module = self.service.deactivate_module(module.id)
self.assertFalse(deactivated_module.is_active)
def test_check_module_dependencies(self):
"""Test module dependency checking"""
# Create dependent module first
dependent_module_data = {
'name': 'Core Module',
'code': 'core',
'description': 'Core module',
'category': 'core',
'version': '1.0.0',
'is_active': True,
'config_schema': {'features': ['core']},
'pricing_tier': 'free'
}
self.service.create_module(dependent_module_data)
# Create module with dependency
module_data = {
'name': 'Test Module',
'code': 'test',
'description': 'A test module',
'category': 'industry',
'version': '1.0.0',
'is_active': True,
'dependencies': ['core'],
'config_schema': {'features': ['test']},
'pricing_tier': 'premium'
}
module = self.service.create_module(module_data)
dependencies = self.service.check_module_dependencies(module.id)
self.assertTrue(dependencies['dependencies_met'])
self.assertEqual(len(dependencies['dependencies']), 1)
class PaymentServiceTest(TestCase):
"""Test cases for PaymentService"""
def setUp(self):
self.service = PaymentService()
self.tenant = Tenant.objects.create(
name='Test Business Sdn Bhd',
schema_name='test_business',
domain='testbusiness.com',
business_type='retail'
)
self.subscription = Subscription.objects.create(
tenant=self.tenant,
plan='premium',
status='active',
start_date=date.today(),
end_date=date.today() + timedelta(days=30),
amount=Decimal('299.00'),
currency='MYR'
)
@patch('backend.src.core.services.payment_service.PaymentService.process_payment_gateway')
def test_create_payment_success(self, mock_process_payment):
"""Test successful payment creation"""
mock_process_payment.return_value = {'success': True, 'transaction_id': 'TX123456'}
payment_data = {
'tenant': self.tenant,
'subscription': self.subscription,
'amount': Decimal('299.00'),
'currency': 'MYR',
'payment_method': 'fpx',
'description': 'Monthly subscription payment'
}
payment = self.service.create_payment(payment_data)
self.assertEqual(payment.tenant, self.tenant)
self.assertEqual(payment.amount, Decimal('299.00'))
self.assertEqual(payment.status, 'completed')
def test_create_payment_invalid_amount(self):
"""Test payment creation with invalid amount"""
payment_data = {
'tenant': self.tenant,
'subscription': self.subscription,
'amount': Decimal('-100.00'),
'currency': 'MYR',
'payment_method': 'fpx',
'description': 'Invalid payment'
}
with self.assertRaises(Exception):
self.service.create_payment(payment_data)
@patch('backend.src.core.services.payment_service.PaymentService.process_payment_gateway')
def test_process_payment_refund(self, mock_process_payment):
"""Test payment refund processing"""
mock_process_payment.return_value = {'success': True, 'refund_id': 'RF123456'}
payment = PaymentTransaction.objects.create(
tenant=self.tenant,
subscription=self.subscription,
transaction_id='TX123456',
amount=Decimal('299.00'),
currency='MYR',
payment_method='fpx',
status='completed',
payment_date=timezone.now()
)
refund_result = self.service.process_refund(payment.id, Decimal('100.00'))
self.assertTrue(refund_result['success'])
self.assertEqual(refund_result['refund_id'], 'RF123456')
def test_get_payment_history(self):
"""Test getting payment history"""
payment = PaymentTransaction.objects.create(
tenant=self.tenant,
subscription=self.subscription,
transaction_id='TX123456',
amount=Decimal('299.00'),
currency='MYR',
payment_method='fpx',
status='completed',
payment_date=timezone.now()
)
history = self.service.get_payment_history(self.tenant.id)
self.assertEqual(len(history), 1)
self.assertEqual(history[0]['transaction_id'], 'TX123456')
def test_check_payment_status(self):
"""Test checking payment status"""
payment = PaymentTransaction.objects.create(
tenant=self.tenant,
subscription=self.subscription,
transaction_id='TX123456',
amount=Decimal('299.00'),
currency='MYR',
payment_method='fpx',
status='completed',
payment_date=timezone.now()
)
status = self.service.check_payment_status(payment.transaction_id)
self.assertEqual(status['status'], 'completed')
self.assertEqual(status['amount'], Decimal('299.00'))
def test_validate_payment_method(self):
"""Test payment method validation"""
valid_methods = ['fpx', 'credit_card', 'debit_card', 'ewallet', 'cash']
for method in valid_methods:
is_valid = self.service.validate_payment_method(method)
self.assertTrue(is_valid)
invalid_method = 'invalid_method'
is_valid = self.service.validate_payment_method(invalid_method)
self.assertFalse(is_valid)