1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
4 import * as chai from 'chai'
12 flushAndRunMultipleServers,
14 setAccessTokensToServers,
15 updateCustomSubConfig,
21 } from '@shared/extra-utils'
22 import { getStats } from '@shared/extra-utils/server/stats'
23 import { ActivityType, ServerStats, VideoPlaylistPrivacy } from '@shared/models'
25 const expect = chai.expect
27 describe('Test stats (excluding redundancy)', function () {
28 let servers: ServerInfo[] = []
32 password: 'super_password'
35 before(async function () {
38 servers = await flushAndRunMultipleServers(3)
40 await setAccessTokensToServers(servers)
42 await doubleFollow(servers[0], servers[1])
44 await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: user.username, password: user.password })
46 const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { fixture: 'video_short.webm' })
47 const videoUUID = resVideo.body.video.uuid
49 await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'comment')
51 await viewVideo(servers[0].url, videoUUID)
53 // Wait the video views repeatable job
56 await servers[2].followsCommand.follow({ targets: [ servers[0].url ] })
57 await waitJobs(servers)
60 it('Should have the correct stats on instance 1', async function () {
61 const res = await getStats(servers[0].url)
62 const data: ServerStats = res.body
64 expect(data.totalLocalVideoComments).to.equal(1)
65 expect(data.totalLocalVideos).to.equal(1)
66 expect(data.totalLocalVideoViews).to.equal(1)
67 expect(data.totalLocalVideoFilesSize).to.equal(218910)
68 expect(data.totalUsers).to.equal(2)
69 expect(data.totalVideoComments).to.equal(1)
70 expect(data.totalVideos).to.equal(1)
71 expect(data.totalInstanceFollowers).to.equal(2)
72 expect(data.totalInstanceFollowing).to.equal(1)
73 expect(data.totalLocalPlaylists).to.equal(0)
76 it('Should have the correct stats on instance 2', async function () {
77 const res = await getStats(servers[1].url)
78 const data: ServerStats = res.body
80 expect(data.totalLocalVideoComments).to.equal(0)
81 expect(data.totalLocalVideos).to.equal(0)
82 expect(data.totalLocalVideoViews).to.equal(0)
83 expect(data.totalLocalVideoFilesSize).to.equal(0)
84 expect(data.totalUsers).to.equal(1)
85 expect(data.totalVideoComments).to.equal(1)
86 expect(data.totalVideos).to.equal(1)
87 expect(data.totalInstanceFollowers).to.equal(1)
88 expect(data.totalInstanceFollowing).to.equal(1)
89 expect(data.totalLocalPlaylists).to.equal(0)
92 it('Should have the correct stats on instance 3', async function () {
93 const res = await getStats(servers[2].url)
94 const data: ServerStats = res.body
96 expect(data.totalLocalVideoComments).to.equal(0)
97 expect(data.totalLocalVideos).to.equal(0)
98 expect(data.totalLocalVideoViews).to.equal(0)
99 expect(data.totalUsers).to.equal(1)
100 expect(data.totalVideoComments).to.equal(1)
101 expect(data.totalVideos).to.equal(1)
102 expect(data.totalInstanceFollowing).to.equal(1)
103 expect(data.totalInstanceFollowers).to.equal(0)
104 expect(data.totalLocalPlaylists).to.equal(0)
107 it('Should have the correct total videos stats after an unfollow', async function () {
110 await servers[2].followsCommand.unfollow({ target: servers[0] })
111 await waitJobs(servers)
113 const res = await getStats(servers[2].url)
114 const data: ServerStats = res.body
116 expect(data.totalVideos).to.equal(0)
119 it('Should have the correct active user stats', async function () {
120 const server = servers[0]
123 const res = await getStats(server.url)
124 const data: ServerStats = res.body
125 expect(data.totalDailyActiveUsers).to.equal(1)
126 expect(data.totalWeeklyActiveUsers).to.equal(1)
127 expect(data.totalMonthlyActiveUsers).to.equal(1)
131 await userLogin(server, user)
133 const res = await getStats(server.url)
134 const data: ServerStats = res.body
135 expect(data.totalDailyActiveUsers).to.equal(2)
136 expect(data.totalWeeklyActiveUsers).to.equal(2)
137 expect(data.totalMonthlyActiveUsers).to.equal(2)
141 it('Should have the correct active channel stats', async function () {
142 const server = servers[0]
145 const res = await getStats(server.url)
146 const data: ServerStats = res.body
147 expect(data.totalLocalDailyActiveVideoChannels).to.equal(1)
148 expect(data.totalLocalWeeklyActiveVideoChannels).to.equal(1)
149 expect(data.totalLocalMonthlyActiveVideoChannels).to.equal(1)
153 const channelAttributes = {
154 name: 'stats_channel',
155 displayName: 'My stats channel'
157 const resChannel = await addVideoChannel(server.url, server.accessToken, channelAttributes)
158 channelId = resChannel.body.videoChannel.id
160 const res = await getStats(server.url)
161 const data: ServerStats = res.body
162 expect(data.totalLocalDailyActiveVideoChannels).to.equal(1)
163 expect(data.totalLocalWeeklyActiveVideoChannels).to.equal(1)
164 expect(data.totalLocalMonthlyActiveVideoChannels).to.equal(1)
168 await uploadVideo(server.url, server.accessToken, { fixture: 'video_short.webm', channelId })
170 const res = await getStats(server.url)
171 const data: ServerStats = res.body
172 expect(data.totalLocalDailyActiveVideoChannels).to.equal(2)
173 expect(data.totalLocalWeeklyActiveVideoChannels).to.equal(2)
174 expect(data.totalLocalMonthlyActiveVideoChannels).to.equal(2)
178 it('Should have the correct playlist stats', async function () {
179 const server = servers[0]
182 const resStats = await getStats(server.url)
183 const dataStats: ServerStats = resStats.body
184 expect(dataStats.totalLocalPlaylists).to.equal(0)
188 await createVideoPlaylist({
190 token: server.accessToken,
192 displayName: 'playlist for count',
193 privacy: VideoPlaylistPrivacy.PUBLIC,
194 videoChannelId: channelId
198 const resStats = await getStats(server.url)
199 const dataStats: ServerStats = resStats.body
200 expect(dataStats.totalLocalPlaylists).to.equal(1)
204 it('Should correctly count video file sizes if transcoding is enabled', async function () {
207 await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
229 await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video', fixture: 'video_short.webm' })
231 await waitJobs(servers)
234 const res = await getStats(servers[1].url)
235 const data: ServerStats = res.body
236 expect(data.totalLocalVideoFilesSize).to.equal(0)
240 const res = await getStats(servers[0].url)
241 const data: ServerStats = res.body
242 expect(data.totalLocalVideoFilesSize).to.be.greaterThan(500000)
243 expect(data.totalLocalVideoFilesSize).to.be.lessThan(600000)
247 it('Should have the correct AP stats', async function () {
250 await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
256 const res1 = await getStats(servers[1].url)
257 const first = res1.body as ServerStats
259 for (let i = 0; i < 10; i++) {
260 await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video' })
263 await waitJobs(servers)
267 const res2 = await getStats(servers[1].url)
268 const second: ServerStats = res2.body
270 expect(second.totalActivityPubMessagesProcessed).to.be.greaterThan(first.totalActivityPubMessagesProcessed)
271 const apTypes: ActivityType[] = [
272 'Create', 'Update', 'Delete', 'Follow', 'Accept', 'Announce', 'Undo', 'Like', 'Reject', 'View', 'Dislike', 'Flag'
275 const processed = apTypes.reduce(
276 (previous, type) => previous + second['totalActivityPub' + type + 'MessagesSuccesses'],
279 expect(second.totalActivityPubMessagesProcessed).to.equal(processed)
280 expect(second.totalActivityPubMessagesSuccesses).to.equal(processed)
282 expect(second.totalActivityPubMessagesErrors).to.equal(0)
284 for (const apType of apTypes) {
285 expect(second['totalActivityPub' + apType + 'MessagesErrors']).to.equal(0)
290 const res3 = await getStats(servers[1].url)
291 const third: ServerStats = res3.body
293 expect(third.totalActivityPubMessagesWaiting).to.equal(0)
294 expect(third.activityPubMessagesProcessedPerSecond).to.be.lessThan(second.activityPubMessagesProcessedPerSecond)
297 after(async function () {
298 await cleanupTests(servers)