]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/tests/utils/videos/videos.ts
Remove unused webserver configuration
[github/Chocobozzz/PeerTube.git] / server / tests / utils / videos / videos.ts
CommitLineData
a20399c9
C
1/* tslint:disable:no-unused-expression */
2
3import { expect } from 'chai'
fdbda9e3 4import { readFile } from 'fs'
fdbda9e3 5import * as parseTorrent from 'parse-torrent'
b1f5b93e 6import { extname, isAbsolute, join } from 'path'
c5d31dba
C
7import * as request from 'supertest'
8import { getMyUserInformation, makeGetRequest, readFilePromise, ServerInfo } from '../'
9import { VideoPrivacy } from '../../../../shared/models/videos'
a20399c9
C
10import { VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_PRIVACIES } from '../../../initializers'
11import { dateIsValid, webtorrentAdd } from '../index'
0e1dc3e7
C
12
13type VideoAttributes = {
14 name?: string
15 category?: number
16 licence?: number
17 language?: number
18 nsfw?: boolean
47564bbe 19 commentsEnabled?: boolean
0e1dc3e7
C
20 description?: string
21 tags?: string[]
5f04dd2f 22 channelId?: number
11474c3c 23 privacy?: VideoPrivacy
0e1dc3e7
C
24 fixture?: string
25}
26
27function getVideoCategories (url: string) {
28 const path = '/api/v1/videos/categories'
29
eec63bbc
C
30 return makeGetRequest({
31 url,
59651eee
C
32 path,
33 statusCodeExpected: 200
eec63bbc 34 })
0e1dc3e7
C
35}
36
37function getVideoLicences (url: string) {
38 const path = '/api/v1/videos/licences'
39
eec63bbc
C
40 return makeGetRequest({
41 url,
59651eee
C
42 path,
43 statusCodeExpected: 200
eec63bbc 44 })
0e1dc3e7
C
45}
46
47function getVideoLanguages (url: string) {
48 const path = '/api/v1/videos/languages'
49
eec63bbc
C
50 return makeGetRequest({
51 url,
59651eee
C
52 path,
53 statusCodeExpected: 200
eec63bbc 54 })
0e1dc3e7
C
55}
56
11474c3c
C
57function getVideoPrivacies (url: string) {
58 const path = '/api/v1/videos/privacies'
59
eec63bbc
C
60 return makeGetRequest({
61 url,
59651eee
C
62 path,
63 statusCodeExpected: 200
eec63bbc 64 })
11474c3c
C
65}
66
11474c3c 67function getVideo (url: string, id: number | string, expectedStatus = 200) {
0e1dc3e7
C
68 const path = '/api/v1/videos/' + id
69
70 return request(url)
71 .get(path)
72 .set('Accept', 'application/json')
11474c3c
C
73 .expect(expectedStatus)
74}
75
1f3e9fec
C
76function viewVideo (url: string, id: number | string, expectedStatus = 204) {
77 const path = '/api/v1/videos/' + id + '/views'
78
79 return request(url)
80 .post(path)
81 .set('Accept', 'application/json')
82 .expect(expectedStatus)
83}
84
11474c3c
C
85function getVideoWithToken (url: string, token: string, id: number | string, expectedStatus = 200) {
86 const path = '/api/v1/videos/' + id
87
88 return request(url)
89 .get(path)
90 .set('Authorization', 'Bearer ' + token)
91 .set('Accept', 'application/json')
92 .expect(expectedStatus)
0e1dc3e7
C
93}
94
9567011b
C
95function getVideoDescription (url: string, descriptionPath: string) {
96 return request(url)
97 .get(descriptionPath)
98 .set('Accept', 'application/json')
99 .expect(200)
100 .expect('Content-Type', /json/)
101}
102
0e1dc3e7
C
103function getVideosList (url: string) {
104 const path = '/api/v1/videos'
105
106 return request(url)
107 .get(path)
108 .query({ sort: 'name' })
109 .set('Accept', 'application/json')
110 .expect(200)
111 .expect('Content-Type', /json/)
112}
113
11474c3c
C
114function getMyVideos (url: string, accessToken: string, start: number, count: number, sort?: string) {
115 const path = '/api/v1/users/me/videos'
116
117 const req = request(url)
118 .get(path)
119 .query({ start: start })
120 .query({ count: count })
121
122 if (sort) req.query({ sort })
123
124 return req.set('Accept', 'application/json')
125 .set('Authorization', 'Bearer ' + accessToken)
126 .expect(200)
127 .expect('Content-Type', /json/)
128}
129
0e1dc3e7
C
130function getVideosListPagination (url: string, start: number, count: number, sort?: string) {
131 const path = '/api/v1/videos'
132
133 const req = request(url)
134 .get(path)
135 .query({ start: start })
136 .query({ count: count })
137
138 if (sort) req.query({ sort })
139
140 return req.set('Accept', 'application/json')
141 .expect(200)
142 .expect('Content-Type', /json/)
143}
144
145function getVideosListSort (url: string, sort: string) {
146 const path = '/api/v1/videos'
147
148 return request(url)
149 .get(path)
150 .query({ sort: sort })
151 .set('Accept', 'application/json')
152 .expect(200)
153 .expect('Content-Type', /json/)
154}
155
11ba2ab3 156function removeVideo (url: string, token: string, id: number | string, expectedStatus = 204) {
0e1dc3e7
C
157 const path = '/api/v1/videos'
158
159 return request(url)
160 .delete(path + '/' + id)
161 .set('Accept', 'application/json')
162 .set('Authorization', 'Bearer ' + token)
163 .expect(expectedStatus)
164}
165
f3aaa9a9 166function searchVideo (url: string, search: string) {
0e1dc3e7
C
167 const path = '/api/v1/videos'
168 const req = request(url)
f3aaa9a9
C
169 .get(path + '/search')
170 .query({ search })
171 .set('Accept', 'application/json')
0e1dc3e7
C
172
173 return req.expect(200)
f3aaa9a9 174 .expect('Content-Type', /json/)
0e1dc3e7
C
175}
176
f3aaa9a9 177function searchVideoWithPagination (url: string, search: string, start: number, count: number, sort?: string) {
0e1dc3e7
C
178 const path = '/api/v1/videos'
179
180 const req = request(url)
f3aaa9a9 181 .get(path + '/search')
0e1dc3e7 182 .query({ start })
f3aaa9a9 183 .query({ search })
0e1dc3e7 184 .query({ count })
0e1dc3e7
C
185
186 if (sort) req.query({ sort })
187
188 return req.set('Accept', 'application/json')
189 .expect(200)
190 .expect('Content-Type', /json/)
191}
192
193function searchVideoWithSort (url: string, search: string, sort: string) {
194 const path = '/api/v1/videos'
195
196 return request(url)
f3aaa9a9
C
197 .get(path + '/search')
198 .query({ search })
0e1dc3e7
C
199 .query({ sort })
200 .set('Accept', 'application/json')
201 .expect(200)
202 .expect('Content-Type', /json/)
203}
204
c5911fd3 205async function testVideoImage (url: string, imageName: string, imagePath: string, extension = '.jpg') {
0e1dc3e7
C
206 // Don't test images if the node env is not set
207 // Because we need a special ffmpeg version for this test
208 if (process.env['NODE_TEST_IMAGE']) {
209 const res = await request(url)
210 .get(imagePath)
211 .expect(200)
212
c5911fd3 213 const data = await readFilePromise(join(__dirname, '..', '..', 'api', 'fixtures', imageName + extension))
0e1dc3e7
C
214
215 return data.equals(res.body)
216 } else {
217 console.log('Do not test images. Enable it by setting NODE_TEST_IMAGE env variable.')
218 return true
219 }
220}
221
e11f68a3 222async function uploadVideo (url: string, accessToken: string, videoAttributesArg: VideoAttributes, specialStatus = 200) {
e95561cd 223 const path = '/api/v1/videos/upload'
5f04dd2f
C
224 let defaultChannelId = '1'
225
226 try {
227 const res = await getMyUserInformation(url, accessToken)
228 defaultChannelId = res.body.videoChannels[0].id
229 } catch (e) { /* empty */ }
0e1dc3e7
C
230
231 // Default attributes
232 let attributes = {
233 name: 'my super video',
234 category: 5,
235 licence: 4,
236 language: 3,
5f04dd2f 237 channelId: defaultChannelId,
0e1dc3e7
C
238 nsfw: true,
239 description: 'my super description',
240 tags: [ 'tag' ],
11474c3c 241 privacy: VideoPrivacy.PUBLIC,
47564bbe 242 commentsEnabled: true,
0e1dc3e7
C
243 fixture: 'video_short.webm'
244 }
245 attributes = Object.assign(attributes, videoAttributesArg)
246
247 const req = request(url)
248 .post(path)
249 .set('Accept', 'application/json')
250 .set('Authorization', 'Bearer ' + accessToken)
251 .field('name', attributes.name)
252 .field('category', attributes.category.toString())
253 .field('licence', attributes.licence.toString())
0e1dc3e7 254 .field('nsfw', JSON.stringify(attributes.nsfw))
47564bbe 255 .field('commentsEnabled', JSON.stringify(attributes.commentsEnabled))
0e1dc3e7 256 .field('description', attributes.description)
11474c3c 257 .field('privacy', attributes.privacy.toString())
5f04dd2f 258 .field('channelId', attributes.channelId)
0e1dc3e7 259
8df87ce7
C
260 if (attributes.language !== undefined) {
261 req.field('language', attributes.language.toString())
262 }
263
0e1dc3e7
C
264 for (let i = 0; i < attributes.tags.length; i++) {
265 req.field('tags[' + i + ']', attributes.tags[i])
266 }
267
14d3270f 268 let filePath = ''
0e1dc3e7 269 if (isAbsolute(attributes.fixture)) {
14d3270f 270 filePath = attributes.fixture
0e1dc3e7 271 } else {
331128ed 272 filePath = join(__dirname, '..', '..', 'api', 'fixtures', attributes.fixture)
0e1dc3e7
C
273 }
274
14d3270f 275 return req.attach('videofile', filePath)
0e1dc3e7
C
276 .expect(specialStatus)
277}
278
47564bbe 279function updateVideo (url: string, accessToken: string, id: number | string, attributes: VideoAttributes, specialStatus = 204) {
0e1dc3e7
C
280 const path = '/api/v1/videos/' + id
281 const body = {}
282
283 if (attributes.name) body['name'] = attributes.name
284 if (attributes.category) body['category'] = attributes.category
285 if (attributes.licence) body['licence'] = attributes.licence
286 if (attributes.language) body['language'] = attributes.language
47564bbe
C
287 if (attributes.nsfw !== undefined) body['nsfw'] = JSON.stringify(attributes.nsfw)
288 if (attributes.commentsEnabled !== undefined) body['commentsEnabled'] = JSON.stringify(attributes.commentsEnabled)
0e1dc3e7
C
289 if (attributes.description) body['description'] = attributes.description
290 if (attributes.tags) body['tags'] = attributes.tags
11474c3c 291 if (attributes.privacy) body['privacy'] = attributes.privacy
0e1dc3e7
C
292
293 return request(url)
294 .put(path)
295 .send(body)
296 .set('Accept', 'application/json')
297 .set('Authorization', 'Bearer ' + accessToken)
298 .expect(specialStatus)
299}
300
301function rateVideo (url: string, accessToken: string, id: number, rating: string, specialStatus = 204) {
302 const path = '/api/v1/videos/' + id + '/rate'
303
304 return request(url)
305 .put(path)
306 .set('Accept', 'application/json')
307 .set('Authorization', 'Bearer ' + accessToken)
308 .send({ rating })
309 .expect(specialStatus)
310}
311
14d3270f 312function parseTorrentVideo (server: ServerInfo, videoUUID: string, resolution: number) {
fdbda9e3 313 return new Promise<any>((res, rej) => {
14d3270f 314 const torrentName = videoUUID + '-' + resolution + '.torrent'
331128ed 315 const torrentPath = join(__dirname, '..', '..', '..', '..', 'test' + server.serverNumber, 'torrents', torrentName)
fdbda9e3
C
316 readFile(torrentPath, (err, data) => {
317 if (err) return rej(err)
318
319 return res(parseTorrent(data))
320 })
321 })
322}
323
a20399c9
C
324async function completeVideoCheck (
325 url: string,
326 video: any,
327 attributes: {
328 name: string
329 category: number
330 licence: number
331 language: number
332 nsfw: boolean
47564bbe 333 commentsEnabled: boolean
a20399c9
C
334 description: string
335 host: string
336 account: string
337 isLocal: boolean,
338 tags: string[],
339 privacy: number,
b1f5b93e
C
340 likes?: number,
341 dislikes?: number,
342 duration: number,
a20399c9
C
343 channel: {
344 name: string,
b1f5b93e 345 description
a20399c9
C
346 isLocal: boolean
347 }
348 fixture: string,
349 files: {
350 resolution: number
351 size: number
352 }[]
353 }
354) {
b1f5b93e
C
355 if (!attributes.likes) attributes.likes = 0
356 if (!attributes.dislikes) attributes.dislikes = 0
357
a20399c9
C
358 expect(video.name).to.equal(attributes.name)
359 expect(video.category).to.equal(attributes.category)
b1f5b93e 360 expect(video.categoryLabel).to.equal(VIDEO_CATEGORIES[attributes.category] || 'Misc')
a20399c9 361 expect(video.licence).to.equal(attributes.licence)
b1f5b93e 362 expect(video.licenceLabel).to.equal(VIDEO_LICENCES[attributes.licence] || 'Unknown')
a20399c9 363 expect(video.language).to.equal(attributes.language)
b1f5b93e 364 expect(video.languageLabel).to.equal(VIDEO_LANGUAGES[attributes.language] || 'Unknown')
a20399c9
C
365 expect(video.nsfw).to.equal(attributes.nsfw)
366 expect(video.description).to.equal(attributes.description)
367 expect(video.serverHost).to.equal(attributes.host)
368 expect(video.accountName).to.equal(attributes.account)
b1f5b93e
C
369 expect(video.likes).to.equal(attributes.likes)
370 expect(video.dislikes).to.equal(attributes.dislikes)
a20399c9 371 expect(video.isLocal).to.equal(attributes.isLocal)
b1f5b93e 372 expect(video.duration).to.equal(attributes.duration)
a20399c9
C
373 expect(dateIsValid(video.createdAt)).to.be.true
374 expect(dateIsValid(video.updatedAt)).to.be.true
375
376 const res = await getVideo(url, video.id)
377 const videoDetails = res.body
378
379 expect(videoDetails.files).to.have.lengthOf(attributes.files.length)
380 expect(videoDetails.tags).to.deep.equal(attributes.tags)
381 expect(videoDetails.privacy).to.deep.equal(attributes.privacy)
382 expect(videoDetails.privacyLabel).to.deep.equal(VIDEO_PRIVACIES[attributes.privacy])
383 expect(videoDetails.account.name).to.equal(attributes.account)
47564bbe 384 expect(videoDetails.commentsEnabled).to.equal(attributes.commentsEnabled)
a20399c9
C
385
386 expect(videoDetails.channel.name).to.equal(attributes.channel.name)
387 expect(videoDetails.channel.isLocal).to.equal(attributes.channel.isLocal)
388 expect(dateIsValid(videoDetails.channel.createdAt)).to.be.true
389 expect(dateIsValid(videoDetails.channel.updatedAt)).to.be.true
390
391 for (const attributeFile of attributes.files) {
392 const file = videoDetails.files.find(f => f.resolution === attributeFile.resolution)
393 expect(file).not.to.be.undefined
394
b1f5b93e
C
395 let extension = extname(attributes.fixture)
396 // Transcoding enabled on server 2, extension will always be .mp4
397 if (attributes.host === 'localhost:9002') extension = '.mp4'
398
a20399c9
C
399 const magnetUri = file.magnetUri
400 expect(file.magnetUri).to.have.lengthOf.above(2)
b1f5b93e
C
401 expect(file.torrentUrl).to.equal(`http://${attributes.host}/static/torrents/${videoDetails.uuid}-${file.resolution}.torrent`)
402 expect(file.fileUrl).to.equal(`http://${attributes.host}/static/webseed/${videoDetails.uuid}-${file.resolution}${extension}`)
a20399c9
C
403 expect(file.resolution).to.equal(attributeFile.resolution)
404 expect(file.resolutionLabel).to.equal(attributeFile.resolution + 'p')
b1f5b93e
C
405
406 const minSize = attributeFile.size - ((10 * attributeFile.size) / 100)
407 const maxSize = attributeFile.size + ((10 * attributeFile.size) / 100)
408 expect(file.size).to.be.above(minSize).and.below(maxSize)
a20399c9
C
409
410 const test = await testVideoImage(url, attributes.fixture, videoDetails.thumbnailPath)
411 expect(test).to.equal(true)
412
413 const torrent = await webtorrentAdd(magnetUri, true)
414 expect(torrent.files).to.be.an('array')
415 expect(torrent.files.length).to.equal(1)
416 expect(torrent.files[0].path).to.exist.and.to.not.equal('')
417 }
418}
419
0e1dc3e7
C
420// ---------------------------------------------------------------------------
421
422export {
9567011b 423 getVideoDescription,
0e1dc3e7
C
424 getVideoCategories,
425 getVideoLicences,
11474c3c 426 getVideoPrivacies,
0e1dc3e7 427 getVideoLanguages,
11474c3c 428 getMyVideos,
0e1dc3e7 429 getVideo,
11474c3c 430 getVideoWithToken,
0e1dc3e7
C
431 getVideosList,
432 getVideosListPagination,
433 getVideosListSort,
434 removeVideo,
435 searchVideo,
436 searchVideoWithPagination,
437 searchVideoWithSort,
438 testVideoImage,
439 uploadVideo,
440 updateVideo,
fdbda9e3 441 rateVideo,
1f3e9fec 442 viewVideo,
a20399c9
C
443 parseTorrentVideo,
444 completeVideoCheck
0e1dc3e7 445}