]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/tests/api/utils.js
3cc769f265a26066ba85dd668700073d1955767c
[github/Chocobozzz/PeerTube.git] / server / tests / api / utils.js
1 'use strict'
2
3 const childProcess = require('child_process')
4 const exec = childProcess.exec
5 const fork = childProcess.fork
6 const fs = require('fs')
7 const pathUtils = require('path')
8 const request = require('supertest')
9
10 const testUtils = {
11 dateIsValid: dateIsValid,
12 flushTests: flushTests,
13 getAllVideosListBy: getAllVideosListBy,
14 getClient: getClient,
15 getFriendsList: getFriendsList,
16 getVideo: getVideo,
17 getVideosList: getVideosList,
18 getVideosListPagination: getVideosListPagination,
19 getVideosListSort: getVideosListSort,
20 login: login,
21 loginAndGetAccessToken: loginAndGetAccessToken,
22 makeFriends: makeFriends,
23 quitFriends: quitFriends,
24 removeVideo: removeVideo,
25 flushAndRunMultipleServers: flushAndRunMultipleServers,
26 runServer: runServer,
27 searchVideo: searchVideo,
28 searchVideoWithPagination: searchVideoWithPagination,
29 searchVideoWithSort: searchVideoWithSort,
30 testImage: testImage,
31 uploadVideo: uploadVideo
32 }
33
34 // ---------------------- Export functions --------------------
35
36 function dateIsValid (dateString) {
37 const dateToCheck = new Date(dateString)
38 const now = new Date()
39
40 // Check if the interval is more than 2 minutes
41 if (now - dateToCheck > 120000) return false
42
43 return true
44 }
45
46 function flushTests (callback) {
47 exec('npm run clean:server:test', callback)
48 }
49
50 function getAllVideosListBy (url, end) {
51 const path = '/api/v1/videos'
52
53 request(url)
54 .get(path)
55 .query({ sort: 'createdDate' })
56 .query({ start: 0 })
57 .query({ count: 10000 })
58 .set('Accept', 'application/json')
59 .expect(200)
60 .expect('Content-Type', /json/)
61 .end(end)
62 }
63
64 function getClient (url, end) {
65 const path = '/api/v1/users/client'
66
67 request(url)
68 .get(path)
69 .set('Accept', 'application/json')
70 .expect(200)
71 .expect('Content-Type', /json/)
72 .end(end)
73 }
74
75 function getFriendsList (url, end) {
76 const path = '/api/v1/pods/'
77
78 request(url)
79 .get(path)
80 .set('Accept', 'application/json')
81 .expect(200)
82 .expect('Content-Type', /json/)
83 .end(end)
84 }
85
86 function getVideo (url, id, end) {
87 const path = '/api/v1/videos/' + id
88
89 request(url)
90 .get(path)
91 .set('Accept', 'application/json')
92 .expect(200)
93 .expect('Content-Type', /json/)
94 .end(end)
95 }
96
97 function getVideosList (url, end) {
98 const path = '/api/v1/videos'
99
100 request(url)
101 .get(path)
102 .query({ sort: 'name' })
103 .set('Accept', 'application/json')
104 .expect(200)
105 .expect('Content-Type', /json/)
106 .end(end)
107 }
108
109 function getVideosListPagination (url, start, count, end) {
110 const path = '/api/v1/videos'
111
112 request(url)
113 .get(path)
114 .query({ start: start })
115 .query({ count: count })
116 .set('Accept', 'application/json')
117 .expect(200)
118 .expect('Content-Type', /json/)
119 .end(end)
120 }
121
122 function getVideosListSort (url, sort, end) {
123 const path = '/api/v1/videos'
124
125 request(url)
126 .get(path)
127 .query({ sort: sort })
128 .set('Accept', 'application/json')
129 .expect(200)
130 .expect('Content-Type', /json/)
131 .end(end)
132 }
133
134 function login (url, client, user, expectedStatus, end) {
135 if (!end) {
136 end = expectedStatus
137 expectedStatus = 200
138 }
139
140 const path = '/api/v1/users/token'
141
142 const body = {
143 client_id: client.id,
144 client_secret: client.secret,
145 username: user.username,
146 password: user.password,
147 response_type: 'code',
148 grant_type: 'password',
149 scope: 'upload'
150 }
151
152 request(url)
153 .post(path)
154 .type('form')
155 .send(body)
156 .expect(expectedStatus)
157 .end(end)
158 }
159
160 function loginAndGetAccessToken (server, callback) {
161 login(server.url, server.client, server.user, 200, function (err, res) {
162 if (err) return callback(err)
163
164 return callback(null, res.body.access_token)
165 })
166 }
167
168 function makeFriends (url, accessToken, expectedStatus, callback) {
169 if (!callback) {
170 callback = expectedStatus
171 expectedStatus = 204
172 }
173
174 const path = '/api/v1/pods/makefriends'
175
176 // The first pod make friend with the third
177 request(url)
178 .get(path)
179 .set('Accept', 'application/json')
180 .set('Authorization', 'Bearer ' + accessToken)
181 .expect(expectedStatus)
182 .end(function (err, res) {
183 if (err) throw err
184
185 // Wait for the request between pods
186 setTimeout(callback, 1000)
187 })
188 }
189
190 function quitFriends (url, accessToken, expectedStatus, callback) {
191 if (!callback) {
192 callback = expectedStatus
193 expectedStatus = 204
194 }
195
196 const path = '/api/v1/pods/quitfriends'
197
198 // The first pod make friend with the third
199 request(url)
200 .get(path)
201 .set('Accept', 'application/json')
202 .set('Authorization', 'Bearer ' + accessToken)
203 .expect(expectedStatus)
204 .end(function (err, res) {
205 if (err) throw err
206
207 // Wait for the request between pods
208 setTimeout(callback, 1000)
209 })
210 }
211
212 function removeVideo (url, token, id, expectedStatus, end) {
213 if (!end) {
214 end = expectedStatus
215 expectedStatus = 204
216 }
217
218 const path = '/api/v1/videos'
219
220 request(url)
221 .delete(path + '/' + id)
222 .set('Accept', 'application/json')
223 .set('Authorization', 'Bearer ' + token)
224 .expect(expectedStatus)
225 .end(end)
226 }
227
228 function flushAndRunMultipleServers (totalServers, serversRun) {
229 let apps = []
230 let urls = []
231 let i = 0
232
233 function anotherServerDone (number, app, url) {
234 apps[number - 1] = app
235 urls[number - 1] = url
236 i++
237 if (i === totalServers) {
238 serversRun(apps, urls)
239 }
240 }
241
242 flushTests(function () {
243 for (let j = 1; j <= totalServers; j++) {
244 // For the virtual buffer
245 setTimeout(function () {
246 runServer(j, function (app, url) {
247 anotherServerDone(j, app, url)
248 })
249 }, 1000 * j)
250 }
251 })
252 }
253
254 function runServer (number, callback) {
255 const server = {
256 app: null,
257 url: `http://localhost:${9000 + number}`,
258 client: {
259 id: null,
260 secret: null
261 },
262 user: {
263 username: null,
264 password: null
265 }
266 }
267
268 // These actions are async so we need to be sure that they have both been done
269 const serverRunString = {
270 'Connected to mongodb': false,
271 'Server listening on port': false
272 }
273
274 const regexps = {
275 client_id: 'Client id: ([a-f0-9]+)',
276 client_secret: 'Client secret: (.+)',
277 user_username: 'Username: (.+)',
278 user_password: 'User password: (.+)'
279 }
280
281 // Share the environment
282 const env = Object.create(process.env)
283 env.NODE_ENV = 'test'
284 env.NODE_APP_INSTANCE = number
285 const options = {
286 silent: true,
287 env: env,
288 detached: true
289 }
290
291 server.app = fork(pathUtils.join(__dirname, '../../../server.js'), [], options)
292 server.app.stdout.on('data', function onStdout (data) {
293 let dontContinue = false
294
295 // Capture things if we want to
296 for (const key of Object.keys(regexps)) {
297 const regexp = regexps[key]
298 const matches = data.toString().match(regexp)
299 if (matches !== null) {
300 if (key === 'client_id') server.client.id = matches[1]
301 else if (key === 'client_secret') server.client.secret = matches[1]
302 else if (key === 'user_username') server.user.username = matches[1]
303 else if (key === 'user_password') server.user.password = matches[1]
304 }
305 }
306
307 // Check if all required sentences are here
308 for (const key of Object.keys(serverRunString)) {
309 if (data.toString().indexOf(key) !== -1) serverRunString[key] = true
310 if (serverRunString[key] === false) dontContinue = true
311 }
312
313 // If no, there is maybe one thing not already initialized (mongodb...)
314 if (dontContinue === true) return
315
316 server.app.stdout.removeListener('data', onStdout)
317 callback(server)
318 })
319 }
320
321 function searchVideo (url, search, field, end) {
322 if (!end) {
323 end = field
324 field = null
325 }
326
327 const path = '/api/v1/videos'
328 const req = request(url)
329 .get(path + '/search/' + search)
330 .set('Accept', 'application/json')
331
332 if (field) req.query({ field: field })
333 req.expect(200)
334 .expect('Content-Type', /json/)
335 .end(end)
336 }
337
338 function searchVideoWithPagination (url, search, field, start, count, end) {
339 const path = '/api/v1/videos'
340
341 request(url)
342 .get(path + '/search/' + search)
343 .query({ start: start })
344 .query({ count: count })
345 .query({ field: field })
346 .set('Accept', 'application/json')
347 .expect(200)
348 .expect('Content-Type', /json/)
349 .end(end)
350 }
351
352 function searchVideoWithSort (url, search, sort, end) {
353 const path = '/api/v1/videos'
354
355 request(url)
356 .get(path + '/search/' + search)
357 .query({ sort: sort })
358 .set('Accept', 'application/json')
359 .expect(200)
360 .expect('Content-Type', /json/)
361 .end(end)
362 }
363
364 function testImage (url, videoName, imagePath, callback) {
365 // Don't test images if the node env is not set
366 // Because we need a special ffmpeg version for this test
367 if (process.env.NODE_TEST_IMAGE) {
368 request(url)
369 .get(imagePath)
370 .expect(200)
371 .end(function (err, res) {
372 if (err) return callback(err)
373
374 fs.readFile(pathUtils.join(__dirname, 'fixtures', videoName + '.jpg'), function (err, data) {
375 if (err) return callback(err)
376
377 callback(null, data.equals(res.body))
378 })
379 })
380 } else {
381 console.log('Do not test images. Enable it by setting NODE_TEST_IMAGE env variable.')
382 callback(null, true)
383 }
384 }
385
386 function uploadVideo (url, accessToken, name, description, tags, fixture, specialStatus, end) {
387 if (!end) {
388 end = specialStatus
389 specialStatus = 204
390 }
391
392 const path = '/api/v1/videos'
393
394 const req = request(url)
395 .post(path)
396 .set('Accept', 'application/json')
397 .set('Authorization', 'Bearer ' + accessToken)
398 .field('name', name)
399 .field('description', description)
400
401 for (let i = 0; i < tags.length; i++) {
402 req.field('tags[' + i + ']', tags[i])
403 }
404
405 let filepath = ''
406 if (pathUtils.isAbsolute(fixture)) {
407 filepath = fixture
408 } else {
409 filepath = pathUtils.join(__dirname, 'fixtures', fixture)
410 }
411
412 req.attach('videofile', filepath)
413 .expect(specialStatus)
414 .end(end)
415 }
416
417 // ---------------------------------------------------------------------------
418
419 module.exports = testUtils