Upgrade server dep'
[oweals/peertube.git] / server / tests / utils / videos.ts
1 import { readFile } from 'fs'
2 import * as request from 'supertest'
3 import { join, isAbsolute } from 'path'
4 import * as parseTorrent from 'parse-torrent'
5
6 import { makeGetRequest } from './requests'
7 import { readFilePromise } from './miscs'
8 import { ServerInfo } from './servers'
9 import { getMyUserInformation } from './users'
10 import { VideoPrivacy } from '../../../shared'
11
12 type VideoAttributes = {
13   name?: string
14   category?: number
15   licence?: number
16   language?: number
17   nsfw?: boolean
18   description?: string
19   tags?: string[]
20   channelId?: number
21   privacy?: VideoPrivacy
22   fixture?: string
23 }
24
25 function getVideoCategories (url: string) {
26   const path = '/api/v1/videos/categories'
27
28   return makeGetRequest(url, path)
29 }
30
31 function getVideoLicences (url: string) {
32   const path = '/api/v1/videos/licences'
33
34   return makeGetRequest(url, path)
35 }
36
37 function getVideoLanguages (url: string) {
38   const path = '/api/v1/videos/languages'
39
40   return makeGetRequest(url, path)
41 }
42
43 function getVideoPrivacies (url: string) {
44   const path = '/api/v1/videos/privacies'
45
46   return makeGetRequest(url, path)
47 }
48
49 function getVideo (url: string, id: number | string, expectedStatus = 200) {
50   const path = '/api/v1/videos/' + id
51
52   return request(url)
53           .get(path)
54           .set('Accept', 'application/json')
55           .expect(expectedStatus)
56 }
57
58 function getVideoWithToken (url: string, token: string, id: number | string, expectedStatus = 200) {
59   const path = '/api/v1/videos/' + id
60
61   return request(url)
62     .get(path)
63     .set('Authorization', 'Bearer ' + token)
64     .set('Accept', 'application/json')
65     .expect(expectedStatus)
66 }
67
68 function getVideoDescription (url: string, descriptionPath: string) {
69   return request(url)
70     .get(descriptionPath)
71     .set('Accept', 'application/json')
72     .expect(200)
73     .expect('Content-Type', /json/)
74 }
75
76 function getVideosList (url: string) {
77   const path = '/api/v1/videos'
78
79   return request(url)
80           .get(path)
81           .query({ sort: 'name' })
82           .set('Accept', 'application/json')
83           .expect(200)
84           .expect('Content-Type', /json/)
85 }
86
87 function getMyVideos (url: string, accessToken: string, start: number, count: number, sort?: string) {
88   const path = '/api/v1/users/me/videos'
89
90   const req = request(url)
91     .get(path)
92     .query({ start: start })
93     .query({ count: count })
94
95   if (sort) req.query({ sort })
96
97   return req.set('Accept', 'application/json')
98     .set('Authorization', 'Bearer ' + accessToken)
99     .expect(200)
100     .expect('Content-Type', /json/)
101 }
102
103 function getVideosListPagination (url: string, start: number, count: number, sort?: string) {
104   const path = '/api/v1/videos'
105
106   const req = request(url)
107               .get(path)
108               .query({ start: start })
109               .query({ count: count })
110
111   if (sort) req.query({ sort })
112
113   return req.set('Accept', 'application/json')
114            .expect(200)
115            .expect('Content-Type', /json/)
116 }
117
118 function getVideosListSort (url: string, sort: string) {
119   const path = '/api/v1/videos'
120
121   return request(url)
122           .get(path)
123           .query({ sort: sort })
124           .set('Accept', 'application/json')
125           .expect(200)
126           .expect('Content-Type', /json/)
127 }
128
129 function removeVideo (url: string, token: string, id: number, expectedStatus = 204) {
130   const path = '/api/v1/videos'
131
132   return request(url)
133           .delete(path + '/' + id)
134           .set('Accept', 'application/json')
135           .set('Authorization', 'Bearer ' + token)
136           .expect(expectedStatus)
137 }
138
139 function searchVideo (url: string, search: string, field?: string) {
140   const path = '/api/v1/videos'
141   const req = request(url)
142                 .get(path + '/search/' + search)
143                 .set('Accept', 'application/json')
144
145   if (field) req.query({ field })
146
147   return req.expect(200)
148             .expect('Content-Type', /json/)
149 }
150
151 function searchVideoWithPagination (url: string, search: string, field: string, start: number, count: number, sort?: string) {
152   const path = '/api/v1/videos'
153
154   const req = request(url)
155                 .get(path + '/search/' + search)
156                 .query({ start })
157                 .query({ count })
158                 .query({ field })
159
160   if (sort) req.query({ sort })
161
162   return req.set('Accept', 'application/json')
163             .expect(200)
164             .expect('Content-Type', /json/)
165 }
166
167 function searchVideoWithSort (url: string, search: string, sort: string) {
168   const path = '/api/v1/videos'
169
170   return request(url)
171           .get(path + '/search/' + search)
172           .query({ sort })
173           .set('Accept', 'application/json')
174           .expect(200)
175           .expect('Content-Type', /json/)
176 }
177
178 async function testVideoImage (url: string, imageName: string, imagePath: string) {
179   // Don't test images if the node env is not set
180   // Because we need a special ffmpeg version for this test
181   if (process.env['NODE_TEST_IMAGE']) {
182     const res = await request(url)
183                         .get(imagePath)
184                         .expect(200)
185
186     const data = await readFilePromise(join(__dirname, '..', 'api', 'fixtures', imageName + '.jpg'))
187
188     return data.equals(res.body)
189   } else {
190     console.log('Do not test images. Enable it by setting NODE_TEST_IMAGE env variable.')
191     return true
192   }
193 }
194
195 async function uploadVideo (url: string, accessToken: string, videoAttributesArg: VideoAttributes, specialStatus = 204) {
196   const path = '/api/v1/videos/upload'
197   let defaultChannelId = '1'
198
199   try {
200     const res = await getMyUserInformation(url, accessToken)
201     defaultChannelId = res.body.videoChannels[0].id
202   } catch (e) { /* empty */ }
203
204   // Default attributes
205   let attributes = {
206     name: 'my super video',
207     category: 5,
208     licence: 4,
209     language: 3,
210     channelId: defaultChannelId,
211     nsfw: true,
212     description: 'my super description',
213     tags: [ 'tag' ],
214     privacy: VideoPrivacy.PUBLIC,
215     fixture: 'video_short.webm'
216   }
217   attributes = Object.assign(attributes, videoAttributesArg)
218
219   const req = request(url)
220               .post(path)
221               .set('Accept', 'application/json')
222               .set('Authorization', 'Bearer ' + accessToken)
223               .field('name', attributes.name)
224               .field('category', attributes.category.toString())
225               .field('licence', attributes.licence.toString())
226               .field('nsfw', JSON.stringify(attributes.nsfw))
227               .field('description', attributes.description)
228               .field('privacy', attributes.privacy.toString())
229               .field('channelId', attributes.channelId)
230
231   if (attributes.language !== undefined) {
232     req.field('language', attributes.language.toString())
233   }
234
235   for (let i = 0; i < attributes.tags.length; i++) {
236     req.field('tags[' + i + ']', attributes.tags[i])
237   }
238
239   let filePath = ''
240   if (isAbsolute(attributes.fixture)) {
241     filePath = attributes.fixture
242   } else {
243     filePath = join(__dirname, '..', 'api', 'fixtures', attributes.fixture)
244   }
245
246   return req.attach('videofile', filePath)
247             .expect(specialStatus)
248 }
249
250 function updateVideo (url: string, accessToken: string, id: number, attributes: VideoAttributes, specialStatus = 204) {
251   const path = '/api/v1/videos/' + id
252   const body = {}
253
254   if (attributes.name) body['name'] = attributes.name
255   if (attributes.category) body['category'] = attributes.category
256   if (attributes.licence) body['licence'] = attributes.licence
257   if (attributes.language) body['language'] = attributes.language
258   if (attributes.nsfw) body['nsfw'] = attributes.nsfw
259   if (attributes.description) body['description'] = attributes.description
260   if (attributes.tags) body['tags'] = attributes.tags
261   if (attributes.privacy) body['privacy'] = attributes.privacy
262
263   return request(url)
264           .put(path)
265           .send(body)
266           .set('Accept', 'application/json')
267           .set('Authorization', 'Bearer ' + accessToken)
268           .expect(specialStatus)
269 }
270
271 function rateVideo (url: string, accessToken: string, id: number, rating: string, specialStatus = 204) {
272   const path = '/api/v1/videos/' + id + '/rate'
273
274   return request(url)
275           .put(path)
276           .set('Accept', 'application/json')
277           .set('Authorization', 'Bearer ' + accessToken)
278           .send({ rating })
279           .expect(specialStatus)
280 }
281
282 function parseTorrentVideo (server: ServerInfo, videoUUID: string, resolution: number) {
283   return new Promise<any>((res, rej) => {
284     const torrentName = videoUUID + '-' + resolution + '.torrent'
285     const torrentPath = join(__dirname, '..', '..', '..', 'test' + server.serverNumber, 'torrents', torrentName)
286     readFile(torrentPath, (err, data) => {
287       if (err) return rej(err)
288
289       return res(parseTorrent(data))
290     })
291   })
292 }
293
294 // ---------------------------------------------------------------------------
295
296 export {
297   getVideoDescription,
298   getVideoCategories,
299   getVideoLicences,
300   getVideoPrivacies,
301   getVideoLanguages,
302   getMyVideos,
303   getVideo,
304   getVideoWithToken,
305   getVideosList,
306   getVideosListPagination,
307   getVideosListSort,
308   removeVideo,
309   searchVideo,
310   searchVideoWithPagination,
311   searchVideoWithSort,
312   testVideoImage,
313   uploadVideo,
314   updateVideo,
315   rateVideo,
316   parseTorrentVideo
317 }