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