aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/tests/api/views/video-views-counter.ts
blob: ca33ff9cd395965b4766de7c0d251edf678c87cf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */

import { expect } from 'chai'
import { FfmpegCommand } from 'fluent-ffmpeg'
import { prepareViewsServers, prepareViewsVideos, processViewsBuffer } from '@server/tests/shared'
import { wait } from '@shared/core-utils'
import { cleanupTests, PeerTubeServer, stopFfmpeg, waitJobs } from '@shared/server-commands'

describe('Test video views/viewers counters', function () {
  let servers: PeerTubeServer[]

  async function checkCounter (field: 'views' | 'viewers', id: string, expected: number) {
    for (const server of servers) {
      const video = await server.videos.get({ id })

      const messageSuffix = video.isLive
        ? 'live video'
        : 'vod video'

      expect(video[field]).to.equal(expected, `${field} not valid on server ${server.serverNumber} for ${messageSuffix} ${video.uuid}`)
    }
  }

  before(async function () {
    this.timeout(120000)

    servers = await prepareViewsServers()
  })

  describe('Test views counter on VOD', function () {
    let videoUUID: string

    before(async function () {
      this.timeout(120000)

      const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
      videoUUID = uuid

      await waitJobs(servers)
    })

    it('Should not view a video if watch time is below the threshold', async function () {
      await servers[0].views.simulateViewer({ id: videoUUID, currentTimes: [ 1, 2 ] })
      await processViewsBuffer(servers)

      await checkCounter('views', videoUUID, 0)
    })

    it('Should view a video if watch time is above the threshold', async function () {
      await servers[0].views.simulateViewer({ id: videoUUID, currentTimes: [ 1, 4 ] })
      await processViewsBuffer(servers)

      await checkCounter('views', videoUUID, 1)
    })

    it('Should not view again this video with the same IP', async function () {
      await servers[0].views.simulateViewer({ id: videoUUID, xForwardedFor: '0.0.0.1,127.0.0.1', currentTimes: [ 1, 4 ] })
      await servers[0].views.simulateViewer({ id: videoUUID, xForwardedFor: '0.0.0.1,127.0.0.1', currentTimes: [ 1, 4 ] })
      await processViewsBuffer(servers)

      await checkCounter('views', videoUUID, 2)
    })

    it('Should view the video from server 2 and send the event', async function () {
      await servers[1].views.simulateViewer({ id: videoUUID, currentTimes: [ 1, 4 ] })
      await waitJobs(servers)
      await processViewsBuffer(servers)

      await checkCounter('views', videoUUID, 3)
    })
  })

  describe('Test views and viewers counters on live and VOD', function () {
    let liveVideoId: string
    let vodVideoId: string
    let command: FfmpegCommand

    before(async function () {
      this.timeout(120000);

      ({ vodVideoId, liveVideoId, ffmpegCommand: command } = await prepareViewsVideos({ servers, live: true, vod: true }))
    })

    it('Should display no views and viewers', async function () {
      await checkCounter('views', liveVideoId, 0)
      await checkCounter('viewers', liveVideoId, 0)

      await checkCounter('views', vodVideoId, 0)
      await checkCounter('viewers', vodVideoId, 0)
    })

    it('Should view twice and display 1 view/viewer', async function () {
      this.timeout(30000)

      await servers[0].views.simulateViewer({ id: liveVideoId, currentTimes: [ 0, 35 ] })
      await servers[0].views.simulateViewer({ id: liveVideoId, currentTimes: [ 0, 35 ] })
      await servers[0].views.simulateViewer({ id: vodVideoId, currentTimes: [ 0, 5 ] })
      await servers[0].views.simulateViewer({ id: vodVideoId, currentTimes: [ 0, 5 ] })

      await waitJobs(servers)
      await checkCounter('viewers', liveVideoId, 1)
      await checkCounter('viewers', vodVideoId, 1)

      await processViewsBuffer(servers)

      await checkCounter('views', liveVideoId, 1)
      await checkCounter('views', vodVideoId, 1)
    })

    it('Should wait and display 0 viewers but still have 1 view', async function () {
      this.timeout(30000)

      await wait(12000)
      await waitJobs(servers)

      await checkCounter('views', liveVideoId, 1)
      await checkCounter('viewers', liveVideoId, 0)

      await checkCounter('views', vodVideoId, 1)
      await checkCounter('viewers', vodVideoId, 0)
    })

    it('Should view on a remote and on local and display 2 viewers and 3 views', async function () {
      this.timeout(30000)

      await servers[0].views.simulateViewer({ id: vodVideoId, currentTimes: [ 0, 5 ] })
      await servers[1].views.simulateViewer({ id: vodVideoId, currentTimes: [ 0, 5 ] })
      await servers[1].views.simulateViewer({ id: vodVideoId, currentTimes: [ 0, 5 ] })

      await servers[0].views.simulateViewer({ id: liveVideoId, currentTimes: [ 0, 35 ] })
      await servers[1].views.simulateViewer({ id: liveVideoId, currentTimes: [ 0, 35 ] })
      await servers[1].views.simulateViewer({ id: liveVideoId, currentTimes: [ 0, 35 ] })

      await waitJobs(servers)

      await checkCounter('viewers', liveVideoId, 2)
      await checkCounter('viewers', vodVideoId, 2)

      await processViewsBuffer(servers)

      await checkCounter('views', liveVideoId, 3)
      await checkCounter('views', vodVideoId, 3)
    })

    after(async function () {
      await stopFfmpeg(command)
    })
  })

  after(async function () {
    await cleanupTests(servers)
  })
})