]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/tests/api/server/follows.ts
Add ability for instances to follow any actor
[github/Chocobozzz/PeerTube.git] / server / tests / api / server / follows.ts
CommitLineData
a1587156 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
0f91ae62 2
0f91ae62 3import 'mocha'
2b02c520 4import * as chai from 'chai'
0f91ae62 5import {
2b02c520
C
6 cleanupTests,
7 completeVideoCheck,
4c7e60bc 8 createMultipleServers,
2b02c520 9 dateIsValid,
2b02c520 10 expectAccountFollows,
4d029ef8 11 expectChannelsFollows,
254d3579 12 PeerTubeServer,
2b02c520
C
13 setAccessTokensToServers,
14 testCaptionFile,
2b02c520
C
15 waitJobs
16} from '@shared/extra-utils'
4d029ef8 17import { VideoCreateResult, VideoPrivacy } from '@shared/models'
0f91ae62
C
18
19const expect = chai.expect
20
21describe('Test follows', function () {
254d3579 22 let servers: PeerTubeServer[] = []
0f91ae62
C
23
24 before(async function () {
e212f887 25 this.timeout(30000)
0f91ae62 26
254d3579 27 servers = await createMultipleServers(3)
0f91ae62
C
28
29 // Get the access tokens
30 await setAccessTokensToServers(servers)
31 })
32
4d029ef8 33 describe('Data propagation after follow', function () {
0f91ae62 34
4d029ef8
C
35 it('Should not have followers/followings', async function () {
36 for (const server of servers) {
37 const bodies = await Promise.all([
38 server.follows.getFollowers({ start: 0, count: 5, sort: 'createdAt' }),
39 server.follows.getFollowings({ start: 0, count: 5, sort: 'createdAt' })
40 ])
0f91ae62 41
4d029ef8
C
42 for (const body of bodies) {
43 expect(body.total).to.equal(0)
0f91ae62 44
4d029ef8
C
45 const follows = body.data
46 expect(follows).to.be.an('array')
47 expect(follows).to.have.lengthOf(0)
48 }
49 }
50 })
0f91ae62 51
4d029ef8
C
52 it('Should have server 1 following root account of server 2 and server 3', async function () {
53 this.timeout(30000)
0f91ae62 54
4d029ef8
C
55 await servers[0].follows.follow({
56 hosts: [ servers[2].url ],
57 handles: [ 'root@' + servers[1].host ]
58 })
0f91ae62 59
4d029ef8
C
60 await waitJobs(servers)
61 })
0f91ae62 62
4d029ef8
C
63 it('Should have 2 followings on server 1', async function () {
64 const body = await servers[0].follows.getFollowings({ start: 0, count: 1, sort: 'createdAt' })
65 expect(body.total).to.equal(2)
0f91ae62 66
4d029ef8
C
67 let follows = body.data
68 expect(follows).to.be.an('array')
69 expect(follows).to.have.lengthOf(1)
0f91ae62 70
4d029ef8
C
71 const body2 = await servers[0].follows.getFollowings({ start: 1, count: 1, sort: 'createdAt' })
72 follows = follows.concat(body2.data)
0f91ae62 73
4d029ef8
C
74 const server2Follow = follows.find(f => f.following.host === servers[1].host)
75 const server3Follow = follows.find(f => f.following.host === servers[2].host)
0f91ae62 76
4d029ef8
C
77 expect(server2Follow).to.not.be.undefined
78 expect(server2Follow.following.name).to.equal('root')
79 expect(server2Follow.state).to.equal('accepted')
97ecddae 80
4d029ef8
C
81 expect(server3Follow).to.not.be.undefined
82 expect(server3Follow.following.name).to.equal('peertube')
83 expect(server3Follow.state).to.equal('accepted')
84 })
b8f4167f 85
4d029ef8
C
86 it('Should have 0 followings on server 2 and 3', async function () {
87 for (const server of [ servers[1], servers[2] ]) {
88 const body = await server.follows.getFollowings({ start: 0, count: 5, sort: 'createdAt' })
89 expect(body.total).to.equal(0)
97ecddae 90
c3d29f69 91 const follows = body.data
4d029ef8
C
92 expect(follows).to.be.an('array')
93 expect(follows).to.have.lengthOf(0)
97ecddae 94 }
4d029ef8 95 })
97ecddae 96
4d029ef8
C
97 it('Should have 1 followers on server 3', async function () {
98 const body = await servers[2].follows.getFollowers({ start: 0, count: 1, sort: 'createdAt' })
99 expect(body.total).to.equal(1)
100
101 const follows = body.data
102 expect(follows).to.be.an('array')
103 expect(follows).to.have.lengthOf(1)
104 expect(follows[0].follower.host).to.equal('localhost:' + servers[0].port)
105 })
106
107 it('Should have 0 followers on server 1 and 2', async function () {
108 for (const server of [ servers[0], servers[1] ]) {
109 const body = await server.follows.getFollowers({ start: 0, count: 5, sort: 'createdAt' })
110 expect(body.total).to.equal(0)
111
112 const follows = body.data
113 expect(follows).to.be.an('array')
114 expect(follows).to.have.lengthOf(0)
97ecddae 115 }
4d029ef8
C
116 })
117
118 it('Should search/filter followings on server 1', async function () {
119 const sort = 'createdAt'
120 const start = 0
121 const count = 1
97ecddae
C
122
123 {
4d029ef8
C
124 const search = ':' + servers[1].port
125
126 {
127 const body = await servers[0].follows.getFollowings({ start, count, sort, search })
128 expect(body.total).to.equal(1)
129
130 const follows = body.data
131 expect(follows).to.have.lengthOf(1)
132 expect(follows[0].following.host).to.equal(servers[1].host)
133 }
134
135 {
136 const body = await servers[0].follows.getFollowings({ start, count, sort, search, state: 'accepted' })
137 expect(body.total).to.equal(1)
138 expect(body.data).to.have.lengthOf(1)
139 }
140
141 {
142 const body = await servers[0].follows.getFollowings({ start, count, sort, search, state: 'accepted', actorType: 'Person' })
143 expect(body.total).to.equal(1)
144 expect(body.data).to.have.lengthOf(1)
145 }
146
147 {
148 const body = await servers[0].follows.getFollowings({
149 start,
150 count,
151 sort,
152 search,
153 state: 'accepted',
154 actorType: 'Application'
155 })
156 expect(body.total).to.equal(0)
157 expect(body.data).to.have.lengthOf(0)
158 }
159
160 {
161 const body = await servers[0].follows.getFollowings({ start, count, sort, search, state: 'pending' })
162 expect(body.total).to.equal(0)
163 expect(body.data).to.have.lengthOf(0)
164 }
97ecddae
C
165 }
166
167 {
4d029ef8 168 const body = await servers[0].follows.getFollowings({ start, count, sort, search: 'root' })
c3d29f69
C
169 expect(body.total).to.equal(1)
170 expect(body.data).to.have.lengthOf(1)
97ecddae
C
171 }
172
173 {
4d029ef8 174 const body = await servers[0].follows.getFollowings({ start, count, sort, search: 'bla' })
c3d29f69 175 expect(body.total).to.equal(0)
4d029ef8 176
c3d29f69 177 expect(body.data).to.have.lengthOf(0)
97ecddae 178 }
4d029ef8 179 })
b014b6b9 180
4d029ef8
C
181 it('Should search/filter followers on server 2', async function () {
182 const start = 0
183 const count = 5
184 const sort = 'createdAt'
b014b6b9 185
4d029ef8
C
186 {
187 const search = servers[0].port + ''
b014b6b9 188
4d029ef8
C
189 {
190 const body = await servers[2].follows.getFollowers({ start, count, sort, search })
191 expect(body.total).to.equal(1)
0f91ae62 192
4d029ef8
C
193 const follows = body.data
194 expect(follows).to.have.lengthOf(1)
195 expect(follows[0].following.host).to.equal(servers[2].host)
196 }
0f91ae62 197
4d029ef8
C
198 {
199 const body = await servers[2].follows.getFollowers({ start, count, sort, search, state: 'accepted' })
200 expect(body.total).to.equal(1)
201 expect(body.data).to.have.lengthOf(1)
202 }
0f91ae62 203
4d029ef8
C
204 {
205 const body = await servers[2].follows.getFollowers({ start, count, sort, search, state: 'accepted', actorType: 'Person' })
206 expect(body.total).to.equal(0)
207 expect(body.data).to.have.lengthOf(0)
208 }
0f91ae62 209
4d029ef8
C
210 {
211 const body = await servers[2].follows.getFollowers({
212 start,
213 count,
214 sort,
215 search,
216 state: 'accepted',
217 actorType: 'Application'
218 })
219 expect(body.total).to.equal(1)
220 expect(body.data).to.have.lengthOf(1)
221 }
97ecddae 222
4d029ef8
C
223 {
224 const body = await servers[2].follows.getFollowers({ start, count, sort, search, state: 'pending' })
225 expect(body.total).to.equal(0)
226 expect(body.data).to.have.lengthOf(0)
227 }
228 }
b8f4167f 229
97ecddae 230 {
4d029ef8
C
231 const body = await servers[2].follows.getFollowers({ start, count, sort, search: 'bla' })
232 expect(body.total).to.equal(0)
97ecddae 233
c3d29f69 234 const follows = body.data
4d029ef8 235 expect(follows).to.have.lengthOf(0)
97ecddae 236 }
4d029ef8 237 })
97ecddae 238
4d029ef8
C
239 it('Should have the correct follows counts', async function () {
240 await expectAccountFollows({ server: servers[0], handle: 'peertube@' + servers[0].host, followers: 0, following: 2 })
241 await expectAccountFollows({ server: servers[0], handle: 'root@' + servers[1].host, followers: 1, following: 0 })
242 await expectAccountFollows({ server: servers[0], handle: 'peertube@' + servers[2].host, followers: 1, following: 0 })
97ecddae 243
4d029ef8
C
244 // Server 2 and 3 does not know server 1 follow another server (there was not a refresh)
245 await expectAccountFollows({ server: servers[1], handle: 'peertube@' + servers[0].host, followers: 0, following: 1 })
246 await expectAccountFollows({ server: servers[1], handle: 'root@' + servers[1].host, followers: 1, following: 0 })
247 await expectAccountFollows({ server: servers[1], handle: 'peertube@' + servers[1].host, followers: 0, following: 0 })
97ecddae 248
4d029ef8
C
249 await expectAccountFollows({ server: servers[2], handle: 'peertube@' + servers[0].host, followers: 0, following: 1 })
250 await expectAccountFollows({ server: servers[2], handle: 'peertube@' + servers[2].host, followers: 1, following: 0 })
251 })
97ecddae 252
4d029ef8
C
253 it('Should unfollow server 3 on server 1', async function () {
254 this.timeout(15000)
b014b6b9 255
4d029ef8
C
256 await servers[0].follows.unfollow({ target: servers[2] })
257
258 await waitJobs(servers)
259 })
260
261 it('Should not follow server 3 on server 1 anymore', async function () {
262 const body = await servers[0].follows.getFollowings({ start: 0, count: 2, sort: 'createdAt' })
263 expect(body.total).to.equal(1)
b014b6b9 264
c3d29f69 265 const follows = body.data
4d029ef8
C
266 expect(follows).to.be.an('array')
267 expect(follows).to.have.lengthOf(1)
b014b6b9 268
4d029ef8
C
269 expect(follows[0].following.host).to.equal(servers[1].host)
270 })
0f91ae62 271
4d029ef8
C
272 it('Should not have server 1 as follower on server 3 anymore', async function () {
273 const body = await servers[2].follows.getFollowers({ start: 0, count: 1, sort: 'createdAt' })
274 expect(body.total).to.equal(0)
0f91ae62 275
4d029ef8
C
276 const follows = body.data
277 expect(follows).to.be.an('array')
278 expect(follows).to.have.lengthOf(0)
279 })
32b2b43c 280
4d029ef8
C
281 it('Should have the correct follows counts after the unfollow', async function () {
282 await expectAccountFollows({ server: servers[0], handle: 'peertube@' + servers[0].host, followers: 0, following: 1 })
283 await expectAccountFollows({ server: servers[0], handle: 'root@' + servers[1].host, followers: 1, following: 0 })
284 await expectAccountFollows({ server: servers[0], handle: 'peertube@' + servers[2].host, followers: 0, following: 0 })
32b2b43c 285
4d029ef8
C
286 await expectAccountFollows({ server: servers[1], handle: 'peertube@' + servers[0].host, followers: 0, following: 1 })
287 await expectAccountFollows({ server: servers[1], handle: 'root@' + servers[1].host, followers: 1, following: 0 })
288 await expectAccountFollows({ server: servers[1], handle: 'peertube@' + servers[1].host, followers: 0, following: 0 })
32b2b43c 289
4d029ef8
C
290 await expectAccountFollows({ server: servers[2], handle: 'peertube@' + servers[0].host, followers: 0, following: 0 })
291 await expectAccountFollows({ server: servers[2], handle: 'peertube@' + servers[2].host, followers: 0, following: 0 })
292 })
0f91ae62 293
4d029ef8
C
294 it('Should upload a video on server 2 and 3 and propagate only the video of server 2', async function () {
295 this.timeout(60000)
0f91ae62 296
4d029ef8
C
297 await servers[1].videos.upload({ attributes: { name: 'server2' } })
298 await servers[2].videos.upload({ attributes: { name: 'server3' } })
0f91ae62 299
4d029ef8 300 await waitJobs(servers)
0f91ae62 301
4d029ef8
C
302 {
303 const { total, data } = await servers[0].videos.list()
304 expect(total).to.equal(1)
305 expect(data[0].name).to.equal('server2')
306 }
0f91ae62 307
4d029ef8
C
308 {
309 const { total, data } = await servers[1].videos.list()
310 expect(total).to.equal(1)
311 expect(data[0].name).to.equal('server2')
312 }
0f91ae62 313
4d029ef8
C
314 {
315 const { total, data } = await servers[2].videos.list()
316 expect(total).to.equal(1)
317 expect(data[0].name).to.equal('server3')
318 }
319 })
0f91ae62 320
4d029ef8
C
321 it('Should remove account follow', async function () {
322 this.timeout(15000)
0f91ae62 323
4d029ef8 324 await servers[0].follows.unfollow({ target: 'root@' + servers[1].host })
32b2b43c 325
4d029ef8
C
326 await waitJobs(servers)
327 })
32b2b43c 328
4d029ef8
C
329 it('Should have removed the account follow', async function () {
330 await expectAccountFollows({ server: servers[0], handle: 'root@' + servers[1].host, followers: 0, following: 0 })
331 await expectAccountFollows({ server: servers[1], handle: 'root@' + servers[1].host, followers: 0, following: 0 })
32b2b43c 332
4d029ef8
C
333 {
334 const { total, data } = await servers[0].follows.getFollowings()
335 expect(total).to.equal(0)
336 expect(data).to.have.lengthOf(0)
337 }
0f91ae62 338
4d029ef8
C
339 {
340 const { total, data } = await servers[0].videos.list()
341 expect(total).to.equal(0)
342 expect(data).to.have.lengthOf(0)
343 }
344 })
0f91ae62 345
4d029ef8
C
346 it('Should follow a channel', async function () {
347 this.timeout(15000)
0f91ae62 348
4d029ef8
C
349 await servers[0].follows.follow({
350 handles: [ 'root_channel@' + servers[1].host ]
351 })
0f91ae62 352
4d029ef8 353 await waitJobs(servers)
0f91ae62 354
4d029ef8
C
355 await expectChannelsFollows({ server: servers[0], handle: 'root_channel@' + servers[1].host, followers: 1, following: 0 })
356 await expectChannelsFollows({ server: servers[1], handle: 'root_channel@' + servers[1].host, followers: 1, following: 0 })
357
358 {
359 const { total, data } = await servers[0].follows.getFollowings()
360 expect(total).to.equal(1)
361 expect(data).to.have.lengthOf(1)
362 }
363
364 {
365 const { total, data } = await servers[0].videos.list()
366 expect(total).to.equal(1)
367 expect(data).to.have.lengthOf(1)
368 }
369 })
0f91ae62
C
370 })
371
4d029ef8
C
372 describe('Should propagate data on a new server follow', function () {
373 let video4: VideoCreateResult
d8553faa 374
b1f5b93e 375 before(async function () {
8b381422 376 this.timeout(50000)
c46edbc2 377
b1f5b93e
C
378 const video4Attributes = {
379 name: 'server3-4',
380 category: 2,
381 nsfw: true,
382 licence: 6,
383 tags: [ 'tag1', 'tag2', 'tag3' ]
384 }
d8553faa 385
89d241a7
C
386 await servers[2].videos.upload({ attributes: { name: 'server3-2' } })
387 await servers[2].videos.upload({ attributes: { name: 'server3-3' } })
4d029ef8 388 video4 = await servers[2].videos.upload({ attributes: video4Attributes })
89d241a7
C
389 await servers[2].videos.upload({ attributes: { name: 'server3-5' } })
390 await servers[2].videos.upload({ attributes: { name: 'server3-6' } })
d8553faa 391
db799da3 392 {
89d241a7 393 const userAccessToken = await servers[2].users.generateUserAndToken('captain')
db799da3 394
4d029ef8
C
395 await servers[2].videos.rate({ id: video4.id, rating: 'like' })
396 await servers[2].videos.rate({ token: userAccessToken, id: video4.id, rating: 'dislike' })
397 }
c883db6d 398
4d029ef8
C
399 {
400 await servers[2].comments.createThread({ videoId: video4.id, text: 'my super first comment' })
c883db6d 401
4d029ef8
C
402 await servers[2].comments.addReplyToLastThread({ text: 'my super answer to thread 1' })
403 await servers[2].comments.addReplyToLastReply({ text: 'my super answer to answer of thread 1' })
404 await servers[2].comments.addReplyToLastThread({ text: 'my second answer to thread 1' })
405 }
db799da3 406
4d029ef8
C
407 {
408 const { id: threadId } = await servers[2].comments.createThread({ videoId: video4.id, text: 'will be deleted' })
409 await servers[2].comments.addReplyToLastThread({ text: 'answer to deleted' })
d8553faa 410
4d029ef8 411 const { id: replyId } = await servers[2].comments.addReplyToLastThread({ text: 'will also be deleted' })
c46edbc2 412
4d029ef8 413 await servers[2].comments.addReplyToLastReply({ text: 'my second answer to deleted' })
40e87e9e 414
4d029ef8
C
415 await servers[2].comments.delete({ videoId: video4.id, commentId: threadId })
416 await servers[2].comments.delete({ videoId: video4.id, commentId: replyId })
b1f5b93e 417 }
c46edbc2 418
4d029ef8
C
419 await servers[2].captions.createVideoCaption({
420 language: 'ar',
421 videoId: video4.id,
422 fixture: 'subtitle-good2.vtt'
423 })
424
3cd0734f 425 await waitJobs(servers)
b1f5b93e
C
426
427 // Server 1 follows server 3
4d029ef8 428 await servers[0].follows.follow({ hosts: [ servers[2].url ] })
b1f5b93e 429
3cd0734f 430 await waitJobs(servers)
b1f5b93e
C
431 })
432
4d029ef8
C
433 it('Should have the correct follows counts', async function () {
434 await expectAccountFollows({ server: servers[0], handle: 'peertube@' + servers[0].host, followers: 0, following: 2 })
435 await expectAccountFollows({ server: servers[0], handle: 'root@' + servers[1].host, followers: 0, following: 0 })
436 await expectChannelsFollows({ server: servers[0], handle: 'root_channel@' + servers[1].host, followers: 1, following: 0 })
437 await expectAccountFollows({ server: servers[0], handle: 'peertube@' + servers[2].host, followers: 1, following: 0 })
32b2b43c 438
4d029ef8
C
439 await expectAccountFollows({ server: servers[1], handle: 'peertube@' + servers[0].host, followers: 0, following: 1 })
440 await expectAccountFollows({ server: servers[1], handle: 'peertube@' + servers[1].host, followers: 0, following: 0 })
441 await expectAccountFollows({ server: servers[1], handle: 'root@' + servers[1].host, followers: 0, following: 0 })
442 await expectChannelsFollows({ server: servers[1], handle: 'root_channel@' + servers[1].host, followers: 1, following: 0 })
32b2b43c 443
4d029ef8
C
444 await expectAccountFollows({ server: servers[2], handle: 'peertube@' + servers[0].host, followers: 0, following: 1 })
445 await expectAccountFollows({ server: servers[2], handle: 'peertube@' + servers[2].host, followers: 1, following: 0 })
32b2b43c
C
446 })
447
40e87e9e 448 it('Should have propagated videos', async function () {
89d241a7 449 const { total, data } = await servers[0].videos.list()
d23dd9fb 450 expect(total).to.equal(7)
b1f5b93e 451
d23dd9fb
C
452 const video2 = data.find(v => v.name === 'server3-2')
453 video4 = data.find(v => v.name === 'server3-4')
454 const video6 = data.find(v => v.name === 'server3-6')
b1f5b93e
C
455
456 expect(video2).to.not.be.undefined
457 expect(video4).to.not.be.undefined
458 expect(video6).to.not.be.undefined
459
460 const isLocal = false
461 const checkAttributes = {
462 name: 'server3-4',
463 category: 2,
464 licence: 6,
9d3ef9fe 465 language: 'zh',
b1f5b93e
C
466 nsfw: true,
467 description: 'my super description',
2422c46b 468 support: 'my super support text',
b64c950a
C
469 account: {
470 name: 'root',
4d029ef8 471 host: servers[2].host
b64c950a 472 },
b1f5b93e 473 isLocal,
47564bbe 474 commentsEnabled: true,
7f2cfe3a 475 downloadEnabled: true,
b1f5b93e
C
476 duration: 5,
477 tags: [ 'tag1', 'tag2', 'tag3' ],
478 privacy: VideoPrivacy.PUBLIC,
479 likes: 1,
480 dislikes: 1,
481 channel: {
f6eebcb3
C
482 displayName: 'Main root channel',
483 name: 'root_channel',
b1f5b93e
C
484 description: '',
485 isLocal
486 },
487 fixture: 'video_short.webm',
488 files: [
489 {
490 resolution: 720,
491 size: 218910
492 }
493 ]
494 }
d23dd9fb 495 await completeVideoCheck(servers[0], video4, checkAttributes)
b1f5b93e 496 })
c46edbc2 497
40e87e9e 498 it('Should have propagated comments', async function () {
89d241a7 499 const { total, data } = await servers[0].comments.listThreads({ videoId: video4.id, sort: 'createdAt' })
db799da3 500
12edc149
C
501 expect(total).to.equal(2)
502 expect(data).to.be.an('array')
503 expect(data).to.have.lengthOf(2)
c883db6d
C
504
505 {
12edc149 506 const comment = data[0]
c883db6d
C
507 expect(comment.inReplyToCommentId).to.be.null
508 expect(comment.text).equal('my super first comment')
509 expect(comment.videoId).to.equal(video4.id)
510 expect(comment.id).to.equal(comment.threadId)
511 expect(comment.account.name).to.equal('root')
4d029ef8 512 expect(comment.account.host).to.equal(servers[2].host)
c883db6d
C
513 expect(comment.totalReplies).to.equal(3)
514 expect(dateIsValid(comment.createdAt as string)).to.be.true
515 expect(dateIsValid(comment.updatedAt as string)).to.be.true
516
517 const threadId = comment.threadId
518
89d241a7 519 const tree = await servers[0].comments.getThread({ videoId: video4.id, threadId })
c883db6d
C
520 expect(tree.comment.text).equal('my super first comment')
521 expect(tree.children).to.have.lengthOf(2)
522
a1587156 523 const firstChild = tree.children[0]
c883db6d
C
524 expect(firstChild.comment.text).to.equal('my super answer to thread 1')
525 expect(firstChild.children).to.have.lengthOf(1)
526
a1587156 527 const childOfFirstChild = firstChild.children[0]
c883db6d
C
528 expect(childOfFirstChild.comment.text).to.equal('my super answer to answer of thread 1')
529 expect(childOfFirstChild.children).to.have.lengthOf(0)
530
a1587156 531 const secondChild = tree.children[1]
c883db6d
C
532 expect(secondChild.comment.text).to.equal('my second answer to thread 1')
533 expect(secondChild.children).to.have.lengthOf(0)
534 }
535
536 {
12edc149 537 const deletedComment = data[1]
c883db6d
C
538 expect(deletedComment).to.not.be.undefined
539 expect(deletedComment.isDeleted).to.be.true
540 expect(deletedComment.deletedAt).to.not.be.null
541 expect(deletedComment.text).to.equal('')
542 expect(deletedComment.inReplyToCommentId).to.be.null
543 expect(deletedComment.account).to.be.null
9de33c6b 544 expect(deletedComment.totalReplies).to.equal(2)
c883db6d
C
545 expect(dateIsValid(deletedComment.deletedAt as string)).to.be.true
546
89d241a7 547 const tree = await servers[0].comments.getThread({ videoId: video4.id, threadId: deletedComment.threadId })
c883db6d
C
548 const [ commentRoot, deletedChildRoot ] = tree.children
549
550 expect(deletedChildRoot).to.not.be.undefined
551 expect(deletedChildRoot.comment.isDeleted).to.be.true
552 expect(deletedChildRoot.comment.deletedAt).to.not.be.null
553 expect(deletedChildRoot.comment.text).to.equal('')
554 expect(deletedChildRoot.comment.inReplyToCommentId).to.equal(deletedComment.id)
555 expect(deletedChildRoot.comment.account).to.be.null
556 expect(deletedChildRoot.children).to.have.lengthOf(1)
557
558 const answerToDeletedChild = deletedChildRoot.children[0]
559 expect(answerToDeletedChild.comment).to.not.be.undefined
560 expect(answerToDeletedChild.comment.inReplyToCommentId).to.equal(deletedChildRoot.comment.id)
561 expect(answerToDeletedChild.comment.text).to.equal('my second answer to deleted')
562 expect(answerToDeletedChild.comment.account.name).to.equal('root')
563
564 expect(commentRoot.comment).to.not.be.undefined
565 expect(commentRoot.comment.inReplyToCommentId).to.equal(deletedComment.id)
566 expect(commentRoot.comment.text).to.equal('answer to deleted')
567 expect(commentRoot.comment.account.name).to.equal('root')
568 }
b1f5b93e 569 })
f05a1c30 570
40e87e9e 571 it('Should have propagated captions', async function () {
89d241a7 572 const body = await servers[0].captions.listVideoCaptions({ videoId: video4.id })
a2470c9f
C
573 expect(body.total).to.equal(1)
574 expect(body.data).to.have.lengthOf(1)
40e87e9e 575
a2470c9f 576 const caption1 = body.data[0]
40e87e9e
C
577 expect(caption1.language.id).to.equal('ar')
578 expect(caption1.language.label).to.equal('Arabic')
a35a2279 579 expect(caption1.captionPath).to.match(new RegExp('^/lazy-static/video-captions/.+-ar.vtt$'))
40e87e9e
C
580 await testCaptionFile(servers[0].url, caption1.captionPath, 'Subtitle good 2.')
581 })
582
f05a1c30
C
583 it('Should unfollow server 3 on server 1 and does not list server 3 videos', async function () {
584 this.timeout(5000)
585
4d029ef8 586 await servers[0].follows.unfollow({ target: servers[2] })
f05a1c30 587
3cd0734f 588 await waitJobs(servers)
f05a1c30 589
89d241a7 590 const { total } = await servers[0].videos.list()
d23dd9fb 591 expect(total).to.equal(1)
f05a1c30 592 })
4d029ef8
C
593 })
594
595 describe('Should propagate data on a new channel follow', function () {
596
597 before(async function () {
598 this.timeout(60000)
f05a1c30 599
4d029ef8
C
600 await servers[2].videos.upload({ attributes: { name: 'server3-7' } })
601
602 await waitJobs(servers)
603
604 const video = await servers[0].videos.find({ name: 'server3-7' })
605 expect(video).to.not.exist
606 })
607
608 it('Should have propagated channel video', async function () {
609 this.timeout(60000)
610
611 await servers[0].follows.follow({ handles: [ 'root_channel@' + servers[2].host ] })
612
613 await waitJobs(servers)
614
615 const video = await servers[0].videos.find({ name: 'server3-7' })
616
617 expect(video).to.exist
618 })
c46edbc2
C
619 })
620
7c3b7976
C
621 after(async function () {
622 await cleanupTests(servers)
0f91ae62
C
623 })
624})