from django.test import TestCase from django.urls import reverse from rest_framework.test import APITestCase, APIClient from rest_framework import status from unittest.mock import patch, MagicMock from .models import User, FriendRequest, Invitation, UsernameUserManager from torrent.models import Torrent from .views import UserViewSet, FriendRequestViewSet class UserModelTestCase(TestCase): def setUp(self): self.user = User.objects.create_user( username='testuser', email='test@example.com', password='testpassword', max_size=1000000 ) self.friend = User.objects.create_user( username='frienduser', email='friend@example.com', password='friendpassword' ) def test_size_used_property(self): """Test the size_used property returns the correct total size of user's torrents""" # Initially no torrents, so size should be 0 self.assertEqual(self.user.size_used, 0) # Create a torrent for the user Torrent.objects.create( id='abc123', name='Test Torrent', user=self.user, size=5000, transmission_data={} ) # Create another torrent Torrent.objects.create( id='def456', name='Another Torrent', user=self.user, size=3000, transmission_data={} ) # Clear cached_property if it exists if hasattr(self.user, 'total_size'): delattr(self.user, 'total_size') # Size used should be the sum of torrent sizes self.assertEqual(self.user.size_used, 8000) def test_min_infos_property(self): """Test the min_infos property returns the correct user info""" expected_info = { 'username': 'testuser', 'id': self.user.id } self.assertEqual(self.user.min_infos, expected_info) class UsernameUserManagerTestCase(TestCase): def test_create_user(self): """Test creating a regular user""" user = User.objects.create_user( username='newuser', email='new@example.com', password='newpassword' ) self.assertFalse(user.is_staff) self.assertFalse(user.is_superuser) self.assertEqual(user.username, 'newuser') self.assertEqual(user.email, 'new@example.com') self.assertTrue(user.check_password('newpassword')) def test_create_superuser(self): """Test creating a superuser""" admin = User.objects.create_superuser( username='admin', email='admin@example.com', password='adminpassword' ) self.assertTrue(admin.is_staff) self.assertTrue(admin.is_superuser) self.assertEqual(admin.username, 'admin') self.assertEqual(admin.email, 'admin@example.com') def test_create_user_without_username(self): """Test creating a user without username raises error""" with self.assertRaises(ValueError): User.objects.create_user( username='', email='test@example.com', password='testpassword' ) def test_create_user_without_email(self): """Test creating a user without email raises error""" with self.assertRaises(ValueError): User.objects.create_user( username='testuser', email='', password='testpassword' ) class FriendRequestModelTestCase(TestCase): def setUp(self): self.sender = User.objects.create_user( username='sender', email='sender@example.com', password='senderpassword' ) self.receiver = User.objects.create_user( username='receiver', email='receiver@example.com', password='receiverpassword' ) def test_friend_request_creation(self): """Test creating a friend request""" friend_request = FriendRequest.objects.create( sender=self.sender, receiver=self.receiver ) self.assertEqual(friend_request.sender, self.sender) self.assertEqual(friend_request.receiver, self.receiver) def test_unique_together_constraint(self): """Test that the unique_together constraint works""" FriendRequest.objects.create( sender=self.sender, receiver=self.receiver ) # Creating another request with the same sender and receiver should raise an error with self.assertRaises(Exception): FriendRequest.objects.create( sender=self.sender, receiver=self.receiver ) class InvitationModelTestCase(TestCase): def setUp(self): self.creator = User.objects.create_user( username='creator', email='creator@example.com', password='creatorpassword' ) def test_invitation_creation(self): """Test creating an invitation""" invitation = Invitation.objects.create( created_by=self.creator ) self.assertEqual(invitation.created_by, self.creator) self.assertIsNotNone(invitation.token) self.assertIsNone(invitation.user) def test_invitation_assignment(self): """Test assigning an invitation to a user""" invitation = Invitation.objects.create( created_by=self.creator ) new_user = User.objects.create_user( username='newuser', email='new@example.com', password='newpassword' ) invitation.user = new_user invitation.save() # Refresh from database invitation.refresh_from_db() self.assertEqual(invitation.user, new_user) class UserViewSetTestCase(APITestCase): def setUp(self): self.user = User.objects.create_user( username='testuser', email='test@example.com', password='testpassword' ) self.friend = User.objects.create_user( username='frienduser', email='friend@example.com', password='friendpassword' ) self.client = APIClient() self.client.force_authenticate(user=self.user) def test_list_users(self): """Test listing users""" url = reverse('user-list') response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data), 2) # Should include both users def test_retrieve_user(self): """Test retrieving a specific user""" url = reverse('user-detail', args=[self.friend.id]) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['username'], 'frienduser') def test_add_friend_request(self): """Test adding a friend request""" url = reverse('user-add-friend-request', args=[self.friend.username]) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertTrue(response.data['success']) self.assertEqual(response.data['message'], 'Request sent') # Verify the friend request was created self.assertTrue(FriendRequest.objects.filter( sender=self.user, receiver=self.friend ).exists()) def test_add_friend_request_nonexistent_user(self): """Test adding a friend request to a nonexistent user""" url = reverse('user-add-friend-request', args=['nonexistentuser']) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertFalse(response.data['success']) self.assertEqual(response.data['message'], "User 'nonexistentuser' doesn't exist") def test_remove_friend(self): """Test removing a friend""" # First add as friend self.user.friends.add(self.friend) url = reverse('user-remove-friend', args=[self.friend.id]) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertTrue(response.data['success']) # Verify the friend was removed self.assertFalse(self.user.friends.filter(id=self.friend.id).exists()) @patch('user.views.shutil.disk_usage') def test_user_stats(self, mock_disk_usage): """Test getting user stats""" # Mock disk_usage return value mock_disk_usage.return_value = MagicMock( total=1000000, used=500000, free=500000 ) # Create torrents for the user Torrent.objects.create( id='abc123', name='Test Torrent', user=self.user, size=5000, transmission_data={} ) url = reverse('user-user-stats') response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) # Check that the response contains the expected fields self.assertIn('torrents_size', response.data) self.assertIn('torrents_len', response.data) self.assertIn('user_max_size', response.data) self.assertIn('disk_total', response.data) self.assertIn('disk_used', response.data) self.assertIn('disk_free', response.data) class FriendRequestViewSetTestCase(APITestCase): def setUp(self): self.user = User.objects.create_user( username='testuser', email='test@example.com', password='testpassword' ) self.sender = User.objects.create_user( username='sender', email='sender@example.com', password='senderpassword' ) self.client = APIClient() self.client.force_authenticate(user=self.user) # Create a friend request self.friend_request = FriendRequest.objects.create( sender=self.sender, receiver=self.user ) def test_list_friend_requests(self): """Test listing friend requests""" url = reverse('friendrequest-list') response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data), 1) self.assertEqual(response.data[0]['sender']['username'], 'sender') def test_delete_friend_request(self): """Test deleting a friend request""" url = reverse('friendrequest-detail', args=[self.friend_request.id]) response = self.client.delete(url) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) # Verify the friend request was deleted self.assertFalse(FriendRequest.objects.filter(id=self.friend_request.id).exists())