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, processViewsBuffer } from '@server/tests/shared'
7 import { wait } from '@shared/core-utils'
8 import { cleanupTests, PeerTubeServer, stopFfmpeg, waitJobs } from '@shared/server-commands'
10 const expect = chai.expect
12 describe('Test video views/viewers counters', function () {
13 let servers: PeerTubeServer[]
15 async function checkCounter (field: 'views' | 'viewers', id: string, expected: number) {
16 for (const server of servers) {
17 const video = await server.videos.get({ id })
19 const messageSuffix = video.isLive
23 expect(video[field]).to.equal(expected, `${field} not valid on server ${server.serverNumber} for ${messageSuffix} ${video.uuid}`)
27 before(async function () {
30 servers = await prepareViewsServers()
33 describe('Test views counter on VOD', function () {
36 before(async function () {
39 const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
42 await waitJobs(servers)
45 it('Should not view a video if watch time is below the threshold', async function () {
46 await servers[0].views.simulateViewer({ id: videoUUID, currentTimes: [ 1, 2 ] })
47 await processViewsBuffer(servers)
49 await checkCounter('views', videoUUID, 0)
52 it('Should view a video if watch time is above the threshold', async function () {
53 await servers[0].views.simulateViewer({ id: videoUUID, currentTimes: [ 1, 4 ] })
54 await processViewsBuffer(servers)
56 await checkCounter('views', videoUUID, 1)
59 it('Should not view again this video with the same IP', async function () {
60 await servers[0].views.simulateViewer({ id: videoUUID, xForwardedFor: '0.0.0.1,127.0.0.1', currentTimes: [ 1, 4 ] })
61 await servers[0].views.simulateViewer({ id: videoUUID, xForwardedFor: '0.0.0.1,127.0.0.1', currentTimes: [ 1, 4 ] })
62 await processViewsBuffer(servers)
64 await checkCounter('views', videoUUID, 2)
67 it('Should view the video from server 2 and send the event', async function () {
68 await servers[1].views.simulateViewer({ id: videoUUID, currentTimes: [ 1, 4 ] })
69 await waitJobs(servers)
70 await processViewsBuffer(servers)
72 await checkCounter('views', videoUUID, 3)
76 describe('Test views and viewers counters on live and VOD', function () {
77 let liveVideoId: string
78 let vodVideoId: string
79 let command: FfmpegCommand
81 before(async function () {
84 ({ vodVideoId, liveVideoId, ffmpegCommand: command } = await prepareViewsVideos({ servers, live: true, vod: true }))
87 it('Should display no views and viewers', async function () {
88 await checkCounter('views', liveVideoId, 0)
89 await checkCounter('viewers', liveVideoId, 0)
91 await checkCounter('views', vodVideoId, 0)
92 await checkCounter('viewers', vodVideoId, 0)
95 it('Should view twice and display 1 view/viewer', async function () {
98 await servers[0].views.simulateViewer({ id: liveVideoId, currentTimes: [ 0, 35 ] })
99 await servers[0].views.simulateViewer({ id: liveVideoId, currentTimes: [ 0, 35 ] })
100 await servers[0].views.simulateViewer({ id: vodVideoId, currentTimes: [ 0, 5 ] })
101 await servers[0].views.simulateViewer({ id: vodVideoId, currentTimes: [ 0, 5 ] })
103 await waitJobs(servers)
104 await checkCounter('viewers', liveVideoId, 1)
105 await checkCounter('viewers', vodVideoId, 1)
107 await processViewsBuffer(servers)
109 await checkCounter('views', liveVideoId, 1)
110 await checkCounter('views', vodVideoId, 1)
113 it('Should wait and display 0 viewers but still have 1 view', async function () {
117 await waitJobs(servers)
119 await checkCounter('views', liveVideoId, 1)
120 await checkCounter('viewers', liveVideoId, 0)
122 await checkCounter('views', vodVideoId, 1)
123 await checkCounter('viewers', vodVideoId, 0)
126 it('Should view on a remote and on local and display 2 viewers and 3 views', async function () {
129 await servers[0].views.simulateViewer({ id: vodVideoId, currentTimes: [ 0, 5 ] })
130 await servers[1].views.simulateViewer({ id: vodVideoId, currentTimes: [ 0, 5 ] })
131 await servers[1].views.simulateViewer({ id: vodVideoId, currentTimes: [ 0, 5 ] })
133 await servers[0].views.simulateViewer({ id: liveVideoId, currentTimes: [ 0, 35 ] })
134 await servers[1].views.simulateViewer({ id: liveVideoId, currentTimes: [ 0, 35 ] })
135 await servers[1].views.simulateViewer({ id: liveVideoId, currentTimes: [ 0, 35 ] })
137 await waitJobs(servers)
139 await checkCounter('viewers', liveVideoId, 2)
140 await checkCounter('viewers', vodVideoId, 2)
142 await processViewsBuffer(servers)
144 await checkCounter('views', liveVideoId, 3)
145 await checkCounter('views', vodVideoId, 3)
148 after(async function () {
149 await stopFfmpeg(command)
153 after(async function () {
154 await cleanupTests(servers)