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