diff options
Diffstat (limited to 'server/tests')
36 files changed, 2542 insertions, 51 deletions
diff --git a/server/tests/api/check-params/blocklist.ts b/server/tests/api/check-params/blocklist.ts new file mode 100644 index 000000000..c745ac975 --- /dev/null +++ b/server/tests/api/check-params/blocklist.ts | |||
@@ -0,0 +1,494 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import 'mocha' | ||
4 | |||
5 | import { | ||
6 | createUser, | ||
7 | doubleFollow, | ||
8 | flushAndRunMultipleServers, | ||
9 | flushTests, | ||
10 | killallServers, | ||
11 | makeDeleteRequest, | ||
12 | makeGetRequest, | ||
13 | makePostBodyRequest, | ||
14 | ServerInfo, | ||
15 | setAccessTokensToServers, userLogin | ||
16 | } from '../../utils' | ||
17 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params' | ||
18 | |||
19 | describe('Test blocklist API validators', function () { | ||
20 | let servers: ServerInfo[] | ||
21 | let server: ServerInfo | ||
22 | let userAccessToken: string | ||
23 | |||
24 | before(async function () { | ||
25 | this.timeout(60000) | ||
26 | |||
27 | await flushTests() | ||
28 | |||
29 | servers = await flushAndRunMultipleServers(2) | ||
30 | await setAccessTokensToServers(servers) | ||
31 | |||
32 | server = servers[0] | ||
33 | |||
34 | const user = { username: 'user1', password: 'password' } | ||
35 | await createUser(server.url, server.accessToken, user.username, user.password) | ||
36 | |||
37 | userAccessToken = await userLogin(server, user) | ||
38 | |||
39 | await doubleFollow(servers[0], servers[1]) | ||
40 | }) | ||
41 | |||
42 | // --------------------------------------------------------------- | ||
43 | |||
44 | describe('When managing user blocklist', function () { | ||
45 | |||
46 | describe('When managing user accounts blocklist', function () { | ||
47 | const path = '/api/v1/users/me/blocklist/accounts' | ||
48 | |||
49 | describe('When listing blocked accounts', function () { | ||
50 | it('Should fail with an unauthenticated user', async function () { | ||
51 | await makeGetRequest({ | ||
52 | url: server.url, | ||
53 | path, | ||
54 | statusCodeExpected: 401 | ||
55 | }) | ||
56 | }) | ||
57 | |||
58 | it('Should fail with a bad start pagination', async function () { | ||
59 | await checkBadStartPagination(server.url, path, server.accessToken) | ||
60 | }) | ||
61 | |||
62 | it('Should fail with a bad count pagination', async function () { | ||
63 | await checkBadCountPagination(server.url, path, server.accessToken) | ||
64 | }) | ||
65 | |||
66 | it('Should fail with an incorrect sort', async function () { | ||
67 | await checkBadSortPagination(server.url, path, server.accessToken) | ||
68 | }) | ||
69 | }) | ||
70 | |||
71 | describe('When blocking an account', function () { | ||
72 | it('Should fail with an unauthenticated user', async function () { | ||
73 | await makePostBodyRequest({ | ||
74 | url: server.url, | ||
75 | path, | ||
76 | fields: { accountName: 'user1' }, | ||
77 | statusCodeExpected: 401 | ||
78 | }) | ||
79 | }) | ||
80 | |||
81 | it('Should fail with an unknown account', async function () { | ||
82 | await makePostBodyRequest({ | ||
83 | url: server.url, | ||
84 | token: server.accessToken, | ||
85 | path, | ||
86 | fields: { accountName: 'user2' }, | ||
87 | statusCodeExpected: 404 | ||
88 | }) | ||
89 | }) | ||
90 | |||
91 | it('Should fail to block ourselves', async function () { | ||
92 | await makePostBodyRequest({ | ||
93 | url: server.url, | ||
94 | token: server.accessToken, | ||
95 | path, | ||
96 | fields: { accountName: 'root' }, | ||
97 | statusCodeExpected: 409 | ||
98 | }) | ||
99 | }) | ||
100 | |||
101 | it('Should succeed with the correct params', async function () { | ||
102 | await makePostBodyRequest({ | ||
103 | url: server.url, | ||
104 | token: server.accessToken, | ||
105 | path, | ||
106 | fields: { accountName: 'user1' }, | ||
107 | statusCodeExpected: 204 | ||
108 | }) | ||
109 | }) | ||
110 | }) | ||
111 | |||
112 | describe('When unblocking an account', function () { | ||
113 | it('Should fail with an unauthenticated user', async function () { | ||
114 | await makeDeleteRequest({ | ||
115 | url: server.url, | ||
116 | path: path + '/user1', | ||
117 | statusCodeExpected: 401 | ||
118 | }) | ||
119 | }) | ||
120 | |||
121 | it('Should fail with an unknown account block', async function () { | ||
122 | await makeDeleteRequest({ | ||
123 | url: server.url, | ||
124 | path: path + '/user2', | ||
125 | token: server.accessToken, | ||
126 | statusCodeExpected: 404 | ||
127 | }) | ||
128 | }) | ||
129 | |||
130 | it('Should succeed with the correct params', async function () { | ||
131 | await makeDeleteRequest({ | ||
132 | url: server.url, | ||
133 | path: path + '/user1', | ||
134 | token: server.accessToken, | ||
135 | statusCodeExpected: 204 | ||
136 | }) | ||
137 | }) | ||
138 | }) | ||
139 | }) | ||
140 | |||
141 | describe('When managing user servers blocklist', function () { | ||
142 | const path = '/api/v1/users/me/blocklist/servers' | ||
143 | |||
144 | describe('When listing blocked servers', function () { | ||
145 | it('Should fail with an unauthenticated user', async function () { | ||
146 | await makeGetRequest({ | ||
147 | url: server.url, | ||
148 | path, | ||
149 | statusCodeExpected: 401 | ||
150 | }) | ||
151 | }) | ||
152 | |||
153 | it('Should fail with a bad start pagination', async function () { | ||
154 | await checkBadStartPagination(server.url, path, server.accessToken) | ||
155 | }) | ||
156 | |||
157 | it('Should fail with a bad count pagination', async function () { | ||
158 | await checkBadCountPagination(server.url, path, server.accessToken) | ||
159 | }) | ||
160 | |||
161 | it('Should fail with an incorrect sort', async function () { | ||
162 | await checkBadSortPagination(server.url, path, server.accessToken) | ||
163 | }) | ||
164 | }) | ||
165 | |||
166 | describe('When blocking a server', function () { | ||
167 | it('Should fail with an unauthenticated user', async function () { | ||
168 | await makePostBodyRequest({ | ||
169 | url: server.url, | ||
170 | path, | ||
171 | fields: { host: 'localhost:9002' }, | ||
172 | statusCodeExpected: 401 | ||
173 | }) | ||
174 | }) | ||
175 | |||
176 | it('Should fail with an unknown server', async function () { | ||
177 | await makePostBodyRequest({ | ||
178 | url: server.url, | ||
179 | token: server.accessToken, | ||
180 | path, | ||
181 | fields: { host: 'localhost:9003' }, | ||
182 | statusCodeExpected: 404 | ||
183 | }) | ||
184 | }) | ||
185 | |||
186 | it('Should fail with our own server', async function () { | ||
187 | await makePostBodyRequest({ | ||
188 | url: server.url, | ||
189 | token: server.accessToken, | ||
190 | path, | ||
191 | fields: { host: 'localhost:9001' }, | ||
192 | statusCodeExpected: 409 | ||
193 | }) | ||
194 | }) | ||
195 | |||
196 | it('Should succeed with the correct params', async function () { | ||
197 | await makePostBodyRequest({ | ||
198 | url: server.url, | ||
199 | token: server.accessToken, | ||
200 | path, | ||
201 | fields: { host: 'localhost:9002' }, | ||
202 | statusCodeExpected: 204 | ||
203 | }) | ||
204 | }) | ||
205 | }) | ||
206 | |||
207 | describe('When unblocking a server', function () { | ||
208 | it('Should fail with an unauthenticated user', async function () { | ||
209 | await makeDeleteRequest({ | ||
210 | url: server.url, | ||
211 | path: path + '/localhost:9002', | ||
212 | statusCodeExpected: 401 | ||
213 | }) | ||
214 | }) | ||
215 | |||
216 | it('Should fail with an unknown server block', async function () { | ||
217 | await makeDeleteRequest({ | ||
218 | url: server.url, | ||
219 | path: path + '/localhost:9003', | ||
220 | token: server.accessToken, | ||
221 | statusCodeExpected: 404 | ||
222 | }) | ||
223 | }) | ||
224 | |||
225 | it('Should succeed with the correct params', async function () { | ||
226 | await makeDeleteRequest({ | ||
227 | url: server.url, | ||
228 | path: path + '/localhost:9002', | ||
229 | token: server.accessToken, | ||
230 | statusCodeExpected: 204 | ||
231 | }) | ||
232 | }) | ||
233 | }) | ||
234 | }) | ||
235 | }) | ||
236 | |||
237 | describe('When managing server blocklist', function () { | ||
238 | |||
239 | describe('When managing server accounts blocklist', function () { | ||
240 | const path = '/api/v1/server/blocklist/accounts' | ||
241 | |||
242 | describe('When listing blocked accounts', function () { | ||
243 | it('Should fail with an unauthenticated user', async function () { | ||
244 | await makeGetRequest({ | ||
245 | url: server.url, | ||
246 | path, | ||
247 | statusCodeExpected: 401 | ||
248 | }) | ||
249 | }) | ||
250 | |||
251 | it('Should fail with a user without the appropriate rights', async function () { | ||
252 | await makeGetRequest({ | ||
253 | url: server.url, | ||
254 | token: userAccessToken, | ||
255 | path, | ||
256 | statusCodeExpected: 403 | ||
257 | }) | ||
258 | }) | ||
259 | |||
260 | it('Should fail with a bad start pagination', async function () { | ||
261 | await checkBadStartPagination(server.url, path, server.accessToken) | ||
262 | }) | ||
263 | |||
264 | it('Should fail with a bad count pagination', async function () { | ||
265 | await checkBadCountPagination(server.url, path, server.accessToken) | ||
266 | }) | ||
267 | |||
268 | it('Should fail with an incorrect sort', async function () { | ||
269 | await checkBadSortPagination(server.url, path, server.accessToken) | ||
270 | }) | ||
271 | }) | ||
272 | |||
273 | describe('When blocking an account', function () { | ||
274 | it('Should fail with an unauthenticated user', async function () { | ||
275 | await makePostBodyRequest({ | ||
276 | url: server.url, | ||
277 | path, | ||
278 | fields: { accountName: 'user1' }, | ||
279 | statusCodeExpected: 401 | ||
280 | }) | ||
281 | }) | ||
282 | |||
283 | it('Should fail with a user without the appropriate rights', async function () { | ||
284 | await makePostBodyRequest({ | ||
285 | url: server.url, | ||
286 | token: userAccessToken, | ||
287 | path, | ||
288 | fields: { accountName: 'user1' }, | ||
289 | statusCodeExpected: 403 | ||
290 | }) | ||
291 | }) | ||
292 | |||
293 | it('Should fail with an unknown account', async function () { | ||
294 | await makePostBodyRequest({ | ||
295 | url: server.url, | ||
296 | token: server.accessToken, | ||
297 | path, | ||
298 | fields: { accountName: 'user2' }, | ||
299 | statusCodeExpected: 404 | ||
300 | }) | ||
301 | }) | ||
302 | |||
303 | it('Should fail to block ourselves', async function () { | ||
304 | await makePostBodyRequest({ | ||
305 | url: server.url, | ||
306 | token: server.accessToken, | ||
307 | path, | ||
308 | fields: { accountName: 'root' }, | ||
309 | statusCodeExpected: 409 | ||
310 | }) | ||
311 | }) | ||
312 | |||
313 | it('Should succeed with the correct params', async function () { | ||
314 | await makePostBodyRequest({ | ||
315 | url: server.url, | ||
316 | token: server.accessToken, | ||
317 | path, | ||
318 | fields: { accountName: 'user1' }, | ||
319 | statusCodeExpected: 204 | ||
320 | }) | ||
321 | }) | ||
322 | }) | ||
323 | |||
324 | describe('When unblocking an account', function () { | ||
325 | it('Should fail with an unauthenticated user', async function () { | ||
326 | await makeDeleteRequest({ | ||
327 | url: server.url, | ||
328 | path: path + '/user1', | ||
329 | statusCodeExpected: 401 | ||
330 | }) | ||
331 | }) | ||
332 | |||
333 | it('Should fail with a user without the appropriate rights', async function () { | ||
334 | await makeDeleteRequest({ | ||
335 | url: server.url, | ||
336 | path: path + '/user1', | ||
337 | token: userAccessToken, | ||
338 | statusCodeExpected: 403 | ||
339 | }) | ||
340 | }) | ||
341 | |||
342 | it('Should fail with an unknown account block', async function () { | ||
343 | await makeDeleteRequest({ | ||
344 | url: server.url, | ||
345 | path: path + '/user2', | ||
346 | token: server.accessToken, | ||
347 | statusCodeExpected: 404 | ||
348 | }) | ||
349 | }) | ||
350 | |||
351 | it('Should succeed with the correct params', async function () { | ||
352 | await makeDeleteRequest({ | ||
353 | url: server.url, | ||
354 | path: path + '/user1', | ||
355 | token: server.accessToken, | ||
356 | statusCodeExpected: 204 | ||
357 | }) | ||
358 | }) | ||
359 | }) | ||
360 | }) | ||
361 | |||
362 | describe('When managing server servers blocklist', function () { | ||
363 | const path = '/api/v1/server/blocklist/servers' | ||
364 | |||
365 | describe('When listing blocked servers', function () { | ||
366 | it('Should fail with an unauthenticated user', async function () { | ||
367 | await makeGetRequest({ | ||
368 | url: server.url, | ||
369 | path, | ||
370 | statusCodeExpected: 401 | ||
371 | }) | ||
372 | }) | ||
373 | |||
374 | it('Should fail with a user without the appropriate rights', async function () { | ||
375 | await makeGetRequest({ | ||
376 | url: server.url, | ||
377 | token: userAccessToken, | ||
378 | path, | ||
379 | statusCodeExpected: 403 | ||
380 | }) | ||
381 | }) | ||
382 | |||
383 | it('Should fail with a bad start pagination', async function () { | ||
384 | await checkBadStartPagination(server.url, path, server.accessToken) | ||
385 | }) | ||
386 | |||
387 | it('Should fail with a bad count pagination', async function () { | ||
388 | await checkBadCountPagination(server.url, path, server.accessToken) | ||
389 | }) | ||
390 | |||
391 | it('Should fail with an incorrect sort', async function () { | ||
392 | await checkBadSortPagination(server.url, path, server.accessToken) | ||
393 | }) | ||
394 | }) | ||
395 | |||
396 | describe('When blocking a server', function () { | ||
397 | it('Should fail with an unauthenticated user', async function () { | ||
398 | await makePostBodyRequest({ | ||
399 | url: server.url, | ||
400 | path, | ||
401 | fields: { host: 'localhost:9002' }, | ||
402 | statusCodeExpected: 401 | ||
403 | }) | ||
404 | }) | ||
405 | |||
406 | it('Should fail with a user without the appropriate rights', async function () { | ||
407 | await makePostBodyRequest({ | ||
408 | url: server.url, | ||
409 | token: userAccessToken, | ||
410 | path, | ||
411 | fields: { host: 'localhost:9002' }, | ||
412 | statusCodeExpected: 403 | ||
413 | }) | ||
414 | }) | ||
415 | |||
416 | it('Should fail with an unknown server', async function () { | ||
417 | await makePostBodyRequest({ | ||
418 | url: server.url, | ||
419 | token: server.accessToken, | ||
420 | path, | ||
421 | fields: { host: 'localhost:9003' }, | ||
422 | statusCodeExpected: 404 | ||
423 | }) | ||
424 | }) | ||
425 | |||
426 | it('Should fail with our own server', async function () { | ||
427 | await makePostBodyRequest({ | ||
428 | url: server.url, | ||
429 | token: server.accessToken, | ||
430 | path, | ||
431 | fields: { host: 'localhost:9001' }, | ||
432 | statusCodeExpected: 409 | ||
433 | }) | ||
434 | }) | ||
435 | |||
436 | it('Should succeed with the correct params', async function () { | ||
437 | await makePostBodyRequest({ | ||
438 | url: server.url, | ||
439 | token: server.accessToken, | ||
440 | path, | ||
441 | fields: { host: 'localhost:9002' }, | ||
442 | statusCodeExpected: 204 | ||
443 | }) | ||
444 | }) | ||
445 | }) | ||
446 | |||
447 | describe('When unblocking a server', function () { | ||
448 | it('Should fail with an unauthenticated user', async function () { | ||
449 | await makeDeleteRequest({ | ||
450 | url: server.url, | ||
451 | path: path + '/localhost:9002', | ||
452 | statusCodeExpected: 401 | ||
453 | }) | ||
454 | }) | ||
455 | |||
456 | it('Should fail with a user without the appropriate rights', async function () { | ||
457 | await makeDeleteRequest({ | ||
458 | url: server.url, | ||
459 | path: path + '/localhost:9002', | ||
460 | token: userAccessToken, | ||
461 | statusCodeExpected: 403 | ||
462 | }) | ||
463 | }) | ||
464 | |||
465 | it('Should fail with an unknown server block', async function () { | ||
466 | await makeDeleteRequest({ | ||
467 | url: server.url, | ||
468 | path: path + '/localhost:9003', | ||
469 | token: server.accessToken, | ||
470 | statusCodeExpected: 404 | ||
471 | }) | ||
472 | }) | ||
473 | |||
474 | it('Should succeed with the correct params', async function () { | ||
475 | await makeDeleteRequest({ | ||
476 | url: server.url, | ||
477 | path: path + '/localhost:9002', | ||
478 | token: server.accessToken, | ||
479 | statusCodeExpected: 204 | ||
480 | }) | ||
481 | }) | ||
482 | }) | ||
483 | }) | ||
484 | }) | ||
485 | |||
486 | after(async function () { | ||
487 | killallServers(servers) | ||
488 | |||
489 | // Keep the logs if the test failed | ||
490 | if (this['ok']) { | ||
491 | await flushTests() | ||
492 | } | ||
493 | }) | ||
494 | }) | ||
diff --git a/server/tests/api/check-params/index.ts b/server/tests/api/check-params/index.ts index 44460a167..877ceb0a7 100644 --- a/server/tests/api/check-params/index.ts +++ b/server/tests/api/check-params/index.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | // Order of the tests we want to execute | 1 | // Order of the tests we want to execute |
2 | import './accounts' | 2 | import './accounts' |
3 | import './blocklist' | ||
3 | import './config' | 4 | import './config' |
4 | import './follows' | 5 | import './follows' |
5 | import './jobs' | 6 | import './jobs' |
@@ -15,3 +16,5 @@ import './video-channels' | |||
15 | import './video-comments' | 16 | import './video-comments' |
16 | import './video-imports' | 17 | import './video-imports' |
17 | import './videos' | 18 | import './videos' |
19 | import './videos-filter' | ||
20 | import './videos-history' | ||
diff --git a/server/tests/api/check-params/users.ts b/server/tests/api/check-params/users.ts index cbfa0c137..ec46609a4 100644 --- a/server/tests/api/check-params/users.ts +++ b/server/tests/api/check-params/users.ts | |||
@@ -315,7 +315,7 @@ describe('Test users API validators', function () { | |||
315 | 315 | ||
316 | it('Should fail with a too long description', async function () { | 316 | it('Should fail with a too long description', async function () { |
317 | const fields = { | 317 | const fields = { |
318 | description: 'super'.repeat(60) | 318 | description: 'super'.repeat(201) |
319 | } | 319 | } |
320 | 320 | ||
321 | await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields }) | 321 | await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields }) |
diff --git a/server/tests/api/check-params/video-channels.ts b/server/tests/api/check-params/video-channels.ts index 3a7942945..e5696224d 100644 --- a/server/tests/api/check-params/video-channels.ts +++ b/server/tests/api/check-params/video-channels.ts | |||
@@ -118,12 +118,12 @@ describe('Test video channels API validator', function () { | |||
118 | }) | 118 | }) |
119 | 119 | ||
120 | it('Should fail with a long description', async function () { | 120 | it('Should fail with a long description', async function () { |
121 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(150) }) | 121 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(201) }) |
122 | await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields }) | 122 | await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields }) |
123 | }) | 123 | }) |
124 | 124 | ||
125 | it('Should fail with a long support text', async function () { | 125 | it('Should fail with a long support text', async function () { |
126 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(150) }) | 126 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(201) }) |
127 | await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields }) | 127 | await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields }) |
128 | }) | 128 | }) |
129 | 129 | ||
@@ -185,12 +185,12 @@ describe('Test video channels API validator', function () { | |||
185 | }) | 185 | }) |
186 | 186 | ||
187 | it('Should fail with a long description', async function () { | 187 | it('Should fail with a long description', async function () { |
188 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(150) }) | 188 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(201) }) |
189 | await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | 189 | await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields }) |
190 | }) | 190 | }) |
191 | 191 | ||
192 | it('Should fail with a long support text', async function () { | 192 | it('Should fail with a long support text', async function () { |
193 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(150) }) | 193 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(201) }) |
194 | await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | 194 | await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields }) |
195 | }) | 195 | }) |
196 | 196 | ||
diff --git a/server/tests/api/check-params/video-imports.ts b/server/tests/api/check-params/video-imports.ts index 44645b0e2..b51f3d2cd 100644 --- a/server/tests/api/check-params/video-imports.ts +++ b/server/tests/api/check-params/video-imports.ts | |||
@@ -140,7 +140,7 @@ describe('Test video imports API validator', function () { | |||
140 | }) | 140 | }) |
141 | 141 | ||
142 | it('Should fail with a long support text', async function () { | 142 | it('Should fail with a long support text', async function () { |
143 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(150) }) | 143 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(201) }) |
144 | 144 | ||
145 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | 145 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) |
146 | }) | 146 | }) |
diff --git a/server/tests/api/check-params/videos-filter.ts b/server/tests/api/check-params/videos-filter.ts new file mode 100644 index 000000000..784cd8ba1 --- /dev/null +++ b/server/tests/api/check-params/videos-filter.ts | |||
@@ -0,0 +1,127 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { | ||
6 | createUser, | ||
7 | flushTests, | ||
8 | killallServers, | ||
9 | makeGetRequest, | ||
10 | runServer, | ||
11 | ServerInfo, | ||
12 | setAccessTokensToServers, | ||
13 | userLogin | ||
14 | } from '../../utils' | ||
15 | import { UserRole } from '../../../../shared/models/users' | ||
16 | |||
17 | const expect = chai.expect | ||
18 | |||
19 | async function testEndpoints (server: ServerInfo, token: string, filter: string, statusCodeExpected: number) { | ||
20 | const paths = [ | ||
21 | '/api/v1/video-channels/root_channel/videos', | ||
22 | '/api/v1/accounts/root/videos', | ||
23 | '/api/v1/videos', | ||
24 | '/api/v1/search/videos' | ||
25 | ] | ||
26 | |||
27 | for (const path of paths) { | ||
28 | await makeGetRequest({ | ||
29 | url: server.url, | ||
30 | path, | ||
31 | token, | ||
32 | query: { | ||
33 | filter | ||
34 | }, | ||
35 | statusCodeExpected | ||
36 | }) | ||
37 | } | ||
38 | } | ||
39 | |||
40 | describe('Test videos filters', function () { | ||
41 | let server: ServerInfo | ||
42 | let userAccessToken: string | ||
43 | let moderatorAccessToken: string | ||
44 | |||
45 | // --------------------------------------------------------------- | ||
46 | |||
47 | before(async function () { | ||
48 | this.timeout(30000) | ||
49 | |||
50 | await flushTests() | ||
51 | |||
52 | server = await runServer(1) | ||
53 | |||
54 | await setAccessTokensToServers([ server ]) | ||
55 | |||
56 | const user = { username: 'user1', password: 'my super password' } | ||
57 | await createUser(server.url, server.accessToken, user.username, user.password) | ||
58 | userAccessToken = await userLogin(server, user) | ||
59 | |||
60 | const moderator = { username: 'moderator', password: 'my super password' } | ||
61 | await createUser( | ||
62 | server.url, | ||
63 | server.accessToken, | ||
64 | moderator.username, | ||
65 | moderator.password, | ||
66 | undefined, | ||
67 | undefined, | ||
68 | UserRole.MODERATOR | ||
69 | ) | ||
70 | moderatorAccessToken = await userLogin(server, moderator) | ||
71 | }) | ||
72 | |||
73 | describe('When setting a video filter', function () { | ||
74 | |||
75 | it('Should fail with a bad filter', async function () { | ||
76 | await testEndpoints(server, server.accessToken, 'bad-filter', 400) | ||
77 | }) | ||
78 | |||
79 | it('Should succeed with a good filter', async function () { | ||
80 | await testEndpoints(server, server.accessToken,'local', 200) | ||
81 | }) | ||
82 | |||
83 | it('Should fail to list all-local with a simple user', async function () { | ||
84 | await testEndpoints(server, userAccessToken, 'all-local', 401) | ||
85 | }) | ||
86 | |||
87 | it('Should succeed to list all-local with a moderator', async function () { | ||
88 | await testEndpoints(server, moderatorAccessToken, 'all-local', 200) | ||
89 | }) | ||
90 | |||
91 | it('Should succeed to list all-local with an admin', async function () { | ||
92 | await testEndpoints(server, server.accessToken, 'all-local', 200) | ||
93 | }) | ||
94 | |||
95 | // Because we cannot authenticate the user on the RSS endpoint | ||
96 | it('Should fail on the feeds endpoint with the all-local filter', async function () { | ||
97 | await makeGetRequest({ | ||
98 | url: server.url, | ||
99 | path: '/feeds/videos.json', | ||
100 | statusCodeExpected: 401, | ||
101 | query: { | ||
102 | filter: 'all-local' | ||
103 | } | ||
104 | }) | ||
105 | }) | ||
106 | |||
107 | it('Should succed on the feeds endpoint with the local filter', async function () { | ||
108 | await makeGetRequest({ | ||
109 | url: server.url, | ||
110 | path: '/feeds/videos.json', | ||
111 | statusCodeExpected: 200, | ||
112 | query: { | ||
113 | filter: 'local' | ||
114 | } | ||
115 | }) | ||
116 | }) | ||
117 | }) | ||
118 | |||
119 | after(async function () { | ||
120 | killallServers([ server ]) | ||
121 | |||
122 | // Keep the logs if the test failed | ||
123 | if (this['ok']) { | ||
124 | await flushTests() | ||
125 | } | ||
126 | }) | ||
127 | }) | ||
diff --git a/server/tests/api/check-params/videos-history.ts b/server/tests/api/check-params/videos-history.ts new file mode 100644 index 000000000..808c3b616 --- /dev/null +++ b/server/tests/api/check-params/videos-history.ts | |||
@@ -0,0 +1,79 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { | ||
6 | flushTests, | ||
7 | killallServers, | ||
8 | makePostBodyRequest, | ||
9 | makePutBodyRequest, | ||
10 | runServer, | ||
11 | ServerInfo, | ||
12 | setAccessTokensToServers, | ||
13 | uploadVideo | ||
14 | } from '../../utils' | ||
15 | |||
16 | const expect = chai.expect | ||
17 | |||
18 | describe('Test videos history API validator', function () { | ||
19 | let path: string | ||
20 | let server: ServerInfo | ||
21 | |||
22 | // --------------------------------------------------------------- | ||
23 | |||
24 | before(async function () { | ||
25 | this.timeout(30000) | ||
26 | |||
27 | await flushTests() | ||
28 | |||
29 | server = await runServer(1) | ||
30 | |||
31 | await setAccessTokensToServers([ server ]) | ||
32 | |||
33 | const res = await uploadVideo(server.url, server.accessToken, {}) | ||
34 | const videoUUID = res.body.video.uuid | ||
35 | |||
36 | path = '/api/v1/videos/' + videoUUID + '/watching' | ||
37 | }) | ||
38 | |||
39 | describe('When notifying a user is watching a video', function () { | ||
40 | |||
41 | it('Should fail with an unauthenticated user', async function () { | ||
42 | const fields = { currentTime: 5 } | ||
43 | await makePutBodyRequest({ url: server.url, path, fields, statusCodeExpected: 401 }) | ||
44 | }) | ||
45 | |||
46 | it('Should fail with an incorrect video id', async function () { | ||
47 | const fields = { currentTime: 5 } | ||
48 | const path = '/api/v1/videos/blabla/watching' | ||
49 | await makePutBodyRequest({ url: server.url, path, fields, token: server.accessToken, statusCodeExpected: 400 }) | ||
50 | }) | ||
51 | |||
52 | it('Should fail with an unknown video', async function () { | ||
53 | const fields = { currentTime: 5 } | ||
54 | const path = '/api/v1/videos/d91fff41-c24d-4508-8e13-3bd5902c3b02/watching' | ||
55 | |||
56 | await makePutBodyRequest({ url: server.url, path, fields, token: server.accessToken, statusCodeExpected: 404 }) | ||
57 | }) | ||
58 | |||
59 | it('Should fail with a bad current time', async function () { | ||
60 | const fields = { currentTime: 'hello' } | ||
61 | await makePutBodyRequest({ url: server.url, path, fields, token: server.accessToken, statusCodeExpected: 400 }) | ||
62 | }) | ||
63 | |||
64 | it('Should succeed with the correct parameters', async function () { | ||
65 | const fields = { currentTime: 5 } | ||
66 | |||
67 | await makePutBodyRequest({ url: server.url, path, fields, token: server.accessToken, statusCodeExpected: 204 }) | ||
68 | }) | ||
69 | }) | ||
70 | |||
71 | after(async function () { | ||
72 | killallServers([ server ]) | ||
73 | |||
74 | // Keep the logs if the test failed | ||
75 | if (this['ok']) { | ||
76 | await flushTests() | ||
77 | } | ||
78 | }) | ||
79 | }) | ||
diff --git a/server/tests/api/check-params/videos.ts b/server/tests/api/check-params/videos.ts index 904d22870..699f135c7 100644 --- a/server/tests/api/check-params/videos.ts +++ b/server/tests/api/check-params/videos.ts | |||
@@ -233,7 +233,7 @@ describe('Test videos API validator', function () { | |||
233 | }) | 233 | }) |
234 | 234 | ||
235 | it('Should fail with a long support text', async function () { | 235 | it('Should fail with a long support text', async function () { |
236 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(150) }) | 236 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(201) }) |
237 | const attaches = baseCorrectAttaches | 237 | const attaches = baseCorrectAttaches |
238 | 238 | ||
239 | await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | 239 | await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) |
@@ -482,7 +482,7 @@ describe('Test videos API validator', function () { | |||
482 | }) | 482 | }) |
483 | 483 | ||
484 | it('Should fail with a long support text', async function () { | 484 | it('Should fail with a long support text', async function () { |
485 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(150) }) | 485 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(201) }) |
486 | 486 | ||
487 | await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) | 487 | await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) |
488 | }) | 488 | }) |
diff --git a/server/tests/api/index-4.ts b/server/tests/api/index-4.ts new file mode 100644 index 000000000..8e69b95a6 --- /dev/null +++ b/server/tests/api/index-4.ts | |||
@@ -0,0 +1 @@ | |||
import './redundancy' | |||
diff --git a/server/tests/api/index.ts b/server/tests/api/index.ts index 2d996dbf9..bc140f860 100644 --- a/server/tests/api/index.ts +++ b/server/tests/api/index.ts | |||
@@ -2,3 +2,4 @@ | |||
2 | import './index-1' | 2 | import './index-1' |
3 | import './index-2' | 3 | import './index-2' |
4 | import './index-3' | 4 | import './index-3' |
5 | import './index-4' | ||
diff --git a/server/tests/api/redundancy/index.ts b/server/tests/api/redundancy/index.ts new file mode 100644 index 000000000..8e69b95a6 --- /dev/null +++ b/server/tests/api/redundancy/index.ts | |||
@@ -0,0 +1 @@ | |||
import './redundancy' | |||
diff --git a/server/tests/api/redundancy/redundancy.ts b/server/tests/api/redundancy/redundancy.ts new file mode 100644 index 000000000..1960854b6 --- /dev/null +++ b/server/tests/api/redundancy/redundancy.ts | |||
@@ -0,0 +1,483 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { VideoDetails } from '../../../../shared/models/videos' | ||
6 | import { | ||
7 | doubleFollow, | ||
8 | flushAndRunMultipleServers, | ||
9 | getFollowingListPaginationAndSort, | ||
10 | getVideo, | ||
11 | immutableAssign, | ||
12 | killallServers, makeGetRequest, | ||
13 | root, | ||
14 | ServerInfo, | ||
15 | setAccessTokensToServers, unfollow, | ||
16 | uploadVideo, | ||
17 | viewVideo, | ||
18 | wait, | ||
19 | waitUntilLog, | ||
20 | checkVideoFilesWereRemoved, removeVideo | ||
21 | } from '../../utils' | ||
22 | import { waitJobs } from '../../utils/server/jobs' | ||
23 | import * as magnetUtil from 'magnet-uri' | ||
24 | import { updateRedundancy } from '../../utils/server/redundancy' | ||
25 | import { ActorFollow } from '../../../../shared/models/actors' | ||
26 | import { readdir } from 'fs-extra' | ||
27 | import { join } from 'path' | ||
28 | import { VideoRedundancyStrategy } from '../../../../shared/models/redundancy' | ||
29 | import { getStats } from '../../utils/server/stats' | ||
30 | import { ServerStats } from '../../../../shared/models/server/server-stats.model' | ||
31 | |||
32 | const expect = chai.expect | ||
33 | |||
34 | let servers: ServerInfo[] = [] | ||
35 | let video1Server2UUID: string | ||
36 | |||
37 | function checkMagnetWebseeds (file: { magnetUri: string, resolution: { id: number } }, baseWebseeds: string[], server: ServerInfo) { | ||
38 | const parsed = magnetUtil.decode(file.magnetUri) | ||
39 | |||
40 | for (const ws of baseWebseeds) { | ||
41 | const found = parsed.urlList.find(url => url === `${ws}-${file.resolution.id}.mp4`) | ||
42 | expect(found, `Webseed ${ws} not found in ${file.magnetUri} on server ${server.url}`).to.not.be.undefined | ||
43 | } | ||
44 | |||
45 | expect(parsed.urlList).to.have.lengthOf(baseWebseeds.length) | ||
46 | } | ||
47 | |||
48 | async function runServers (strategy: VideoRedundancyStrategy, additionalParams: any = {}) { | ||
49 | const config = { | ||
50 | redundancy: { | ||
51 | videos: { | ||
52 | check_interval: '5 seconds', | ||
53 | strategies: [ | ||
54 | immutableAssign({ | ||
55 | min_lifetime: '1 hour', | ||
56 | strategy: strategy, | ||
57 | size: '100KB' | ||
58 | }, additionalParams) | ||
59 | ] | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | servers = await flushAndRunMultipleServers(3, config) | ||
64 | |||
65 | // Get the access tokens | ||
66 | await setAccessTokensToServers(servers) | ||
67 | |||
68 | { | ||
69 | const res = await uploadVideo(servers[ 1 ].url, servers[ 1 ].accessToken, { name: 'video 1 server 2' }) | ||
70 | video1Server2UUID = res.body.video.uuid | ||
71 | |||
72 | await viewVideo(servers[ 1 ].url, video1Server2UUID) | ||
73 | } | ||
74 | |||
75 | await waitJobs(servers) | ||
76 | |||
77 | // Server 1 and server 2 follow each other | ||
78 | await doubleFollow(servers[ 0 ], servers[ 1 ]) | ||
79 | // Server 1 and server 3 follow each other | ||
80 | await doubleFollow(servers[ 0 ], servers[ 2 ]) | ||
81 | // Server 2 and server 3 follow each other | ||
82 | await doubleFollow(servers[ 1 ], servers[ 2 ]) | ||
83 | |||
84 | await waitJobs(servers) | ||
85 | } | ||
86 | |||
87 | async function check1WebSeed (strategy: VideoRedundancyStrategy, videoUUID?: string) { | ||
88 | if (!videoUUID) videoUUID = video1Server2UUID | ||
89 | |||
90 | const webseeds = [ | ||
91 | 'http://localhost:9002/static/webseed/' + videoUUID | ||
92 | ] | ||
93 | |||
94 | for (const server of servers) { | ||
95 | { | ||
96 | const res = await getVideo(server.url, videoUUID) | ||
97 | |||
98 | const video: VideoDetails = res.body | ||
99 | for (const f of video.files) { | ||
100 | checkMagnetWebseeds(f, webseeds, server) | ||
101 | } | ||
102 | } | ||
103 | } | ||
104 | } | ||
105 | |||
106 | async function checkStatsWith2Webseed (strategy: VideoRedundancyStrategy) { | ||
107 | const res = await getStats(servers[0].url) | ||
108 | const data: ServerStats = res.body | ||
109 | |||
110 | expect(data.videosRedundancy).to.have.lengthOf(1) | ||
111 | const stat = data.videosRedundancy[0] | ||
112 | |||
113 | expect(stat.strategy).to.equal(strategy) | ||
114 | expect(stat.totalSize).to.equal(102400) | ||
115 | expect(stat.totalUsed).to.be.at.least(1).and.below(102401) | ||
116 | expect(stat.totalVideoFiles).to.equal(4) | ||
117 | expect(stat.totalVideos).to.equal(1) | ||
118 | } | ||
119 | |||
120 | async function checkStatsWith1Webseed (strategy: VideoRedundancyStrategy) { | ||
121 | const res = await getStats(servers[0].url) | ||
122 | const data: ServerStats = res.body | ||
123 | |||
124 | expect(data.videosRedundancy).to.have.lengthOf(1) | ||
125 | |||
126 | const stat = data.videosRedundancy[0] | ||
127 | expect(stat.strategy).to.equal(strategy) | ||
128 | expect(stat.totalSize).to.equal(102400) | ||
129 | expect(stat.totalUsed).to.equal(0) | ||
130 | expect(stat.totalVideoFiles).to.equal(0) | ||
131 | expect(stat.totalVideos).to.equal(0) | ||
132 | } | ||
133 | |||
134 | async function check2Webseeds (strategy: VideoRedundancyStrategy, videoUUID?: string) { | ||
135 | if (!videoUUID) videoUUID = video1Server2UUID | ||
136 | |||
137 | const webseeds = [ | ||
138 | 'http://localhost:9001/static/webseed/' + videoUUID, | ||
139 | 'http://localhost:9002/static/webseed/' + videoUUID | ||
140 | ] | ||
141 | |||
142 | for (const server of servers) { | ||
143 | const res = await getVideo(server.url, videoUUID) | ||
144 | |||
145 | const video: VideoDetails = res.body | ||
146 | |||
147 | for (const file of video.files) { | ||
148 | checkMagnetWebseeds(file, webseeds, server) | ||
149 | |||
150 | // Only servers 1 and 2 have the video | ||
151 | if (server.serverNumber !== 3) { | ||
152 | await makeGetRequest({ | ||
153 | url: server.url, | ||
154 | statusCodeExpected: 200, | ||
155 | path: '/static/webseed/' + `${videoUUID}-${file.resolution.id}.mp4`, | ||
156 | contentType: null | ||
157 | }) | ||
158 | } | ||
159 | } | ||
160 | } | ||
161 | |||
162 | for (const directory of [ 'test1', 'test2' ]) { | ||
163 | const files = await readdir(join(root(), directory, 'videos')) | ||
164 | expect(files).to.have.length.at.least(4) | ||
165 | |||
166 | for (const resolution of [ 240, 360, 480, 720 ]) { | ||
167 | expect(files.find(f => f === `${videoUUID}-${resolution}.mp4`)).to.not.be.undefined | ||
168 | } | ||
169 | } | ||
170 | } | ||
171 | |||
172 | async function enableRedundancyOnServer1 () { | ||
173 | await updateRedundancy(servers[ 0 ].url, servers[ 0 ].accessToken, servers[ 1 ].host, true) | ||
174 | |||
175 | const res = await getFollowingListPaginationAndSort(servers[ 0 ].url, 0, 5, '-createdAt') | ||
176 | const follows: ActorFollow[] = res.body.data | ||
177 | const server2 = follows.find(f => f.following.host === 'localhost:9002') | ||
178 | const server3 = follows.find(f => f.following.host === 'localhost:9003') | ||
179 | |||
180 | expect(server3).to.not.be.undefined | ||
181 | expect(server3.following.hostRedundancyAllowed).to.be.false | ||
182 | |||
183 | expect(server2).to.not.be.undefined | ||
184 | expect(server2.following.hostRedundancyAllowed).to.be.true | ||
185 | } | ||
186 | |||
187 | async function disableRedundancyOnServer1 () { | ||
188 | await updateRedundancy(servers[ 0 ].url, servers[ 0 ].accessToken, servers[ 1 ].host, false) | ||
189 | |||
190 | const res = await getFollowingListPaginationAndSort(servers[ 0 ].url, 0, 5, '-createdAt') | ||
191 | const follows: ActorFollow[] = res.body.data | ||
192 | const server2 = follows.find(f => f.following.host === 'localhost:9002') | ||
193 | const server3 = follows.find(f => f.following.host === 'localhost:9003') | ||
194 | |||
195 | expect(server3).to.not.be.undefined | ||
196 | expect(server3.following.hostRedundancyAllowed).to.be.false | ||
197 | |||
198 | expect(server2).to.not.be.undefined | ||
199 | expect(server2.following.hostRedundancyAllowed).to.be.false | ||
200 | } | ||
201 | |||
202 | async function cleanServers () { | ||
203 | killallServers(servers) | ||
204 | } | ||
205 | |||
206 | describe('Test videos redundancy', function () { | ||
207 | |||
208 | describe('With most-views strategy', function () { | ||
209 | const strategy = 'most-views' | ||
210 | |||
211 | before(function () { | ||
212 | this.timeout(120000) | ||
213 | |||
214 | return runServers(strategy) | ||
215 | }) | ||
216 | |||
217 | it('Should have 1 webseed on the first video', async function () { | ||
218 | await check1WebSeed(strategy) | ||
219 | await checkStatsWith1Webseed(strategy) | ||
220 | }) | ||
221 | |||
222 | it('Should enable redundancy on server 1', function () { | ||
223 | return enableRedundancyOnServer1() | ||
224 | }) | ||
225 | |||
226 | it('Should have 2 webseed on the first video', async function () { | ||
227 | this.timeout(40000) | ||
228 | |||
229 | await waitJobs(servers) | ||
230 | await waitUntilLog(servers[0], 'Duplicated ', 4) | ||
231 | await waitJobs(servers) | ||
232 | |||
233 | await check2Webseeds(strategy) | ||
234 | await checkStatsWith2Webseed(strategy) | ||
235 | }) | ||
236 | |||
237 | it('Should undo redundancy on server 1 and remove duplicated videos', async function () { | ||
238 | this.timeout(40000) | ||
239 | |||
240 | await disableRedundancyOnServer1() | ||
241 | |||
242 | await waitJobs(servers) | ||
243 | await wait(5000) | ||
244 | |||
245 | await check1WebSeed(strategy) | ||
246 | |||
247 | await checkVideoFilesWereRemoved(video1Server2UUID, servers[0].serverNumber, [ 'videos' ]) | ||
248 | }) | ||
249 | |||
250 | after(function () { | ||
251 | return cleanServers() | ||
252 | }) | ||
253 | }) | ||
254 | |||
255 | describe('With trending strategy', function () { | ||
256 | const strategy = 'trending' | ||
257 | |||
258 | before(function () { | ||
259 | this.timeout(120000) | ||
260 | |||
261 | return runServers(strategy) | ||
262 | }) | ||
263 | |||
264 | it('Should have 1 webseed on the first video', async function () { | ||
265 | await check1WebSeed(strategy) | ||
266 | await checkStatsWith1Webseed(strategy) | ||
267 | }) | ||
268 | |||
269 | it('Should enable redundancy on server 1', function () { | ||
270 | return enableRedundancyOnServer1() | ||
271 | }) | ||
272 | |||
273 | it('Should have 2 webseed on the first video', async function () { | ||
274 | this.timeout(40000) | ||
275 | |||
276 | await waitJobs(servers) | ||
277 | await waitUntilLog(servers[0], 'Duplicated ', 4) | ||
278 | await waitJobs(servers) | ||
279 | |||
280 | await check2Webseeds(strategy) | ||
281 | await checkStatsWith2Webseed(strategy) | ||
282 | }) | ||
283 | |||
284 | it('Should unfollow on server 1 and remove duplicated videos', async function () { | ||
285 | this.timeout(40000) | ||
286 | |||
287 | await unfollow(servers[0].url, servers[0].accessToken, servers[1]) | ||
288 | |||
289 | await waitJobs(servers) | ||
290 | await wait(5000) | ||
291 | |||
292 | await check1WebSeed(strategy) | ||
293 | |||
294 | await checkVideoFilesWereRemoved(video1Server2UUID, servers[0].serverNumber, [ 'videos' ]) | ||
295 | }) | ||
296 | |||
297 | after(function () { | ||
298 | return cleanServers() | ||
299 | }) | ||
300 | }) | ||
301 | |||
302 | describe('With recently added strategy', function () { | ||
303 | const strategy = 'recently-added' | ||
304 | |||
305 | before(function () { | ||
306 | this.timeout(120000) | ||
307 | |||
308 | return runServers(strategy, { min_views: 3 }) | ||
309 | }) | ||
310 | |||
311 | it('Should have 1 webseed on the first video', async function () { | ||
312 | await check1WebSeed(strategy) | ||
313 | await checkStatsWith1Webseed(strategy) | ||
314 | }) | ||
315 | |||
316 | it('Should enable redundancy on server 1', function () { | ||
317 | return enableRedundancyOnServer1() | ||
318 | }) | ||
319 | |||
320 | it('Should still have 1 webseed on the first video', async function () { | ||
321 | this.timeout(40000) | ||
322 | |||
323 | await waitJobs(servers) | ||
324 | await wait(15000) | ||
325 | await waitJobs(servers) | ||
326 | |||
327 | await check1WebSeed(strategy) | ||
328 | await checkStatsWith1Webseed(strategy) | ||
329 | }) | ||
330 | |||
331 | it('Should view 2 times the first video to have > min_views config', async function () { | ||
332 | this.timeout(40000) | ||
333 | |||
334 | await viewVideo(servers[ 0 ].url, video1Server2UUID) | ||
335 | await viewVideo(servers[ 2 ].url, video1Server2UUID) | ||
336 | |||
337 | await wait(10000) | ||
338 | await waitJobs(servers) | ||
339 | }) | ||
340 | |||
341 | it('Should have 2 webseed on the first video', async function () { | ||
342 | this.timeout(40000) | ||
343 | |||
344 | await waitJobs(servers) | ||
345 | await waitUntilLog(servers[0], 'Duplicated ', 4) | ||
346 | await waitJobs(servers) | ||
347 | |||
348 | await check2Webseeds(strategy) | ||
349 | await checkStatsWith2Webseed(strategy) | ||
350 | }) | ||
351 | |||
352 | it('Should remove the video and the redundancy files', async function () { | ||
353 | this.timeout(20000) | ||
354 | |||
355 | await removeVideo(servers[1].url, servers[1].accessToken, video1Server2UUID) | ||
356 | |||
357 | await waitJobs(servers) | ||
358 | |||
359 | for (const server of servers) { | ||
360 | await checkVideoFilesWereRemoved(video1Server2UUID, server.serverNumber) | ||
361 | } | ||
362 | }) | ||
363 | |||
364 | after(function () { | ||
365 | return cleanServers() | ||
366 | }) | ||
367 | }) | ||
368 | |||
369 | describe('Test expiration', function () { | ||
370 | const strategy = 'recently-added' | ||
371 | |||
372 | async function checkContains (servers: ServerInfo[], str: string) { | ||
373 | for (const server of servers) { | ||
374 | const res = await getVideo(server.url, video1Server2UUID) | ||
375 | const video: VideoDetails = res.body | ||
376 | |||
377 | for (const f of video.files) { | ||
378 | expect(f.magnetUri).to.contain(str) | ||
379 | } | ||
380 | } | ||
381 | } | ||
382 | |||
383 | async function checkNotContains (servers: ServerInfo[], str: string) { | ||
384 | for (const server of servers) { | ||
385 | const res = await getVideo(server.url, video1Server2UUID) | ||
386 | const video: VideoDetails = res.body | ||
387 | |||
388 | for (const f of video.files) { | ||
389 | expect(f.magnetUri).to.not.contain(str) | ||
390 | } | ||
391 | } | ||
392 | } | ||
393 | |||
394 | before(async function () { | ||
395 | this.timeout(120000) | ||
396 | |||
397 | await runServers(strategy, { min_lifetime: '7 seconds', min_views: 0 }) | ||
398 | |||
399 | await enableRedundancyOnServer1() | ||
400 | }) | ||
401 | |||
402 | it('Should still have 2 webseeds after 10 seconds', async function () { | ||
403 | this.timeout(40000) | ||
404 | |||
405 | await wait(10000) | ||
406 | |||
407 | try { | ||
408 | await checkContains(servers, 'http%3A%2F%2Flocalhost%3A9001') | ||
409 | } catch { | ||
410 | // Maybe a server deleted a redundancy in the scheduler | ||
411 | await wait(2000) | ||
412 | |||
413 | await checkContains(servers, 'http%3A%2F%2Flocalhost%3A9001') | ||
414 | } | ||
415 | }) | ||
416 | |||
417 | it('Should stop server 1 and expire video redundancy', async function () { | ||
418 | this.timeout(40000) | ||
419 | |||
420 | killallServers([ servers[0] ]) | ||
421 | |||
422 | await wait(10000) | ||
423 | |||
424 | await checkNotContains([ servers[1], servers[2] ], 'http%3A%2F%2Flocalhost%3A9001') | ||
425 | }) | ||
426 | |||
427 | after(function () { | ||
428 | return killallServers([ servers[1], servers[2] ]) | ||
429 | }) | ||
430 | }) | ||
431 | |||
432 | describe('Test file replacement', function () { | ||
433 | let video2Server2UUID: string | ||
434 | const strategy = 'recently-added' | ||
435 | |||
436 | before(async function () { | ||
437 | this.timeout(120000) | ||
438 | |||
439 | await runServers(strategy, { min_lifetime: '7 seconds', min_views: 0 }) | ||
440 | |||
441 | await enableRedundancyOnServer1() | ||
442 | |||
443 | await waitJobs(servers) | ||
444 | await waitUntilLog(servers[0], 'Duplicated ', 4) | ||
445 | await waitJobs(servers) | ||
446 | |||
447 | await check2Webseeds(strategy) | ||
448 | await checkStatsWith2Webseed(strategy) | ||
449 | |||
450 | const res = await uploadVideo(servers[ 1 ].url, servers[ 1 ].accessToken, { name: 'video 2 server 2' }) | ||
451 | video2Server2UUID = res.body.video.uuid | ||
452 | }) | ||
453 | |||
454 | it('Should cache video 2 webseed on the first video', async function () { | ||
455 | this.timeout(50000) | ||
456 | |||
457 | await waitJobs(servers) | ||
458 | |||
459 | await wait(7000) | ||
460 | |||
461 | try { | ||
462 | await check1WebSeed(strategy, video1Server2UUID) | ||
463 | await check2Webseeds(strategy, video2Server2UUID) | ||
464 | } catch { | ||
465 | await wait(3000) | ||
466 | |||
467 | try { | ||
468 | await check1WebSeed(strategy, video1Server2UUID) | ||
469 | await check2Webseeds(strategy, video2Server2UUID) | ||
470 | } catch { | ||
471 | await wait(5000) | ||
472 | |||
473 | await check1WebSeed(strategy, video1Server2UUID) | ||
474 | await check2Webseeds(strategy, video2Server2UUID) | ||
475 | } | ||
476 | } | ||
477 | }) | ||
478 | |||
479 | after(function () { | ||
480 | return cleanServers() | ||
481 | }) | ||
482 | }) | ||
483 | }) | ||
diff --git a/server/tests/api/server/follows.ts b/server/tests/api/server/follows.ts index 310c291bf..e80e93e7f 100644 --- a/server/tests/api/server/follows.ts +++ b/server/tests/api/server/follows.ts | |||
@@ -93,7 +93,26 @@ describe('Test follows', function () { | |||
93 | expect(server3Follow.state).to.equal('accepted') | 93 | expect(server3Follow.state).to.equal('accepted') |
94 | }) | 94 | }) |
95 | 95 | ||
96 | it('Should have 0 followings on server 1 and 2', async function () { | 96 | it('Should search followings on server 1', async function () { |
97 | { | ||
98 | const res = await getFollowingListPaginationAndSort(servers[ 0 ].url, 0, 1, 'createdAt', ':9002') | ||
99 | const follows = res.body.data | ||
100 | |||
101 | expect(res.body.total).to.equal(1) | ||
102 | expect(follows.length).to.equal(1) | ||
103 | expect(follows[ 0 ].following.host).to.equal('localhost:9002') | ||
104 | } | ||
105 | |||
106 | { | ||
107 | const res = await getFollowingListPaginationAndSort(servers[ 0 ].url, 0, 1, 'createdAt', 'bla') | ||
108 | const follows = res.body.data | ||
109 | |||
110 | expect(res.body.total).to.equal(0) | ||
111 | expect(follows.length).to.equal(0) | ||
112 | } | ||
113 | }) | ||
114 | |||
115 | it('Should have 0 followings on server 2 and 3', async function () { | ||
97 | for (const server of [ servers[1], servers[2] ]) { | 116 | for (const server of [ servers[1], servers[2] ]) { |
98 | const res = await getFollowingListPaginationAndSort(server.url, 0, 5, 'createdAt') | 117 | const res = await getFollowingListPaginationAndSort(server.url, 0, 5, 'createdAt') |
99 | const follows = res.body.data | 118 | const follows = res.body.data |
@@ -116,6 +135,25 @@ describe('Test follows', function () { | |||
116 | } | 135 | } |
117 | }) | 136 | }) |
118 | 137 | ||
138 | it('Should search followers on server 2', async function () { | ||
139 | { | ||
140 | const res = await getFollowersListPaginationAndSort(servers[ 2 ].url, 0, 5, 'createdAt', '9001') | ||
141 | const follows = res.body.data | ||
142 | |||
143 | expect(res.body.total).to.equal(1) | ||
144 | expect(follows.length).to.equal(1) | ||
145 | expect(follows[ 0 ].following.host).to.equal('localhost:9003') | ||
146 | } | ||
147 | |||
148 | { | ||
149 | const res = await getFollowersListPaginationAndSort(servers[ 2 ].url, 0, 5, 'createdAt', 'bla') | ||
150 | const follows = res.body.data | ||
151 | |||
152 | expect(res.body.total).to.equal(0) | ||
153 | expect(follows.length).to.equal(0) | ||
154 | } | ||
155 | }) | ||
156 | |||
119 | it('Should have 0 followers on server 1', async function () { | 157 | it('Should have 0 followers on server 1', async function () { |
120 | const res = await getFollowersListPaginationAndSort(servers[0].url, 0, 5, 'createdAt') | 158 | const res = await getFollowersListPaginationAndSort(servers[0].url, 0, 5, 'createdAt') |
121 | const follows = res.body.data | 159 | const follows = res.body.data |
diff --git a/server/tests/api/server/index.ts b/server/tests/api/server/index.ts index c74c68a33..eeb8b7a28 100644 --- a/server/tests/api/server/index.ts +++ b/server/tests/api/server/index.ts | |||
@@ -3,7 +3,6 @@ import './email' | |||
3 | import './follows' | 3 | import './follows' |
4 | import './handle-down' | 4 | import './handle-down' |
5 | import './jobs' | 5 | import './jobs' |
6 | import './redundancy' | ||
7 | import './reverse-proxy' | 6 | import './reverse-proxy' |
8 | import './stats' | 7 | import './stats' |
9 | import './tracker' | 8 | import './tracker' |
diff --git a/server/tests/api/server/redundancy.ts b/server/tests/api/server/redundancy.ts index 1960854b6..f50d6e3cf 100644 --- a/server/tests/api/server/redundancy.ts +++ b/server/tests/api/server/redundancy.ts | |||
@@ -419,7 +419,7 @@ describe('Test videos redundancy', function () { | |||
419 | 419 | ||
420 | killallServers([ servers[0] ]) | 420 | killallServers([ servers[0] ]) |
421 | 421 | ||
422 | await wait(10000) | 422 | await wait(15000) |
423 | 423 | ||
424 | await checkNotContains([ servers[1], servers[2] ], 'http%3A%2F%2Flocalhost%3A9001') | 424 | await checkNotContains([ servers[1], servers[2] ], 'http%3A%2F%2Flocalhost%3A9001') |
425 | }) | 425 | }) |
@@ -452,26 +452,22 @@ describe('Test videos redundancy', function () { | |||
452 | }) | 452 | }) |
453 | 453 | ||
454 | it('Should cache video 2 webseed on the first video', async function () { | 454 | it('Should cache video 2 webseed on the first video', async function () { |
455 | this.timeout(50000) | 455 | this.timeout(120000) |
456 | 456 | ||
457 | await waitJobs(servers) | 457 | await waitJobs(servers) |
458 | 458 | ||
459 | await wait(7000) | 459 | let checked = false |
460 | 460 | ||
461 | try { | 461 | while (checked === false) { |
462 | await check1WebSeed(strategy, video1Server2UUID) | 462 | await wait(1000) |
463 | await check2Webseeds(strategy, video2Server2UUID) | ||
464 | } catch { | ||
465 | await wait(3000) | ||
466 | 463 | ||
467 | try { | 464 | try { |
468 | await check1WebSeed(strategy, video1Server2UUID) | 465 | await check1WebSeed(strategy, video1Server2UUID) |
469 | await check2Webseeds(strategy, video2Server2UUID) | 466 | await check2Webseeds(strategy, video2Server2UUID) |
470 | } catch { | ||
471 | await wait(5000) | ||
472 | 467 | ||
473 | await check1WebSeed(strategy, video1Server2UUID) | 468 | checked = true |
474 | await check2Webseeds(strategy, video2Server2UUID) | 469 | } catch { |
470 | checked = false | ||
475 | } | 471 | } |
476 | } | 472 | } |
477 | }) | 473 | }) |
diff --git a/server/tests/api/users/blocklist.ts b/server/tests/api/users/blocklist.ts new file mode 100644 index 000000000..eed4b9f3e --- /dev/null +++ b/server/tests/api/users/blocklist.ts | |||
@@ -0,0 +1,511 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { AccountBlock, ServerBlock, Video } from '../../../../shared/index' | ||
6 | import { | ||
7 | createUser, | ||
8 | doubleFollow, | ||
9 | flushAndRunMultipleServers, | ||
10 | flushTests, | ||
11 | killallServers, | ||
12 | ServerInfo, | ||
13 | uploadVideo, | ||
14 | userLogin | ||
15 | } from '../../utils/index' | ||
16 | import { setAccessTokensToServers } from '../../utils/users/login' | ||
17 | import { getVideosListWithToken, getVideosList } from '../../utils/videos/videos' | ||
18 | import { | ||
19 | addVideoCommentReply, | ||
20 | addVideoCommentThread, | ||
21 | getVideoCommentThreads, | ||
22 | getVideoThreadComments | ||
23 | } from '../../utils/videos/video-comments' | ||
24 | import { waitJobs } from '../../utils/server/jobs' | ||
25 | import { VideoComment, VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model' | ||
26 | import { | ||
27 | addAccountToAccountBlocklist, | ||
28 | addAccountToServerBlocklist, | ||
29 | addServerToAccountBlocklist, | ||
30 | addServerToServerBlocklist, | ||
31 | getAccountBlocklistByAccount, | ||
32 | getAccountBlocklistByServer, | ||
33 | getServerBlocklistByAccount, | ||
34 | getServerBlocklistByServer, | ||
35 | removeAccountFromAccountBlocklist, | ||
36 | removeAccountFromServerBlocklist, | ||
37 | removeServerFromAccountBlocklist, | ||
38 | removeServerFromServerBlocklist | ||
39 | } from '../../utils/users/blocklist' | ||
40 | |||
41 | const expect = chai.expect | ||
42 | |||
43 | async function checkAllVideos (url: string, token: string) { | ||
44 | { | ||
45 | const res = await getVideosListWithToken(url, token) | ||
46 | |||
47 | expect(res.body.data).to.have.lengthOf(4) | ||
48 | } | ||
49 | |||
50 | { | ||
51 | const res = await getVideosList(url) | ||
52 | |||
53 | expect(res.body.data).to.have.lengthOf(4) | ||
54 | } | ||
55 | } | ||
56 | |||
57 | async function checkAllComments (url: string, token: string, videoUUID: string) { | ||
58 | const resThreads = await getVideoCommentThreads(url, videoUUID, 0, 5, '-createdAt', token) | ||
59 | |||
60 | const threads: VideoComment[] = resThreads.body.data | ||
61 | expect(threads).to.have.lengthOf(2) | ||
62 | |||
63 | for (const thread of threads) { | ||
64 | const res = await getVideoThreadComments(url, videoUUID, thread.id, token) | ||
65 | |||
66 | const tree: VideoCommentThreadTree = res.body | ||
67 | expect(tree.children).to.have.lengthOf(1) | ||
68 | } | ||
69 | } | ||
70 | |||
71 | describe('Test blocklist', function () { | ||
72 | let servers: ServerInfo[] | ||
73 | let videoUUID1: string | ||
74 | let videoUUID2: string | ||
75 | let userToken1: string | ||
76 | let userModeratorToken: string | ||
77 | let userToken2: string | ||
78 | |||
79 | before(async function () { | ||
80 | this.timeout(60000) | ||
81 | |||
82 | await flushTests() | ||
83 | |||
84 | servers = await flushAndRunMultipleServers(2) | ||
85 | await setAccessTokensToServers(servers) | ||
86 | |||
87 | { | ||
88 | const user = { username: 'user1', password: 'password' } | ||
89 | await createUser(servers[0].url, servers[0].accessToken, user.username, user.password) | ||
90 | |||
91 | userToken1 = await userLogin(servers[0], user) | ||
92 | await uploadVideo(servers[0].url, userToken1, { name: 'video user 1' }) | ||
93 | } | ||
94 | |||
95 | { | ||
96 | const user = { username: 'moderator', password: 'password' } | ||
97 | await createUser(servers[0].url, servers[0].accessToken, user.username, user.password) | ||
98 | |||
99 | userModeratorToken = await userLogin(servers[0], user) | ||
100 | } | ||
101 | |||
102 | { | ||
103 | const user = { username: 'user2', password: 'password' } | ||
104 | await createUser(servers[1].url, servers[1].accessToken, user.username, user.password) | ||
105 | |||
106 | userToken2 = await userLogin(servers[1], user) | ||
107 | await uploadVideo(servers[1].url, userToken2, { name: 'video user 2' }) | ||
108 | } | ||
109 | |||
110 | { | ||
111 | const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video server 1' }) | ||
112 | videoUUID1 = res.body.video.uuid | ||
113 | } | ||
114 | |||
115 | { | ||
116 | const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video server 2' }) | ||
117 | videoUUID2 = res.body.video.uuid | ||
118 | } | ||
119 | |||
120 | await doubleFollow(servers[0], servers[1]) | ||
121 | |||
122 | { | ||
123 | const resComment = await addVideoCommentThread(servers[ 0 ].url, servers[ 0 ].accessToken, videoUUID1, 'comment root 1') | ||
124 | const resReply = await addVideoCommentReply(servers[ 0 ].url, userToken1, videoUUID1, resComment.body.comment.id, 'comment user 1') | ||
125 | await addVideoCommentReply(servers[ 0 ].url, servers[ 0 ].accessToken, videoUUID1, resReply.body.comment.id, 'comment root 1') | ||
126 | } | ||
127 | |||
128 | { | ||
129 | const resComment = await addVideoCommentThread(servers[ 0 ].url, userToken1, videoUUID1, 'comment user 1') | ||
130 | await addVideoCommentReply(servers[ 0 ].url, servers[ 0 ].accessToken, videoUUID1, resComment.body.comment.id, 'comment root 1') | ||
131 | } | ||
132 | |||
133 | await waitJobs(servers) | ||
134 | }) | ||
135 | |||
136 | describe('User blocklist', function () { | ||
137 | |||
138 | describe('When managing account blocklist', function () { | ||
139 | it('Should list all videos', function () { | ||
140 | return checkAllVideos(servers[ 0 ].url, servers[ 0 ].accessToken) | ||
141 | }) | ||
142 | |||
143 | it('Should list the comments', function () { | ||
144 | return checkAllComments(servers[ 0 ].url, servers[ 0 ].accessToken, videoUUID1) | ||
145 | }) | ||
146 | |||
147 | it('Should block a remote account', async function () { | ||
148 | await addAccountToAccountBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'user2@localhost:9002') | ||
149 | }) | ||
150 | |||
151 | it('Should hide its videos', async function () { | ||
152 | const res = await getVideosListWithToken(servers[ 0 ].url, servers[ 0 ].accessToken) | ||
153 | |||
154 | const videos: Video[] = res.body.data | ||
155 | expect(videos).to.have.lengthOf(3) | ||
156 | |||
157 | const v = videos.find(v => v.name === 'video user 2') | ||
158 | expect(v).to.be.undefined | ||
159 | }) | ||
160 | |||
161 | it('Should block a local account', async function () { | ||
162 | await addAccountToAccountBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'user1') | ||
163 | }) | ||
164 | |||
165 | it('Should hide its videos', async function () { | ||
166 | const res = await getVideosListWithToken(servers[ 0 ].url, servers[ 0 ].accessToken) | ||
167 | |||
168 | const videos: Video[] = res.body.data | ||
169 | expect(videos).to.have.lengthOf(2) | ||
170 | |||
171 | const v = videos.find(v => v.name === 'video user 1') | ||
172 | expect(v).to.be.undefined | ||
173 | }) | ||
174 | |||
175 | it('Should hide its comments', async function () { | ||
176 | const resThreads = await getVideoCommentThreads(servers[ 0 ].url, videoUUID1, 0, 5, '-createdAt', servers[ 0 ].accessToken) | ||
177 | |||
178 | const threads: VideoComment[] = resThreads.body.data | ||
179 | expect(threads).to.have.lengthOf(1) | ||
180 | expect(threads[ 0 ].totalReplies).to.equal(0) | ||
181 | |||
182 | const t = threads.find(t => t.text === 'comment user 1') | ||
183 | expect(t).to.be.undefined | ||
184 | |||
185 | for (const thread of threads) { | ||
186 | const res = await getVideoThreadComments(servers[ 0 ].url, videoUUID1, thread.id, servers[ 0 ].accessToken) | ||
187 | |||
188 | const tree: VideoCommentThreadTree = res.body | ||
189 | expect(tree.children).to.have.lengthOf(0) | ||
190 | } | ||
191 | }) | ||
192 | |||
193 | it('Should list all the videos with another user', async function () { | ||
194 | return checkAllVideos(servers[ 0 ].url, userToken1) | ||
195 | }) | ||
196 | |||
197 | it('Should list all the comments with another user', async function () { | ||
198 | return checkAllComments(servers[ 0 ].url, userToken1, videoUUID1) | ||
199 | }) | ||
200 | |||
201 | it('Should list blocked accounts', async function () { | ||
202 | { | ||
203 | const res = await getAccountBlocklistByAccount(servers[ 0 ].url, servers[ 0 ].accessToken, 0, 1, 'createdAt') | ||
204 | const blocks: AccountBlock[] = res.body.data | ||
205 | |||
206 | expect(res.body.total).to.equal(2) | ||
207 | |||
208 | const block = blocks[ 0 ] | ||
209 | expect(block.byAccount.displayName).to.equal('root') | ||
210 | expect(block.byAccount.name).to.equal('root') | ||
211 | expect(block.blockedAccount.displayName).to.equal('user2') | ||
212 | expect(block.blockedAccount.name).to.equal('user2') | ||
213 | expect(block.blockedAccount.host).to.equal('localhost:9002') | ||
214 | } | ||
215 | |||
216 | { | ||
217 | const res = await getAccountBlocklistByAccount(servers[ 0 ].url, servers[ 0 ].accessToken, 1, 2, 'createdAt') | ||
218 | const blocks: AccountBlock[] = res.body.data | ||
219 | |||
220 | expect(res.body.total).to.equal(2) | ||
221 | |||
222 | const block = blocks[ 0 ] | ||
223 | expect(block.byAccount.displayName).to.equal('root') | ||
224 | expect(block.byAccount.name).to.equal('root') | ||
225 | expect(block.blockedAccount.displayName).to.equal('user1') | ||
226 | expect(block.blockedAccount.name).to.equal('user1') | ||
227 | expect(block.blockedAccount.host).to.equal('localhost:9001') | ||
228 | } | ||
229 | }) | ||
230 | |||
231 | it('Should unblock the remote account', async function () { | ||
232 | await removeAccountFromAccountBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'user2@localhost:9002') | ||
233 | }) | ||
234 | |||
235 | it('Should display its videos', async function () { | ||
236 | const res = await getVideosListWithToken(servers[ 0 ].url, servers[ 0 ].accessToken) | ||
237 | |||
238 | const videos: Video[] = res.body.data | ||
239 | expect(videos).to.have.lengthOf(3) | ||
240 | |||
241 | const v = videos.find(v => v.name === 'video user 2') | ||
242 | expect(v).not.to.be.undefined | ||
243 | }) | ||
244 | |||
245 | it('Should unblock the local account', async function () { | ||
246 | await removeAccountFromAccountBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'user1') | ||
247 | }) | ||
248 | |||
249 | it('Should display its comments', function () { | ||
250 | return checkAllComments(servers[ 0 ].url, servers[ 0 ].accessToken, videoUUID1) | ||
251 | }) | ||
252 | }) | ||
253 | |||
254 | describe('When managing server blocklist', function () { | ||
255 | it('Should list all videos', function () { | ||
256 | return checkAllVideos(servers[ 0 ].url, servers[ 0 ].accessToken) | ||
257 | }) | ||
258 | |||
259 | it('Should list the comments', function () { | ||
260 | return checkAllComments(servers[ 0 ].url, servers[ 0 ].accessToken, videoUUID1) | ||
261 | }) | ||
262 | |||
263 | it('Should block a remote server', async function () { | ||
264 | await addServerToAccountBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'localhost:9002') | ||
265 | }) | ||
266 | |||
267 | it('Should hide its videos', async function () { | ||
268 | const res = await getVideosListWithToken(servers[ 0 ].url, servers[ 0 ].accessToken) | ||
269 | |||
270 | const videos: Video[] = res.body.data | ||
271 | expect(videos).to.have.lengthOf(2) | ||
272 | |||
273 | const v1 = videos.find(v => v.name === 'video user 2') | ||
274 | const v2 = videos.find(v => v.name === 'video server 2') | ||
275 | |||
276 | expect(v1).to.be.undefined | ||
277 | expect(v2).to.be.undefined | ||
278 | }) | ||
279 | |||
280 | it('Should list all the videos with another user', async function () { | ||
281 | return checkAllVideos(servers[ 0 ].url, userToken1) | ||
282 | }) | ||
283 | |||
284 | it('Should hide its comments') | ||
285 | |||
286 | it('Should list blocked servers', async function () { | ||
287 | const res = await getServerBlocklistByAccount(servers[ 0 ].url, servers[ 0 ].accessToken, 0, 1, 'createdAt') | ||
288 | const blocks: ServerBlock[] = res.body.data | ||
289 | |||
290 | expect(res.body.total).to.equal(1) | ||
291 | |||
292 | const block = blocks[ 0 ] | ||
293 | expect(block.byAccount.displayName).to.equal('root') | ||
294 | expect(block.byAccount.name).to.equal('root') | ||
295 | expect(block.blockedServer.host).to.equal('localhost:9002') | ||
296 | }) | ||
297 | |||
298 | it('Should unblock the remote server', async function () { | ||
299 | await removeServerFromAccountBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'localhost:9002') | ||
300 | }) | ||
301 | |||
302 | it('Should display its videos', function () { | ||
303 | return checkAllVideos(servers[ 0 ].url, servers[ 0 ].accessToken) | ||
304 | }) | ||
305 | |||
306 | it('Should display its comments', function () { | ||
307 | return checkAllComments(servers[ 0 ].url, servers[ 0 ].accessToken, videoUUID1) | ||
308 | }) | ||
309 | }) | ||
310 | }) | ||
311 | |||
312 | describe('Server blocklist', function () { | ||
313 | |||
314 | describe('When managing account blocklist', function () { | ||
315 | it('Should list all videos', async function () { | ||
316 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
317 | await checkAllVideos(servers[ 0 ].url, token) | ||
318 | } | ||
319 | }) | ||
320 | |||
321 | it('Should list the comments', async function () { | ||
322 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
323 | await checkAllComments(servers[ 0 ].url, token, videoUUID1) | ||
324 | } | ||
325 | }) | ||
326 | |||
327 | it('Should block a remote account', async function () { | ||
328 | await addAccountToServerBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'user2@localhost:9002') | ||
329 | }) | ||
330 | |||
331 | it('Should hide its videos', async function () { | ||
332 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
333 | const res = await getVideosListWithToken(servers[ 0 ].url, token) | ||
334 | |||
335 | const videos: Video[] = res.body.data | ||
336 | expect(videos).to.have.lengthOf(3) | ||
337 | |||
338 | const v = videos.find(v => v.name === 'video user 2') | ||
339 | expect(v).to.be.undefined | ||
340 | } | ||
341 | }) | ||
342 | |||
343 | it('Should block a local account', async function () { | ||
344 | await addAccountToServerBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'user1') | ||
345 | }) | ||
346 | |||
347 | it('Should hide its videos', async function () { | ||
348 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
349 | const res = await getVideosListWithToken(servers[ 0 ].url, token) | ||
350 | |||
351 | const videos: Video[] = res.body.data | ||
352 | expect(videos).to.have.lengthOf(2) | ||
353 | |||
354 | const v = videos.find(v => v.name === 'video user 1') | ||
355 | expect(v).to.be.undefined | ||
356 | } | ||
357 | }) | ||
358 | |||
359 | it('Should hide its comments', async function () { | ||
360 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
361 | const resThreads = await getVideoCommentThreads(servers[ 0 ].url, videoUUID1, 0, 5, '-createdAt', token) | ||
362 | |||
363 | const threads: VideoComment[] = resThreads.body.data | ||
364 | expect(threads).to.have.lengthOf(1) | ||
365 | expect(threads[ 0 ].totalReplies).to.equal(0) | ||
366 | |||
367 | const t = threads.find(t => t.text === 'comment user 1') | ||
368 | expect(t).to.be.undefined | ||
369 | |||
370 | for (const thread of threads) { | ||
371 | const res = await getVideoThreadComments(servers[ 0 ].url, videoUUID1, thread.id, token) | ||
372 | |||
373 | const tree: VideoCommentThreadTree = res.body | ||
374 | expect(tree.children).to.have.lengthOf(0) | ||
375 | } | ||
376 | } | ||
377 | }) | ||
378 | |||
379 | it('Should list blocked accounts', async function () { | ||
380 | { | ||
381 | const res = await getAccountBlocklistByServer(servers[ 0 ].url, servers[ 0 ].accessToken, 0, 1, 'createdAt') | ||
382 | const blocks: AccountBlock[] = res.body.data | ||
383 | |||
384 | expect(res.body.total).to.equal(2) | ||
385 | |||
386 | const block = blocks[ 0 ] | ||
387 | expect(block.byAccount.displayName).to.equal('peertube') | ||
388 | expect(block.byAccount.name).to.equal('peertube') | ||
389 | expect(block.blockedAccount.displayName).to.equal('user2') | ||
390 | expect(block.blockedAccount.name).to.equal('user2') | ||
391 | expect(block.blockedAccount.host).to.equal('localhost:9002') | ||
392 | } | ||
393 | |||
394 | { | ||
395 | const res = await getAccountBlocklistByServer(servers[ 0 ].url, servers[ 0 ].accessToken, 1, 2, 'createdAt') | ||
396 | const blocks: AccountBlock[] = res.body.data | ||
397 | |||
398 | expect(res.body.total).to.equal(2) | ||
399 | |||
400 | const block = blocks[ 0 ] | ||
401 | expect(block.byAccount.displayName).to.equal('peertube') | ||
402 | expect(block.byAccount.name).to.equal('peertube') | ||
403 | expect(block.blockedAccount.displayName).to.equal('user1') | ||
404 | expect(block.blockedAccount.name).to.equal('user1') | ||
405 | expect(block.blockedAccount.host).to.equal('localhost:9001') | ||
406 | } | ||
407 | }) | ||
408 | |||
409 | it('Should unblock the remote account', async function () { | ||
410 | await removeAccountFromServerBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'user2@localhost:9002') | ||
411 | }) | ||
412 | |||
413 | it('Should display its videos', async function () { | ||
414 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
415 | const res = await getVideosListWithToken(servers[ 0 ].url, token) | ||
416 | |||
417 | const videos: Video[] = res.body.data | ||
418 | expect(videos).to.have.lengthOf(3) | ||
419 | |||
420 | const v = videos.find(v => v.name === 'video user 2') | ||
421 | expect(v).not.to.be.undefined | ||
422 | } | ||
423 | }) | ||
424 | |||
425 | it('Should unblock the local account', async function () { | ||
426 | await removeAccountFromServerBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'user1') | ||
427 | }) | ||
428 | |||
429 | it('Should display its comments', async function () { | ||
430 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
431 | await checkAllComments(servers[ 0 ].url, token, videoUUID1) | ||
432 | } | ||
433 | }) | ||
434 | }) | ||
435 | |||
436 | describe('When managing server blocklist', function () { | ||
437 | it('Should list all videos', async function () { | ||
438 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
439 | await checkAllVideos(servers[ 0 ].url, token) | ||
440 | } | ||
441 | }) | ||
442 | |||
443 | it('Should list the comments', async function () { | ||
444 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
445 | await checkAllComments(servers[ 0 ].url, token, videoUUID1) | ||
446 | } | ||
447 | }) | ||
448 | |||
449 | it('Should block a remote server', async function () { | ||
450 | await addServerToServerBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'localhost:9002') | ||
451 | }) | ||
452 | |||
453 | it('Should hide its videos', async function () { | ||
454 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
455 | const res1 = await getVideosList(servers[ 0 ].url) | ||
456 | const res2 = await getVideosListWithToken(servers[ 0 ].url, token) | ||
457 | |||
458 | for (const res of [ res1, res2 ]) { | ||
459 | const videos: Video[] = res.body.data | ||
460 | expect(videos).to.have.lengthOf(2) | ||
461 | |||
462 | const v1 = videos.find(v => v.name === 'video user 2') | ||
463 | const v2 = videos.find(v => v.name === 'video server 2') | ||
464 | |||
465 | expect(v1).to.be.undefined | ||
466 | expect(v2).to.be.undefined | ||
467 | } | ||
468 | } | ||
469 | }) | ||
470 | |||
471 | it('Should hide its comments') | ||
472 | |||
473 | it('Should list blocked servers', async function () { | ||
474 | const res = await getServerBlocklistByServer(servers[ 0 ].url, servers[ 0 ].accessToken, 0, 1, 'createdAt') | ||
475 | const blocks: ServerBlock[] = res.body.data | ||
476 | |||
477 | expect(res.body.total).to.equal(1) | ||
478 | |||
479 | const block = blocks[ 0 ] | ||
480 | expect(block.byAccount.displayName).to.equal('peertube') | ||
481 | expect(block.byAccount.name).to.equal('peertube') | ||
482 | expect(block.blockedServer.host).to.equal('localhost:9002') | ||
483 | }) | ||
484 | |||
485 | it('Should unblock the remote server', async function () { | ||
486 | await removeServerFromServerBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'localhost:9002') | ||
487 | }) | ||
488 | |||
489 | it('Should list all videos', async function () { | ||
490 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
491 | await checkAllVideos(servers[ 0 ].url, token) | ||
492 | } | ||
493 | }) | ||
494 | |||
495 | it('Should list the comments', async function () { | ||
496 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
497 | await checkAllComments(servers[ 0 ].url, token, videoUUID1) | ||
498 | } | ||
499 | }) | ||
500 | }) | ||
501 | }) | ||
502 | |||
503 | after(async function () { | ||
504 | killallServers(servers) | ||
505 | |||
506 | // Keep the logs if the test failed | ||
507 | if (this[ 'ok' ]) { | ||
508 | await flushTests() | ||
509 | } | ||
510 | }) | ||
511 | }) | ||
diff --git a/server/tests/api/users/index.ts b/server/tests/api/users/index.ts index 21d75da3e..0a1b8b0b2 100644 --- a/server/tests/api/users/index.ts +++ b/server/tests/api/users/index.ts | |||
@@ -1,3 +1,4 @@ | |||
1 | import './blocklist' | ||
1 | import './user-subscriptions' | 2 | import './user-subscriptions' |
2 | import './users' | 3 | import './users' |
3 | import './users-verification' | 4 | import './users-verification' |
diff --git a/server/tests/api/users/users-multiple-servers.ts b/server/tests/api/users/users-multiple-servers.ts index b67072851..d8699db17 100644 --- a/server/tests/api/users/users-multiple-servers.ts +++ b/server/tests/api/users/users-multiple-servers.ts | |||
@@ -148,6 +148,12 @@ describe('Test users with multiple servers', function () { | |||
148 | expect(rootServer1Get.displayName).to.equal('my super display name') | 148 | expect(rootServer1Get.displayName).to.equal('my super display name') |
149 | expect(rootServer1Get.description).to.equal('my super description updated') | 149 | expect(rootServer1Get.description).to.equal('my super description updated') |
150 | 150 | ||
151 | if (server.serverNumber === 1) { | ||
152 | expect(rootServer1Get.userId).to.be.a('number') | ||
153 | } else { | ||
154 | expect(rootServer1Get.userId).to.be.undefined | ||
155 | } | ||
156 | |||
151 | await testImage(server.url, 'avatar2-resized', rootServer1Get.avatar.path, '.png') | 157 | await testImage(server.url, 'avatar2-resized', rootServer1Get.avatar.path, '.png') |
152 | } | 158 | } |
153 | }) | 159 | }) |
diff --git a/server/tests/api/users/users.ts b/server/tests/api/users/users.ts index 8b9c6b455..513bca8a0 100644 --- a/server/tests/api/users/users.ts +++ b/server/tests/api/users/users.ts | |||
@@ -180,7 +180,7 @@ describe('Test users', function () { | |||
180 | it('Should be able to upload a video again') | 180 | it('Should be able to upload a video again') |
181 | 181 | ||
182 | it('Should be able to create a new user', async function () { | 182 | it('Should be able to create a new user', async function () { |
183 | await createUser(server.url, accessToken, user.username,user.password, 2 * 1024 * 1024) | 183 | await createUser(server.url, accessToken, user.username, user.password, 2 * 1024 * 1024) |
184 | }) | 184 | }) |
185 | 185 | ||
186 | it('Should be able to login with this user', async function () { | 186 | it('Should be able to login with this user', async function () { |
@@ -322,6 +322,40 @@ describe('Test users', function () { | |||
322 | expect(users[ 1 ].nsfwPolicy).to.equal('display') | 322 | expect(users[ 1 ].nsfwPolicy).to.equal('display') |
323 | }) | 323 | }) |
324 | 324 | ||
325 | it('Should search user by username', async function () { | ||
326 | const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 2, 'createdAt', 'oot') | ||
327 | const users = res.body.data as User[] | ||
328 | |||
329 | expect(res.body.total).to.equal(1) | ||
330 | expect(users.length).to.equal(1) | ||
331 | |||
332 | expect(users[ 0 ].username).to.equal('root') | ||
333 | }) | ||
334 | |||
335 | it('Should search user by email', async function () { | ||
336 | { | ||
337 | const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 2, 'createdAt', 'r_1@exam') | ||
338 | const users = res.body.data as User[] | ||
339 | |||
340 | expect(res.body.total).to.equal(1) | ||
341 | expect(users.length).to.equal(1) | ||
342 | |||
343 | expect(users[ 0 ].username).to.equal('user_1') | ||
344 | expect(users[ 0 ].email).to.equal('user_1@example.com') | ||
345 | } | ||
346 | |||
347 | { | ||
348 | const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 2, 'createdAt', 'example') | ||
349 | const users = res.body.data as User[] | ||
350 | |||
351 | expect(res.body.total).to.equal(2) | ||
352 | expect(users.length).to.equal(2) | ||
353 | |||
354 | expect(users[ 0 ].username).to.equal('root') | ||
355 | expect(users[ 1 ].username).to.equal('user_1') | ||
356 | } | ||
357 | }) | ||
358 | |||
325 | it('Should update my password', async function () { | 359 | it('Should update my password', async function () { |
326 | await updateMyUser({ | 360 | await updateMyUser({ |
327 | url: server.url, | 361 | url: server.url, |
diff --git a/server/tests/api/videos/index.ts b/server/tests/api/videos/index.ts index bf58f9c79..9bdb78491 100644 --- a/server/tests/api/videos/index.ts +++ b/server/tests/api/videos/index.ts | |||
@@ -14,4 +14,6 @@ import './video-nsfw' | |||
14 | import './video-privacy' | 14 | import './video-privacy' |
15 | import './video-schedule-update' | 15 | import './video-schedule-update' |
16 | import './video-transcoder' | 16 | import './video-transcoder' |
17 | import './videos-filter' | ||
18 | import './videos-history' | ||
17 | import './videos-overview' | 19 | import './videos-overview' |
diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts index 4553ee855..b9ace2885 100644 --- a/server/tests/api/videos/multiple-servers.ts +++ b/server/tests/api/videos/multiple-servers.ts | |||
@@ -987,19 +987,19 @@ describe('Test multiple servers', function () { | |||
987 | files: [ | 987 | files: [ |
988 | { | 988 | { |
989 | resolution: 720, | 989 | resolution: 720, |
990 | size: 36000 | 990 | size: 72000 |
991 | }, | 991 | }, |
992 | { | 992 | { |
993 | resolution: 480, | 993 | resolution: 480, |
994 | size: 21000 | 994 | size: 45000 |
995 | }, | 995 | }, |
996 | { | 996 | { |
997 | resolution: 360, | 997 | resolution: 360, |
998 | size: 17000 | 998 | size: 34600 |
999 | }, | 999 | }, |
1000 | { | 1000 | { |
1001 | resolution: 240, | 1001 | resolution: 240, |
1002 | size: 13000 | 1002 | size: 24770 |
1003 | } | 1003 | } |
1004 | ] | 1004 | ] |
1005 | } | 1005 | } |
diff --git a/server/tests/api/videos/single-server.ts b/server/tests/api/videos/single-server.ts index e3d62b7a0..089c3df25 100644 --- a/server/tests/api/videos/single-server.ts +++ b/server/tests/api/videos/single-server.ts | |||
@@ -118,7 +118,7 @@ describe('Test a single server', function () { | |||
118 | const categories = res.body | 118 | const categories = res.body |
119 | expect(Object.keys(categories)).to.have.length.above(10) | 119 | expect(Object.keys(categories)).to.have.length.above(10) |
120 | 120 | ||
121 | expect(categories[11]).to.equal('News') | 121 | expect(categories[11]).to.equal('News & Politics') |
122 | }) | 122 | }) |
123 | 123 | ||
124 | it('Should list video licences', async function () { | 124 | it('Should list video licences', async function () { |
diff --git a/server/tests/api/videos/video-imports.ts b/server/tests/api/videos/video-imports.ts index b7866d529..aaee79a4a 100644 --- a/server/tests/api/videos/video-imports.ts +++ b/server/tests/api/videos/video-imports.ts | |||
@@ -30,7 +30,7 @@ describe('Test video imports', function () { | |||
30 | const videoHttp: VideoDetails = resHttp.body | 30 | const videoHttp: VideoDetails = resHttp.body |
31 | 31 | ||
32 | expect(videoHttp.name).to.equal('small video - youtube') | 32 | expect(videoHttp.name).to.equal('small video - youtube') |
33 | expect(videoHttp.category.label).to.equal('News') | 33 | expect(videoHttp.category.label).to.equal('News & Politics') |
34 | expect(videoHttp.licence.label).to.equal('Attribution') | 34 | expect(videoHttp.licence.label).to.equal('Attribution') |
35 | expect(videoHttp.language.label).to.equal('Unknown') | 35 | expect(videoHttp.language.label).to.equal('Unknown') |
36 | expect(videoHttp.nsfw).to.be.false | 36 | expect(videoHttp.nsfw).to.be.false |
diff --git a/server/tests/api/videos/video-transcoder.ts b/server/tests/api/videos/video-transcoder.ts index 0f83d4d57..85795d2ed 100644 --- a/server/tests/api/videos/video-transcoder.ts +++ b/server/tests/api/videos/video-transcoder.ts | |||
@@ -4,8 +4,8 @@ import * as chai from 'chai' | |||
4 | import 'mocha' | 4 | import 'mocha' |
5 | import { omit } from 'lodash' | 5 | import { omit } from 'lodash' |
6 | import * as ffmpeg from 'fluent-ffmpeg' | 6 | import * as ffmpeg from 'fluent-ffmpeg' |
7 | import { VideoDetails, VideoState } from '../../../../shared/models/videos' | 7 | import { getMaxBitrate, VideoDetails, VideoResolution, VideoState } from '../../../../shared/models/videos' |
8 | import { getVideoFileFPS, audio } from '../../../helpers/ffmpeg-utils' | 8 | import { audio, getVideoFileBitrate, getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffmpeg-utils' |
9 | import { | 9 | import { |
10 | buildAbsoluteFixturePath, | 10 | buildAbsoluteFixturePath, |
11 | doubleFollow, | 11 | doubleFollow, |
@@ -18,10 +18,13 @@ import { | |||
18 | ServerInfo, | 18 | ServerInfo, |
19 | setAccessTokensToServers, | 19 | setAccessTokensToServers, |
20 | uploadVideo, | 20 | uploadVideo, |
21 | webtorrentAdd | 21 | webtorrentAdd, |
22 | generateHighBitrateVideo | ||
22 | } from '../../utils' | 23 | } from '../../utils' |
23 | import { join } from 'path' | 24 | import { join } from 'path' |
24 | import { waitJobs } from '../../utils/server/jobs' | 25 | import { waitJobs } from '../../utils/server/jobs' |
26 | import { pathExists } from 'fs-extra' | ||
27 | import { VIDEO_TRANSCODING_FPS } from '../../../../server/initializers/constants' | ||
25 | 28 | ||
26 | const expect = chai.expect | 29 | const expect = chai.expect |
27 | 30 | ||
@@ -121,7 +124,7 @@ describe('Test video transcoding', function () { | |||
121 | expect(videoDetails.files).to.have.lengthOf(4) | 124 | expect(videoDetails.files).to.have.lengthOf(4) |
122 | 125 | ||
123 | const path = join(root(), 'test2', 'videos', video.uuid + '-240.mp4') | 126 | const path = join(root(), 'test2', 'videos', video.uuid + '-240.mp4') |
124 | const probe = await audio.get(ffmpeg, path) | 127 | const probe = await audio.get(path) |
125 | 128 | ||
126 | if (probe.audioStream) { | 129 | if (probe.audioStream) { |
127 | expect(probe.audioStream[ 'codec_name' ]).to.be.equal('aac') | 130 | expect(probe.audioStream[ 'codec_name' ]).to.be.equal('aac') |
@@ -152,7 +155,7 @@ describe('Test video transcoding', function () { | |||
152 | 155 | ||
153 | expect(videoDetails.files).to.have.lengthOf(4) | 156 | expect(videoDetails.files).to.have.lengthOf(4) |
154 | const path = join(root(), 'test2', 'videos', video.uuid + '-240.mp4') | 157 | const path = join(root(), 'test2', 'videos', video.uuid + '-240.mp4') |
155 | const probe = await audio.get(ffmpeg, path) | 158 | const probe = await audio.get(path) |
156 | expect(probe).to.not.have.property('audioStream') | 159 | expect(probe).to.not.have.property('audioStream') |
157 | } | 160 | } |
158 | }) | 161 | }) |
@@ -177,9 +180,9 @@ describe('Test video transcoding', function () { | |||
177 | 180 | ||
178 | expect(videoDetails.files).to.have.lengthOf(4) | 181 | expect(videoDetails.files).to.have.lengthOf(4) |
179 | const fixturePath = buildAbsoluteFixturePath(videoAttributes.fixture) | 182 | const fixturePath = buildAbsoluteFixturePath(videoAttributes.fixture) |
180 | const fixtureVideoProbe = await audio.get(ffmpeg, fixturePath) | 183 | const fixtureVideoProbe = await audio.get(fixturePath) |
181 | const path = join(root(), 'test2', 'videos', video.uuid + '-240.mp4') | 184 | const path = join(root(), 'test2', 'videos', video.uuid + '-240.mp4') |
182 | const videoProbe = await audio.get(ffmpeg, path) | 185 | const videoProbe = await audio.get(path) |
183 | if (videoProbe.audioStream && fixtureVideoProbe.audioStream) { | 186 | if (videoProbe.audioStream && fixtureVideoProbe.audioStream) { |
184 | const toOmit = [ 'max_bit_rate', 'duration', 'duration_ts', 'nb_frames', 'start_time', 'start_pts' ] | 187 | const toOmit = [ 'max_bit_rate', 'duration', 'duration_ts', 'nb_frames', 'start_time', 'start_pts' ] |
185 | expect(omit(videoProbe.audioStream, toOmit)).to.be.deep.equal(omit(fixtureVideoProbe.audioStream, toOmit)) | 188 | expect(omit(videoProbe.audioStream, toOmit)).to.be.deep.equal(omit(fixtureVideoProbe.audioStream, toOmit)) |
@@ -228,7 +231,7 @@ describe('Test video transcoding', function () { | |||
228 | } | 231 | } |
229 | }) | 232 | }) |
230 | 233 | ||
231 | it('Should wait transcoding before publishing the video', async function () { | 234 | it('Should wait for transcoding before publishing the video', async function () { |
232 | this.timeout(80000) | 235 | this.timeout(80000) |
233 | 236 | ||
234 | { | 237 | { |
@@ -281,6 +284,45 @@ describe('Test video transcoding', function () { | |||
281 | } | 284 | } |
282 | }) | 285 | }) |
283 | 286 | ||
287 | it('Should respect maximum bitrate values', async function () { | ||
288 | this.timeout(160000) | ||
289 | |||
290 | let tempFixturePath: string | ||
291 | |||
292 | { | ||
293 | tempFixturePath = await generateHighBitrateVideo() | ||
294 | |||
295 | const bitrate = await getVideoFileBitrate(tempFixturePath) | ||
296 | expect(bitrate).to.be.above(getMaxBitrate(VideoResolution.H_1080P, 60, VIDEO_TRANSCODING_FPS)) | ||
297 | } | ||
298 | |||
299 | const videoAttributes = { | ||
300 | name: 'high bitrate video', | ||
301 | description: 'high bitrate video', | ||
302 | fixture: tempFixturePath | ||
303 | } | ||
304 | |||
305 | await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes) | ||
306 | |||
307 | await waitJobs(servers) | ||
308 | |||
309 | for (const server of servers) { | ||
310 | const res = await getVideosList(server.url) | ||
311 | |||
312 | const video = res.body.data.find(v => v.name === videoAttributes.name) | ||
313 | |||
314 | for (const resolution of ['240', '360', '480', '720', '1080']) { | ||
315 | const path = join(root(), 'test2', 'videos', video.uuid + '-' + resolution + '.mp4') | ||
316 | const bitrate = await getVideoFileBitrate(path) | ||
317 | const fps = await getVideoFileFPS(path) | ||
318 | const resolution2 = await getVideoFileResolution(path) | ||
319 | |||
320 | expect(resolution2.videoFileResolution.toString()).to.equal(resolution) | ||
321 | expect(bitrate).to.be.below(getMaxBitrate(resolution2.videoFileResolution, fps, VIDEO_TRANSCODING_FPS)) | ||
322 | } | ||
323 | } | ||
324 | }) | ||
325 | |||
284 | after(async function () { | 326 | after(async function () { |
285 | killallServers(servers) | 327 | killallServers(servers) |
286 | }) | 328 | }) |
diff --git a/server/tests/api/videos/videos-filter.ts b/server/tests/api/videos/videos-filter.ts new file mode 100644 index 000000000..a7588129f --- /dev/null +++ b/server/tests/api/videos/videos-filter.ts | |||
@@ -0,0 +1,130 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { | ||
6 | createUser, | ||
7 | doubleFollow, | ||
8 | flushAndRunMultipleServers, | ||
9 | flushTests, | ||
10 | killallServers, | ||
11 | makeGetRequest, | ||
12 | ServerInfo, | ||
13 | setAccessTokensToServers, | ||
14 | uploadVideo, | ||
15 | userLogin | ||
16 | } from '../../utils' | ||
17 | import { Video, VideoPrivacy } from '../../../../shared/models/videos' | ||
18 | import { UserRole } from '../../../../shared/models/users' | ||
19 | |||
20 | const expect = chai.expect | ||
21 | |||
22 | async function getVideosNames (server: ServerInfo, token: string, filter: string, statusCodeExpected = 200) { | ||
23 | const paths = [ | ||
24 | '/api/v1/video-channels/root_channel/videos', | ||
25 | '/api/v1/accounts/root/videos', | ||
26 | '/api/v1/videos', | ||
27 | '/api/v1/search/videos' | ||
28 | ] | ||
29 | |||
30 | const videosResults: Video[][] = [] | ||
31 | |||
32 | for (const path of paths) { | ||
33 | const res = await makeGetRequest({ | ||
34 | url: server.url, | ||
35 | path, | ||
36 | token, | ||
37 | query: { | ||
38 | sort: 'createdAt', | ||
39 | filter | ||
40 | }, | ||
41 | statusCodeExpected | ||
42 | }) | ||
43 | |||
44 | videosResults.push(res.body.data.map(v => v.name)) | ||
45 | } | ||
46 | |||
47 | return videosResults | ||
48 | } | ||
49 | |||
50 | describe('Test videos filter validator', function () { | ||
51 | let servers: ServerInfo[] | ||
52 | |||
53 | // --------------------------------------------------------------- | ||
54 | |||
55 | before(async function () { | ||
56 | this.timeout(120000) | ||
57 | |||
58 | await flushTests() | ||
59 | |||
60 | servers = await flushAndRunMultipleServers(2) | ||
61 | |||
62 | await setAccessTokensToServers(servers) | ||
63 | |||
64 | for (const server of servers) { | ||
65 | const moderator = { username: 'moderator', password: 'my super password' } | ||
66 | await createUser( | ||
67 | server.url, | ||
68 | server.accessToken, | ||
69 | moderator.username, | ||
70 | moderator.password, | ||
71 | undefined, | ||
72 | undefined, | ||
73 | UserRole.MODERATOR | ||
74 | ) | ||
75 | server['moderatorAccessToken'] = await userLogin(server, moderator) | ||
76 | |||
77 | await uploadVideo(server.url, server.accessToken, { name: 'public ' + server.serverNumber }) | ||
78 | |||
79 | { | ||
80 | const attributes = { name: 'unlisted ' + server.serverNumber, privacy: VideoPrivacy.UNLISTED } | ||
81 | await uploadVideo(server.url, server.accessToken, attributes) | ||
82 | } | ||
83 | |||
84 | { | ||
85 | const attributes = { name: 'private ' + server.serverNumber, privacy: VideoPrivacy.PRIVATE } | ||
86 | await uploadVideo(server.url, server.accessToken, attributes) | ||
87 | } | ||
88 | } | ||
89 | |||
90 | await doubleFollow(servers[0], servers[1]) | ||
91 | }) | ||
92 | |||
93 | describe('Check videos filter', function () { | ||
94 | |||
95 | it('Should display local videos', async function () { | ||
96 | for (const server of servers) { | ||
97 | const namesResults = await getVideosNames(server, server.accessToken, 'local') | ||
98 | for (const names of namesResults) { | ||
99 | expect(names).to.have.lengthOf(1) | ||
100 | expect(names[ 0 ]).to.equal('public ' + server.serverNumber) | ||
101 | } | ||
102 | } | ||
103 | }) | ||
104 | |||
105 | it('Should display all local videos by the admin or the moderator', async function () { | ||
106 | for (const server of servers) { | ||
107 | for (const token of [ server.accessToken, server['moderatorAccessToken'] ]) { | ||
108 | |||
109 | const namesResults = await getVideosNames(server, token, 'all-local') | ||
110 | for (const names of namesResults) { | ||
111 | expect(names).to.have.lengthOf(3) | ||
112 | |||
113 | expect(names[ 0 ]).to.equal('public ' + server.serverNumber) | ||
114 | expect(names[ 1 ]).to.equal('unlisted ' + server.serverNumber) | ||
115 | expect(names[ 2 ]).to.equal('private ' + server.serverNumber) | ||
116 | } | ||
117 | } | ||
118 | } | ||
119 | }) | ||
120 | }) | ||
121 | |||
122 | after(async function () { | ||
123 | killallServers(servers) | ||
124 | |||
125 | // Keep the logs if the test failed | ||
126 | if (this['ok']) { | ||
127 | await flushTests() | ||
128 | } | ||
129 | }) | ||
130 | }) | ||
diff --git a/server/tests/api/videos/videos-history.ts b/server/tests/api/videos/videos-history.ts new file mode 100644 index 000000000..6d289b288 --- /dev/null +++ b/server/tests/api/videos/videos-history.ts | |||
@@ -0,0 +1,128 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { | ||
6 | flushTests, | ||
7 | getVideosListWithToken, | ||
8 | getVideoWithToken, | ||
9 | killallServers, makePutBodyRequest, | ||
10 | runServer, searchVideoWithToken, | ||
11 | ServerInfo, | ||
12 | setAccessTokensToServers, | ||
13 | uploadVideo | ||
14 | } from '../../utils' | ||
15 | import { Video, VideoDetails } from '../../../../shared/models/videos' | ||
16 | import { userWatchVideo } from '../../utils/videos/video-history' | ||
17 | |||
18 | const expect = chai.expect | ||
19 | |||
20 | describe('Test videos history', function () { | ||
21 | let server: ServerInfo = null | ||
22 | let video1UUID: string | ||
23 | let video2UUID: string | ||
24 | let video3UUID: string | ||
25 | |||
26 | before(async function () { | ||
27 | this.timeout(30000) | ||
28 | |||
29 | await flushTests() | ||
30 | |||
31 | server = await runServer(1) | ||
32 | |||
33 | await setAccessTokensToServers([ server ]) | ||
34 | |||
35 | { | ||
36 | const res = await uploadVideo(server.url, server.accessToken, { name: 'video 1' }) | ||
37 | video1UUID = res.body.video.uuid | ||
38 | } | ||
39 | |||
40 | { | ||
41 | const res = await uploadVideo(server.url, server.accessToken, { name: 'video 2' }) | ||
42 | video2UUID = res.body.video.uuid | ||
43 | } | ||
44 | |||
45 | { | ||
46 | const res = await uploadVideo(server.url, server.accessToken, { name: 'video 3' }) | ||
47 | video3UUID = res.body.video.uuid | ||
48 | } | ||
49 | }) | ||
50 | |||
51 | it('Should get videos, without watching history', async function () { | ||
52 | const res = await getVideosListWithToken(server.url, server.accessToken) | ||
53 | const videos: Video[] = res.body.data | ||
54 | |||
55 | for (const video of videos) { | ||
56 | const resDetail = await getVideoWithToken(server.url, server.accessToken, video.id) | ||
57 | const videoDetails: VideoDetails = resDetail.body | ||
58 | |||
59 | expect(video.userHistory).to.be.undefined | ||
60 | expect(videoDetails.userHistory).to.be.undefined | ||
61 | } | ||
62 | }) | ||
63 | |||
64 | it('Should watch the first and second video', async function () { | ||
65 | await userWatchVideo(server.url, server.accessToken, video1UUID, 3) | ||
66 | await userWatchVideo(server.url, server.accessToken, video2UUID, 8) | ||
67 | }) | ||
68 | |||
69 | it('Should return the correct history when listing, searching and getting videos', async function () { | ||
70 | const videosOfVideos: Video[][] = [] | ||
71 | |||
72 | { | ||
73 | const res = await getVideosListWithToken(server.url, server.accessToken) | ||
74 | videosOfVideos.push(res.body.data) | ||
75 | } | ||
76 | |||
77 | { | ||
78 | const res = await searchVideoWithToken(server.url, 'video', server.accessToken) | ||
79 | videosOfVideos.push(res.body.data) | ||
80 | } | ||
81 | |||
82 | for (const videos of videosOfVideos) { | ||
83 | const video1 = videos.find(v => v.uuid === video1UUID) | ||
84 | const video2 = videos.find(v => v.uuid === video2UUID) | ||
85 | const video3 = videos.find(v => v.uuid === video3UUID) | ||
86 | |||
87 | expect(video1.userHistory).to.not.be.undefined | ||
88 | expect(video1.userHistory.currentTime).to.equal(3) | ||
89 | |||
90 | expect(video2.userHistory).to.not.be.undefined | ||
91 | expect(video2.userHistory.currentTime).to.equal(8) | ||
92 | |||
93 | expect(video3.userHistory).to.be.undefined | ||
94 | } | ||
95 | |||
96 | { | ||
97 | const resDetail = await getVideoWithToken(server.url, server.accessToken, video1UUID) | ||
98 | const videoDetails: VideoDetails = resDetail.body | ||
99 | |||
100 | expect(videoDetails.userHistory).to.not.be.undefined | ||
101 | expect(videoDetails.userHistory.currentTime).to.equal(3) | ||
102 | } | ||
103 | |||
104 | { | ||
105 | const resDetail = await getVideoWithToken(server.url, server.accessToken, video2UUID) | ||
106 | const videoDetails: VideoDetails = resDetail.body | ||
107 | |||
108 | expect(videoDetails.userHistory).to.not.be.undefined | ||
109 | expect(videoDetails.userHistory.currentTime).to.equal(8) | ||
110 | } | ||
111 | |||
112 | { | ||
113 | const resDetail = await getVideoWithToken(server.url, server.accessToken, video3UUID) | ||
114 | const videoDetails: VideoDetails = resDetail.body | ||
115 | |||
116 | expect(videoDetails.userHistory).to.be.undefined | ||
117 | } | ||
118 | }) | ||
119 | |||
120 | after(async function () { | ||
121 | killallServers([ server ]) | ||
122 | |||
123 | // Keep the logs if the test failed | ||
124 | if (this['ok']) { | ||
125 | await flushTests() | ||
126 | } | ||
127 | }) | ||
128 | }) | ||
diff --git a/server/tests/cli/optimize-old-videos.ts b/server/tests/cli/optimize-old-videos.ts new file mode 100644 index 000000000..66dd39cce --- /dev/null +++ b/server/tests/cli/optimize-old-videos.ts | |||
@@ -0,0 +1,120 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import 'mocha' | ||
4 | import * as chai from 'chai' | ||
5 | import { getMaxBitrate, Video, VideoDetails, VideoResolution } from '../../../shared/models/videos' | ||
6 | import { | ||
7 | doubleFollow, | ||
8 | execCLI, | ||
9 | flushAndRunMultipleServers, | ||
10 | flushTests, generateHighBitrateVideo, | ||
11 | getEnvCli, | ||
12 | getVideo, | ||
13 | getVideosList, | ||
14 | killallServers, root, | ||
15 | ServerInfo, | ||
16 | setAccessTokensToServers, | ||
17 | uploadVideo, viewVideo, wait | ||
18 | } from '../utils' | ||
19 | import { waitJobs } from '../utils/server/jobs' | ||
20 | import { getVideoFileBitrate, getVideoFileFPS, getVideoFileResolution } from '../../helpers/ffmpeg-utils' | ||
21 | import { VIDEO_TRANSCODING_FPS } from '../../initializers' | ||
22 | import { join } from 'path' | ||
23 | |||
24 | const expect = chai.expect | ||
25 | |||
26 | describe('Test optimize old videos', function () { | ||
27 | let servers: ServerInfo[] = [] | ||
28 | let video1UUID: string | ||
29 | let video2UUID: string | ||
30 | |||
31 | before(async function () { | ||
32 | this.timeout(200000) | ||
33 | |||
34 | await flushTests() | ||
35 | |||
36 | // Run server 2 to have transcoding enabled | ||
37 | servers = await flushAndRunMultipleServers(2) | ||
38 | await setAccessTokensToServers(servers) | ||
39 | |||
40 | await doubleFollow(servers[0], servers[1]) | ||
41 | |||
42 | let tempFixturePath: string | ||
43 | |||
44 | { | ||
45 | tempFixturePath = await generateHighBitrateVideo() | ||
46 | |||
47 | const bitrate = await getVideoFileBitrate(tempFixturePath) | ||
48 | expect(bitrate).to.be.above(getMaxBitrate(VideoResolution.H_1080P, 60, VIDEO_TRANSCODING_FPS)) | ||
49 | } | ||
50 | |||
51 | // Upload two videos for our needs | ||
52 | const res1 = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video1', fixture: tempFixturePath }) | ||
53 | video1UUID = res1.body.video.uuid | ||
54 | const res2 = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video2', fixture: tempFixturePath }) | ||
55 | video2UUID = res2.body.video.uuid | ||
56 | |||
57 | await waitJobs(servers) | ||
58 | }) | ||
59 | |||
60 | it('Should have two video files on each server', async function () { | ||
61 | this.timeout(30000) | ||
62 | |||
63 | for (const server of servers) { | ||
64 | const res = await getVideosList(server.url) | ||
65 | const videos = res.body.data | ||
66 | expect(videos).to.have.lengthOf(2) | ||
67 | |||
68 | for (const video of videos) { | ||
69 | const res2 = await getVideo(server.url, video.uuid) | ||
70 | const videoDetail: VideoDetails = res2.body | ||
71 | expect(videoDetail.files).to.have.lengthOf(1) | ||
72 | } | ||
73 | } | ||
74 | }) | ||
75 | |||
76 | it('Should run optimize script', async function () { | ||
77 | this.timeout(120000) | ||
78 | |||
79 | const env = getEnvCli(servers[0]) | ||
80 | await execCLI(`${env} npm run optimize-old-videos`) | ||
81 | |||
82 | await waitJobs(servers) | ||
83 | |||
84 | for (const server of servers) { | ||
85 | const res = await getVideosList(server.url) | ||
86 | const videos: Video[] = res.body.data | ||
87 | |||
88 | expect(videos).to.have.lengthOf(2) | ||
89 | |||
90 | for (const video of videos) { | ||
91 | await viewVideo(server.url, video.uuid) | ||
92 | |||
93 | // Refresh video | ||
94 | await waitJobs(servers) | ||
95 | await wait(5000) | ||
96 | await waitJobs(servers) | ||
97 | |||
98 | const res2 = await getVideo(server.url, video.uuid) | ||
99 | const videosDetails: VideoDetails = res2.body | ||
100 | |||
101 | expect(videosDetails.files).to.have.lengthOf(1) | ||
102 | const file = videosDetails.files[0] | ||
103 | |||
104 | expect(file.size).to.be.below(5000000) | ||
105 | |||
106 | const path = join(root(), 'test1', 'videos', video.uuid + '-' + file.resolution.id + '.mp4') | ||
107 | const bitrate = await getVideoFileBitrate(path) | ||
108 | const fps = await getVideoFileFPS(path) | ||
109 | const resolution = await getVideoFileResolution(path) | ||
110 | |||
111 | expect(resolution.videoFileResolution).to.equal(file.resolution.id) | ||
112 | expect(bitrate).to.be.below(getMaxBitrate(resolution.videoFileResolution, fps, VIDEO_TRANSCODING_FPS)) | ||
113 | } | ||
114 | } | ||
115 | }) | ||
116 | |||
117 | after(async function () { | ||
118 | killallServers(servers) | ||
119 | }) | ||
120 | }) | ||
diff --git a/server/tests/helpers/core-utils.ts b/server/tests/helpers/core-utils.ts new file mode 100644 index 000000000..a6d829a9f --- /dev/null +++ b/server/tests/helpers/core-utils.ts | |||
@@ -0,0 +1,48 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { | ||
6 | parseBytes | ||
7 | } from '../../helpers/core-utils' | ||
8 | |||
9 | const expect = chai.expect | ||
10 | |||
11 | describe('Parse Bytes', function () { | ||
12 | it('Should pass when given valid value', async function () { | ||
13 | // just return it | ||
14 | expect(parseBytes(1024)).to.be.eq(1024) | ||
15 | expect(parseBytes(1048576)).to.be.eq(1048576) | ||
16 | expect(parseBytes('1024')).to.be.eq(1024) | ||
17 | expect(parseBytes('1048576')).to.be.eq(1048576) | ||
18 | |||
19 | // sizes | ||
20 | expect(parseBytes('1B')).to.be.eq(1024) | ||
21 | expect(parseBytes('1MB')).to.be.eq(1048576) | ||
22 | expect(parseBytes('1GB')).to.be.eq(1073741824) | ||
23 | expect(parseBytes('1TB')).to.be.eq(1099511627776) | ||
24 | |||
25 | expect(parseBytes('5GB')).to.be.eq(5368709120) | ||
26 | expect(parseBytes('5TB')).to.be.eq(5497558138880) | ||
27 | |||
28 | expect(parseBytes('1024B')).to.be.eq(1048576) | ||
29 | expect(parseBytes('1024MB')).to.be.eq(1073741824) | ||
30 | expect(parseBytes('1024GB')).to.be.eq(1099511627776) | ||
31 | expect(parseBytes('1024TB')).to.be.eq(1125899906842624) | ||
32 | |||
33 | // with whitespace | ||
34 | expect(parseBytes('1 GB')).to.be.eq(1073741824) | ||
35 | expect(parseBytes('1\tGB')).to.be.eq(1073741824) | ||
36 | |||
37 | // sum value | ||
38 | expect(parseBytes('1TB 1024MB')).to.be.eq(1100585369600) | ||
39 | expect(parseBytes('4GB 1024MB')).to.be.eq(5368709120) | ||
40 | expect(parseBytes('4TB 1024GB')).to.be.eq(5497558138880) | ||
41 | expect(parseBytes('4TB 1024GB 0MB')).to.be.eq(5497558138880) | ||
42 | expect(parseBytes('1024TB 1024GB 1024MB')).to.be.eq(1127000492212224) | ||
43 | }) | ||
44 | |||
45 | it('Should be invalid when given invalid value', async function () { | ||
46 | expect(parseBytes('6GB 1GB')).to.be.eq(6) | ||
47 | }) | ||
48 | }) | ||
diff --git a/server/tests/helpers/index.ts b/server/tests/helpers/index.ts new file mode 100644 index 000000000..40c7dc70e --- /dev/null +++ b/server/tests/helpers/index.ts | |||
@@ -0,0 +1 @@ | |||
import './core-utils' | |||
diff --git a/server/tests/utils/miscs/miscs.ts b/server/tests/utils/miscs/miscs.ts index b2f80e9b1..589daa420 100644 --- a/server/tests/utils/miscs/miscs.ts +++ b/server/tests/utils/miscs/miscs.ts | |||
@@ -4,7 +4,8 @@ import * as chai from 'chai' | |||
4 | import { isAbsolute, join } from 'path' | 4 | import { isAbsolute, join } from 'path' |
5 | import * as request from 'supertest' | 5 | import * as request from 'supertest' |
6 | import * as WebTorrent from 'webtorrent' | 6 | import * as WebTorrent from 'webtorrent' |
7 | import { readFile } from 'fs-extra' | 7 | import { pathExists, readFile } from 'fs-extra' |
8 | import * as ffmpeg from 'fluent-ffmpeg' | ||
8 | 9 | ||
9 | const expect = chai.expect | 10 | const expect = chai.expect |
10 | let webtorrent = new WebTorrent() | 11 | let webtorrent = new WebTorrent() |
@@ -51,14 +52,41 @@ async function testImage (url: string, imageName: string, imagePath: string, ext | |||
51 | expect(data.length).to.be.below(maxLength) | 52 | expect(data.length).to.be.below(maxLength) |
52 | } | 53 | } |
53 | 54 | ||
54 | function buildAbsoluteFixturePath (path: string) { | 55 | function buildAbsoluteFixturePath (path: string, customTravisPath = false) { |
55 | if (isAbsolute(path)) { | 56 | if (isAbsolute(path)) { |
56 | return path | 57 | return path |
57 | } | 58 | } |
58 | 59 | ||
60 | if (customTravisPath && process.env.TRAVIS) return join(process.env.HOME, 'fixtures', path) | ||
61 | |||
59 | return join(__dirname, '..', '..', 'fixtures', path) | 62 | return join(__dirname, '..', '..', 'fixtures', path) |
60 | } | 63 | } |
61 | 64 | ||
65 | async function generateHighBitrateVideo () { | ||
66 | const tempFixturePath = buildAbsoluteFixturePath('video_high_bitrate_1080p.mp4', true) | ||
67 | |||
68 | const exists = await pathExists(tempFixturePath) | ||
69 | if (!exists) { | ||
70 | |||
71 | // Generate a random, high bitrate video on the fly, so we don't have to include | ||
72 | // a large file in the repo. The video needs to have a certain minimum length so | ||
73 | // that FFmpeg properly applies bitrate limits. | ||
74 | // https://stackoverflow.com/a/15795112 | ||
75 | return new Promise<string>(async (res, rej) => { | ||
76 | ffmpeg() | ||
77 | .outputOptions([ '-f rawvideo', '-video_size 1920x1080', '-i /dev/urandom' ]) | ||
78 | .outputOptions([ '-ac 2', '-f s16le', '-i /dev/urandom', '-t 10' ]) | ||
79 | .outputOptions([ '-maxrate 10M', '-bufsize 10M' ]) | ||
80 | .output(tempFixturePath) | ||
81 | .on('error', rej) | ||
82 | .on('end', () => res(tempFixturePath)) | ||
83 | .run() | ||
84 | }) | ||
85 | } | ||
86 | |||
87 | return tempFixturePath | ||
88 | } | ||
89 | |||
62 | // --------------------------------------------------------------------------- | 90 | // --------------------------------------------------------------------------- |
63 | 91 | ||
64 | export { | 92 | export { |
@@ -68,5 +96,6 @@ export { | |||
68 | immutableAssign, | 96 | immutableAssign, |
69 | testImage, | 97 | testImage, |
70 | buildAbsoluteFixturePath, | 98 | buildAbsoluteFixturePath, |
71 | root | 99 | root, |
100 | generateHighBitrateVideo | ||
72 | } | 101 | } |
diff --git a/server/tests/utils/requests/requests.ts b/server/tests/utils/requests/requests.ts index 27a529eda..5796540f7 100644 --- a/server/tests/utils/requests/requests.ts +++ b/server/tests/utils/requests/requests.ts | |||
@@ -37,9 +37,7 @@ function makeDeleteRequest (options: { | |||
37 | 37 | ||
38 | if (options.token) req.set('Authorization', 'Bearer ' + options.token) | 38 | if (options.token) req.set('Authorization', 'Bearer ' + options.token) |
39 | 39 | ||
40 | return req | 40 | return req.expect(options.statusCodeExpected) |
41 | .expect('Content-Type', /json/) | ||
42 | .expect(options.statusCodeExpected) | ||
43 | } | 41 | } |
44 | 42 | ||
45 | function makeUploadRequest (options: { | 43 | function makeUploadRequest (options: { |
diff --git a/server/tests/utils/server/follows.ts b/server/tests/utils/server/follows.ts index 8a65a958b..7741757a6 100644 --- a/server/tests/utils/server/follows.ts +++ b/server/tests/utils/server/follows.ts | |||
@@ -2,7 +2,7 @@ import * as request from 'supertest' | |||
2 | import { ServerInfo } from './servers' | 2 | import { ServerInfo } from './servers' |
3 | import { waitJobs } from './jobs' | 3 | import { waitJobs } from './jobs' |
4 | 4 | ||
5 | function getFollowersListPaginationAndSort (url: string, start: number, count: number, sort: string) { | 5 | function getFollowersListPaginationAndSort (url: string, start: number, count: number, sort: string, search?: string) { |
6 | const path = '/api/v1/server/followers' | 6 | const path = '/api/v1/server/followers' |
7 | 7 | ||
8 | return request(url) | 8 | return request(url) |
@@ -10,12 +10,13 @@ function getFollowersListPaginationAndSort (url: string, start: number, count: n | |||
10 | .query({ start }) | 10 | .query({ start }) |
11 | .query({ count }) | 11 | .query({ count }) |
12 | .query({ sort }) | 12 | .query({ sort }) |
13 | .query({ search }) | ||
13 | .set('Accept', 'application/json') | 14 | .set('Accept', 'application/json') |
14 | .expect(200) | 15 | .expect(200) |
15 | .expect('Content-Type', /json/) | 16 | .expect('Content-Type', /json/) |
16 | } | 17 | } |
17 | 18 | ||
18 | function getFollowingListPaginationAndSort (url: string, start: number, count: number, sort: string) { | 19 | function getFollowingListPaginationAndSort (url: string, start: number, count: number, sort: string, search?: string) { |
19 | const path = '/api/v1/server/following' | 20 | const path = '/api/v1/server/following' |
20 | 21 | ||
21 | return request(url) | 22 | return request(url) |
@@ -23,6 +24,7 @@ function getFollowingListPaginationAndSort (url: string, start: number, count: n | |||
23 | .query({ start }) | 24 | .query({ start }) |
24 | .query({ count }) | 25 | .query({ count }) |
25 | .query({ sort }) | 26 | .query({ sort }) |
27 | .query({ search }) | ||
26 | .set('Accept', 'application/json') | 28 | .set('Accept', 'application/json') |
27 | .expect(200) | 29 | .expect(200) |
28 | .expect('Content-Type', /json/) | 30 | .expect('Content-Type', /json/) |
diff --git a/server/tests/utils/users/blocklist.ts b/server/tests/utils/users/blocklist.ts new file mode 100644 index 000000000..35b537571 --- /dev/null +++ b/server/tests/utils/users/blocklist.ts | |||
@@ -0,0 +1,198 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import { makeDeleteRequest, makePostBodyRequest } from '../index' | ||
4 | import { makeGetRequest } from '../requests/requests' | ||
5 | |||
6 | function getAccountBlocklistByAccount ( | ||
7 | url: string, | ||
8 | token: string, | ||
9 | start: number, | ||
10 | count: number, | ||
11 | sort = '-createdAt', | ||
12 | statusCodeExpected = 200 | ||
13 | ) { | ||
14 | const path = '/api/v1/users/me/blocklist/accounts' | ||
15 | |||
16 | return makeGetRequest({ | ||
17 | url, | ||
18 | token, | ||
19 | query: { start, count, sort }, | ||
20 | path, | ||
21 | statusCodeExpected | ||
22 | }) | ||
23 | } | ||
24 | |||
25 | function addAccountToAccountBlocklist (url: string, token: string, accountToBlock: string, statusCodeExpected = 204) { | ||
26 | const path = '/api/v1/users/me/blocklist/accounts' | ||
27 | |||
28 | return makePostBodyRequest({ | ||
29 | url, | ||
30 | path, | ||
31 | token, | ||
32 | fields: { | ||
33 | accountName: accountToBlock | ||
34 | }, | ||
35 | statusCodeExpected | ||
36 | }) | ||
37 | } | ||
38 | |||
39 | function removeAccountFromAccountBlocklist (url: string, token: string, accountToUnblock: string, statusCodeExpected = 204) { | ||
40 | const path = '/api/v1/users/me/blocklist/accounts/' + accountToUnblock | ||
41 | |||
42 | return makeDeleteRequest({ | ||
43 | url, | ||
44 | path, | ||
45 | token, | ||
46 | statusCodeExpected | ||
47 | }) | ||
48 | } | ||
49 | |||
50 | function getServerBlocklistByAccount ( | ||
51 | url: string, | ||
52 | token: string, | ||
53 | start: number, | ||
54 | count: number, | ||
55 | sort = '-createdAt', | ||
56 | statusCodeExpected = 200 | ||
57 | ) { | ||
58 | const path = '/api/v1/users/me/blocklist/servers' | ||
59 | |||
60 | return makeGetRequest({ | ||
61 | url, | ||
62 | token, | ||
63 | query: { start, count, sort }, | ||
64 | path, | ||
65 | statusCodeExpected | ||
66 | }) | ||
67 | } | ||
68 | |||
69 | function addServerToAccountBlocklist (url: string, token: string, serverToBlock: string, statusCodeExpected = 204) { | ||
70 | const path = '/api/v1/users/me/blocklist/servers' | ||
71 | |||
72 | return makePostBodyRequest({ | ||
73 | url, | ||
74 | path, | ||
75 | token, | ||
76 | fields: { | ||
77 | host: serverToBlock | ||
78 | }, | ||
79 | statusCodeExpected | ||
80 | }) | ||
81 | } | ||
82 | |||
83 | function removeServerFromAccountBlocklist (url: string, token: string, serverToBlock: string, statusCodeExpected = 204) { | ||
84 | const path = '/api/v1/users/me/blocklist/servers/' + serverToBlock | ||
85 | |||
86 | return makeDeleteRequest({ | ||
87 | url, | ||
88 | path, | ||
89 | token, | ||
90 | statusCodeExpected | ||
91 | }) | ||
92 | } | ||
93 | |||
94 | function getAccountBlocklistByServer ( | ||
95 | url: string, | ||
96 | token: string, | ||
97 | start: number, | ||
98 | count: number, | ||
99 | sort = '-createdAt', | ||
100 | statusCodeExpected = 200 | ||
101 | ) { | ||
102 | const path = '/api/v1/server/blocklist/accounts' | ||
103 | |||
104 | return makeGetRequest({ | ||
105 | url, | ||
106 | token, | ||
107 | query: { start, count, sort }, | ||
108 | path, | ||
109 | statusCodeExpected | ||
110 | }) | ||
111 | } | ||
112 | |||
113 | function addAccountToServerBlocklist (url: string, token: string, accountToBlock: string, statusCodeExpected = 204) { | ||
114 | const path = '/api/v1/server/blocklist/accounts' | ||
115 | |||
116 | return makePostBodyRequest({ | ||
117 | url, | ||
118 | path, | ||
119 | token, | ||
120 | fields: { | ||
121 | accountName: accountToBlock | ||
122 | }, | ||
123 | statusCodeExpected | ||
124 | }) | ||
125 | } | ||
126 | |||
127 | function removeAccountFromServerBlocklist (url: string, token: string, accountToUnblock: string, statusCodeExpected = 204) { | ||
128 | const path = '/api/v1/server/blocklist/accounts/' + accountToUnblock | ||
129 | |||
130 | return makeDeleteRequest({ | ||
131 | url, | ||
132 | path, | ||
133 | token, | ||
134 | statusCodeExpected | ||
135 | }) | ||
136 | } | ||
137 | |||
138 | function getServerBlocklistByServer ( | ||
139 | url: string, | ||
140 | token: string, | ||
141 | start: number, | ||
142 | count: number, | ||
143 | sort = '-createdAt', | ||
144 | statusCodeExpected = 200 | ||
145 | ) { | ||
146 | const path = '/api/v1/server/blocklist/servers' | ||
147 | |||
148 | return makeGetRequest({ | ||
149 | url, | ||
150 | token, | ||
151 | query: { start, count, sort }, | ||
152 | path, | ||
153 | statusCodeExpected | ||
154 | }) | ||
155 | } | ||
156 | |||
157 | function addServerToServerBlocklist (url: string, token: string, serverToBlock: string, statusCodeExpected = 204) { | ||
158 | const path = '/api/v1/server/blocklist/servers' | ||
159 | |||
160 | return makePostBodyRequest({ | ||
161 | url, | ||
162 | path, | ||
163 | token, | ||
164 | fields: { | ||
165 | host: serverToBlock | ||
166 | }, | ||
167 | statusCodeExpected | ||
168 | }) | ||
169 | } | ||
170 | |||
171 | function removeServerFromServerBlocklist (url: string, token: string, serverToBlock: string, statusCodeExpected = 204) { | ||
172 | const path = '/api/v1/server/blocklist/servers/' + serverToBlock | ||
173 | |||
174 | return makeDeleteRequest({ | ||
175 | url, | ||
176 | path, | ||
177 | token, | ||
178 | statusCodeExpected | ||
179 | }) | ||
180 | } | ||
181 | |||
182 | // --------------------------------------------------------------------------- | ||
183 | |||
184 | export { | ||
185 | getAccountBlocklistByAccount, | ||
186 | addAccountToAccountBlocklist, | ||
187 | removeAccountFromAccountBlocklist, | ||
188 | getServerBlocklistByAccount, | ||
189 | addServerToAccountBlocklist, | ||
190 | removeServerFromAccountBlocklist, | ||
191 | |||
192 | getAccountBlocklistByServer, | ||
193 | addAccountToServerBlocklist, | ||
194 | removeAccountFromServerBlocklist, | ||
195 | getServerBlocklistByServer, | ||
196 | addServerToServerBlocklist, | ||
197 | removeServerFromServerBlocklist | ||
198 | } | ||
diff --git a/server/tests/utils/users/users.ts b/server/tests/utils/users/users.ts index 41d8ce265..d77233d62 100644 --- a/server/tests/utils/users/users.ts +++ b/server/tests/utils/users/users.ts | |||
@@ -112,7 +112,7 @@ function getUsersList (url: string, accessToken: string) { | |||
112 | .expect('Content-Type', /json/) | 112 | .expect('Content-Type', /json/) |
113 | } | 113 | } |
114 | 114 | ||
115 | function getUsersListPaginationAndSort (url: string, accessToken: string, start: number, count: number, sort: string) { | 115 | function getUsersListPaginationAndSort (url: string, accessToken: string, start: number, count: number, sort: string, search?: string) { |
116 | const path = '/api/v1/users' | 116 | const path = '/api/v1/users' |
117 | 117 | ||
118 | return request(url) | 118 | return request(url) |
@@ -120,6 +120,7 @@ function getUsersListPaginationAndSort (url: string, accessToken: string, start: | |||
120 | .query({ start }) | 120 | .query({ start }) |
121 | .query({ count }) | 121 | .query({ count }) |
122 | .query({ sort }) | 122 | .query({ sort }) |
123 | .query({ search }) | ||
123 | .set('Accept', 'application/json') | 124 | .set('Accept', 'application/json') |
124 | .set('Authorization', 'Bearer ' + accessToken) | 125 | .set('Authorization', 'Bearer ' + accessToken) |
125 | .expect(200) | 126 | .expect(200) |
diff --git a/server/tests/utils/videos/video-comments.ts b/server/tests/utils/videos/video-comments.ts index 1b9ee452e..7d4cae364 100644 --- a/server/tests/utils/videos/video-comments.ts +++ b/server/tests/utils/videos/video-comments.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import * as request from 'supertest' | 1 | import * as request from 'supertest' |
2 | import { makeDeleteRequest } from '../' | 2 | import { makeDeleteRequest } from '../' |
3 | 3 | ||
4 | function getVideoCommentThreads (url: string, videoId: number | string, start: number, count: number, sort?: string) { | 4 | function getVideoCommentThreads (url: string, videoId: number | string, start: number, count: number, sort?: string, token?: string) { |
5 | const path = '/api/v1/videos/' + videoId + '/comment-threads' | 5 | const path = '/api/v1/videos/' + videoId + '/comment-threads' |
6 | 6 | ||
7 | const req = request(url) | 7 | const req = request(url) |
@@ -10,20 +10,24 @@ function getVideoCommentThreads (url: string, videoId: number | string, start: n | |||
10 | .query({ count: count }) | 10 | .query({ count: count }) |
11 | 11 | ||
12 | if (sort) req.query({ sort }) | 12 | if (sort) req.query({ sort }) |
13 | if (token) req.set('Authorization', 'Bearer ' + token) | ||
13 | 14 | ||
14 | return req.set('Accept', 'application/json') | 15 | return req.set('Accept', 'application/json') |
15 | .expect(200) | 16 | .expect(200) |
16 | .expect('Content-Type', /json/) | 17 | .expect('Content-Type', /json/) |
17 | } | 18 | } |
18 | 19 | ||
19 | function getVideoThreadComments (url: string, videoId: number | string, threadId: number) { | 20 | function getVideoThreadComments (url: string, videoId: number | string, threadId: number, token?: string) { |
20 | const path = '/api/v1/videos/' + videoId + '/comment-threads/' + threadId | 21 | const path = '/api/v1/videos/' + videoId + '/comment-threads/' + threadId |
21 | 22 | ||
22 | return request(url) | 23 | const req = request(url) |
23 | .get(path) | 24 | .get(path) |
24 | .set('Accept', 'application/json') | 25 | .set('Accept', 'application/json') |
25 | .expect(200) | 26 | |
26 | .expect('Content-Type', /json/) | 27 | if (token) req.set('Authorization', 'Bearer ' + token) |
28 | |||
29 | return req.expect(200) | ||
30 | .expect('Content-Type', /json/) | ||
27 | } | 31 | } |
28 | 32 | ||
29 | function addVideoCommentThread (url: string, token: string, videoId: number | string, text: string, expectedStatus = 200) { | 33 | function addVideoCommentThread (url: string, token: string, videoId: number | string, text: string, expectedStatus = 200) { |
diff --git a/server/tests/utils/videos/video-history.ts b/server/tests/utils/videos/video-history.ts new file mode 100644 index 000000000..7635478f7 --- /dev/null +++ b/server/tests/utils/videos/video-history.ts | |||
@@ -0,0 +1,14 @@ | |||
1 | import { makePutBodyRequest } from '../requests/requests' | ||
2 | |||
3 | function userWatchVideo (url: string, token: string, videoId: number | string, currentTime: number) { | ||
4 | const path = '/api/v1/videos/' + videoId + '/watching' | ||
5 | const fields = { currentTime } | ||
6 | |||
7 | return makePutBodyRequest({ url, path, token, fields, statusCodeExpected: 204 }) | ||
8 | } | ||
9 | |||
10 | // --------------------------------------------------------------------------- | ||
11 | |||
12 | export { | ||
13 | userWatchVideo | ||
14 | } | ||