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