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