Fix jobs tests
[oweals/peertube.git] / server / tests / api / server / handle-down.ts
1 /* tslint:disable:no-unused-expression */
2
3 import * as chai from 'chai'
4 import 'mocha'
5 import { JobState, Video } from '../../../../shared/models'
6 import { VideoPrivacy } from '../../../../shared/models/videos'
7 import { VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model'
8 import { completeVideoCheck, getVideo, immutableAssign, reRunServer, unfollow, viewVideo } from '../../utils'
9 import {
10   flushAndRunMultipleServers,
11   getVideosList,
12   killallServers,
13   ServerInfo,
14   setAccessTokensToServers,
15   uploadVideo,
16   wait
17 } from '../../utils/index'
18 import { follow, getFollowersListPaginationAndSort } from '../../utils/server/follows'
19 import { getJobsListPaginationAndSort, waitJobs } from '../../utils/server/jobs'
20 import {
21   addVideoCommentReply,
22   addVideoCommentThread,
23   getVideoCommentThreads,
24   getVideoThreadComments
25 } from '../../utils/videos/video-comments'
26
27 const expect = chai.expect
28
29 describe('Test handle downs', function () {
30   let servers: ServerInfo[] = []
31   let threadIdServer1: number
32   let threadIdServer2: number
33   let commentIdServer1: number
34   let commentIdServer2: number
35   let missedVideo1: Video
36   let missedVideo2: Video
37   let unlistedVideo: Video
38
39   const videoAttributes = {
40     name: 'my super name for server 1',
41     category: 5,
42     licence: 4,
43     language: 'ja',
44     nsfw: true,
45     privacy: VideoPrivacy.PUBLIC,
46     description: 'my super description for server 1',
47     support: 'my super support text for server 1',
48     tags: [ 'tag1p1', 'tag2p1' ],
49     fixture: 'video_short1.webm'
50   }
51
52   const unlistedVideoAttributes = immutableAssign(videoAttributes, {
53     privacy: VideoPrivacy.UNLISTED
54   })
55
56   const checkAttributes = {
57     name: 'my super name for server 1',
58     category: 5,
59     licence: 4,
60     language: 'ja',
61     nsfw: true,
62     description: 'my super description for server 1',
63     support: 'my super support text for server 1',
64     account: {
65       name: 'root',
66       host: 'localhost:9001'
67     },
68     isLocal: false,
69     duration: 10,
70     tags: [ 'tag1p1', 'tag2p1' ],
71     privacy: VideoPrivacy.PUBLIC,
72     commentsEnabled: true,
73     channel: {
74       name: 'root_channel',
75       displayName: 'Main root channel',
76       description: '',
77       isLocal: false
78     },
79     fixture: 'video_short1.webm',
80     files: [
81       {
82         resolution: 720,
83         size: 572456
84       }
85     ]
86   }
87
88   const unlistedCheckAttributes = immutableAssign(checkAttributes, {
89     privacy: VideoPrivacy.UNLISTED
90   })
91
92   before(async function () {
93     this.timeout(30000)
94
95     servers = await flushAndRunMultipleServers(3)
96
97     // Get the access tokens
98     await setAccessTokensToServers(servers)
99   })
100
101   it('Should remove followers that are often down', async function () {
102     this.timeout(60000)
103
104     // Server 2 and 3 follow server 1
105     await follow(servers[1].url, [ servers[0].url ], servers[1].accessToken)
106     await follow(servers[2].url, [ servers[0].url ], servers[2].accessToken)
107
108     await waitJobs(servers)
109
110     // Upload a video to server 1
111     await uploadVideo(servers[0].url, servers[0].accessToken, videoAttributes)
112
113     await waitJobs(servers)
114
115     // And check all servers have this video
116     for (const server of servers) {
117       const res = await getVideosList(server.url)
118       expect(res.body.data).to.be.an('array')
119       expect(res.body.data).to.have.lengthOf(1)
120     }
121
122     // Kill server 2
123     killallServers([ servers[1] ])
124
125     // Remove server 2 follower
126     for (let i = 0; i < 10; i++) {
127       await uploadVideo(servers[ 0 ].url, servers[ 0 ].accessToken, videoAttributes)
128     }
129
130     await waitJobs(servers[0])
131
132     // Kill server 3
133     killallServers([ servers[2] ])
134
135     const resLastVideo1 = await uploadVideo(servers[ 0 ].url, servers[ 0 ].accessToken, videoAttributes)
136     missedVideo1 = resLastVideo1.body.video
137
138     const resLastVideo2 = await uploadVideo(servers[ 0 ].url, servers[ 0 ].accessToken, videoAttributes)
139     missedVideo2 = resLastVideo2.body.video
140
141     // Unlisted video
142     let resVideo = await uploadVideo(servers[ 0 ].url, servers[ 0 ].accessToken, unlistedVideoAttributes)
143     unlistedVideo = resVideo.body.video
144
145     // Add comments to video 2
146     {
147       const text = 'thread 1'
148       let resComment = await addVideoCommentThread(servers[0].url, servers[0].accessToken, missedVideo2.uuid, text)
149       let comment = resComment.body.comment
150       threadIdServer1 = comment.id
151
152       resComment = await addVideoCommentReply(servers[0].url, servers[0].accessToken, missedVideo2.uuid, comment.id, 'comment 1-1')
153       comment = resComment.body.comment
154
155       resComment = await addVideoCommentReply(servers[0].url, servers[0].accessToken, missedVideo2.uuid, comment.id, 'comment 1-2')
156       commentIdServer1 = resComment.body.comment.id
157     }
158
159     await waitJobs(servers[0])
160     // Wait scheduler
161     await wait(11000)
162
163     // Only server 3 is still a follower of server 1
164     const res = await getFollowersListPaginationAndSort(servers[0].url, 0, 2, 'createdAt')
165     expect(res.body.data).to.be.an('array')
166     expect(res.body.data).to.have.lengthOf(1)
167     expect(res.body.data[0].follower.host).to.equal('localhost:9003')
168   })
169
170   it('Should not have pending/processing jobs anymore', async function () {
171     const states: JobState[] = [ 'waiting', 'active' ]
172
173     for (const state of states) {
174       const res = await getJobsListPaginationAndSort(servers[ 0 ].url, servers[ 0 ].accessToken, state,0, 50, '-createdAt')
175       expect(res.body.data).to.have.length(0)
176     }
177   })
178
179   it('Should re-follow server 1', async function () {
180     this.timeout(35000)
181
182     await reRunServer(servers[1])
183     await reRunServer(servers[2])
184
185     await unfollow(servers[1].url, servers[1].accessToken, servers[0])
186     await waitJobs(servers)
187
188     await follow(servers[1].url, [ servers[0].url ], servers[1].accessToken)
189
190     await waitJobs(servers)
191
192     const res = await getFollowersListPaginationAndSort(servers[0].url, 0, 2, 'createdAt')
193     expect(res.body.data).to.be.an('array')
194     expect(res.body.data).to.have.lengthOf(2)
195   })
196
197   it('Should send a view to server 3, and automatically fetch the video', async function () {
198     this.timeout(15000)
199
200     const res1 = await getVideosList(servers[2].url)
201     expect(res1.body.data).to.be.an('array')
202     expect(res1.body.data).to.have.lengthOf(11)
203
204     await viewVideo(servers[0].url, missedVideo1.uuid)
205     await viewVideo(servers[0].url, unlistedVideo.uuid)
206
207     await waitJobs(servers)
208
209     const res = await getVideosList(servers[2].url)
210     expect(res.body.data).to.be.an('array')
211     // 1 video is unlisted
212     expect(res.body.data).to.have.lengthOf(12)
213
214     // Check unlisted video
215     const resVideo = await getVideo(servers[2].url, unlistedVideo.uuid)
216     expect(resVideo.body).not.to.be.undefined
217
218     await completeVideoCheck(servers[2].url, resVideo.body, unlistedCheckAttributes)
219   })
220
221   it('Should send comments on a video to server 3, and automatically fetch the video', async function () {
222     this.timeout(25000)
223
224     await addVideoCommentReply(servers[0].url, servers[0].accessToken, missedVideo2.uuid, commentIdServer1, 'comment 1-3')
225
226     await waitJobs(servers)
227
228     const resVideo = await getVideo(servers[2].url, missedVideo2.uuid)
229     expect(resVideo.body).not.to.be.undefined
230
231     {
232       let resComment = await getVideoCommentThreads(servers[2].url, missedVideo2.uuid, 0, 5)
233       expect(resComment.body.data).to.be.an('array')
234       expect(resComment.body.data).to.have.lengthOf(1)
235
236       threadIdServer2 = resComment.body.data[0].id
237
238       resComment = await getVideoThreadComments(servers[2].url, missedVideo2.uuid, threadIdServer2)
239
240       const tree: VideoCommentThreadTree = resComment.body
241       expect(tree.comment.text).equal('thread 1')
242       expect(tree.children).to.have.lengthOf(1)
243
244       const firstChild = tree.children[0]
245       expect(firstChild.comment.text).to.equal('comment 1-1')
246       expect(firstChild.children).to.have.lengthOf(1)
247
248       const childOfFirstChild = firstChild.children[0]
249       expect(childOfFirstChild.comment.text).to.equal('comment 1-2')
250       expect(childOfFirstChild.children).to.have.lengthOf(1)
251
252       const childOfChildFirstChild = childOfFirstChild.children[0]
253       expect(childOfChildFirstChild.comment.text).to.equal('comment 1-3')
254       expect(childOfChildFirstChild.children).to.have.lengthOf(0)
255
256       commentIdServer2 = childOfChildFirstChild.comment.id
257     }
258   })
259
260   it('Should correctly reply to the comment', async function () {
261     this.timeout(15000)
262
263     await addVideoCommentReply(servers[2].url, servers[2].accessToken, missedVideo2.uuid, commentIdServer2, 'comment 1-4')
264
265     await waitJobs(servers)
266
267     {
268       const resComment = await getVideoThreadComments(servers[0].url, missedVideo2.uuid, threadIdServer1)
269
270       const tree: VideoCommentThreadTree = resComment.body
271       expect(tree.comment.text).equal('thread 1')
272       expect(tree.children).to.have.lengthOf(1)
273
274       const firstChild = tree.children[0]
275       expect(firstChild.comment.text).to.equal('comment 1-1')
276       expect(firstChild.children).to.have.lengthOf(1)
277
278       const childOfFirstChild = firstChild.children[0]
279       expect(childOfFirstChild.comment.text).to.equal('comment 1-2')
280       expect(childOfFirstChild.children).to.have.lengthOf(1)
281
282       const childOfChildFirstChild = childOfFirstChild.children[0]
283       expect(childOfChildFirstChild.comment.text).to.equal('comment 1-3')
284       expect(childOfChildFirstChild.children).to.have.lengthOf(1)
285
286       const childOfChildOfChildOfFirstChild = childOfChildFirstChild.children[0]
287       expect(childOfChildOfChildOfFirstChild.comment.text).to.equal('comment 1-4')
288       expect(childOfChildOfChildOfFirstChild.children).to.have.lengthOf(0)
289     }
290   })
291
292   after(async function () {
293     killallServers(servers)
294   })
295 })