11from django .contrib .auth .models import User
2+ from apps .users .models import Profile
23from django .urls import reverse
34from rest_framework import status
45from rest_framework .test import APITestCase , APIClient
5- from .models import Chat , Message
6+ from django .test import TestCase
7+ from apps .chat .models import Chat , Message , MutedUser , BlockedUser , ReportedUser
68from apps .chat .consumers import ChatConsumer
9+ from django .utils .timezone import now
10+ import time
11+ from django .core .exceptions import ValidationError
712
813def test_chat_consumer_init ():
914 consumer = ChatConsumer ()
1015 assert consumer is not None
1116
1217class ChatAPITestCase (APITestCase ):
13-
1418 def setUp (self ):
1519 self .user1 = User .objects .create_user (username = 'alice' , password = 'pass1234' )
1620 self .user2 = User .objects .create_user (username = 'bob' , password = 'pass1234' )
@@ -63,21 +67,197 @@ def test_send_message(self):
6367 self .assertEqual (message .content , 'Hello Bob!' )
6468 self .assertEqual (message .sender , self .user1 )
6569
70+ def test_create_chat_missing_user2 (self ):
71+ url = reverse ('chat-list' )
72+ response = self .client .post (url , {}) # Missing "user2"
73+ self .assertEqual (response .status_code , 400 )
74+ self .assertIn ("user2" , response .data )
6675
67- def test_list_chat_messages (self ):
68- chat , created = Chat .objects .get_or_create_chat (self .user1 , self .user2 )
69- Message .objects .create (chat = chat , sender = self .user1 , content = 'Hi Bob!' )
70- Message .objects .create (chat = chat , sender = self .user2 , content = 'Hey Alice!' )
76+ def test_create_chat_user2_not_found (self ):
77+ url = reverse ('chat-list' )
78+ response = self .client .post (url , {"user2" : 9999 }) # non-existent ID
79+ self .assertEqual (response .status_code , 400 )
80+ self .assertIn ("user2" , response .data )
7181
72- url = reverse ('chat-messages' , kwargs = {'pk' : chat .id })
82+ def test_create_chat_already_exists (self ):
83+ Chat .objects .get_or_create_chat (self .user1 , self .user2 )
84+ url = reverse ('chat-list' )
85+ response = self .client .post (url , {"user2" : self .user2 .id })
86+ self .assertEqual (response .status_code , 400 )
87+ self .assertIn ("Chat already exists" , str (response .data ))
88+
89+ def test_get_messages_custom_action (self ):
90+ chat , _ = Chat .objects .get_or_create_chat (self .user1 , self .user2 )
91+ Message .objects .create (chat = chat , sender = self .user1 , content = "Hello!" )
92+ url = reverse ('chat-messages' , args = [chat .id ]) # Must match router name
93+ response = self .client .get (url )
94+ self .assertEqual (response .status_code , 200 )
95+ self .assertEqual (len (response .data ), 1 )
96+ self .assertEqual (response .data [0 ]['content' ], "Hello!" )
97+
98+ # https://chatgpt.com/share/681180bd-8930-800c-9f58-8f4de378d8e2
99+ class ChatModelTests (TestCase ):
100+ def setUp (self ):
101+ self .user1 = User .objects .create_user (username = 'alice' , password = 'pass1234' )
102+ self .user2 = User .objects .create_user (username = 'bob' , password = 'pass1234' )
103+ self .profile1 = Profile .objects .create (user = self .user1 , role = 1 )
104+ self .profile2 = Profile .objects .create (user = self .user2 , role = 1 )
105+
106+ def test_chat_str (self ):
107+ chat = Chat .objects .create (user1 = self .user1 , user2 = self .user2 )
108+ expected_str = f"Chat between { self .user1 } and { self .user2 } "
109+ self .assertEqual (str (chat ), expected_str )
110+
111+ def test_message_str (self ):
112+ chat = Chat .objects .create (user1 = self .user1 , user2 = self .user2 )
113+ message = Message .objects .create (chat = chat , sender = self .user1 , content = "Hello!" , timestamp = now ())
114+ expected_str = f"From { self .user1 } in Chat { chat .id } at { message .timestamp } "
115+ self .assertEqual (str (message ), expected_str )
116+
117+ def test_muted_user_str (self ):
118+ muted = MutedUser .objects .create (muted_user = self .profile2 , muted_by = self .profile1 )
119+ expected_str = f"{ self .profile1 } muted { self .profile2 } "
120+ self .assertEqual (str (muted ), expected_str )
121+
122+ def test_blocked_user_str (self ):
123+ blocked = BlockedUser .objects .create (blocked_user = self .profile2 , blocked_by = self .profile1 )
124+ expected_str = f"{ self .profile1 } blocked { self .profile2 } "
125+ self .assertEqual (str (blocked ), expected_str )
126+
127+ def test_reported_user_str (self ):
128+ reported = ReportedUser .objects .create (reported_user = self .profile2 , reported_by = self .profile1 , reason = "Spam" )
129+ expected_str = f"{ self .profile1 } reported { self .profile2 } "
130+ self .assertEqual (str (reported ), expected_str )
131+
132+ def test_muted_user_clean_valid (self ):
133+ muted = MutedUser (muted_user = self .profile2 , muted_by = self .profile1 )
134+ muted .clean () # Should not raise
135+
136+ def test_muted_user_clean_invalid (self ):
137+ muted = MutedUser (muted_user = self .profile1 , muted_by = self .profile1 )
138+ with self .assertRaises (ValidationError ) as context :
139+ muted .clean ()
140+ self .assertIn ("You cannot mute yourself." , str (context .exception ))
141+
142+ def test_blocked_user_clean_valid (self ):
143+ blocked = BlockedUser (blocked_user = self .profile2 , blocked_by = self .profile1 )
144+ blocked .clean () # should not raise
145+
146+ def test_blocked_user_clean_invalid (self ):
147+ blocked = BlockedUser (blocked_user = self .profile1 , blocked_by = self .profile1 )
148+ with self .assertRaises (ValidationError ) as context :
149+ blocked .clean ()
150+ self .assertIn ("You cannot block yourself." , str (context .exception ))
151+
152+ class ChatManagerTests (TestCase ):
153+ def setUp (self ):
154+ self .user1 = User .objects .create_user (username = 'alice' , password = 'pass1234' )
155+ self .user2 = User .objects .create_user (username = 'bob' , password = 'pass1234' )
156+ self .profile1 = Profile .objects .create (user = self .user1 , role = 1 )
157+ self .profile2 = Profile .objects .create (user = self .user2 , role = 1 )
158+ self .chat , _ = Chat .objects .get_or_create_chat (self .user1 , self .user2 )
159+
160+ def test_get_or_create_chat_orders_users (self ):
161+ Chat .objects .all ().delete ()
162+ chat1 , created1 = Chat .objects .get_or_create_chat (self .user2 , self .user1 )
163+ self .assertTrue (created1 )
164+ self .assertEqual (chat1 .user1 , min (self .user1 , self .user2 , key = lambda u : u .id ))
165+ self .assertEqual (chat1 .user2 , max (self .user1 , self .user2 , key = lambda u : u .id ))
166+
167+ # should not create a new one
168+ chat2 , created2 = Chat .objects .get_or_create_chat (self .user1 , self .user2 )
169+ self .assertFalse (created2 )
170+ self .assertEqual (chat1 .id , chat2 .id )
171+
172+ def test_get_other_user (self ):
173+ chat , _ = Chat .objects .get_or_create_chat (self .user1 , self .user2 )
174+ self .assertEqual (Chat .objects .get_other_user (chat , self .user1 ), self .user2 )
175+ self .assertEqual (Chat .objects .get_other_user (chat , self .user2 ), self .user1 )
176+
177+ def test_user_blocked_or_muted_blocked (self ):
178+ chat , _ = Chat .objects .get_or_create_chat (self .user1 , self .user2 )
179+ BlockedUser .objects .create (blocked_by = self .profile2 , blocked_user = self .profile1 )
180+
181+ with self .assertRaises (PermissionError ) as ctx :
182+ Chat .objects .user_blocked_or_muted (chat , self .user1 )
183+ self .assertIn ("blocked" , str (ctx .exception ))
184+
185+ def test_user_blocked_or_muted_muted (self ):
186+ chat , _ = Chat .objects .get_or_create_chat (self .user1 , self .user2 )
187+ MutedUser .objects .create (muted_by = self .profile2 , muted_user = self .profile1 )
188+
189+ with self .assertRaises (PermissionError ) as ctx :
190+ Chat .objects .user_blocked_or_muted (chat , self .user1 )
191+ self .assertIn ("muted" , str (ctx .exception ))
192+
193+ def test_create_message_and_update_timestamp (self ):
194+ old_updated_at = self .chat .updatedAt
195+ time .sleep (0.01 ) # Make sure timestamp will differ
196+ msg = Message .objects .create_message (chat = self .chat , sender = self .user1 , content = "hello!" )
197+
198+ self .chat .refresh_from_db ()
199+ self .assertEqual (msg .content , "hello!" )
200+ self .assertEqual (msg .chat , self .chat )
201+ self .assertGreater (self .chat .updatedAt , old_updated_at )
202+
203+ class MuteBlockReportAPITests (APITestCase ):
204+ def setUp (self ):
205+ self .user1 = User .objects .create_user (username = 'alice' , password = 'pass1234' )
206+ self .user2 = User .objects .create_user (username = 'bob' , password = 'pass1234' )
207+ self .profile1 = Profile .objects .create (user = self .user1 , role = 1 )
208+ self .profile2 = Profile .objects .create (user = self .user2 , role = 1 )
209+
210+ self .client = APIClient ()
211+ self .client .force_authenticate (user = self .user1 )
212+
213+ def test_mute_user (self ):
214+ url = reverse ('mute-list' )
215+ payload = {"muted_user" : self .profile2 .id }
216+ response = self .client .post (url , payload )
217+ self .assertEqual (response .status_code , status .HTTP_201_CREATED )
218+ self .assertEqual (MutedUser .objects .count (), 1 )
219+
220+ def test_duplicate_mute_user (self ):
221+ MutedUser .objects .create (muted_user = self .profile2 , muted_by = self .profile1 )
222+ url = reverse ('mute-list' )
223+ payload = {"muted_user" : self .profile2 .id }
224+ response = self .client .post (url , payload )
225+ self .assertEqual (response .status_code , status .HTTP_400_BAD_REQUEST )
226+
227+ def test_block_user (self ):
228+ url = reverse ('block-list' )
229+ payload = {"blocked_user" : self .profile2 .id }
230+ response = self .client .post (url , payload )
231+ self .assertEqual (response .status_code , status .HTTP_201_CREATED )
232+ self .assertEqual (BlockedUser .objects .count (), 1 )
233+
234+ def test_duplicate_block_user (self ):
235+ BlockedUser .objects .create (blocked_user = self .profile2 , blocked_by = self .profile1 )
236+ url = reverse ('block-list' )
237+ payload = {"blocked_user" : self .profile2 .id }
238+ response = self .client .post (url , payload )
239+ self .assertEqual (response .status_code , status .HTTP_400_BAD_REQUEST )
240+
241+ def test_report_user (self ):
242+ url = reverse ('report-list' )
243+ payload = {
244+ "reported_user" : self .profile2 .id ,
245+ "reason" : "Spam"
246+ }
247+ response = self .client .post (url , payload )
248+ self .assertEqual (response .status_code , status .HTTP_201_CREATED )
249+ self .assertEqual (ReportedUser .objects .count (), 1 )
250+
251+ def test_list_blocked_users (self ):
252+ BlockedUser .objects .create (blocked_user = self .profile2 , blocked_by = self .profile1 )
253+ url = reverse ('block-list' )
73254 response = self .client .get (url )
74255 self .assertEqual (response .status_code , status .HTTP_200_OK )
75- self .assertEqual (len (response .data ), 2 )
76- self .assertEqual (response .data [0 ]['content' ], 'Hi Bob!' )
77- self .assertEqual (response .data [1 ]['content' ], 'Hey Alice!' )
256+ self .assertEqual (len (response .data ), 1 )
78257
79- def test_unauthenticated_access (self ):
80- self . client . logout ( )
81- url = reverse ('chat -list' )
258+ def test_list_reported_users (self ):
259+ ReportedUser . objects . create ( reported_user = self . profile2 , reported_by = self . profile1 , reason = "Spam" )
260+ url = reverse ('report -list' )
82261 response = self .client .get (url )
83- self .assertEqual (response .status_code , status .HTTP_401_UNAUTHORIZED )
262+ self .assertEqual (response .status_code , status .HTTP_200_OK )
263+ self .assertEqual (len (response .data ), 1 )
0 commit comments