Add miniature quick actions to add video to Watch later playlist
[oweals/peertube.git] / server / tests / api / users / users.ts
1 /* tslint:disable:no-unused-expression */
2
3 import * as chai from 'chai'
4 import 'mocha'
5 import { User, UserRole, Video, MyUser } from '../../../../shared/index'
6 import {
7   blockUser,
8   cleanupTests,
9   createUser,
10   deleteMe,
11   flushAndRunServer,
12   getAccountRatings,
13   getBlacklistedVideosList,
14   getMyUserInformation,
15   getMyUserVideoQuotaUsed,
16   getMyUserVideoRating,
17   getUserInformation,
18   getUsersList,
19   getUsersListPaginationAndSort,
20   getVideoChannel,
21   getVideosList, installPlugin,
22   login,
23   makePutBodyRequest,
24   rateVideo,
25   registerUserWithChannel,
26   removeUser,
27   removeVideo,
28   ServerInfo,
29   testImage,
30   unblockUser,
31   updateMyAvatar,
32   updateMyUser,
33   updateUser,
34   uploadVideo,
35   userLogin
36 } from '../../../../shared/extra-utils'
37 import { follow } from '../../../../shared/extra-utils/server/follows'
38 import { setAccessTokensToServers } from '../../../../shared/extra-utils/users/login'
39 import { getMyVideos } from '../../../../shared/extra-utils/videos/videos'
40 import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
41
42 const expect = chai.expect
43
44 describe('Test users', function () {
45   let server: ServerInfo
46   let accessToken: string
47   let accessTokenUser: string
48   let videoId: number
49   let userId: number
50   const user = {
51     username: 'user_1',
52     password: 'super password'
53   }
54
55   before(async function () {
56     this.timeout(30000)
57     server = await flushAndRunServer(1)
58
59     await setAccessTokensToServers([ server ])
60
61     await installPlugin({ url: server.url, accessToken: server.accessToken, npmName: 'peertube-theme-background-red' })
62   })
63
64   describe('OAuth client', function () {
65     it('Should create a new client')
66
67     it('Should return the first client')
68
69     it('Should remove the last client')
70
71     it('Should not login with an invalid client id', async function () {
72       const client = { id: 'client', secret: server.client.secret }
73       const res = await login(server.url, client, server.user, 400)
74
75       expect(res.body.error).to.contain('client is invalid')
76     })
77
78     it('Should not login with an invalid client secret', async function () {
79       const client = { id: server.client.id, secret: 'coucou' }
80       const res = await login(server.url, client, server.user, 400)
81
82       expect(res.body.error).to.contain('client is invalid')
83     })
84   })
85
86   describe('Login', function () {
87
88     it('Should not login with an invalid username', async function () {
89       const user = { username: 'captain crochet', password: server.user.password }
90       const res = await login(server.url, server.client, user, 400)
91
92       expect(res.body.error).to.contain('credentials are invalid')
93     })
94
95     it('Should not login with an invalid password', async function () {
96       const user = { username: server.user.username, password: 'mew_three' }
97       const res = await login(server.url, server.client, user, 400)
98
99       expect(res.body.error).to.contain('credentials are invalid')
100     })
101
102     it('Should not be able to upload a video', async function () {
103       accessToken = 'my_super_token'
104
105       const videoAttributes = {}
106       await uploadVideo(server.url, accessToken, videoAttributes, 401)
107     })
108
109     it('Should not be able to follow', async function () {
110       accessToken = 'my_super_token'
111       await follow(server.url, [ 'http://example.com' ], accessToken, 401)
112     })
113
114     it('Should not be able to unfollow')
115
116     it('Should be able to login', async function () {
117       const res = await login(server.url, server.client, server.user, 200)
118
119       accessToken = res.body.access_token
120     })
121
122     it('Should be able to login with an insensitive username', async function () {
123       const user = { username: 'RoOt', password: server.user.password }
124       const res = await login(server.url, server.client, user, 200)
125
126       const user2 = { username: 'rOoT', password: server.user.password }
127       const res2 = await login(server.url, server.client, user2, 200)
128
129       const user3 = { username: 'ROOt', password: server.user.password }
130       const res3 = await login(server.url, server.client, user3, 200)
131     })
132   })
133
134   describe('Upload', function () {
135
136     it('Should upload the video with the correct token', async function () {
137       const videoAttributes = {}
138       await uploadVideo(server.url, accessToken, videoAttributes)
139       const res = await getVideosList(server.url)
140       const video = res.body.data[ 0 ]
141
142       expect(video.account.name).to.equal('root')
143       videoId = video.id
144     })
145
146     it('Should upload the video again with the correct token', async function () {
147       const videoAttributes = {}
148       await uploadVideo(server.url, accessToken, videoAttributes)
149     })
150   })
151
152   describe('Ratings', function () {
153
154     it('Should retrieve a video rating', async function () {
155       await rateVideo(server.url, accessToken, videoId, 'like')
156       const res = await getMyUserVideoRating(server.url, accessToken, videoId)
157       const rating = res.body
158
159       expect(rating.videoId).to.equal(videoId)
160       expect(rating.rating).to.equal('like')
161     })
162
163     it('Should retrieve ratings list', async function () {
164       await rateVideo(server.url, accessToken, videoId, 'like')
165
166       const res = await getAccountRatings(server.url, server.user.username, server.accessToken, null, 200)
167       const ratings = res.body
168
169       expect(ratings.total).to.equal(1)
170       expect(ratings.data[ 0 ].video.id).to.equal(videoId)
171       expect(ratings.data[ 0 ].rating).to.equal('like')
172     })
173
174     it('Should retrieve ratings list by rating type', async function () {
175       {
176         const res = await getAccountRatings(server.url, server.user.username, server.accessToken, 'like')
177         const ratings = res.body
178         expect(ratings.data.length).to.equal(1)
179       }
180
181       {
182         const res = await getAccountRatings(server.url, server.user.username, server.accessToken, 'dislike')
183         const ratings = res.body
184         expect(ratings.data.length).to.equal(0)
185       }
186     })
187   })
188
189   describe('Remove video', function () {
190     it('Should not be able to remove the video with an incorrect token', async function () {
191       await removeVideo(server.url, 'bad_token', videoId, 401)
192     })
193
194     it('Should not be able to remove the video with the token of another account')
195
196     it('Should be able to remove the video with the correct token', async function () {
197       await removeVideo(server.url, accessToken, videoId)
198     })
199   })
200
201   describe('Logout', function () {
202     it('Should logout (revoke token)')
203
204     it('Should not be able to get the user information')
205
206     it('Should not be able to upload a video')
207
208     it('Should not be able to remove a video')
209
210     it('Should not be able to rate a video', async function () {
211       const path = '/api/v1/videos/'
212       const data = {
213         rating: 'likes'
214       }
215
216       const options = {
217         url: server.url,
218         path: path + videoId,
219         token: 'wrong token',
220         fields: data,
221         statusCodeExpected: 401
222       }
223       await makePutBodyRequest(options)
224     })
225
226     it('Should be able to login again')
227
228     it('Should have an expired access token')
229
230     it('Should refresh the token')
231
232     it('Should be able to upload a video again')
233   })
234
235   describe('Creating a user', function () {
236
237     it('Should be able to create a new user', async function () {
238       await createUser({
239         url: server.url,
240         accessToken: accessToken,
241         username: user.username,
242         password: user.password,
243         videoQuota: 2 * 1024 * 1024,
244         adminFlags: UserAdminFlag.BY_PASS_VIDEO_AUTO_BLACKLIST
245       })
246     })
247
248     it('Should be able to login with this user', async function () {
249       accessTokenUser = await userLogin(server, user)
250     })
251
252     it('Should be able to get user information', async function () {
253       const res1 = await getMyUserInformation(server.url, accessTokenUser)
254       const userMe: User & MyUser = res1.body
255
256       const res2 = await getUserInformation(server.url, server.accessToken, userMe.id)
257       const userGet: User = res2.body
258
259       for (const user of [ userMe, userGet ]) {
260         expect(user.username).to.equal('user_1')
261         expect(user.email).to.equal('user_1@example.com')
262         expect(user.nsfwPolicy).to.equal('display')
263         expect(user.videoQuota).to.equal(2 * 1024 * 1024)
264         expect(user.roleLabel).to.equal('User')
265         expect(user.id).to.be.a('number')
266         expect(user.account.displayName).to.equal('user_1')
267         expect(user.account.description).to.be.null
268       }
269
270       expect(userMe.adminFlags).to.be.undefined
271       expect(userGet.adminFlags).to.equal(UserAdminFlag.BY_PASS_VIDEO_AUTO_BLACKLIST)
272
273       expect(userMe.specialPlaylists).to.have.lengthOf(1)
274     })
275   })
276
277   describe('My videos & quotas', function () {
278
279     it('Should be able to upload a video with this user', async function () {
280       this.timeout(5000)
281
282       const videoAttributes = {
283         name: 'super user video',
284         fixture: 'video_short.webm'
285       }
286       await uploadVideo(server.url, accessTokenUser, videoAttributes)
287     })
288
289     it('Should have video quota updated', async function () {
290       const res = await getMyUserVideoQuotaUsed(server.url, accessTokenUser)
291       const data = res.body
292
293       expect(data.videoQuotaUsed).to.equal(218910)
294
295       const resUsers = await getUsersList(server.url, server.accessToken)
296
297       const users: User[] = resUsers.body.data
298       const tmpUser = users.find(u => u.username === user.username)
299       expect(tmpUser.videoQuotaUsed).to.equal(218910)
300     })
301
302     it('Should be able to list my videos', async function () {
303       const res = await getMyVideos(server.url, accessTokenUser, 0, 5)
304       expect(res.body.total).to.equal(1)
305
306       const videos = res.body.data
307       expect(videos).to.have.lengthOf(1)
308
309       const video: Video = videos[ 0 ]
310       expect(video.name).to.equal('super user video')
311       expect(video.thumbnailPath).to.not.be.null
312       expect(video.previewPath).to.not.be.null
313     })
314
315     it('Should be able to search in my videos', async function () {
316       {
317         const res = await getMyVideos(server.url, accessTokenUser, 0, 5, '-createdAt', 'user video')
318         expect(res.body.total).to.equal(1)
319
320         const videos = res.body.data
321         expect(videos).to.have.lengthOf(1)
322       }
323
324       {
325         const res = await getMyVideos(server.url, accessTokenUser, 0, 5, '-createdAt', 'toto')
326         expect(res.body.total).to.equal(0)
327
328         const videos = res.body.data
329         expect(videos).to.have.lengthOf(0)
330       }
331     })
332   })
333
334   describe('Users listing', function () {
335
336     it('Should list all the users', async function () {
337       const res = await getUsersList(server.url, server.accessToken)
338       const result = res.body
339       const total = result.total
340       const users = result.data
341
342       expect(total).to.equal(2)
343       expect(users).to.be.an('array')
344       expect(users.length).to.equal(2)
345
346       const user = users[ 0 ]
347       expect(user.username).to.equal('user_1')
348       expect(user.email).to.equal('user_1@example.com')
349       expect(user.nsfwPolicy).to.equal('display')
350
351       const rootUser = users[ 1 ]
352       expect(rootUser.username).to.equal('root')
353       expect(rootUser.email).to.equal('admin' + server.internalServerNumber + '@example.com')
354       expect(user.nsfwPolicy).to.equal('display')
355
356       userId = user.id
357     })
358
359     it('Should list only the first user by username asc', async function () {
360       const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 1, 'username')
361
362       const result = res.body
363       const total = result.total
364       const users = result.data
365
366       expect(total).to.equal(2)
367       expect(users.length).to.equal(1)
368
369       const user = users[ 0 ]
370       expect(user.username).to.equal('root')
371       expect(user.email).to.equal('admin' + server.internalServerNumber + '@example.com')
372       expect(user.roleLabel).to.equal('Administrator')
373       expect(user.nsfwPolicy).to.equal('display')
374     })
375
376     it('Should list only the first user by username desc', async function () {
377       const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 1, '-username')
378       const result = res.body
379       const total = result.total
380       const users = result.data
381
382       expect(total).to.equal(2)
383       expect(users.length).to.equal(1)
384
385       const user = users[ 0 ]
386       expect(user.username).to.equal('user_1')
387       expect(user.email).to.equal('user_1@example.com')
388       expect(user.nsfwPolicy).to.equal('display')
389     })
390
391     it('Should list only the second user by createdAt desc', async function () {
392       const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 1, '-createdAt')
393       const result = res.body
394       const total = result.total
395       const users = result.data
396
397       expect(total).to.equal(2)
398       expect(users.length).to.equal(1)
399
400       const user = users[ 0 ]
401       expect(user.username).to.equal('user_1')
402       expect(user.email).to.equal('user_1@example.com')
403       expect(user.nsfwPolicy).to.equal('display')
404     })
405
406     it('Should list all the users by createdAt asc', async function () {
407       const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 2, 'createdAt')
408       const result = res.body
409       const total = result.total
410       const users = result.data
411
412       expect(total).to.equal(2)
413       expect(users.length).to.equal(2)
414
415       expect(users[ 0 ].username).to.equal('root')
416       expect(users[ 0 ].email).to.equal('admin' + server.internalServerNumber + '@example.com')
417       expect(users[ 0 ].nsfwPolicy).to.equal('display')
418
419       expect(users[ 1 ].username).to.equal('user_1')
420       expect(users[ 1 ].email).to.equal('user_1@example.com')
421       expect(users[ 1 ].nsfwPolicy).to.equal('display')
422     })
423
424     it('Should search user by username', async function () {
425       const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 2, 'createdAt', 'oot')
426       const users = res.body.data as User[]
427
428       expect(res.body.total).to.equal(1)
429       expect(users.length).to.equal(1)
430
431       expect(users[ 0 ].username).to.equal('root')
432     })
433
434     it('Should search user by email', async function () {
435       {
436         const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 2, 'createdAt', 'r_1@exam')
437         const users = res.body.data as User[]
438
439         expect(res.body.total).to.equal(1)
440         expect(users.length).to.equal(1)
441
442         expect(users[ 0 ].username).to.equal('user_1')
443         expect(users[ 0 ].email).to.equal('user_1@example.com')
444       }
445
446       {
447         const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 2, 'createdAt', 'example')
448         const users = res.body.data as User[]
449
450         expect(res.body.total).to.equal(2)
451         expect(users.length).to.equal(2)
452
453         expect(users[ 0 ].username).to.equal('root')
454         expect(users[ 1 ].username).to.equal('user_1')
455       }
456     })
457   })
458
459   describe('Update my account', function () {
460     it('Should update my password', async function () {
461       await updateMyUser({
462         url: server.url,
463         accessToken: accessTokenUser,
464         currentPassword: 'super password',
465         password: 'new password'
466       })
467       user.password = 'new password'
468
469       await userLogin(server, user, 200)
470     })
471
472     it('Should be able to change the NSFW display attribute', async function () {
473       await updateMyUser({
474         url: server.url,
475         accessToken: accessTokenUser,
476         nsfwPolicy: 'do_not_list'
477       })
478
479       const res = await getMyUserInformation(server.url, accessTokenUser)
480       const user = res.body
481
482       expect(user.username).to.equal('user_1')
483       expect(user.email).to.equal('user_1@example.com')
484       expect(user.nsfwPolicy).to.equal('do_not_list')
485       expect(user.videoQuota).to.equal(2 * 1024 * 1024)
486       expect(user.id).to.be.a('number')
487       expect(user.account.displayName).to.equal('user_1')
488       expect(user.account.description).to.be.null
489     })
490
491     it('Should be able to change the autoPlayVideo attribute', async function () {
492       await updateMyUser({
493         url: server.url,
494         accessToken: accessTokenUser,
495         autoPlayVideo: false
496       })
497
498       const res = await getMyUserInformation(server.url, accessTokenUser)
499       const user = res.body
500
501       expect(user.autoPlayVideo).to.be.false
502     })
503
504     it('Should be able to change the autoPlayNextVideo attribute', async function () {
505       await updateMyUser({
506         url: server.url,
507         accessToken: accessTokenUser,
508         autoPlayNextVideo: true
509       })
510
511       const res = await getMyUserInformation(server.url, accessTokenUser)
512       const user = res.body
513
514       expect(user.autoPlayNextVideo).to.be.true
515     })
516
517     it('Should be able to change the email attribute', async function () {
518       await updateMyUser({
519         url: server.url,
520         accessToken: accessTokenUser,
521         currentPassword: 'new password',
522         email: 'updated@example.com'
523       })
524
525       const res = await getMyUserInformation(server.url, accessTokenUser)
526       const user = res.body
527
528       expect(user.username).to.equal('user_1')
529       expect(user.email).to.equal('updated@example.com')
530       expect(user.nsfwPolicy).to.equal('do_not_list')
531       expect(user.videoQuota).to.equal(2 * 1024 * 1024)
532       expect(user.id).to.be.a('number')
533       expect(user.account.displayName).to.equal('user_1')
534       expect(user.account.description).to.be.null
535     })
536
537     it('Should be able to update my avatar', async function () {
538       const fixture = 'avatar.png'
539
540       await updateMyAvatar({
541         url: server.url,
542         accessToken: accessTokenUser,
543         fixture
544       })
545
546       const res = await getMyUserInformation(server.url, accessTokenUser)
547       const user = res.body
548
549       await testImage(server.url, 'avatar-resized', user.account.avatar.path, '.png')
550     })
551
552     it('Should be able to update my display name', async function () {
553       await updateMyUser({
554         url: server.url,
555         accessToken: accessTokenUser,
556         displayName: 'new display name'
557       })
558
559       const res = await getMyUserInformation(server.url, accessTokenUser)
560       const user = res.body
561
562       expect(user.username).to.equal('user_1')
563       expect(user.email).to.equal('updated@example.com')
564       expect(user.nsfwPolicy).to.equal('do_not_list')
565       expect(user.videoQuota).to.equal(2 * 1024 * 1024)
566       expect(user.id).to.be.a('number')
567       expect(user.account.displayName).to.equal('new display name')
568       expect(user.account.description).to.be.null
569     })
570
571     it('Should be able to update my description', async function () {
572       await updateMyUser({
573         url: server.url,
574         accessToken: accessTokenUser,
575         description: 'my super description updated'
576       })
577
578       const res = await getMyUserInformation(server.url, accessTokenUser)
579       const user: User = res.body
580
581       expect(user.username).to.equal('user_1')
582       expect(user.email).to.equal('updated@example.com')
583       expect(user.nsfwPolicy).to.equal('do_not_list')
584       expect(user.videoQuota).to.equal(2 * 1024 * 1024)
585       expect(user.id).to.be.a('number')
586       expect(user.account.displayName).to.equal('new display name')
587       expect(user.account.description).to.equal('my super description updated')
588       expect(user.noWelcomeModal).to.be.false
589       expect(user.noInstanceConfigWarningModal).to.be.false
590     })
591
592     it('Should be able to update my theme', async function () {
593       for (const theme of [ 'background-red', 'default', 'instance-default' ]) {
594         await updateMyUser({
595           url: server.url,
596           accessToken: accessTokenUser,
597           theme
598         })
599
600         const res = await getMyUserInformation(server.url, accessTokenUser)
601         const body: User = res.body
602
603         expect(body.theme).to.equal(theme)
604       }
605     })
606
607     it('Should be able to update my modal preferences', async function () {
608       await updateMyUser({
609         url: server.url,
610         accessToken: accessTokenUser,
611         noInstanceConfigWarningModal: true,
612         noWelcomeModal: true
613       })
614
615       const res = await getMyUserInformation(server.url, accessTokenUser)
616       const user: User = res.body
617
618       expect(user.noWelcomeModal).to.be.true
619       expect(user.noInstanceConfigWarningModal).to.be.true
620     })
621   })
622
623   describe('Updating another user', function () {
624
625     it('Should be able to update another user', async function () {
626       await updateUser({
627         url: server.url,
628         userId,
629         accessToken,
630         email: 'updated2@example.com',
631         emailVerified: true,
632         videoQuota: 42,
633         role: UserRole.MODERATOR,
634         adminFlags: UserAdminFlag.NONE
635       })
636
637       const res = await getUserInformation(server.url, accessToken, userId)
638       const user = res.body
639
640       expect(user.username).to.equal('user_1')
641       expect(user.email).to.equal('updated2@example.com')
642       expect(user.emailVerified).to.be.true
643       expect(user.nsfwPolicy).to.equal('do_not_list')
644       expect(user.videoQuota).to.equal(42)
645       expect(user.roleLabel).to.equal('Moderator')
646       expect(user.id).to.be.a('number')
647       expect(user.adminFlags).to.equal(UserAdminFlag.NONE)
648     })
649
650     it('Should have removed the user token', async function () {
651       await getMyUserVideoQuotaUsed(server.url, accessTokenUser, 401)
652
653       accessTokenUser = await userLogin(server, user)
654     })
655
656     it('Should be able to update another user password', async function () {
657       await updateUser({
658         url: server.url,
659         userId,
660         accessToken,
661         password: 'password updated'
662       })
663
664       await getMyUserVideoQuotaUsed(server.url, accessTokenUser, 401)
665
666       await userLogin(server, user, 400)
667
668       user.password = 'password updated'
669       accessTokenUser = await userLogin(server, user)
670     })
671   })
672
673   describe('Video blacklists', function () {
674     it('Should be able to list video blacklist by a moderator', async function () {
675       await getBlacklistedVideosList({ url: server.url, token: accessTokenUser })
676     })
677   })
678
679   describe('Remove a user', function () {
680     it('Should be able to remove this user', async function () {
681       await removeUser(server.url, userId, accessToken)
682     })
683
684     it('Should not be able to login with this user', async function () {
685       await userLogin(server, user, 400)
686     })
687
688     it('Should not have videos of this user', async function () {
689       const res = await getVideosList(server.url)
690
691       expect(res.body.total).to.equal(1)
692
693       const video = res.body.data[ 0 ]
694       expect(video.account.name).to.equal('root')
695     })
696   })
697
698   describe('Registering a new user', function () {
699     it('Should register a new user', async function () {
700       const user = { displayName: 'super user 15', username: 'user_15', password: 'my super password' }
701       const channel = { name: 'my_user_15_channel', displayName: 'my channel rocks' }
702
703       await registerUserWithChannel({ url: server.url, user, channel })
704     })
705
706     it('Should be able to login with this registered user', async function () {
707       const user15 = {
708         username: 'user_15',
709         password: 'my super password'
710       }
711
712       accessToken = await userLogin(server, user15)
713     })
714
715     it('Should have the correct display name', async function () {
716       const res = await getMyUserInformation(server.url, accessToken)
717       const user: User = res.body
718
719       expect(user.account.displayName).to.equal('super user 15')
720     })
721
722     it('Should have the correct video quota', async function () {
723       const res = await getMyUserInformation(server.url, accessToken)
724       const user = res.body
725
726       expect(user.videoQuota).to.equal(5 * 1024 * 1024)
727     })
728
729     it('Should have created the channel', async function () {
730       const res = await getVideoChannel(server.url, 'my_user_15_channel')
731
732       expect(res.body.displayName).to.equal('my channel rocks')
733     })
734
735     it('Should remove me', async function () {
736       {
737         const res = await getUsersList(server.url, server.accessToken)
738         expect(res.body.data.find(u => u.username === 'user_15')).to.not.be.undefined
739       }
740
741       await deleteMe(server.url, accessToken)
742
743       {
744         const res = await getUsersList(server.url, server.accessToken)
745         expect(res.body.data.find(u => u.username === 'user_15')).to.be.undefined
746       }
747     })
748   })
749
750   describe('User blocking', function () {
751     it('Should block and unblock a user', async function () {
752       const user16 = {
753         username: 'user_16',
754         password: 'my super password'
755       }
756       const resUser = await createUser({
757         url: server.url,
758         accessToken: server.accessToken,
759         username: user16.username,
760         password: user16.password
761       })
762       const user16Id = resUser.body.user.id
763
764       accessToken = await userLogin(server, user16)
765
766       await getMyUserInformation(server.url, accessToken, 200)
767       await blockUser(server.url, user16Id, server.accessToken)
768
769       await getMyUserInformation(server.url, accessToken, 401)
770       await userLogin(server, user16, 400)
771
772       await unblockUser(server.url, user16Id, server.accessToken)
773       accessToken = await userLogin(server, user16)
774       await getMyUserInformation(server.url, accessToken, 200)
775     })
776   })
777
778   after(async function () {
779     await cleanupTests([ server ])
780   })
781 })