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