1
+ import datetime
1
2
from datetime import datetime as dt , timedelta , timezone
2
3
from unittest .mock import patch
3
4
from urllib .parse import quote
@@ -16,7 +17,7 @@ def setUp(self):
16
17
self .client .force_authenticate (user = None )
17
18
18
19
def test_detail_lookup_returns_401 (self ):
19
- url = reverse ('bot:infraction-detail' , args = (5 ,), host = 'api' )
20
+ url = reverse ('bot:infraction-detail' , args = (6 ,), host = 'api' )
20
21
response = self .client .get (url )
21
22
22
23
self .assertEqual (response .status_code , 401 )
@@ -34,7 +35,7 @@ def test_create_returns_401(self):
34
35
self .assertEqual (response .status_code , 401 )
35
36
36
37
def test_partial_update_returns_401 (self ):
37
- url = reverse ('bot:infraction-detail' , args = (5 ,), host = 'api' )
38
+ url = reverse ('bot:infraction-detail' , args = (6 ,), host = 'api' )
38
39
response = self .client .patch (url , data = {'reason' : 'Have a nice day.' })
39
40
40
41
self .assertEqual (response .status_code , 401 )
@@ -44,7 +45,7 @@ class InfractionTests(APISubdomainTestCase):
44
45
@classmethod
45
46
def setUpTestData (cls ):
46
47
cls .user = User .objects .create (
47
- id = 5 ,
48
+ id = 6 ,
48
49
name = 'james' ,
49
50
discriminator = 1 ,
50
51
)
@@ -64,6 +65,30 @@ def setUpTestData(cls):
64
65
reason = 'James is an ass, and we won\' t be working with him again.' ,
65
66
active = False
66
67
)
68
+ cls .mute_permanent = Infraction .objects .create (
69
+ user_id = cls .user .id ,
70
+ actor_id = cls .user .id ,
71
+ type = 'mute' ,
72
+ reason = 'He has a filthy mouth and I am his soap.' ,
73
+ active = True ,
74
+ expires_at = None
75
+ )
76
+ cls .superstar_expires_soon = Infraction .objects .create (
77
+ user_id = cls .user .id ,
78
+ actor_id = cls .user .id ,
79
+ type = 'superstar' ,
80
+ reason = 'This one doesn\' t matter anymore.' ,
81
+ active = True ,
82
+ expires_at = datetime .datetime .utcnow () + datetime .timedelta (hours = 5 )
83
+ )
84
+ cls .voiceban_expires_later = Infraction .objects .create (
85
+ user_id = cls .user .id ,
86
+ actor_id = cls .user .id ,
87
+ type = 'voice_ban' ,
88
+ reason = 'Jet engine mic' ,
89
+ active = True ,
90
+ expires_at = datetime .datetime .utcnow () + datetime .timedelta (days = 5 )
91
+ )
67
92
68
93
def test_list_all (self ):
69
94
"""Tests the list-view, which should be ordered by inserted_at (newest first)."""
@@ -73,9 +98,12 @@ def test_list_all(self):
73
98
self .assertEqual (response .status_code , 200 )
74
99
infractions = response .json ()
75
100
76
- self .assertEqual (len (infractions ), 2 )
77
- self .assertEqual (infractions [0 ]['id' ], self .ban_inactive .id )
78
- self .assertEqual (infractions [1 ]['id' ], self .ban_hidden .id )
101
+ self .assertEqual (len (infractions ), 5 )
102
+ self .assertEqual (infractions [0 ]['id' ], self .voiceban_expires_later .id )
103
+ self .assertEqual (infractions [1 ]['id' ], self .superstar_expires_soon .id )
104
+ self .assertEqual (infractions [2 ]['id' ], self .mute_permanent .id )
105
+ self .assertEqual (infractions [3 ]['id' ], self .ban_inactive .id )
106
+ self .assertEqual (infractions [4 ]['id' ], self .ban_hidden .id )
79
107
80
108
def test_filter_search (self ):
81
109
url = reverse ('bot:infraction-list' , host = 'api' )
@@ -98,6 +126,140 @@ def test_filter_field(self):
98
126
self .assertEqual (len (infractions ), 1 )
99
127
self .assertEqual (infractions [0 ]['id' ], self .ban_hidden .id )
100
128
129
+ def test_filter_permanent_false (self ):
130
+ url = reverse ('bot:infraction-list' , host = 'api' )
131
+ response = self .client .get (f'{ url } ?type=mute&permanent=false' )
132
+
133
+ self .assertEqual (response .status_code , 200 )
134
+ infractions = response .json ()
135
+
136
+ self .assertEqual (len (infractions ), 0 )
137
+
138
+ def test_filter_permanent_true (self ):
139
+ url = reverse ('bot:infraction-list' , host = 'api' )
140
+ response = self .client .get (f'{ url } ?type=mute&permanent=true' )
141
+
142
+ self .assertEqual (response .status_code , 200 )
143
+ infractions = response .json ()
144
+
145
+ self .assertEqual (infractions [0 ]['id' ], self .mute_permanent .id )
146
+
147
+ def test_filter_after (self ):
148
+ url = reverse ('bot:infraction-list' , host = 'api' )
149
+ target_time = datetime .datetime .utcnow () + datetime .timedelta (hours = 5 )
150
+ response = self .client .get (f'{ url } ?type=superstar&expires_after={ target_time .isoformat ()} ' )
151
+
152
+ self .assertEqual (response .status_code , 200 )
153
+ infractions = response .json ()
154
+ self .assertEqual (len (infractions ), 0 )
155
+
156
+ def test_filter_before (self ):
157
+ url = reverse ('bot:infraction-list' , host = 'api' )
158
+ target_time = datetime .datetime .utcnow () + datetime .timedelta (hours = 5 )
159
+ response = self .client .get (f'{ url } ?type=superstar&expires_before={ target_time .isoformat ()} ' )
160
+
161
+ self .assertEqual (response .status_code , 200 )
162
+ infractions = response .json ()
163
+ self .assertEqual (len (infractions ), 1 )
164
+ self .assertEqual (infractions [0 ]['id' ], self .superstar_expires_soon .id )
165
+
166
+ def test_filter_after_invalid (self ):
167
+ url = reverse ('bot:infraction-list' , host = 'api' )
168
+ response = self .client .get (f'{ url } ?expires_after=gibberish' )
169
+
170
+ self .assertEqual (response .status_code , 400 )
171
+ self .assertEqual (list (response .json ())[0 ], "expires_after" )
172
+
173
+ def test_filter_before_invalid (self ):
174
+ url = reverse ('bot:infraction-list' , host = 'api' )
175
+ response = self .client .get (f'{ url } ?expires_before=000000000' )
176
+
177
+ self .assertEqual (response .status_code , 400 )
178
+ self .assertEqual (list (response .json ())[0 ], "expires_before" )
179
+
180
+ def test_after_before_before (self ):
181
+ url = reverse ('bot:infraction-list' , host = 'api' )
182
+ target_time = datetime .datetime .utcnow () + datetime .timedelta (hours = 4 )
183
+ target_time_late = datetime .datetime .utcnow () + datetime .timedelta (hours = 6 )
184
+ response = self .client .get (
185
+ f'{ url } ?expires_before={ target_time_late .isoformat ()} '
186
+ f'&expires_after={ target_time .isoformat ()} '
187
+ )
188
+
189
+ self .assertEqual (response .status_code , 200 )
190
+ self .assertEqual (len (response .json ()), 1 )
191
+ self .assertEqual (response .json ()[0 ]["id" ], self .superstar_expires_soon .id )
192
+
193
+ def test_after_after_before_invalid (self ):
194
+ url = reverse ('bot:infraction-list' , host = 'api' )
195
+ target_time = datetime .datetime .utcnow () + datetime .timedelta (hours = 5 )
196
+ target_time_late = datetime .datetime .utcnow () + datetime .timedelta (hours = 9 )
197
+ response = self .client .get (
198
+ f'{ url } ?expires_before={ target_time .isoformat ()} '
199
+ f'&expires_after={ target_time_late .isoformat ()} '
200
+ )
201
+
202
+ self .assertEqual (response .status_code , 400 )
203
+ errors = list (response .json ())
204
+ self .assertIn ("expires_before" , errors )
205
+ self .assertIn ("expires_after" , errors )
206
+
207
+ def test_permanent_after_invalid (self ):
208
+ url = reverse ('bot:infraction-list' , host = 'api' )
209
+ target_time = datetime .datetime .utcnow () + datetime .timedelta (hours = 5 )
210
+ response = self .client .get (f'{ url } ?permanent=true&expires_after={ target_time .isoformat ()} ' )
211
+
212
+ self .assertEqual (response .status_code , 400 )
213
+ errors = list (response .json ())
214
+ self .assertEqual ("permanent" , errors [0 ])
215
+
216
+ def test_permanent_before_invalid (self ):
217
+ url = reverse ('bot:infraction-list' , host = 'api' )
218
+ target_time = datetime .datetime .utcnow () + datetime .timedelta (hours = 5 )
219
+ response = self .client .get (f'{ url } ?permanent=true&expires_before={ target_time .isoformat ()} ' )
220
+
221
+ self .assertEqual (response .status_code , 400 )
222
+ errors = list (response .json ())
223
+ self .assertEqual ("permanent" , errors [0 ])
224
+
225
+ def test_nonpermanent_before (self ):
226
+ url = reverse ('bot:infraction-list' , host = 'api' )
227
+ target_time = datetime .datetime .utcnow () + datetime .timedelta (hours = 6 )
228
+ response = self .client .get (
229
+ f'{ url } ?permanent=false&expires_before={ target_time .isoformat ()} '
230
+ )
231
+
232
+ self .assertEqual (response .status_code , 200 )
233
+ self .assertEqual (len (response .json ()), 1 )
234
+ self .assertEqual (response .json ()[0 ]["id" ], self .superstar_expires_soon .id )
235
+
236
+ def test_filter_manytypes (self ):
237
+ url = reverse ('bot:infraction-list' , host = 'api' )
238
+ response = self .client .get (f'{ url } ?types=mute,ban' )
239
+
240
+ self .assertEqual (response .status_code , 200 )
241
+ infractions = response .json ()
242
+ self .assertEqual (len (infractions ), 3 )
243
+
244
+ def test_types_type_invalid (self ):
245
+ url = reverse ('bot:infraction-list' , host = 'api' )
246
+ response = self .client .get (f'{ url } ?types=mute,ban&type=superstar' )
247
+
248
+ self .assertEqual (response .status_code , 400 )
249
+ errors = list (response .json ())
250
+ self .assertEqual ("types" , errors [0 ])
251
+
252
+ def test_sort_expiresby (self ):
253
+ url = reverse ('bot:infraction-list' , host = 'api' )
254
+ response = self .client .get (f'{ url } ?ordering=expires_at&permanent=false' )
255
+ self .assertEqual (response .status_code , 200 )
256
+ infractions = response .json ()
257
+
258
+ self .assertEqual (len (infractions ), 3 )
259
+ self .assertEqual (infractions [0 ]['id' ], self .superstar_expires_soon .id )
260
+ self .assertEqual (infractions [1 ]['id' ], self .voiceban_expires_later .id )
261
+ self .assertEqual (infractions [2 ]['id' ], self .ban_hidden .id )
262
+
101
263
def test_returns_empty_for_no_match (self ):
102
264
url = reverse ('bot:infraction-list' , host = 'api' )
103
265
response = self .client .get (f'{ url } ?type=ban&search=poop' )
@@ -502,7 +664,10 @@ def test_unique_constraint_accepts_active_infractions_for_different_users(self):
502
664
)
503
665
504
666
def test_integrity_error_if_missing_active_field (self ):
505
- pattern = 'null value in column "active" violates not-null constraint'
667
+ pattern = (
668
+ 'null value in column "active" (of relation "api_infraction" )?'
669
+ 'violates not-null constraint'
670
+ )
506
671
with self .assertRaisesRegex (IntegrityError , pattern ):
507
672
Infraction .objects .create (
508
673
user = self .user ,
0 commit comments