]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/tests/api/users/user-notifications.ts
Add user notification base code
[github/Chocobozzz/PeerTube.git] / server / tests / api / users / user-notifications.ts
1 /* tslint:disable:no-unused-expression */
2
3 import * as chai from 'chai'
4 import 'mocha'
5 import {
6 addVideoToBlacklist,
7 createUser,
8 doubleFollow,
9 flushAndRunMultipleServers,
10 flushTests,
11 getMyUserInformation,
12 immutableAssign,
13 removeVideoFromBlacklist,
14 reportVideoAbuse,
15 updateVideo,
16 userLogin,
17 wait
18 } from '../../../../shared/utils'
19 import { killallServers, ServerInfo, uploadVideo } from '../../../../shared/utils/index'
20 import { setAccessTokensToServers } from '../../../../shared/utils/users/login'
21 import { waitJobs } from '../../../../shared/utils/server/jobs'
22 import { getUserNotificationSocket } from '../../../../shared/utils/socket/socket-io'
23 import {
24 CheckerBaseParams,
25 checkNewBlacklistOnMyVideo,
26 checkNewCommentOnMyVideo,
27 checkNewVideoAbuseForModerators,
28 checkNewVideoFromSubscription,
29 getLastNotification,
30 getUserNotifications,
31 markAsReadNotifications,
32 updateMyNotificationSettings
33 } from '../../../../shared/utils/users/user-notifications'
34 import { User, UserNotification, UserNotificationSettingValue } from '../../../../shared/models/users'
35 import { MockSmtpServer } from '../../../../shared/utils/miscs/email'
36 import { addUserSubscription } from '../../../../shared/utils/users/user-subscriptions'
37 import { VideoPrivacy } from '../../../../shared/models/videos'
38 import { getYoutubeVideoUrl, importVideo } from '../../../../shared/utils/videos/video-imports'
39 import { addVideoCommentReply, addVideoCommentThread } from '../../../../shared/utils/videos/video-comments'
40
41 const expect = chai.expect
42
43 async function uploadVideoByRemoteAccount (servers: ServerInfo[], videoNameId: number, additionalParams: any = {}) {
44 const data = Object.assign({ name: 'remote video ' + videoNameId }, additionalParams)
45 const res = await uploadVideo(servers[ 1 ].url, servers[ 1 ].accessToken, data)
46
47 await waitJobs(servers)
48
49 return res.body.video.uuid
50 }
51
52 async function uploadVideoByLocalAccount (servers: ServerInfo[], videoNameId: number, additionalParams: any = {}) {
53 const data = Object.assign({ name: 'local video ' + videoNameId }, additionalParams)
54 const res = await uploadVideo(servers[ 0 ].url, servers[ 0 ].accessToken, data)
55
56 await waitJobs(servers)
57
58 return res.body.video.uuid
59 }
60
61 describe('Test users notifications', function () {
62 let servers: ServerInfo[] = []
63 let userAccessToken: string
64 let userNotifications: UserNotification[] = []
65 let adminNotifications: UserNotification[] = []
66 const emails: object[] = []
67
68 before(async function () {
69 this.timeout(120000)
70
71 await MockSmtpServer.Instance.collectEmails(emails)
72
73 await flushTests()
74
75 const overrideConfig = {
76 smtp: {
77 hostname: 'localhost'
78 }
79 }
80 servers = await flushAndRunMultipleServers(2, overrideConfig)
81
82 // Get the access tokens
83 await setAccessTokensToServers(servers)
84
85 // Server 1 and server 2 follow each other
86 await doubleFollow(servers[0], servers[1])
87
88 await waitJobs(servers)
89
90 const user = {
91 username: 'user_1',
92 password: 'super password'
93 }
94 await createUser(servers[0].url, servers[0].accessToken, user.username, user.password, 10 * 1000 * 1000)
95 userAccessToken = await userLogin(servers[0], user)
96
97 await updateMyNotificationSettings(servers[0].url, userAccessToken, {
98 newCommentOnMyVideo: UserNotificationSettingValue.WEB_NOTIFICATION_AND_EMAIL,
99 newVideoFromSubscription: UserNotificationSettingValue.WEB_NOTIFICATION_AND_EMAIL,
100 blacklistOnMyVideo: UserNotificationSettingValue.WEB_NOTIFICATION_AND_EMAIL,
101 videoAbuseAsModerator: UserNotificationSettingValue.WEB_NOTIFICATION_AND_EMAIL
102 })
103
104 {
105 const socket = getUserNotificationSocket(servers[ 0 ].url, userAccessToken)
106 socket.on('new-notification', n => userNotifications.push(n))
107 }
108 {
109 const socket = getUserNotificationSocket(servers[ 0 ].url, servers[0].accessToken)
110 socket.on('new-notification', n => adminNotifications.push(n))
111 }
112 })
113
114 describe('New video from my subscription notification', function () {
115 let baseParams: CheckerBaseParams
116
117 before(() => {
118 baseParams = {
119 server: servers[0],
120 emails,
121 socketNotifications: userNotifications,
122 token: userAccessToken
123 }
124 })
125
126 it('Should not send notifications if the user does not follow the video publisher', async function () {
127 await uploadVideoByLocalAccount(servers, 1)
128
129 const notification = await getLastNotification(servers[ 0 ].url, userAccessToken)
130 expect(notification).to.be.undefined
131
132 expect(emails).to.have.lengthOf(0)
133 expect(userNotifications).to.have.lengthOf(0)
134 })
135
136 it('Should send a new video notification if the user follows the local video publisher', async function () {
137 await addUserSubscription(servers[0].url, userAccessToken, 'root_channel@localhost:9001')
138
139 const videoNameId = 10
140 const videoName = 'local video ' + videoNameId
141
142 const uuid = await uploadVideoByLocalAccount(servers, videoNameId)
143 await checkNewVideoFromSubscription(baseParams, videoName, uuid, 'presence')
144 })
145
146 it('Should send a new video notification from a remote account', async function () {
147 this.timeout(50000) // Server 2 has transcoding enabled
148
149 await addUserSubscription(servers[0].url, userAccessToken, 'root_channel@localhost:9002')
150
151 const videoNameId = 20
152 const videoName = 'remote video ' + videoNameId
153
154 const uuid = await uploadVideoByRemoteAccount(servers, videoNameId)
155 await checkNewVideoFromSubscription(baseParams, videoName, uuid, 'presence')
156 })
157
158 it('Should send a new video notification on a scheduled publication', async function () {
159 this.timeout(20000)
160
161 const videoNameId = 30
162 const videoName = 'local video ' + videoNameId
163
164 // In 2 seconds
165 let updateAt = new Date(new Date().getTime() + 2000)
166
167 const data = {
168 privacy: VideoPrivacy.PRIVATE,
169 scheduleUpdate: {
170 updateAt: updateAt.toISOString(),
171 privacy: VideoPrivacy.PUBLIC
172 }
173 }
174 const uuid = await uploadVideoByLocalAccount(servers, videoNameId, data)
175
176 await wait(6000)
177 await checkNewVideoFromSubscription(baseParams, videoName, uuid, 'presence')
178 })
179
180 it('Should send a new video notification on a remote scheduled publication', async function () {
181 this.timeout(20000)
182
183 const videoNameId = 40
184 const videoName = 'remote video ' + videoNameId
185
186 // In 2 seconds
187 let updateAt = new Date(new Date().getTime() + 2000)
188
189 const data = {
190 privacy: VideoPrivacy.PRIVATE,
191 scheduleUpdate: {
192 updateAt: updateAt.toISOString(),
193 privacy: VideoPrivacy.PUBLIC
194 }
195 }
196 const uuid = await uploadVideoByRemoteAccount(servers, videoNameId, data)
197
198 await wait(6000)
199 await checkNewVideoFromSubscription(baseParams, videoName, uuid, 'presence')
200 })
201
202 it('Should not send a notification before the video is published', async function () {
203 this.timeout(20000)
204
205 const videoNameId = 50
206 const videoName = 'local video ' + videoNameId
207
208 let updateAt = new Date(new Date().getTime() + 100000)
209
210 const data = {
211 privacy: VideoPrivacy.PRIVATE,
212 scheduleUpdate: {
213 updateAt: updateAt.toISOString(),
214 privacy: VideoPrivacy.PUBLIC
215 }
216 }
217 const uuid = await uploadVideoByLocalAccount(servers, videoNameId, data)
218
219 await wait(6000)
220 await checkNewVideoFromSubscription(baseParams, videoName, uuid, 'absence')
221 })
222
223 it('Should send a new video notification when a video becomes public', async function () {
224 this.timeout(10000)
225
226 const videoNameId = 60
227 const videoName = 'local video ' + videoNameId
228
229 const data = { privacy: VideoPrivacy.PRIVATE }
230 const uuid = await uploadVideoByLocalAccount(servers, videoNameId, data)
231
232 await checkNewVideoFromSubscription(baseParams, videoName, uuid, 'absence')
233
234 await updateVideo(servers[0].url, servers[0].accessToken, uuid, { privacy: VideoPrivacy.PUBLIC })
235
236 await wait(500)
237 await checkNewVideoFromSubscription(baseParams, videoName, uuid, 'presence')
238 })
239
240 it('Should send a new video notification when a remote video becomes public', async function () {
241 this.timeout(20000)
242
243 const videoNameId = 70
244 const videoName = 'remote video ' + videoNameId
245
246 const data = { privacy: VideoPrivacy.PRIVATE }
247 const uuid = await uploadVideoByRemoteAccount(servers, videoNameId, data)
248
249 await checkNewVideoFromSubscription(baseParams, videoName, uuid, 'absence')
250
251 await updateVideo(servers[1].url, servers[1].accessToken, uuid, { privacy: VideoPrivacy.PUBLIC })
252
253 await waitJobs(servers)
254 await checkNewVideoFromSubscription(baseParams, videoName, uuid, 'presence')
255 })
256
257 it('Should not send a new video notification when a video becomes unlisted', async function () {
258 this.timeout(20000)
259
260 const videoNameId = 80
261 const videoName = 'local video ' + videoNameId
262
263 const data = { privacy: VideoPrivacy.PRIVATE }
264 const uuid = await uploadVideoByLocalAccount(servers, videoNameId, data)
265
266 await updateVideo(servers[0].url, servers[0].accessToken, uuid, { privacy: VideoPrivacy.UNLISTED })
267
268 await checkNewVideoFromSubscription(baseParams, videoName, uuid, 'absence')
269 })
270
271 it('Should not send a new video notification when a remote video becomes unlisted', async function () {
272 this.timeout(20000)
273
274 const videoNameId = 90
275 const videoName = 'remote video ' + videoNameId
276
277 const data = { privacy: VideoPrivacy.PRIVATE }
278 const uuid = await uploadVideoByRemoteAccount(servers, videoNameId, data)
279
280 await updateVideo(servers[1].url, servers[1].accessToken, uuid, { privacy: VideoPrivacy.UNLISTED })
281
282 await waitJobs(servers)
283 await checkNewVideoFromSubscription(baseParams, videoName, uuid, 'absence')
284 })
285
286 it('Should send a new video notification after a video import', async function () {
287 this.timeout(30000)
288
289 const resChannel = await getMyUserInformation(servers[0].url, servers[0].accessToken)
290 const channelId = resChannel.body.videoChannels[0].id
291 const videoName = 'local video 100'
292
293 const attributes = {
294 name: videoName,
295 channelId,
296 privacy: VideoPrivacy.PUBLIC,
297 targetUrl: getYoutubeVideoUrl()
298 }
299 const res = await importVideo(servers[0].url, servers[0].accessToken, attributes)
300 const uuid = res.body.video.uuid
301
302 await waitJobs(servers)
303
304 await checkNewVideoFromSubscription(baseParams, videoName, uuid, 'presence')
305 })
306 })
307
308 describe('Comment on my video notifications', function () {
309 let baseParams: CheckerBaseParams
310
311 before(() => {
312 baseParams = {
313 server: servers[0],
314 emails,
315 socketNotifications: userNotifications,
316 token: userAccessToken
317 }
318 })
319
320 it('Should not send a new comment notification after a comment on another video', async function () {
321 this.timeout(10000)
322
323 const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'super video' })
324 const uuid = resVideo.body.video.uuid
325
326 const resComment = await addVideoCommentThread(servers[0].url, servers[0].accessToken, uuid, 'comment')
327 const commentId = resComment.body.comment.id
328
329 await wait(500)
330 await checkNewCommentOnMyVideo(baseParams, uuid, commentId, commentId, 'absence')
331 })
332
333 it('Should not send a new comment notification if I comment my own video', async function () {
334 this.timeout(10000)
335
336 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'super video' })
337 const uuid = resVideo.body.video.uuid
338
339 const resComment = await addVideoCommentThread(servers[0].url, userAccessToken, uuid, 'comment')
340 const commentId = resComment.body.comment.id
341
342 await wait(500)
343 await checkNewCommentOnMyVideo(baseParams, uuid, commentId, commentId, 'absence')
344 })
345
346 it('Should send a new comment notification after a local comment on my video', async function () {
347 this.timeout(10000)
348
349 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'super video' })
350 const uuid = resVideo.body.video.uuid
351
352 const resComment = await addVideoCommentThread(servers[0].url, servers[0].accessToken, uuid, 'comment')
353 const commentId = resComment.body.comment.id
354
355 await wait(500)
356 await checkNewCommentOnMyVideo(baseParams, uuid, commentId, commentId, 'presence')
357 })
358
359 it('Should send a new comment notification after a remote comment on my video', async function () {
360 this.timeout(10000)
361
362 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'super video' })
363 const uuid = resVideo.body.video.uuid
364
365 await waitJobs(servers)
366
367 const resComment = await addVideoCommentThread(servers[1].url, servers[1].accessToken, uuid, 'comment')
368 const commentId = resComment.body.comment.id
369
370 await waitJobs(servers)
371 await checkNewCommentOnMyVideo(baseParams, uuid, commentId, commentId, 'presence')
372 })
373
374 it('Should send a new comment notification after a local reply on my video', async function () {
375 this.timeout(10000)
376
377 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'super video' })
378 const uuid = resVideo.body.video.uuid
379
380 const resThread = await addVideoCommentThread(servers[0].url, servers[0].accessToken, uuid, 'comment')
381 const threadId = resThread.body.comment.id
382
383 const resComment = await addVideoCommentReply(servers[0].url, servers[0].accessToken, uuid, threadId, 'reply')
384 const commentId = resComment.body.comment.id
385
386 await wait(500)
387 await checkNewCommentOnMyVideo(baseParams, uuid, commentId, threadId, 'presence')
388 })
389
390 it('Should send a new comment notification after a remote reply on my video', async function () {
391 this.timeout(10000)
392
393 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'super video' })
394 const uuid = resVideo.body.video.uuid
395 await waitJobs(servers)
396
397 const resThread = await addVideoCommentThread(servers[1].url, servers[1].accessToken, uuid, 'comment')
398 const threadId = resThread.body.comment.id
399
400 const resComment = await addVideoCommentReply(servers[1].url, servers[1].accessToken, uuid, threadId, 'reply')
401 const commentId = resComment.body.comment.id
402
403 await waitJobs(servers)
404 await checkNewCommentOnMyVideo(baseParams, uuid, commentId, threadId, 'presence')
405 })
406 })
407
408 describe('Video abuse for moderators notification' , function () {
409 let baseParams: CheckerBaseParams
410
411 before(() => {
412 baseParams = {
413 server: servers[0],
414 emails,
415 socketNotifications: adminNotifications,
416 token: servers[0].accessToken
417 }
418 })
419
420 it('Should send a notification to moderators on local video abuse', async function () {
421 this.timeout(10000)
422
423 const videoName = 'local video 110'
424
425 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: videoName })
426 const uuid = resVideo.body.video.uuid
427
428 await reportVideoAbuse(servers[0].url, servers[0].accessToken, uuid, 'super reason')
429
430 await waitJobs(servers)
431 await checkNewVideoAbuseForModerators(baseParams, uuid, videoName, 'presence')
432 })
433
434 it('Should send a notification to moderators on remote video abuse', async function () {
435 this.timeout(10000)
436
437 const videoName = 'remote video 120'
438
439 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: videoName })
440 const uuid = resVideo.body.video.uuid
441
442 await waitJobs(servers)
443
444 await reportVideoAbuse(servers[1].url, servers[1].accessToken, uuid, 'super reason')
445
446 await waitJobs(servers)
447 await checkNewVideoAbuseForModerators(baseParams, uuid, videoName, 'presence')
448 })
449 })
450
451 describe('Video blacklist on my video', function () {
452 let baseParams: CheckerBaseParams
453
454 before(() => {
455 baseParams = {
456 server: servers[0],
457 emails,
458 socketNotifications: userNotifications,
459 token: userAccessToken
460 }
461 })
462
463 it('Should send a notification to video owner on blacklist', async function () {
464 this.timeout(10000)
465
466 const videoName = 'local video 130'
467
468 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: videoName })
469 const uuid = resVideo.body.video.uuid
470
471 await addVideoToBlacklist(servers[0].url, servers[0].accessToken, uuid)
472
473 await waitJobs(servers)
474 await checkNewBlacklistOnMyVideo(baseParams, uuid, videoName, 'blacklist')
475 })
476
477 it('Should send a notification to video owner on unblacklist', async function () {
478 this.timeout(10000)
479
480 const videoName = 'local video 130'
481
482 const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: videoName })
483 const uuid = resVideo.body.video.uuid
484
485 await addVideoToBlacklist(servers[0].url, servers[0].accessToken, uuid)
486
487 await waitJobs(servers)
488 await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, uuid)
489 await waitJobs(servers)
490
491 await wait(500)
492 await checkNewBlacklistOnMyVideo(baseParams, uuid, videoName, 'unblacklist')
493 })
494 })
495
496 describe('Mark as read', function () {
497 it('Should mark as read some notifications', async function () {
498 const res = await getUserNotifications(servers[0].url, userAccessToken, 2, 3)
499 const ids = res.body.data.map(n => n.id)
500
501 await markAsReadNotifications(servers[0].url, userAccessToken, ids)
502 })
503
504 it('Should have the notifications marked as read', async function () {
505 const res = await getUserNotifications(servers[0].url, userAccessToken, 0, 10)
506
507 const notifications = res.body.data as UserNotification[]
508 expect(notifications[0].read).to.be.false
509 expect(notifications[1].read).to.be.false
510 expect(notifications[2].read).to.be.true
511 expect(notifications[3].read).to.be.true
512 expect(notifications[4].read).to.be.true
513 expect(notifications[5].read).to.be.false
514 })
515 })
516
517 describe('Notification settings', function () {
518 const baseUpdateNotificationParams = {
519 newCommentOnMyVideo: UserNotificationSettingValue.WEB_NOTIFICATION_AND_EMAIL,
520 newVideoFromSubscription: UserNotificationSettingValue.WEB_NOTIFICATION_AND_EMAIL,
521 videoAbuseAsModerator: UserNotificationSettingValue.WEB_NOTIFICATION_AND_EMAIL,
522 blacklistOnMyVideo: UserNotificationSettingValue.WEB_NOTIFICATION_AND_EMAIL
523 }
524 let baseParams: CheckerBaseParams
525
526 before(() => {
527 baseParams = {
528 server: servers[0],
529 emails,
530 socketNotifications: userNotifications,
531 token: userAccessToken
532 }
533 })
534
535 it('Should not have notifications', async function () {
536 await updateMyNotificationSettings(servers[0].url, userAccessToken, immutableAssign(baseUpdateNotificationParams, {
537 newVideoFromSubscription: UserNotificationSettingValue.NONE
538 }))
539
540 {
541 const res = await getMyUserInformation(servers[0].url, userAccessToken)
542 const info = res.body as User
543 expect(info.notificationSettings.newVideoFromSubscription).to.equal(UserNotificationSettingValue.NONE)
544 }
545
546 const videoNameId = 42
547 const videoName = 'local video ' + videoNameId
548 const uuid = await uploadVideoByLocalAccount(servers, videoNameId)
549
550 const check = { web: true, mail: true }
551 await checkNewVideoFromSubscription(immutableAssign(baseParams, { check }), videoName, uuid, 'absence')
552 })
553
554 it('Should only have web notifications', async function () {
555 await updateMyNotificationSettings(servers[0].url, userAccessToken, immutableAssign(baseUpdateNotificationParams, {
556 newVideoFromSubscription: UserNotificationSettingValue.WEB_NOTIFICATION
557 }))
558
559 {
560 const res = await getMyUserInformation(servers[0].url, userAccessToken)
561 const info = res.body as User
562 expect(info.notificationSettings.newVideoFromSubscription).to.equal(UserNotificationSettingValue.WEB_NOTIFICATION)
563 }
564
565 const videoNameId = 52
566 const videoName = 'local video ' + videoNameId
567 const uuid = await uploadVideoByLocalAccount(servers, videoNameId)
568
569 {
570 const check = { mail: true, web: false }
571 await checkNewVideoFromSubscription(immutableAssign(baseParams, { check }), videoName, uuid, 'absence')
572 }
573
574 {
575 const check = { mail: false, web: true }
576 await checkNewVideoFromSubscription(immutableAssign(baseParams, { check }), videoName, uuid, 'presence')
577 }
578 })
579
580 it('Should only have mail notifications', async function () {
581 await updateMyNotificationSettings(servers[0].url, userAccessToken, immutableAssign(baseUpdateNotificationParams, {
582 newVideoFromSubscription: UserNotificationSettingValue.EMAIL
583 }))
584
585 {
586 const res = await getMyUserInformation(servers[0].url, userAccessToken)
587 const info = res.body as User
588 expect(info.notificationSettings.newVideoFromSubscription).to.equal(UserNotificationSettingValue.EMAIL)
589 }
590
591 const videoNameId = 62
592 const videoName = 'local video ' + videoNameId
593 const uuid = await uploadVideoByLocalAccount(servers, videoNameId)
594
595 {
596 const check = { mail: false, web: true }
597 await checkNewVideoFromSubscription(immutableAssign(baseParams, { check }), videoName, uuid, 'absence')
598 }
599
600 {
601 const check = { mail: true, web: false }
602 await checkNewVideoFromSubscription(immutableAssign(baseParams, { check }), videoName, uuid, 'presence')
603 }
604 })
605
606 it('Should have email and web notifications', async function () {
607 await updateMyNotificationSettings(servers[0].url, userAccessToken, immutableAssign(baseUpdateNotificationParams, {
608 newVideoFromSubscription: UserNotificationSettingValue.WEB_NOTIFICATION_AND_EMAIL
609 }))
610
611 {
612 const res = await getMyUserInformation(servers[0].url, userAccessToken)
613 const info = res.body as User
614 expect(info.notificationSettings.newVideoFromSubscription).to.equal(UserNotificationSettingValue.WEB_NOTIFICATION_AND_EMAIL)
615 }
616
617 const videoNameId = 72
618 const videoName = 'local video ' + videoNameId
619 const uuid = await uploadVideoByLocalAccount(servers, videoNameId)
620
621 await checkNewVideoFromSubscription(baseParams, videoName, uuid, 'presence')
622 })
623 })
624
625 after(async function () {
626 killallServers(servers)
627 })
628 })