1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
4 import * as chai from 'chai'
5 import { FfmpegCommand } from 'fluent-ffmpeg'
6 import { prepareViewsServers, prepareViewsVideos, processViewersStats } from '@server/tests/shared'
7 import { cleanupTests, PeerTubeServer, stopFfmpeg, waitJobs } from '@shared/server-commands'
9 const expect = chai.expect
11 describe('Test views overall stats', function () {
12 let servers: PeerTubeServer[]
14 before(async function () {
17 servers = await prepareViewsServers()
20 describe('Test rates and comments of local videos on VOD', function () {
21 let vodVideoId: string
23 before(async function () {
26 ({ vodVideoId } = await prepareViewsVideos({ servers, live: false, vod: true }))
29 it('Should have the appropriate likes', async function () {
32 await servers[0].videos.rate({ id: vodVideoId, rating: 'like' })
33 await servers[1].videos.rate({ id: vodVideoId, rating: 'like' })
35 await waitJobs(servers)
37 const stats = await servers[0].videoStats.getOverallStats({ videoId: vodVideoId })
39 expect(stats.likes).to.equal(2)
40 expect(stats.dislikes).to.equal(0)
43 it('Should have the appropriate dislikes', async function () {
46 await servers[0].videos.rate({ id: vodVideoId, rating: 'dislike' })
47 await servers[1].videos.rate({ id: vodVideoId, rating: 'dislike' })
49 await waitJobs(servers)
51 const stats = await servers[0].videoStats.getOverallStats({ videoId: vodVideoId })
53 expect(stats.likes).to.equal(0)
54 expect(stats.dislikes).to.equal(2)
57 it('Should have the appropriate comments', async function () {
60 await servers[0].comments.createThread({ videoId: vodVideoId, text: 'root' })
61 await servers[0].comments.addReplyToLastThread({ text: 'reply' })
62 await servers[1].comments.createThread({ videoId: vodVideoId, text: 'root' })
64 await waitJobs(servers)
66 const stats = await servers[0].videoStats.getOverallStats({ videoId: vodVideoId })
67 expect(stats.comments).to.equal(3)
71 describe('Test watch time stats of local videos on live and VOD', function () {
72 let vodVideoId: string
73 let liveVideoId: string
74 let command: FfmpegCommand
76 before(async function () {
79 ({ vodVideoId, liveVideoId, ffmpegCommand: command } = await prepareViewsVideos({ servers, live: true, vod: true }))
82 it('Should display overall stats of a video with no viewers', async function () {
83 for (const videoId of [ liveVideoId, vodVideoId ]) {
84 const stats = await servers[0].videoStats.getOverallStats({ videoId })
86 expect(stats.views).to.equal(0)
87 expect(stats.averageWatchTime).to.equal(0)
88 expect(stats.totalWatchTime).to.equal(0)
92 it('Should display overall stats with 1 viewer below the watch time limit', async function () {
95 for (const videoId of [ liveVideoId, vodVideoId ]) {
96 await servers[0].views.simulateViewer({ id: videoId, currentTimes: [ 0, 1 ] })
99 await processViewersStats(servers)
101 for (const videoId of [ liveVideoId, vodVideoId ]) {
102 const stats = await servers[0].videoStats.getOverallStats({ videoId })
104 expect(stats.views).to.equal(0)
105 expect(stats.averageWatchTime).to.equal(1)
106 expect(stats.totalWatchTime).to.equal(1)
110 it('Should display overall stats with 2 viewers', async function () {
114 await servers[0].views.simulateViewer({ id: vodVideoId, currentTimes: [ 0, 3 ] })
115 await servers[0].views.simulateViewer({ id: liveVideoId, currentTimes: [ 0, 35, 40 ] })
117 await processViewersStats(servers)
120 const stats = await servers[0].videoStats.getOverallStats({ videoId: vodVideoId })
121 expect(stats.views).to.equal(1)
122 expect(stats.averageWatchTime).to.equal(2)
123 expect(stats.totalWatchTime).to.equal(4)
127 const stats = await servers[0].videoStats.getOverallStats({ videoId: liveVideoId })
128 expect(stats.views).to.equal(1)
129 expect(stats.averageWatchTime).to.equal(21)
130 expect(stats.totalWatchTime).to.equal(41)
135 it('Should display overall stats with a remote viewer below the watch time limit', async function () {
138 for (const videoId of [ liveVideoId, vodVideoId ]) {
139 await servers[1].views.simulateViewer({ id: videoId, currentTimes: [ 0, 2 ] })
142 await processViewersStats(servers)
145 const stats = await servers[0].videoStats.getOverallStats({ videoId: vodVideoId })
147 expect(stats.views).to.equal(1)
148 expect(stats.averageWatchTime).to.equal(2)
149 expect(stats.totalWatchTime).to.equal(6)
153 const stats = await servers[0].videoStats.getOverallStats({ videoId: liveVideoId })
155 expect(stats.views).to.equal(1)
156 expect(stats.averageWatchTime).to.equal(14)
157 expect(stats.totalWatchTime).to.equal(43)
161 it('Should display overall stats with a remote viewer above the watch time limit', async function () {
164 await servers[1].views.simulateViewer({ id: vodVideoId, currentTimes: [ 0, 5 ] })
165 await servers[1].views.simulateViewer({ id: liveVideoId, currentTimes: [ 0, 45 ] })
166 await processViewersStats(servers)
169 const stats = await servers[0].videoStats.getOverallStats({ videoId: vodVideoId })
170 expect(stats.views).to.equal(2)
171 expect(stats.averageWatchTime).to.equal(3)
172 expect(stats.totalWatchTime).to.equal(11)
176 const stats = await servers[0].videoStats.getOverallStats({ videoId: liveVideoId })
177 expect(stats.views).to.equal(2)
178 expect(stats.averageWatchTime).to.equal(22)
179 expect(stats.totalWatchTime).to.equal(88)
183 after(async function () {
184 await stopFfmpeg(command)
188 describe('Test watchers peak stats of local videos on VOD', function () {
189 let videoUUID: string
191 before(async function () {
192 this.timeout(120000);
194 ({ vodVideoId: videoUUID } = await prepareViewsVideos({ servers, live: true, vod: true }))
197 it('Should not have watchers peak', async function () {
198 const stats = await servers[0].videoStats.getOverallStats({ videoId: videoUUID })
200 expect(stats.viewersPeak).to.equal(0)
201 expect(stats.viewersPeakDate).to.be.null
204 it('Should have watcher peak with 1 watcher', async function () {
207 const before = new Date()
208 await servers[0].views.simulateViewer({ id: videoUUID, currentTimes: [ 0, 2 ] })
209 const after = new Date()
211 await processViewersStats(servers)
213 const stats = await servers[0].videoStats.getOverallStats({ videoId: videoUUID })
215 expect(stats.viewersPeak).to.equal(1)
216 expect(new Date(stats.viewersPeakDate)).to.be.above(before).and.below(after)
219 it('Should have watcher peak with 2 watchers', async function () {
222 const before = new Date()
223 await servers[0].views.view({ id: videoUUID, currentTime: 0 })
224 await servers[1].views.view({ id: videoUUID, currentTime: 0 })
225 await servers[0].views.view({ id: videoUUID, currentTime: 2 })
226 await servers[1].views.view({ id: videoUUID, currentTime: 2 })
227 const after = new Date()
229 await processViewersStats(servers)
231 const stats = await servers[0].videoStats.getOverallStats({ videoId: videoUUID })
233 expect(stats.viewersPeak).to.equal(2)
234 expect(new Date(stats.viewersPeakDate)).to.be.above(before).and.below(after)
238 describe('Test countries', function () {
240 it('Should not report countries if geoip is disabled', async function () {
243 const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
244 await waitJobs(servers)
246 await servers[1].views.view({ id: uuid, xForwardedFor: '8.8.8.8,127.0.0.1', currentTime: 1 })
248 await processViewersStats(servers)
250 const stats = await servers[0].videoStats.getOverallStats({ videoId: uuid })
251 expect(stats.countries).to.have.lengthOf(0)
254 it('Should report countries if geoip is enabled', async function () {
257 const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
258 await waitJobs(servers)
265 const config = { geo_ip: { enabled: true } }
267 servers[0].run(config),
268 servers[1].run(config)
271 await servers[0].views.view({ id: uuid, xForwardedFor: '8.8.8.8,127.0.0.1', currentTime: 1 })
272 await servers[1].views.view({ id: uuid, xForwardedFor: '8.8.8.4,127.0.0.1', currentTime: 3 })
273 await servers[1].views.view({ id: uuid, xForwardedFor: '80.67.169.12,127.0.0.1', currentTime: 2 })
275 await processViewersStats(servers)
277 const stats = await servers[0].videoStats.getOverallStats({ videoId: uuid })
278 expect(stats.countries).to.have.lengthOf(2)
280 expect(stats.countries[0].isoCode).to.equal('US')
281 expect(stats.countries[0].viewers).to.equal(2)
283 expect(stats.countries[1].isoCode).to.equal('FR')
284 expect(stats.countries[1].viewers).to.equal(1)
288 after(async function () {
289 await cleanupTests(servers)