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