1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
3 import { expect } from 'chai'
4 import { inspect } from 'util'
9 UserNotificationSetting,
10 UserNotificationSettingValue,
12 } from '@shared/models'
14 createMultipleServers,
17 setAccessTokensToServers,
18 setDefaultAccountAvatar,
19 setDefaultChannelAvatar
20 } from '@shared/server-commands'
21 import { MockSmtpServer } from './mock-servers'
23 type CheckerBaseParams = {
24 server: PeerTubeServer
26 socketNotifications: UserNotification[]
28 check?: { web: boolean, mail: boolean }
31 type CheckerType = 'presence' | 'absence'
33 function getAllNotificationsSettings (): UserNotificationSetting {
35 newVideoFromSubscription: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
36 newCommentOnMyVideo: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
37 abuseAsModerator: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
38 videoAutoBlacklistAsModerator: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
39 blacklistOnMyVideo: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
40 myVideoImportFinished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
41 myVideoPublished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
42 commentMention: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
43 newFollow: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
44 newUserRegistration: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
45 newInstanceFollower: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
46 abuseNewMessage: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
47 abuseStateChange: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
48 autoInstanceFollowing: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
49 newPeerTubeVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
50 newPluginVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL
54 async function checkNewVideoFromSubscription (options: CheckerBaseParams & {
57 checkType: CheckerType
59 const { videoName, shortUUID } = options
60 const notificationType = UserNotificationType.NEW_VIDEO_FROM_SUBSCRIPTION
62 function notificationChecker (notification: UserNotification, checkType: CheckerType) {
63 if (checkType === 'presence') {
64 expect(notification).to.not.be.undefined
65 expect(notification.type).to.equal(notificationType)
67 checkVideo(notification.video, videoName, shortUUID)
68 checkActor(notification.video.channel)
70 expect(notification).to.satisfy((n: UserNotification) => {
71 return n === undefined || n.type !== UserNotificationType.NEW_VIDEO_FROM_SUBSCRIPTION || n.video.name !== videoName
76 function emailNotificationFinder (email: object) {
77 const text = email['text']
78 return text.indexOf(shortUUID) !== -1 && text.indexOf('Your subscription') !== -1
81 await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
84 async function checkVideoIsPublished (options: CheckerBaseParams & {
87 checkType: CheckerType
89 const { videoName, shortUUID } = options
90 const notificationType = UserNotificationType.MY_VIDEO_PUBLISHED
92 function notificationChecker (notification: UserNotification, checkType: CheckerType) {
93 if (checkType === 'presence') {
94 expect(notification).to.not.be.undefined
95 expect(notification.type).to.equal(notificationType)
97 checkVideo(notification.video, videoName, shortUUID)
98 checkActor(notification.video.channel)
100 expect(notification.video).to.satisfy(v => v === undefined || v.name !== videoName)
104 function emailNotificationFinder (email: object) {
105 const text: string = email['text']
106 return text.includes(shortUUID) && text.includes('Your video')
109 await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
112 async function checkMyVideoImportIsFinished (options: CheckerBaseParams & {
117 checkType: CheckerType
119 const { videoName, shortUUID, url, success } = options
121 const notificationType = success ? UserNotificationType.MY_VIDEO_IMPORT_SUCCESS : UserNotificationType.MY_VIDEO_IMPORT_ERROR
123 function notificationChecker (notification: UserNotification, checkType: CheckerType) {
124 if (checkType === 'presence') {
125 expect(notification).to.not.be.undefined
126 expect(notification.type).to.equal(notificationType)
128 expect(notification.videoImport.targetUrl).to.equal(url)
130 if (success) checkVideo(notification.videoImport.video, videoName, shortUUID)
132 expect(notification.videoImport).to.satisfy(i => i === undefined || i.targetUrl !== url)
136 function emailNotificationFinder (email: object) {
137 const text: string = email['text']
138 const toFind = success ? ' finished' : ' error'
140 return text.includes(url) && text.includes(toFind)
143 await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
146 async function checkUserRegistered (options: CheckerBaseParams & {
148 checkType: CheckerType
150 const { username } = options
151 const notificationType = UserNotificationType.NEW_USER_REGISTRATION
153 function notificationChecker (notification: UserNotification, checkType: CheckerType) {
154 if (checkType === 'presence') {
155 expect(notification).to.not.be.undefined
156 expect(notification.type).to.equal(notificationType)
158 checkActor(notification.account)
159 expect(notification.account.name).to.equal(username)
161 expect(notification).to.satisfy(n => n.type !== notificationType || n.account.name !== username)
165 function emailNotificationFinder (email: object) {
166 const text: string = email['text']
168 return text.includes(' registered.') && text.includes(username)
171 await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
174 async function checkNewActorFollow (options: CheckerBaseParams & {
175 followType: 'channel' | 'account'
177 followerDisplayName: string
178 followingDisplayName: string
179 checkType: CheckerType
181 const { followType, followerName, followerDisplayName, followingDisplayName } = options
182 const notificationType = UserNotificationType.NEW_FOLLOW
184 function notificationChecker (notification: UserNotification, checkType: CheckerType) {
185 if (checkType === 'presence') {
186 expect(notification).to.not.be.undefined
187 expect(notification.type).to.equal(notificationType)
189 checkActor(notification.actorFollow.follower)
190 expect(notification.actorFollow.follower.displayName).to.equal(followerDisplayName)
191 expect(notification.actorFollow.follower.name).to.equal(followerName)
192 expect(notification.actorFollow.follower.host).to.not.be.undefined
194 const following = notification.actorFollow.following
195 expect(following.displayName).to.equal(followingDisplayName)
196 expect(following.type).to.equal(followType)
198 expect(notification).to.satisfy(n => {
199 return n.type !== notificationType ||
200 (n.actorFollow.follower.name !== followerName && n.actorFollow.following !== followingDisplayName)
205 function emailNotificationFinder (email: object) {
206 const text: string = email['text']
208 return text.includes(followType) && text.includes(followingDisplayName) && text.includes(followerDisplayName)
211 await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
214 async function checkNewInstanceFollower (options: CheckerBaseParams & {
216 checkType: CheckerType
218 const { followerHost } = options
219 const notificationType = UserNotificationType.NEW_INSTANCE_FOLLOWER
221 function notificationChecker (notification: UserNotification, checkType: CheckerType) {
222 if (checkType === 'presence') {
223 expect(notification).to.not.be.undefined
224 expect(notification.type).to.equal(notificationType)
226 checkActor(notification.actorFollow.follower)
227 expect(notification.actorFollow.follower.name).to.equal('peertube')
228 expect(notification.actorFollow.follower.host).to.equal(followerHost)
230 expect(notification.actorFollow.following.name).to.equal('peertube')
232 expect(notification).to.satisfy(n => {
233 return n.type !== notificationType || n.actorFollow.follower.host !== followerHost
238 function emailNotificationFinder (email: object) {
239 const text: string = email['text']
241 return text.includes('instance has a new follower') && text.includes(followerHost)
244 await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
247 async function checkAutoInstanceFollowing (options: CheckerBaseParams & {
249 followingHost: string
250 checkType: CheckerType
252 const { followerHost, followingHost } = options
253 const notificationType = UserNotificationType.AUTO_INSTANCE_FOLLOWING
255 function notificationChecker (notification: UserNotification, checkType: CheckerType) {
256 if (checkType === 'presence') {
257 expect(notification).to.not.be.undefined
258 expect(notification.type).to.equal(notificationType)
260 const following = notification.actorFollow.following
261 checkActor(following)
262 expect(following.name).to.equal('peertube')
263 expect(following.host).to.equal(followingHost)
265 expect(notification.actorFollow.follower.name).to.equal('peertube')
266 expect(notification.actorFollow.follower.host).to.equal(followerHost)
268 expect(notification).to.satisfy(n => {
269 return n.type !== notificationType || n.actorFollow.following.host !== followingHost
274 function emailNotificationFinder (email: object) {
275 const text: string = email['text']
277 return text.includes(' automatically followed a new instance') && text.includes(followingHost)
280 await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
283 async function checkCommentMention (options: CheckerBaseParams & {
287 byAccountDisplayName: string
288 checkType: CheckerType
290 const { shortUUID, commentId, threadId, byAccountDisplayName } = options
291 const notificationType = UserNotificationType.COMMENT_MENTION
293 function notificationChecker (notification: UserNotification, checkType: CheckerType) {
294 if (checkType === 'presence') {
295 expect(notification).to.not.be.undefined
296 expect(notification.type).to.equal(notificationType)
298 checkComment(notification.comment, commentId, threadId)
299 checkActor(notification.comment.account)
300 expect(notification.comment.account.displayName).to.equal(byAccountDisplayName)
302 checkVideo(notification.comment.video, undefined, shortUUID)
304 expect(notification).to.satisfy(n => n.type !== notificationType || n.comment.id !== commentId)
308 function emailNotificationFinder (email: object) {
309 const text: string = email['text']
311 return text.includes(' mentioned ') && text.includes(shortUUID) && text.includes(byAccountDisplayName)
314 await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
317 let lastEmailCount = 0
319 async function checkNewCommentOnMyVideo (options: CheckerBaseParams & {
323 checkType: CheckerType
325 const { server, shortUUID, commentId, threadId, checkType, emails } = options
326 const notificationType = UserNotificationType.NEW_COMMENT_ON_MY_VIDEO
328 function notificationChecker (notification: UserNotification, checkType: CheckerType) {
329 if (checkType === 'presence') {
330 expect(notification).to.not.be.undefined
331 expect(notification.type).to.equal(notificationType)
333 checkComment(notification.comment, commentId, threadId)
334 checkActor(notification.comment.account)
335 checkVideo(notification.comment.video, undefined, shortUUID)
337 expect(notification).to.satisfy((n: UserNotification) => {
338 return n === undefined || n.comment === undefined || n.comment.id !== commentId
343 const commentUrl = `http://localhost:${server.port}/w/${shortUUID};threadId=${threadId}`
345 function emailNotificationFinder (email: object) {
346 return email['text'].indexOf(commentUrl) !== -1
349 await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
351 if (checkType === 'presence') {
352 // We cannot detect email duplicates, so check we received another email
353 expect(emails).to.have.length.above(lastEmailCount)
354 lastEmailCount = emails.length
358 async function checkNewVideoAbuseForModerators (options: CheckerBaseParams & {
361 checkType: CheckerType
363 const { shortUUID, videoName } = options
364 const notificationType = UserNotificationType.NEW_ABUSE_FOR_MODERATORS
366 function notificationChecker (notification: UserNotification, checkType: CheckerType) {
367 if (checkType === 'presence') {
368 expect(notification).to.not.be.undefined
369 expect(notification.type).to.equal(notificationType)
371 expect(notification.abuse.id).to.be.a('number')
372 checkVideo(notification.abuse.video, videoName, shortUUID)
374 expect(notification).to.satisfy((n: UserNotification) => {
375 return n === undefined || n.abuse === undefined || n.abuse.video.shortUUID !== shortUUID
380 function emailNotificationFinder (email: object) {
381 const text = email['text']
382 return text.indexOf(shortUUID) !== -1 && text.indexOf('abuse') !== -1
385 await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
388 async function checkNewAbuseMessage (options: CheckerBaseParams & {
392 checkType: CheckerType
394 const { abuseId, message, toEmail } = options
395 const notificationType = UserNotificationType.ABUSE_NEW_MESSAGE
397 function notificationChecker (notification: UserNotification, checkType: CheckerType) {
398 if (checkType === 'presence') {
399 expect(notification).to.not.be.undefined
400 expect(notification.type).to.equal(notificationType)
402 expect(notification.abuse.id).to.equal(abuseId)
404 expect(notification).to.satisfy((n: UserNotification) => {
405 return n === undefined || n.type !== notificationType || n.abuse === undefined || n.abuse.id !== abuseId
410 function emailNotificationFinder (email: object) {
411 const text = email['text']
412 const to = email['to'].filter(t => t.address === toEmail)
414 return text.indexOf(message) !== -1 && to.length !== 0
417 await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
420 async function checkAbuseStateChange (options: CheckerBaseParams & {
423 checkType: CheckerType
425 const { abuseId, state } = options
426 const notificationType = UserNotificationType.ABUSE_STATE_CHANGE
428 function notificationChecker (notification: UserNotification, checkType: CheckerType) {
429 if (checkType === 'presence') {
430 expect(notification).to.not.be.undefined
431 expect(notification.type).to.equal(notificationType)
433 expect(notification.abuse.id).to.equal(abuseId)
434 expect(notification.abuse.state).to.equal(state)
436 expect(notification).to.satisfy((n: UserNotification) => {
437 return n === undefined || n.abuse === undefined || n.abuse.id !== abuseId
442 function emailNotificationFinder (email: object) {
443 const text = email['text']
445 const contains = state === AbuseState.ACCEPTED
449 return text.indexOf(contains) !== -1
452 await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
455 async function checkNewCommentAbuseForModerators (options: CheckerBaseParams & {
458 checkType: CheckerType
460 const { shortUUID, videoName } = options
461 const notificationType = UserNotificationType.NEW_ABUSE_FOR_MODERATORS
463 function notificationChecker (notification: UserNotification, checkType: CheckerType) {
464 if (checkType === 'presence') {
465 expect(notification).to.not.be.undefined
466 expect(notification.type).to.equal(notificationType)
468 expect(notification.abuse.id).to.be.a('number')
469 checkVideo(notification.abuse.comment.video, videoName, shortUUID)
471 expect(notification).to.satisfy((n: UserNotification) => {
472 return n === undefined || n.abuse === undefined || n.abuse.comment.video.shortUUID !== shortUUID
477 function emailNotificationFinder (email: object) {
478 const text = email['text']
479 return text.indexOf(shortUUID) !== -1 && text.indexOf('abuse') !== -1
482 await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
485 async function checkNewAccountAbuseForModerators (options: CheckerBaseParams & {
487 checkType: CheckerType
489 const { displayName } = options
490 const notificationType = UserNotificationType.NEW_ABUSE_FOR_MODERATORS
492 function notificationChecker (notification: UserNotification, checkType: CheckerType) {
493 if (checkType === 'presence') {
494 expect(notification).to.not.be.undefined
495 expect(notification.type).to.equal(notificationType)
497 expect(notification.abuse.id).to.be.a('number')
498 expect(notification.abuse.account.displayName).to.equal(displayName)
500 expect(notification).to.satisfy((n: UserNotification) => {
501 return n === undefined || n.abuse === undefined || n.abuse.account.displayName !== displayName
506 function emailNotificationFinder (email: object) {
507 const text = email['text']
508 return text.indexOf(displayName) !== -1 && text.indexOf('abuse') !== -1
511 await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
514 async function checkVideoAutoBlacklistForModerators (options: CheckerBaseParams & {
517 checkType: CheckerType
519 const { shortUUID, videoName } = options
520 const notificationType = UserNotificationType.VIDEO_AUTO_BLACKLIST_FOR_MODERATORS
522 function notificationChecker (notification: UserNotification, checkType: CheckerType) {
523 if (checkType === 'presence') {
524 expect(notification).to.not.be.undefined
525 expect(notification.type).to.equal(notificationType)
527 expect(notification.videoBlacklist.video.id).to.be.a('number')
528 checkVideo(notification.videoBlacklist.video, videoName, shortUUID)
530 expect(notification).to.satisfy((n: UserNotification) => {
531 return n === undefined || n.video === undefined || n.video.shortUUID !== shortUUID
536 function emailNotificationFinder (email: object) {
537 const text = email['text']
538 return text.indexOf(shortUUID) !== -1 && email['text'].indexOf('video-auto-blacklist/list') !== -1
541 await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
544 async function checkNewBlacklistOnMyVideo (options: CheckerBaseParams & {
547 blacklistType: 'blacklist' | 'unblacklist'
549 const { videoName, shortUUID, blacklistType } = options
550 const notificationType = blacklistType === 'blacklist'
551 ? UserNotificationType.BLACKLIST_ON_MY_VIDEO
552 : UserNotificationType.UNBLACKLIST_ON_MY_VIDEO
554 function notificationChecker (notification: UserNotification) {
555 expect(notification).to.not.be.undefined
556 expect(notification.type).to.equal(notificationType)
558 const video = blacklistType === 'blacklist' ? notification.videoBlacklist.video : notification.video
560 checkVideo(video, videoName, shortUUID)
563 function emailNotificationFinder (email: object) {
564 const text = email['text']
565 const blacklistText = blacklistType === 'blacklist'
569 return text.includes(shortUUID) && text.includes(blacklistText)
572 await checkNotification({ ...options, notificationChecker, emailNotificationFinder, checkType: 'presence' })
575 async function checkNewPeerTubeVersion (options: CheckerBaseParams & {
576 latestVersion: string
577 checkType: CheckerType
579 const { latestVersion } = options
580 const notificationType = UserNotificationType.NEW_PEERTUBE_VERSION
582 function notificationChecker (notification: UserNotification, checkType: CheckerType) {
583 if (checkType === 'presence') {
584 expect(notification).to.not.be.undefined
585 expect(notification.type).to.equal(notificationType)
587 expect(notification.peertube).to.exist
588 expect(notification.peertube.latestVersion).to.equal(latestVersion)
590 expect(notification).to.satisfy((n: UserNotification) => {
591 return n === undefined || n.peertube === undefined || n.peertube.latestVersion !== latestVersion
596 function emailNotificationFinder (email: object) {
597 const text = email['text']
599 return text.includes(latestVersion)
602 await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
605 async function checkNewPluginVersion (options: CheckerBaseParams & {
606 pluginType: PluginType
608 checkType: CheckerType
610 const { pluginName, pluginType } = options
611 const notificationType = UserNotificationType.NEW_PLUGIN_VERSION
613 function notificationChecker (notification: UserNotification, checkType: CheckerType) {
614 if (checkType === 'presence') {
615 expect(notification).to.not.be.undefined
616 expect(notification.type).to.equal(notificationType)
618 expect(notification.plugin.name).to.equal(pluginName)
619 expect(notification.plugin.type).to.equal(pluginType)
621 expect(notification).to.satisfy((n: UserNotification) => {
622 return n === undefined || n.plugin === undefined || n.plugin.name !== pluginName
627 function emailNotificationFinder (email: object) {
628 const text = email['text']
630 return text.includes(pluginName)
633 await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
636 async function prepareNotificationsTest (serversCount = 3, overrideConfigArg: any = {}) {
637 const userNotifications: UserNotification[] = []
638 const adminNotifications: UserNotification[] = []
639 const adminNotificationsServer2: UserNotification[] = []
640 const emails: object[] = []
642 const port = await MockSmtpServer.Instance.collectEmails(emails)
644 const overrideConfig = {
646 hostname: 'localhost',
653 const servers = await createMultipleServers(serversCount, Object.assign(overrideConfig, overrideConfigArg))
655 await setAccessTokensToServers(servers)
656 await setDefaultChannelAvatar(servers)
657 await setDefaultAccountAvatar(servers)
659 if (serversCount > 1) {
660 await doubleFollow(servers[0], servers[1])
663 const user = { username: 'user_1', password: 'super password' }
664 await servers[0].users.create({ ...user, videoQuota: 10 * 1000 * 1000 })
665 const userAccessToken = await servers[0].login.getAccessToken(user)
667 await servers[0].notifications.updateMySettings({ token: userAccessToken, settings: getAllNotificationsSettings() })
668 await servers[0].notifications.updateMySettings({ settings: getAllNotificationsSettings() })
670 if (serversCount > 1) {
671 await servers[1].notifications.updateMySettings({ settings: getAllNotificationsSettings() })
675 const socket = servers[0].socketIO.getUserNotificationSocket({ token: userAccessToken })
676 socket.on('new-notification', n => userNotifications.push(n))
679 const socket = servers[0].socketIO.getUserNotificationSocket()
680 socket.on('new-notification', n => adminNotifications.push(n))
683 if (serversCount > 1) {
684 const socket = servers[1].socketIO.getUserNotificationSocket()
685 socket.on('new-notification', n => adminNotificationsServer2.push(n))
688 const { videoChannels } = await servers[0].users.getMyInfo()
689 const channelId = videoChannels[0].id
694 adminNotificationsServer2,
702 // ---------------------------------------------------------------------------
705 getAllNotificationsSettings,
709 checkMyVideoImportIsFinished,
711 checkAutoInstanceFollowing,
712 checkVideoIsPublished,
713 checkNewVideoFromSubscription,
715 checkNewCommentOnMyVideo,
716 checkNewBlacklistOnMyVideo,
718 checkNewVideoAbuseForModerators,
719 checkVideoAutoBlacklistForModerators,
720 checkNewAbuseMessage,
721 checkAbuseStateChange,
722 checkNewInstanceFollower,
723 prepareNotificationsTest,
724 checkNewCommentAbuseForModerators,
725 checkNewAccountAbuseForModerators,
726 checkNewPeerTubeVersion,
727 checkNewPluginVersion
730 // ---------------------------------------------------------------------------
732 async function checkNotification (options: CheckerBaseParams & {
733 notificationChecker: (notification: UserNotification, checkType: CheckerType) => void
734 emailNotificationFinder: (email: object) => boolean
735 checkType: CheckerType
737 const { server, token, checkType, notificationChecker, emailNotificationFinder, socketNotifications, emails } = options
739 const check = options.check || { web: true, mail: true }
742 const notification = await server.notifications.getLatest({ token: token })
744 if (notification || checkType !== 'absence') {
745 notificationChecker(notification, checkType)
748 const socketNotification = socketNotifications.find(n => {
750 notificationChecker(n, 'presence')
757 if (checkType === 'presence') {
758 const obj = inspect(socketNotifications, { depth: 5 })
759 expect(socketNotification, 'The socket notification is absent when it should be present. ' + obj).to.not.be.undefined
761 const obj = inspect(socketNotification, { depth: 5 })
762 expect(socketNotification, 'The socket notification is present when it should not be present. ' + obj).to.be.undefined
771 .find(e => emailNotificationFinder(e))
773 if (checkType === 'presence') {
774 const texts = emails.map(e => e.text)
775 expect(email, 'The email is absent when is should be present. ' + inspect(texts)).to.not.be.undefined
777 expect(email, 'The email is present when is should not be present. ' + inspect(email)).to.be.undefined
782 function checkVideo (video: any, videoName?: string, shortUUID?: string) {
784 expect(video.name).to.be.a('string')
785 expect(video.name).to.not.be.empty
786 expect(video.name).to.equal(videoName)
790 expect(video.shortUUID).to.be.a('string')
791 expect(video.shortUUID).to.not.be.empty
792 expect(video.shortUUID).to.equal(shortUUID)
795 expect(video.id).to.be.a('number')
798 function checkActor (actor: any) {
799 expect(actor.displayName).to.be.a('string')
800 expect(actor.displayName).to.not.be.empty
801 expect(actor.host).to.not.be.undefined
804 function checkComment (comment: any, commentId: number, threadId: number) {
805 expect(comment.id).to.equal(commentId)
806 expect(comment.threadId).to.equal(threadId)