]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/tests/api/check-params/video-comments.ts
Add ability to save replay of permanent lives
[github/Chocobozzz/PeerTube.git] / server / tests / api / check-params / video-comments.ts
1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3 import 'mocha'
4 import * as chai from 'chai'
5 import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@server/tests/shared'
6 import { HttpStatusCode, VideoCreateResult, VideoPrivacy } from '@shared/models'
7 import {
8 cleanupTests,
9 createSingleServer,
10 makeDeleteRequest,
11 makeGetRequest,
12 makePostBodyRequest,
13 PeerTubeServer,
14 setAccessTokensToServers
15 } from '@shared/server-commands'
16
17 const expect = chai.expect
18
19 describe('Test video comments API validator', function () {
20 let pathThread: string
21 let pathComment: string
22
23 let server: PeerTubeServer
24
25 let video: VideoCreateResult
26
27 let userAccessToken: string
28 let userAccessToken2: string
29
30 let commentId: number
31 let privateCommentId: number
32 let privateVideo: VideoCreateResult
33
34 // ---------------------------------------------------------------
35
36 before(async function () {
37 this.timeout(30000)
38
39 server = await createSingleServer(1)
40
41 await setAccessTokensToServers([ server ])
42
43 {
44 video = await server.videos.upload({ attributes: {} })
45 pathThread = '/api/v1/videos/' + video.uuid + '/comment-threads'
46 }
47
48 {
49 privateVideo = await server.videos.upload({ attributes: { privacy: VideoPrivacy.PRIVATE } })
50 }
51
52 {
53 const created = await server.comments.createThread({ videoId: video.uuid, text: 'coucou' })
54 commentId = created.id
55 pathComment = '/api/v1/videos/' + video.uuid + '/comments/' + commentId
56 }
57
58 {
59 const created = await server.comments.createThread({ videoId: privateVideo.uuid, text: 'coucou' })
60 privateCommentId = created.id
61 }
62
63 {
64 const user = { username: 'user1', password: 'my super password' }
65 await server.users.create({ username: user.username, password: user.password })
66 userAccessToken = await server.login.getAccessToken(user)
67 }
68
69 {
70 const user = { username: 'user2', password: 'my super password' }
71 await server.users.create({ username: user.username, password: user.password })
72 userAccessToken2 = await server.login.getAccessToken(user)
73 }
74 })
75
76 describe('When listing video comment threads', function () {
77 it('Should fail with a bad start pagination', async function () {
78 await checkBadStartPagination(server.url, pathThread, server.accessToken)
79 })
80
81 it('Should fail with a bad count pagination', async function () {
82 await checkBadCountPagination(server.url, pathThread, server.accessToken)
83 })
84
85 it('Should fail with an incorrect sort', async function () {
86 await checkBadSortPagination(server.url, pathThread, server.accessToken)
87 })
88
89 it('Should fail with an incorrect video', async function () {
90 await makeGetRequest({
91 url: server.url,
92 path: '/api/v1/videos/ba708d62-e3d7-45d9-9d73-41b9097cc02d/comment-threads',
93 expectedStatus: HttpStatusCode.NOT_FOUND_404
94 })
95 })
96
97 it('Should fail with a private video without token', async function () {
98 await makeGetRequest({
99 url: server.url,
100 path: '/api/v1/videos/' + privateVideo.shortUUID + '/comment-threads',
101 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
102 })
103 })
104
105 it('Should fail with another user token', async function () {
106 await makeGetRequest({
107 url: server.url,
108 token: userAccessToken,
109 path: '/api/v1/videos/' + privateVideo.shortUUID + '/comment-threads',
110 expectedStatus: HttpStatusCode.FORBIDDEN_403
111 })
112 })
113
114 it('Should succeed with the correct params', async function () {
115 await makeGetRequest({
116 url: server.url,
117 token: server.accessToken,
118 path: '/api/v1/videos/' + privateVideo.shortUUID + '/comment-threads',
119 expectedStatus: HttpStatusCode.OK_200
120 })
121 })
122 })
123
124 describe('When listing comments of a thread', function () {
125 it('Should fail with an incorrect video', async function () {
126 await makeGetRequest({
127 url: server.url,
128 path: '/api/v1/videos/ba708d62-e3d7-45d9-9d73-41b9097cc02d/comment-threads/' + commentId,
129 expectedStatus: HttpStatusCode.NOT_FOUND_404
130 })
131 })
132
133 it('Should fail with an incorrect thread id', async function () {
134 await makeGetRequest({
135 url: server.url,
136 path: '/api/v1/videos/' + video.shortUUID + '/comment-threads/156',
137 expectedStatus: HttpStatusCode.NOT_FOUND_404
138 })
139 })
140
141 it('Should fail with a private video without token', async function () {
142 await makeGetRequest({
143 url: server.url,
144 path: '/api/v1/videos/' + privateVideo.shortUUID + '/comment-threads/' + privateCommentId,
145 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
146 })
147 })
148
149 it('Should fail with another user token', async function () {
150 await makeGetRequest({
151 url: server.url,
152 token: userAccessToken,
153 path: '/api/v1/videos/' + privateVideo.shortUUID + '/comment-threads/' + privateCommentId,
154 expectedStatus: HttpStatusCode.FORBIDDEN_403
155 })
156 })
157
158 it('Should success with the correct params', async function () {
159 await makeGetRequest({
160 url: server.url,
161 token: server.accessToken,
162 path: '/api/v1/videos/' + privateVideo.shortUUID + '/comment-threads/' + privateCommentId,
163 expectedStatus: HttpStatusCode.OK_200
164 })
165
166 await makeGetRequest({
167 url: server.url,
168 path: '/api/v1/videos/' + video.shortUUID + '/comment-threads/' + commentId,
169 expectedStatus: HttpStatusCode.OK_200
170 })
171 })
172 })
173
174 describe('When adding a video thread', function () {
175
176 it('Should fail with a non authenticated user', async function () {
177 const fields = {
178 text: 'text'
179 }
180 await makePostBodyRequest({
181 url: server.url,
182 path: pathThread,
183 token: 'none',
184 fields,
185 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
186 })
187 })
188
189 it('Should fail with nothing', async function () {
190 const fields = {}
191 await makePostBodyRequest({ url: server.url, path: pathThread, token: server.accessToken, fields })
192 })
193
194 it('Should fail with a short comment', async function () {
195 const fields = {
196 text: ''
197 }
198 await makePostBodyRequest({ url: server.url, path: pathThread, token: server.accessToken, fields })
199 })
200
201 it('Should fail with a long comment', async function () {
202 const fields = {
203 text: 'h'.repeat(10001)
204 }
205 await makePostBodyRequest({ url: server.url, path: pathThread, token: server.accessToken, fields })
206 })
207
208 it('Should fail with an incorrect video', async function () {
209 const path = '/api/v1/videos/ba708d62-e3d7-45d9-9d73-41b9097cc02d/comment-threads'
210 const fields = { text: 'super comment' }
211
212 await makePostBodyRequest({
213 url: server.url,
214 path,
215 token: server.accessToken,
216 fields,
217 expectedStatus: HttpStatusCode.NOT_FOUND_404
218 })
219 })
220
221 it('Should fail with a private video of another user', async function () {
222 const fields = { text: 'super comment' }
223
224 await makePostBodyRequest({
225 url: server.url,
226 path: '/api/v1/videos/' + privateVideo.shortUUID + '/comment-threads',
227 token: userAccessToken,
228 fields,
229 expectedStatus: HttpStatusCode.FORBIDDEN_403
230 })
231 })
232
233 it('Should succeed with the correct parameters', async function () {
234 const fields = { text: 'super comment' }
235
236 await makePostBodyRequest({
237 url: server.url,
238 path: pathThread,
239 token: server.accessToken,
240 fields,
241 expectedStatus: HttpStatusCode.OK_200
242 })
243 })
244 })
245
246 describe('When adding a comment to a thread', function () {
247
248 it('Should fail with a non authenticated user', async function () {
249 const fields = {
250 text: 'text'
251 }
252 await makePostBodyRequest({
253 url: server.url,
254 path: pathComment,
255 token: 'none',
256 fields,
257 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
258 })
259 })
260
261 it('Should fail with nothing', async function () {
262 const fields = {}
263 await makePostBodyRequest({ url: server.url, path: pathComment, token: server.accessToken, fields })
264 })
265
266 it('Should fail with a short comment', async function () {
267 const fields = {
268 text: ''
269 }
270 await makePostBodyRequest({ url: server.url, path: pathComment, token: server.accessToken, fields })
271 })
272
273 it('Should fail with a long comment', async function () {
274 const fields = {
275 text: 'h'.repeat(10001)
276 }
277 await makePostBodyRequest({ url: server.url, path: pathComment, token: server.accessToken, fields })
278 })
279
280 it('Should fail with an incorrect video', async function () {
281 const path = '/api/v1/videos/ba708d62-e3d7-45d9-9d73-41b9097cc02d/comments/' + commentId
282 const fields = {
283 text: 'super comment'
284 }
285 await makePostBodyRequest({
286 url: server.url,
287 path,
288 token: server.accessToken,
289 fields,
290 expectedStatus: HttpStatusCode.NOT_FOUND_404
291 })
292 })
293
294 it('Should fail with a private video of another user', async function () {
295 const fields = { text: 'super comment' }
296
297 await makePostBodyRequest({
298 url: server.url,
299 path: '/api/v1/videos/' + privateVideo.uuid + '/comments/' + privateCommentId,
300 token: userAccessToken,
301 fields,
302 expectedStatus: HttpStatusCode.FORBIDDEN_403
303 })
304 })
305
306 it('Should fail with an incorrect comment', async function () {
307 const path = '/api/v1/videos/' + video.uuid + '/comments/124'
308 const fields = {
309 text: 'super comment'
310 }
311 await makePostBodyRequest({
312 url: server.url,
313 path,
314 token: server.accessToken,
315 fields,
316 expectedStatus: HttpStatusCode.NOT_FOUND_404
317 })
318 })
319
320 it('Should succeed with the correct parameters', async function () {
321 const fields = {
322 text: 'super comment'
323 }
324 await makePostBodyRequest({
325 url: server.url,
326 path: pathComment,
327 token: server.accessToken,
328 fields,
329 expectedStatus: HttpStatusCode.OK_200
330 })
331 })
332 })
333
334 describe('When removing video comments', function () {
335 it('Should fail with a non authenticated user', async function () {
336 await makeDeleteRequest({ url: server.url, path: pathComment, token: 'none', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
337 })
338
339 it('Should fail with another user', async function () {
340 await makeDeleteRequest({
341 url: server.url,
342 path: pathComment,
343 token: userAccessToken,
344 expectedStatus: HttpStatusCode.FORBIDDEN_403
345 })
346 })
347
348 it('Should fail with an incorrect video', async function () {
349 const path = '/api/v1/videos/ba708d62-e3d7-45d9-9d73-41b9097cc02d/comments/' + commentId
350 await makeDeleteRequest({ url: server.url, path, token: server.accessToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
351 })
352
353 it('Should fail with an incorrect comment', async function () {
354 const path = '/api/v1/videos/' + video.uuid + '/comments/124'
355 await makeDeleteRequest({ url: server.url, path, token: server.accessToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
356 })
357
358 it('Should succeed with the same user', async function () {
359 let commentToDelete: number
360
361 {
362 const created = await server.comments.createThread({ videoId: video.uuid, token: userAccessToken, text: 'hello' })
363 commentToDelete = created.id
364 }
365
366 const path = '/api/v1/videos/' + video.uuid + '/comments/' + commentToDelete
367
368 await makeDeleteRequest({ url: server.url, path, token: userAccessToken2, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
369 await makeDeleteRequest({ url: server.url, path, token: userAccessToken, expectedStatus: HttpStatusCode.NO_CONTENT_204 })
370 })
371
372 it('Should succeed with the owner of the video', async function () {
373 let commentToDelete: number
374 let anotherVideoUUID: string
375
376 {
377 const { uuid } = await server.videos.upload({ token: userAccessToken, attributes: { name: 'video' } })
378 anotherVideoUUID = uuid
379 }
380
381 {
382 const created = await server.comments.createThread({ videoId: anotherVideoUUID, text: 'hello' })
383 commentToDelete = created.id
384 }
385
386 const path = '/api/v1/videos/' + anotherVideoUUID + '/comments/' + commentToDelete
387
388 await makeDeleteRequest({ url: server.url, path, token: userAccessToken2, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
389 await makeDeleteRequest({ url: server.url, path, token: userAccessToken, expectedStatus: HttpStatusCode.NO_CONTENT_204 })
390 })
391
392 it('Should succeed with the correct parameters', async function () {
393 await makeDeleteRequest({
394 url: server.url,
395 path: pathComment,
396 token: server.accessToken,
397 expectedStatus: HttpStatusCode.NO_CONTENT_204
398 })
399 })
400 })
401
402 describe('When a video has comments disabled', function () {
403 before(async function () {
404 video = await server.videos.upload({ attributes: { commentsEnabled: false } })
405 pathThread = '/api/v1/videos/' + video.uuid + '/comment-threads'
406 })
407
408 it('Should return an empty thread list', async function () {
409 const res = await makeGetRequest({
410 url: server.url,
411 path: pathThread,
412 expectedStatus: HttpStatusCode.OK_200
413 })
414 expect(res.body.total).to.equal(0)
415 expect(res.body.data).to.have.lengthOf(0)
416 })
417
418 it('Should return an thread comments list')
419
420 it('Should return conflict on thread add', async function () {
421 const fields = {
422 text: 'super comment'
423 }
424 await makePostBodyRequest({
425 url: server.url,
426 path: pathThread,
427 token: server.accessToken,
428 fields,
429 expectedStatus: HttpStatusCode.CONFLICT_409
430 })
431 })
432
433 it('Should return conflict on comment thread add')
434 })
435
436 describe('When listing admin comments threads', function () {
437 const path = '/api/v1/videos/comments'
438
439 it('Should fail with a bad start pagination', async function () {
440 await checkBadStartPagination(server.url, path, server.accessToken)
441 })
442
443 it('Should fail with a bad count pagination', async function () {
444 await checkBadCountPagination(server.url, path, server.accessToken)
445 })
446
447 it('Should fail with an incorrect sort', async function () {
448 await checkBadSortPagination(server.url, path, server.accessToken)
449 })
450
451 it('Should fail with a non authenticated user', async function () {
452 await makeGetRequest({
453 url: server.url,
454 path,
455 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
456 })
457 })
458
459 it('Should fail with a non admin user', async function () {
460 await makeGetRequest({
461 url: server.url,
462 path,
463 token: userAccessToken,
464 expectedStatus: HttpStatusCode.FORBIDDEN_403
465 })
466 })
467
468 it('Should succeed with the correct params', async function () {
469 await makeGetRequest({
470 url: server.url,
471 path,
472 token: server.accessToken,
473 query: {
474 isLocal: false,
475 search: 'toto',
476 searchAccount: 'toto',
477 searchVideo: 'toto'
478 },
479 expectedStatus: HttpStatusCode.OK_200
480 })
481 })
482 })
483
484 after(async function () {
485 await cleanupTests([ server ])
486 })
487 })