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