]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/tests/api/check-params/users.ts
Fix URI search config update
[github/Chocobozzz/PeerTube.git] / server / tests / api / check-params / users.ts
CommitLineData
a1587156 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
0e1dc3e7 2
0e1dc3e7 3import 'mocha'
b488ba1e
C
4import { expect } from 'chai'
5import { omit } from 'lodash'
47564bbe 6import { join } from 'path'
a95a4cc8 7import { User, UserRole, VideoImport, VideoImportState } from '../../../../shared'
0e1dc3e7 8import {
e590b4a5 9 addVideoChannel,
42e1ec25 10 blockUser,
7c3b7976 11 cleanupTests,
42e1ec25
C
12 createUser,
13 deleteMe,
14 flushAndRunServer,
15 getMyUserInformation,
16 getMyUserVideoRating,
18490b07 17 getUserScopedTokens,
42e1ec25
C
18 getUsersList,
19 immutableAssign,
45f1bd72 20 killallServers,
42e1ec25
C
21 makeGetRequest,
22 makePostBodyRequest,
23 makePutBodyRequest,
24 makeUploadRequest,
25 registerUser,
26 removeUser,
18490b07 27 renewUserScopedTokens,
45f1bd72 28 reRunServer,
42e1ec25
C
29 ServerInfo,
30 setAccessTokensToServers,
31 unblockUser,
32 updateUser,
33 uploadVideo,
34 userLogin
94565d52 35} from '../../../../shared/extra-utils'
b488ba1e 36import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
9639bd17 37import {
38 checkBadCountPagination,
39 checkBadSortPagination,
40 checkBadStartPagination
94565d52 41} from '../../../../shared/extra-utils/requests/check-api-params'
94565d52 42import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
18490b07 43import { getGoodVideoUrl, getMagnetURI, getMyVideoImports, importVideo } from '../../../../shared/extra-utils/videos/video-imports'
1eddc9a7 44import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
b488ba1e 45import { VideoPrivacy } from '../../../../shared/models/videos'
2d53be02 46import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
0e1dc3e7
C
47
48describe('Test users API validators', function () {
49 const path = '/api/v1/users/'
50 let userId: number
51 let rootId: number
a95a4cc8 52 let moderatorId: number
0e1dc3e7
C
53 let videoId: number
54 let server: ServerInfo
55 let serverWithRegistrationDisabled: ServerInfo
56 let userAccessToken = ''
a95a4cc8 57 let moderatorAccessToken = ''
45f1bd72
JL
58 let emailPort: number
59 let overrideConfig: Object
0e1dc3e7
C
60
61 // ---------------------------------------------------------------
62
63 before(async function () {
e212f887 64 this.timeout(30000)
0e1dc3e7 65
45f1bd72
JL
66 const emails: object[] = []
67 emailPort = await MockSmtpServer.Instance.collectEmails(emails)
68
69 overrideConfig = { signup: { limit: 8 } }
70
a95a4cc8
C
71 {
72 const res = await Promise.all([
45f1bd72 73 flushAndRunServer(1, overrideConfig),
a95a4cc8
C
74 flushAndRunServer(2)
75 ])
0e1dc3e7 76
a95a4cc8
C
77 server = res[0]
78 serverWithRegistrationDisabled = res[1]
0e1dc3e7 79
a95a4cc8
C
80 await setAccessTokensToServers([ server ])
81 }
82
83 {
84 const user = {
85 username: 'user1',
86 password: 'my super password'
87 }
88
89 const videoQuota = 42000000
90 await createUser({
91 url: server.url,
92 accessToken: server.accessToken,
93 username: user.username,
94 password: user.password,
95 videoQuota: videoQuota
96 })
97 userAccessToken = await userLogin(server, user)
98 }
99
100 {
101 const moderator = {
102 username: 'moderator1',
103 password: 'super password'
104 }
105
106 await createUser({
107 url: server.url,
108 accessToken: server.accessToken,
109 username: moderator.username,
110 password: moderator.password,
111 role: UserRole.MODERATOR
112 })
113
114 moderatorAccessToken = await userLogin(server, moderator)
115 }
116
117 {
118 const moderator = {
119 username: 'moderator2',
120 password: 'super password'
121 }
122
123 await createUser({
124 url: server.url,
125 accessToken: server.accessToken,
126 username: moderator.username,
127 password: moderator.password,
128 role: UserRole.MODERATOR
129 })
130 }
26d21b78 131
187501f8
C
132 {
133 const res = await uploadVideo(server.url, server.accessToken, {})
134 videoId = res.body.video.id
135 }
a95a4cc8
C
136
137 {
138 const res = await getUsersList(server.url, server.accessToken)
139 const users: User[] = res.body.data
140
141 userId = users.find(u => u.username === 'user1').id
142 rootId = users.find(u => u.username === 'root').id
143 moderatorId = users.find(u => u.username === 'moderator2').id
144 }
0e1dc3e7
C
145 })
146
147 describe('When listing users', function () {
148 it('Should fail with a bad start pagination', async function () {
26d21b78 149 await checkBadStartPagination(server.url, path, server.accessToken)
0e1dc3e7
C
150 })
151
152 it('Should fail with a bad count pagination', async function () {
26d21b78 153 await checkBadCountPagination(server.url, path, server.accessToken)
0e1dc3e7
C
154 })
155
156 it('Should fail with an incorrect sort', async function () {
26d21b78 157 await checkBadSortPagination(server.url, path, server.accessToken)
0e1dc3e7 158 })
86d13ec2
C
159
160 it('Should fail with a non authenticated user', async function () {
26d21b78
C
161 await makeGetRequest({
162 url: server.url,
163 path,
2d53be02 164 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
26d21b78 165 })
86d13ec2
C
166 })
167
168 it('Should fail with a non admin user', async function () {
26d21b78
C
169 await makeGetRequest({
170 url: server.url,
171 path,
172 token: userAccessToken,
2d53be02 173 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
26d21b78 174 })
86d13ec2 175 })
0e1dc3e7
C
176 })
177
178 describe('When adding a new user', function () {
26d21b78
C
179 const baseCorrectParams = {
180 username: 'user2',
181 email: 'test@example.com',
182 password: 'my super password',
183 videoQuota: -1,
bee0abff 184 videoQuotaDaily: -1,
1eddc9a7 185 role: UserRole.USER,
3487330d 186 adminFlags: UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST
26d21b78
C
187 }
188
0e1dc3e7 189 it('Should fail with a too small username', async function () {
d0ce42c1 190 const fields = immutableAssign(baseCorrectParams, { username: '' })
0e1dc3e7
C
191
192 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
193 })
194
195 it('Should fail with a too long username', async function () {
9f7a1953 196 const fields = immutableAssign(baseCorrectParams, { username: 'super'.repeat(50) })
0e1dc3e7
C
197
198 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
199 })
200
563d032e 201 it('Should fail with a not lowercase username', async function () {
26d21b78 202 const fields = immutableAssign(baseCorrectParams, { username: 'Toto' })
563d032e
C
203
204 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
205 })
206
0e1dc3e7 207 it('Should fail with an incorrect username', async function () {
26d21b78 208 const fields = immutableAssign(baseCorrectParams, { username: 'my username' })
0e1dc3e7
C
209
210 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
211 })
212
213 it('Should fail with a missing email', async function () {
26d21b78 214 const fields = omit(baseCorrectParams, 'email')
0e1dc3e7
C
215
216 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
217 })
218
219 it('Should fail with an invalid email', async function () {
26d21b78 220 const fields = immutableAssign(baseCorrectParams, { email: 'test_example.com' })
0e1dc3e7
C
221
222 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
223 })
224
225 it('Should fail with a too small password', async function () {
26d21b78 226 const fields = immutableAssign(baseCorrectParams, { password: 'bla' })
0e1dc3e7
C
227
228 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
229 })
230
231 it('Should fail with a too long password', async function () {
26d21b78 232 const fields = immutableAssign(baseCorrectParams, { password: 'super'.repeat(61) })
0e1dc3e7
C
233
234 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
235 })
236
45f1bd72
JL
237 it('Should fail with empty password and no smtp configured', async function () {
238 const fields = immutableAssign(baseCorrectParams, { password: '' })
239
240 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
241 })
242
243 it('Should succeed with no password on a server with smtp enabled', async function () {
244 this.timeout(10000)
245
246 killallServers([ server ])
247
248 const config = immutableAssign(overrideConfig, {
249 smtp: {
250 hostname: 'localhost',
251 port: emailPort
252 }
253 })
254 await reRunServer(server, config)
255
256 const fields = immutableAssign(baseCorrectParams, {
257 password: '',
258 username: 'create_password',
259 email: 'create_password@example.com'
260 })
261
262 await makePostBodyRequest({
263 url: server.url,
264 path: path,
265 token: server.accessToken,
266 fields,
2d53be02 267 statusCodeExpected: HttpStatusCode.OK_200
45f1bd72
JL
268 })
269 })
270
1eddc9a7
C
271 it('Should fail with invalid admin flags', async function () {
272 const fields = immutableAssign(baseCorrectParams, { adminFlags: 'toto' })
273
274 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
275 })
276
0e1dc3e7 277 it('Should fail with an non authenticated user', async function () {
26d21b78
C
278 await makePostBodyRequest({
279 url: server.url,
280 path,
281 token: 'super token',
282 fields: baseCorrectParams,
2d53be02 283 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
26d21b78 284 })
0e1dc3e7
C
285 })
286
287 it('Should fail if we add a user with the same username', async function () {
26d21b78 288 const fields = immutableAssign(baseCorrectParams, { username: 'user1' })
0e1dc3e7 289
2d53be02
RK
290 await makePostBodyRequest({
291 url: server.url,
292 path,
293 token: server.accessToken,
294 fields,
295 statusCodeExpected: HttpStatusCode.CONFLICT_409
296 })
0e1dc3e7
C
297 })
298
299 it('Should fail if we add a user with the same email', async function () {
26d21b78 300 const fields = immutableAssign(baseCorrectParams, { email: 'user1@example.com' })
0e1dc3e7 301
2d53be02
RK
302 await makePostBodyRequest({
303 url: server.url,
304 path,
305 token: server.accessToken,
306 fields,
307 statusCodeExpected: HttpStatusCode.CONFLICT_409
308 })
0e1dc3e7
C
309 })
310
77a5501f 311 it('Should fail without a videoQuota', async function () {
26d21b78 312 const fields = omit(baseCorrectParams, 'videoQuota')
77a5501f
C
313
314 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
315 })
316
bee0abff
FA
317 it('Should fail without a videoQuotaDaily', async function () {
318 const fields = omit(baseCorrectParams, 'videoQuotaDaily')
319
320 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
321 })
322
77a5501f 323 it('Should fail with an invalid videoQuota', async function () {
26d21b78 324 const fields = immutableAssign(baseCorrectParams, { videoQuota: -5 })
757f0da3
C
325
326 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
327 })
328
bee0abff
FA
329 it('Should fail with an invalid videoQuotaDaily', async function () {
330 const fields = immutableAssign(baseCorrectParams, { videoQuotaDaily: -7 })
331
332 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
333 })
334
757f0da3 335 it('Should fail without a user role', async function () {
26d21b78 336 const fields = omit(baseCorrectParams, 'role')
757f0da3
C
337
338 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
339 })
340
341 it('Should fail with an invalid user role', async function () {
26d21b78 342 const fields = immutableAssign(baseCorrectParams, { role: 88989 })
77a5501f
C
343
344 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
345 })
346
2ef6a063
C
347 it('Should fail with a "peertube" username', async function () {
348 const fields = immutableAssign(baseCorrectParams, { username: 'peertube' })
349
350 await makePostBodyRequest({
351 url: server.url,
352 path,
353 token: server.accessToken,
354 fields,
2d53be02 355 statusCodeExpected: HttpStatusCode.CONFLICT_409
2ef6a063
C
356 })
357 })
358
a95a4cc8
C
359 it('Should fail to create a moderator or an admin with a moderator', async function () {
360 for (const role of [ UserRole.MODERATOR, UserRole.ADMINISTRATOR ]) {
361 const fields = immutableAssign(baseCorrectParams, { role })
362
363 await makePostBodyRequest({
364 url: server.url,
365 path,
366 token: moderatorAccessToken,
367 fields,
2d53be02 368 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
a95a4cc8
C
369 })
370 }
371 })
372
373 it('Should succeed to create a user with a moderator', async function () {
374 const fields = immutableAssign(baseCorrectParams, { username: 'a4656', email: 'a4656@example.com', role: UserRole.USER })
375
376 await makePostBodyRequest({
377 url: server.url,
378 path,
379 token: moderatorAccessToken,
380 fields,
2d53be02 381 statusCodeExpected: HttpStatusCode.OK_200
a95a4cc8
C
382 })
383 })
384
0e1dc3e7 385 it('Should succeed with the correct params', async function () {
26d21b78
C
386 await makePostBodyRequest({
387 url: server.url,
388 path,
389 token: server.accessToken,
390 fields: baseCorrectParams,
2d53be02 391 statusCodeExpected: HttpStatusCode.OK_200
26d21b78 392 })
0e1dc3e7
C
393 })
394
395 it('Should fail with a non admin user', async function () {
26d21b78 396 const user = {
0e1dc3e7 397 username: 'user1',
0e1dc3e7
C
398 password: 'my super password'
399 }
26d21b78 400 userAccessToken = await userLogin(server, user)
0e1dc3e7 401
0e1dc3e7
C
402 const fields = {
403 username: 'user3',
404 email: 'test@example.com',
77a5501f
C
405 password: 'my super password',
406 videoQuota: 42000000
0e1dc3e7 407 }
2d53be02 408 await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields, statusCodeExpected: HttpStatusCode.FORBIDDEN_403 })
0e1dc3e7
C
409 })
410 })
411
77a5501f
C
412 describe('When updating my account', function () {
413 it('Should fail with an invalid email attribute', async function () {
414 const fields = {
415 email: 'blabla'
416 }
0e1dc3e7 417
77a5501f 418 await makePutBodyRequest({ url: server.url, path: path + 'me', token: server.accessToken, fields })
0e1dc3e7
C
419 })
420
421 it('Should fail with a too small password', async function () {
422 const fields = {
a890d1e0 423 currentPassword: 'my super password',
0e1dc3e7
C
424 password: 'bla'
425 }
426
77a5501f 427 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
0e1dc3e7
C
428 })
429
430 it('Should fail with a too long password', async function () {
431 const fields = {
a890d1e0 432 currentPassword: 'my super password',
26d21b78 433 password: 'super'.repeat(61)
0e1dc3e7
C
434 }
435
77a5501f 436 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
0e1dc3e7
C
437 })
438
a890d1e0
C
439 it('Should fail without the current password', async function () {
440 const fields = {
441 currentPassword: 'my super password',
442 password: 'super'.repeat(61)
443 }
444
445 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
446 })
447
448 it('Should fail with an invalid current password', async function () {
449 const fields = {
450 currentPassword: 'my super password fail',
451 password: 'super'.repeat(61)
452 }
453
2d53be02
RK
454 await makePutBodyRequest({
455 url: server.url,
456 path: path + 'me',
457 token: userAccessToken,
458 fields,
459 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
460 })
a890d1e0
C
461 })
462
0883b324 463 it('Should fail with an invalid NSFW policy attribute', async function () {
0e1dc3e7 464 const fields = {
0883b324 465 nsfwPolicy: 'hello'
0e1dc3e7
C
466 }
467
77a5501f 468 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
0e1dc3e7
C
469 })
470
7efe153b
AL
471 it('Should fail with an invalid autoPlayVideo attribute', async function () {
472 const fields = {
473 autoPlayVideo: -1
474 }
475
476 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
477 })
478
6aa54148
L
479 it('Should fail with an invalid autoPlayNextVideo attribute', async function () {
480 const fields = {
481 autoPlayNextVideo: -1
482 }
483
484 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
485 })
486
8b9a525a
C
487 it('Should fail with an invalid videosHistoryEnabled attribute', async function () {
488 const fields = {
489 videosHistoryEnabled: -1
490 }
491
492 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
493 })
494
0e1dc3e7
C
495 it('Should fail with an non authenticated user', async function () {
496 const fields = {
a890d1e0 497 currentPassword: 'my super password',
0e1dc3e7
C
498 password: 'my super password'
499 }
500
2d53be02
RK
501 await makePutBodyRequest({
502 url: server.url,
503 path: path + 'me',
504 token: 'super token',
505 fields,
506 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
507 })
0e1dc3e7
C
508 })
509
2422c46b
C
510 it('Should fail with a too long description', async function () {
511 const fields = {
d23e6a1c 512 description: 'super'.repeat(201)
2422c46b
C
513 }
514
515 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
516 })
517
3caf77d3
C
518 it('Should fail with an invalid videoLanguages attribute', async function () {
519 {
520 const fields = {
521 videoLanguages: 'toto'
522 }
523
524 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
525 }
526
527 {
528 const languages = []
529 for (let i = 0; i < 1000; i++) {
530 languages.push('fr')
531 }
532
533 const fields = {
534 videoLanguages: languages
535 }
536
537 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
538 }
539 })
540
9b474844
C
541 it('Should fail with an invalid theme', async function () {
542 const fields = { theme: 'invalid' }
543 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
544 })
545
546 it('Should fail with an unknown theme', async function () {
547 const fields = { theme: 'peertube-theme-unknown' }
548 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
549 })
550
43d0ea7f
C
551 it('Should fail with an invalid noInstanceConfigWarningModal attribute', async function () {
552 const fields = {
553 noInstanceConfigWarningModal: -1
554 }
555
556 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
557 })
558
559 it('Should fail with an invalid noWelcomeModal attribute', async function () {
560 const fields = {
561 noWelcomeModal: -1
562 }
563
564 await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
565 })
566
a890d1e0 567 it('Should succeed to change password with the correct params', async function () {
0e1dc3e7 568 const fields = {
a890d1e0 569 currentPassword: 'my super password',
0e1dc3e7 570 password: 'my super password',
0883b324 571 nsfwPolicy: 'blur',
7efe153b 572 autoPlayVideo: false,
9b474844 573 email: 'super_email@example.com',
43d0ea7f
C
574 theme: 'default',
575 noInstanceConfigWarningModal: true,
576 noWelcomeModal: true
0e1dc3e7
C
577 }
578
2d53be02
RK
579 await makePutBodyRequest({
580 url: server.url,
581 path: path + 'me',
582 token: userAccessToken,
583 fields,
584 statusCodeExpected: HttpStatusCode.NO_CONTENT_204
585 })
77a5501f 586 })
a890d1e0
C
587
588 it('Should succeed without password change with the correct params', async function () {
589 const fields = {
590 nsfwPolicy: 'blur',
5efab546 591 autoPlayVideo: false
a890d1e0
C
592 }
593
2d53be02
RK
594 await makePutBodyRequest({
595 url: server.url,
596 path: path + 'me',
597 token: userAccessToken,
598 fields,
599 statusCodeExpected: HttpStatusCode.NO_CONTENT_204
600 })
a890d1e0 601 })
77a5501f
C
602 })
603
c5911fd3
C
604 describe('When updating my avatar', function () {
605 it('Should fail without an incorrect input file', async function () {
606 const fields = {}
607 const attaches = {
a1587156 608 avatarfile: join(__dirname, '..', '..', 'fixtures', 'video_short.mp4')
c5911fd3 609 }
ac81d1a0 610 await makeUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
c5911fd3
C
611 })
612
01de67b9
C
613 it('Should fail with a big file', async function () {
614 const fields = {}
615 const attaches = {
a1587156 616 avatarfile: join(__dirname, '..', '..', 'fixtures', 'avatar-big.png')
01de67b9 617 }
ac81d1a0 618 await makeUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
01de67b9
C
619 })
620
4bbfc6c6
C
621 it('Should fail with an unauthenticated user', async function () {
622 const fields = {}
623 const attaches = {
a1587156 624 avatarfile: join(__dirname, '..', '..', 'fixtures', 'avatar.png')
4bbfc6c6
C
625 }
626 await makeUploadRequest({
627 url: server.url,
628 path: path + '/me/avatar/pick',
629 fields,
630 attaches,
2d53be02 631 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
4bbfc6c6
C
632 })
633 })
634
c5911fd3
C
635 it('Should succeed with the correct params', async function () {
636 const fields = {}
637 const attaches = {
a1587156 638 avatarfile: join(__dirname, '..', '..', 'fixtures', 'avatar.png')
c5911fd3 639 }
ac81d1a0 640 await makeUploadRequest({
47564bbe
C
641 url: server.url,
642 path: path + '/me/avatar/pick',
643 token: server.accessToken,
644 fields,
645 attaches,
2d53be02 646 statusCodeExpected: HttpStatusCode.OK_200
47564bbe 647 })
c5911fd3
C
648 })
649 })
650
18490b07
C
651 describe('When managing my scoped tokens', function () {
652
653 it('Should fail to get my scoped tokens with an non authenticated user', async function () {
2d53be02 654 await getUserScopedTokens(server.url, null, HttpStatusCode.UNAUTHORIZED_401)
18490b07
C
655 })
656
657 it('Should fail to get my scoped tokens with a bad token', async function () {
2d53be02 658 await getUserScopedTokens(server.url, 'bad', HttpStatusCode.UNAUTHORIZED_401)
18490b07
C
659
660 })
661
662 it('Should succeed to get my scoped tokens', async function () {
663 await getUserScopedTokens(server.url, server.accessToken)
664 })
665
666 it('Should fail to renew my scoped tokens with an non authenticated user', async function () {
2d53be02 667 await renewUserScopedTokens(server.url, null, HttpStatusCode.UNAUTHORIZED_401)
18490b07
C
668 })
669
670 it('Should fail to renew my scoped tokens with a bad token', async function () {
2d53be02 671 await renewUserScopedTokens(server.url, 'bad', HttpStatusCode.UNAUTHORIZED_401)
18490b07
C
672 })
673
674 it('Should succeed to renew my scoped tokens', async function () {
675 await renewUserScopedTokens(server.url, server.accessToken)
676 })
677 })
678
94ff4c23 679 describe('When getting a user', function () {
94ff4c23
C
680
681 it('Should fail with an non authenticated user', async function () {
2d53be02
RK
682 await makeGetRequest({
683 url: server.url,
684 path: path + userId,
685 token: 'super token',
686 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
687 })
94ff4c23
C
688 })
689
690 it('Should fail with a non admin user', async function () {
2d53be02 691 await makeGetRequest({ url: server.url, path, token: userAccessToken, statusCodeExpected: HttpStatusCode.FORBIDDEN_403 })
94ff4c23
C
692 })
693
694 it('Should succeed with the correct params', async function () {
2d53be02 695 await makeGetRequest({ url: server.url, path: path + userId, token: server.accessToken, statusCodeExpected: HttpStatusCode.OK_200 })
94ff4c23
C
696 })
697 })
698
77a5501f
C
699 describe('When updating a user', function () {
700
77a5501f
C
701 it('Should fail with an invalid email attribute', async function () {
702 const fields = {
703 email: 'blabla'
704 }
705
706 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
707 })
708
fc2ec87a
JM
709 it('Should fail with an invalid emailVerified attribute', async function () {
710 const fields = {
711 emailVerified: 'yes'
712 }
713
714 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
715 })
716
77a5501f
C
717 it('Should fail with an invalid videoQuota attribute', async function () {
718 const fields = {
719 videoQuota: -90
720 }
721
722 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
723 })
724
757f0da3
C
725 it('Should fail with an invalid user role attribute', async function () {
726 const fields = {
727 role: 54878
728 }
729
730 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
731 })
732
b426edd4
C
733 it('Should fail with a too small password', async function () {
734 const fields = {
735 currentPassword: 'my super password',
736 password: 'bla'
737 }
738
739 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
740 })
741
742 it('Should fail with a too long password', async function () {
743 const fields = {
744 currentPassword: 'my super password',
745 password: 'super'.repeat(61)
746 }
747
748 await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
749 })
750
77a5501f
C
751 it('Should fail with an non authenticated user', async function () {
752 const fields = {
753 videoQuota: 42
754 }
755
2d53be02
RK
756 await makePutBodyRequest({
757 url: server.url,
758 path: path + userId,
759 token: 'super token',
760 fields,
761 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
762 })
77a5501f
C
763 })
764
f8b8c36b
C
765 it('Should fail when updating root role', async function () {
766 const fields = {
767 role: UserRole.MODERATOR
768 }
769
770 await makePutBodyRequest({ url: server.url, path: path + rootId, token: server.accessToken, fields })
1eddc9a7
C
771 })
772
773 it('Should fail with invalid admin flags', async function () {
774 const fields = { adminFlags: 'toto' }
775
a95a4cc8
C
776 await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
777 })
778
779 it('Should fail to update an admin with a moderator', async function () {
780 const fields = {
781 videoQuota: 42
782 }
783
784 await makePutBodyRequest({
785 url: server.url,
786 path: path + moderatorId,
787 token: moderatorAccessToken,
788 fields,
2d53be02 789 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
a95a4cc8
C
790 })
791 })
792
793 it('Should succeed to update a user with a moderator', async function () {
794 const fields = {
795 videoQuota: 42
796 }
797
798 await makePutBodyRequest({
799 url: server.url,
800 path: path + userId,
801 token: moderatorAccessToken,
802 fields,
2d53be02 803 statusCodeExpected: HttpStatusCode.NO_CONTENT_204
a95a4cc8 804 })
f8b8c36b
C
805 })
806
77a5501f
C
807 it('Should succeed with the correct params', async function () {
808 const fields = {
809 email: 'email@example.com',
fc2ec87a 810 emailVerified: true,
757f0da3 811 videoQuota: 42,
2f1548fd 812 role: UserRole.USER
77a5501f
C
813 }
814
2d53be02
RK
815 await makePutBodyRequest({
816 url: server.url,
817 path: path + userId,
818 token: server.accessToken,
819 fields,
820 statusCodeExpected: HttpStatusCode.NO_CONTENT_204
821 })
0e1dc3e7
C
822 })
823 })
824
825 describe('When getting my information', function () {
826 it('Should fail with a non authenticated user', async function () {
2d53be02 827 await getMyUserInformation(server.url, 'fake_token', HttpStatusCode.UNAUTHORIZED_401)
0e1dc3e7
C
828 })
829
830 it('Should success with the correct parameters', async function () {
26d21b78 831 await getMyUserInformation(server.url, userAccessToken)
0e1dc3e7
C
832 })
833 })
834
835 describe('When getting my video rating', function () {
836 it('Should fail with a non authenticated user', async function () {
2d53be02 837 await getMyUserVideoRating(server.url, 'fake_token', videoId, HttpStatusCode.UNAUTHORIZED_401)
0e1dc3e7
C
838 })
839
840 it('Should fail with an incorrect video uuid', async function () {
2d53be02 841 await getMyUserVideoRating(server.url, server.accessToken, 'blabla', HttpStatusCode.BAD_REQUEST_400)
0e1dc3e7
C
842 })
843
844 it('Should fail with an unknown video', async function () {
2d53be02 845 await getMyUserVideoRating(server.url, server.accessToken, '4da6fde3-88f7-4d16-b119-108df5630b06', HttpStatusCode.NOT_FOUND_404)
0e1dc3e7
C
846 })
847
26d21b78
C
848 it('Should succeed with the correct parameters', async function () {
849 await getMyUserVideoRating(server.url, server.accessToken, videoId)
0e1dc3e7
C
850 })
851 })
852
22834691
C
853 describe('When retrieving my global ratings', function () {
854 const path = '/api/v1/accounts/user1/ratings'
855
856 it('Should fail with a bad start pagination', async function () {
857 await checkBadStartPagination(server.url, path, userAccessToken)
858 })
859
860 it('Should fail with a bad count pagination', async function () {
861 await checkBadCountPagination(server.url, path, userAccessToken)
862 })
863
864 it('Should fail with an incorrect sort', async function () {
865 await checkBadSortPagination(server.url, path, userAccessToken)
866 })
867
868 it('Should fail with a unauthenticated user', async function () {
2d53be02 869 await makeGetRequest({ url: server.url, path, statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401 })
22834691
C
870 })
871
872 it('Should fail with a another user', async function () {
2d53be02 873 await makeGetRequest({ url: server.url, path, token: server.accessToken, statusCodeExpected: HttpStatusCode.FORBIDDEN_403 })
22834691
C
874 })
875
876 it('Should fail with a bad type', async function () {
2d53be02
RK
877 await makeGetRequest({
878 url: server.url,
879 path,
880 token: userAccessToken,
881 query: { rating: 'toto ' },
882 statusCodeExpected: HttpStatusCode.BAD_REQUEST_400
883 })
22834691
C
884 })
885
886 it('Should succeed with the correct params', async function () {
2d53be02 887 await makeGetRequest({ url: server.url, path, token: userAccessToken, statusCodeExpected: HttpStatusCode.OK_200 })
22834691
C
888 })
889 })
890
e6921918 891 describe('When blocking/unblocking/removing user', function () {
0e1dc3e7 892 it('Should fail with an incorrect id', async function () {
2d53be02
RK
893 await removeUser(server.url, 'blabla', server.accessToken, HttpStatusCode.BAD_REQUEST_400)
894 await blockUser(server.url, 'blabla', server.accessToken, HttpStatusCode.BAD_REQUEST_400)
895 await unblockUser(server.url, 'blabla', server.accessToken, HttpStatusCode.BAD_REQUEST_400)
0e1dc3e7
C
896 })
897
898 it('Should fail with the root user', async function () {
2d53be02
RK
899 await removeUser(server.url, rootId, server.accessToken, HttpStatusCode.BAD_REQUEST_400)
900 await blockUser(server.url, rootId, server.accessToken, HttpStatusCode.BAD_REQUEST_400)
901 await unblockUser(server.url, rootId, server.accessToken, HttpStatusCode.BAD_REQUEST_400)
0e1dc3e7
C
902 })
903
904 it('Should return 404 with a non existing id', async function () {
2d53be02
RK
905 await removeUser(server.url, 4545454, server.accessToken, HttpStatusCode.NOT_FOUND_404)
906 await blockUser(server.url, 4545454, server.accessToken, HttpStatusCode.NOT_FOUND_404)
907 await unblockUser(server.url, 4545454, server.accessToken, HttpStatusCode.NOT_FOUND_404)
e6921918
C
908 })
909
910 it('Should fail with a non admin user', async function () {
2d53be02
RK
911 await removeUser(server.url, userId, userAccessToken, HttpStatusCode.FORBIDDEN_403)
912 await blockUser(server.url, userId, userAccessToken, HttpStatusCode.FORBIDDEN_403)
913 await unblockUser(server.url, userId, userAccessToken, HttpStatusCode.FORBIDDEN_403)
0e1dc3e7 914 })
a95a4cc8
C
915
916 it('Should fail on a moderator with a moderator', async function () {
2d53be02
RK
917 await removeUser(server.url, moderatorId, moderatorAccessToken, HttpStatusCode.FORBIDDEN_403)
918 await blockUser(server.url, moderatorId, moderatorAccessToken, HttpStatusCode.FORBIDDEN_403)
919 await unblockUser(server.url, moderatorId, moderatorAccessToken, HttpStatusCode.FORBIDDEN_403)
a95a4cc8
C
920 })
921
922 it('Should succeed on a user with a moderator', async function () {
923 await blockUser(server.url, userId, moderatorAccessToken)
924 await unblockUser(server.url, userId, moderatorAccessToken)
925 })
0e1dc3e7
C
926 })
927
92b9d60c
C
928 describe('When deleting our account', function () {
929 it('Should fail with with the root account', async function () {
2d53be02 930 await deleteMe(server.url, server.accessToken, HttpStatusCode.BAD_REQUEST_400)
92b9d60c
C
931 })
932 })
933
e590b4a5 934 describe('When registering a new user', function () {
0e1dc3e7 935 const registrationPath = path + '/register'
26d21b78
C
936 const baseCorrectParams = {
937 username: 'user3',
1f20622f 938 displayName: 'super user',
26d21b78
C
939 email: 'test3@example.com',
940 password: 'my super password'
941 }
0e1dc3e7
C
942
943 it('Should fail with a too small username', async function () {
d0ce42c1 944 const fields = immutableAssign(baseCorrectParams, { username: '' })
0e1dc3e7
C
945
946 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
947 })
948
949 it('Should fail with a too long username', async function () {
9f7a1953 950 const fields = immutableAssign(baseCorrectParams, { username: 'super'.repeat(50) })
0e1dc3e7
C
951
952 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
953 })
954
955 it('Should fail with an incorrect username', async function () {
26d21b78 956 const fields = immutableAssign(baseCorrectParams, { username: 'my username' })
0e1dc3e7
C
957
958 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
959 })
960
961 it('Should fail with a missing email', async function () {
26d21b78 962 const fields = omit(baseCorrectParams, 'email')
0e1dc3e7
C
963
964 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
965 })
966
967 it('Should fail with an invalid email', async function () {
26d21b78 968 const fields = immutableAssign(baseCorrectParams, { email: 'test_example.com' })
0e1dc3e7
C
969
970 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
971 })
972
973 it('Should fail with a too small password', async function () {
26d21b78 974 const fields = immutableAssign(baseCorrectParams, { password: 'bla' })
0e1dc3e7
C
975
976 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
977 })
978
979 it('Should fail with a too long password', async function () {
26d21b78 980 const fields = immutableAssign(baseCorrectParams, { password: 'super'.repeat(61) })
0e1dc3e7
C
981
982 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
983 })
984
985 it('Should fail if we register a user with the same username', async function () {
26d21b78 986 const fields = immutableAssign(baseCorrectParams, { username: 'root' })
0e1dc3e7 987
26d21b78
C
988 await makePostBodyRequest({
989 url: server.url,
990 path: registrationPath,
991 token: server.accessToken,
992 fields,
2d53be02 993 statusCodeExpected: HttpStatusCode.CONFLICT_409
26d21b78 994 })
0e1dc3e7
C
995 })
996
2ef6a063
C
997 it('Should fail with a "peertube" username', async function () {
998 const fields = immutableAssign(baseCorrectParams, { username: 'peertube' })
999
1000 await makePostBodyRequest({
1001 url: server.url,
1002 path: registrationPath,
1003 token: server.accessToken,
1004 fields,
2d53be02 1005 statusCodeExpected: HttpStatusCode.CONFLICT_409
2ef6a063
C
1006 })
1007 })
1008
0e1dc3e7 1009 it('Should fail if we register a user with the same email', async function () {
7c3b7976 1010 const fields = immutableAssign(baseCorrectParams, { email: 'admin' + server.internalServerNumber + '@example.com' })
0e1dc3e7 1011
26d21b78
C
1012 await makePostBodyRequest({
1013 url: server.url,
1014 path: registrationPath,
1015 token: server.accessToken,
1016 fields,
2d53be02 1017 statusCodeExpected: HttpStatusCode.CONFLICT_409
26d21b78 1018 })
0e1dc3e7
C
1019 })
1020
1f20622f
C
1021 it('Should fail with a bad display name', async function () {
1022 const fields = immutableAssign(baseCorrectParams, { displayName: 'a'.repeat(150) })
1023
1024 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
1025 })
1026
e590b4a5
C
1027 it('Should fail with a bad channel name', async function () {
1028 const fields = immutableAssign(baseCorrectParams, { channel: { name: '[]azf', displayName: 'toto' } })
1029
1030 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
1031 })
1032
1033 it('Should fail with a bad channel display name', async function () {
1034 const fields = immutableAssign(baseCorrectParams, { channel: { name: 'toto', displayName: '' } })
1035
1036 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
1037 })
1038
32d7f2b7 1039 it('Should fail with a channel name that is the same as username', async function () {
1d5342ab
C
1040 const source = { username: 'super_user', channel: { name: 'super_user', displayName: 'display name' } }
1041 const fields = immutableAssign(baseCorrectParams, source)
1042
1043 await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
1044 })
1045
e590b4a5
C
1046 it('Should fail with an existing channel', async function () {
1047 const videoChannelAttributesArg = { name: 'existing_channel', displayName: 'hello', description: 'super description' }
1048 await addVideoChannel(server.url, server.accessToken, videoChannelAttributesArg)
1049
1050 const fields = immutableAssign(baseCorrectParams, { channel: { name: 'existing_channel', displayName: 'toto' } })
1051
2d53be02
RK
1052 await makePostBodyRequest({
1053 url: server.url,
1054 path: registrationPath,
1055 token: server.accessToken,
1056 fields,
1057 statusCodeExpected: HttpStatusCode.CONFLICT_409
1058 })
e590b4a5
C
1059 })
1060
0e1dc3e7 1061 it('Should succeed with the correct params', async function () {
e590b4a5
C
1062 const fields = immutableAssign(baseCorrectParams, { channel: { name: 'super_channel', displayName: 'toto' } })
1063
26d21b78
C
1064 await makePostBodyRequest({
1065 url: server.url,
1066 path: registrationPath,
1067 token: server.accessToken,
e590b4a5 1068 fields: fields,
2d53be02 1069 statusCodeExpected: HttpStatusCode.NO_CONTENT_204
26d21b78 1070 })
0e1dc3e7
C
1071 })
1072
1073 it('Should fail on a server with registration disabled', async function () {
1074 const fields = {
1075 username: 'user4',
1076 email: 'test4@example.com',
1077 password: 'my super password 4'
1078 }
1079
1080 await makePostBodyRequest({
1081 url: serverWithRegistrationDisabled.url,
1082 path: registrationPath,
1083 token: serverWithRegistrationDisabled.accessToken,
1084 fields,
2d53be02 1085 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
0e1dc3e7
C
1086 })
1087 })
1088 })
1089
1090 describe('When registering multiple users on a server with users limit', function () {
1091 it('Should fail when after 3 registrations', async function () {
2d53be02 1092 await registerUser(server.url, 'user42', 'super password', HttpStatusCode.FORBIDDEN_403)
0e1dc3e7
C
1093 })
1094 })
1095
77a5501f 1096 describe('When having a video quota', function () {
bee0abff 1097 it('Should fail with a user having too many videos', async function () {
26d21b78
C
1098 await updateUser({
1099 url: server.url,
1100 userId: rootId,
1101 accessToken: server.accessToken,
77a5501f 1102 videoQuota: 42
26d21b78 1103 })
77a5501f 1104
f2eb23cd 1105 await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413)
77a5501f
C
1106 })
1107
bee0abff 1108 it('Should fail with a registered user having too many videos', async function () {
adc236fe 1109 this.timeout(30000)
77a5501f 1110
26d21b78 1111 const user = {
77a5501f 1112 username: 'user3',
77a5501f
C
1113 password: 'my super password'
1114 }
26d21b78 1115 userAccessToken = await userLogin(server, user)
77a5501f
C
1116
1117 const videoAttributes = { fixture: 'video_short2.webm' }
1118 await uploadVideo(server.url, userAccessToken, videoAttributes)
1119 await uploadVideo(server.url, userAccessToken, videoAttributes)
1120 await uploadVideo(server.url, userAccessToken, videoAttributes)
1121 await uploadVideo(server.url, userAccessToken, videoAttributes)
1122 await uploadVideo(server.url, userAccessToken, videoAttributes)
f2eb23cd 1123 await uploadVideo(server.url, userAccessToken, videoAttributes, HttpStatusCode.PAYLOAD_TOO_LARGE_413)
77a5501f 1124 })
187501f8
C
1125
1126 it('Should fail to import with HTTP/Torrent/magnet', async function () {
a031ab0b 1127 this.timeout(120000)
187501f8
C
1128
1129 const baseAttributes = {
1130 channelId: 1,
1131 privacy: VideoPrivacy.PUBLIC
1132 }
b488ba1e 1133 await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { targetUrl: getGoodVideoUrl() }))
187501f8 1134 await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { magnetUri: getMagnetURI() }))
9a7fd960 1135 await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { torrentfile: 'video-720p.torrent' as any }))
187501f8
C
1136
1137 await waitJobs([ server ])
1138
1139 const res = await getMyVideoImports(server.url, server.accessToken)
1140
1141 expect(res.body.total).to.equal(3)
1142 const videoImports: VideoImport[] = res.body.data
1143 expect(videoImports).to.have.lengthOf(3)
1144
1145 for (const videoImport of videoImports) {
1146 expect(videoImport.state.id).to.equal(VideoImportState.FAILED)
1147 expect(videoImport.error).not.to.be.undefined
1148 expect(videoImport.error).to.contain('user video quota is exceeded')
1149 }
1150 })
77a5501f
C
1151 })
1152
bee0abff 1153 describe('When having a daily video quota', function () {
f2eb23cd 1154 it('Should fail with a user having too many videos daily', async function () {
bee0abff
FA
1155 await updateUser({
1156 url: server.url,
1157 userId: rootId,
1158 accessToken: server.accessToken,
1159 videoQuotaDaily: 42
1160 })
1161
f2eb23cd 1162 await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413)
bee0abff
FA
1163 })
1164 })
1165
1166 describe('When having an absolute and daily video quota', function () {
1167 it('Should fail if exceeding total quota', async function () {
1168 await updateUser({
1169 url: server.url,
1170 userId: rootId,
1171 accessToken: server.accessToken,
1172 videoQuota: 42,
1173 videoQuotaDaily: 1024 * 1024 * 1024
1174 })
1175
f2eb23cd 1176 await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413)
bee0abff
FA
1177 })
1178
1179 it('Should fail if exceeding daily quota', async function () {
1180 await updateUser({
1181 url: server.url,
1182 userId: rootId,
1183 accessToken: server.accessToken,
1184 videoQuota: 1024 * 1024 * 1024,
1185 videoQuotaDaily: 42
1186 })
1187
f2eb23cd 1188 await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413)
bee0abff
FA
1189 })
1190 })
1191
f076daa7
C
1192 describe('When asking a password reset', function () {
1193 const path = '/api/v1/users/ask-reset-password'
1194
1195 it('Should fail with a missing email', async function () {
1196 const fields = {}
1197
1198 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
1199 })
1200
1201 it('Should fail with an invalid email', async function () {
1202 const fields = { email: 'hello' }
1203
1204 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
1205 })
1206
1207 it('Should success with the correct params', async function () {
1208 const fields = { email: 'admin@example.com' }
1209
2d53be02
RK
1210 await makePostBodyRequest({
1211 url: server.url,
1212 path,
1213 token: server.accessToken,
1214 fields,
1215 statusCodeExpected: HttpStatusCode.NO_CONTENT_204
1216 })
f076daa7
C
1217 })
1218 })
1219
d9eaee39
JM
1220 describe('When asking for an account verification email', function () {
1221 const path = '/api/v1/users/ask-send-verify-email'
1222
1223 it('Should fail with a missing email', async function () {
1224 const fields = {}
1225
1226 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
1227 })
1228
1229 it('Should fail with an invalid email', async function () {
1230 const fields = { email: 'hello' }
1231
1232 await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
1233 })
1234
1235 it('Should succeed with the correct params', async function () {
1236 const fields = { email: 'admin@example.com' }
1237
2d53be02
RK
1238 await makePostBodyRequest({
1239 url: server.url,
1240 path,
1241 token: server.accessToken,
1242 fields,
1243 statusCodeExpected: HttpStatusCode.NO_CONTENT_204
1244 })
d9eaee39
JM
1245 })
1246 })
1247
7c3b7976 1248 after(async function () {
45f1bd72
JL
1249 MockSmtpServer.Instance.kill()
1250
7c3b7976 1251 await cleanupTests([ server, serverWithRegistrationDisabled ])
0e1dc3e7
C
1252 })
1253})