UNPKG

14.1 kBJavaScriptView Raw
1'use strict';
2
3const fs = require('fs');
4const md5 = require('md5');
5const path = require('path');
6const request = require('supertest');
7const server = require('./server');
8
9const fileDir = server.fileDir;
10const tempDir = server.tempDir;
11const uploadDir = server.uploadDir;
12const clearTempDir = server.clearTempDir;
13const clearUploadsDir = server.clearUploadsDir;
14
15const mockFiles = ['car.png', 'tree.png', 'basketball.png'];
16
17const mockUser = {
18 firstName: 'Joe',
19 lastName: 'Schmo',
20 email: 'joe@mailinator.com'
21};
22
23// Reset response body.uploadDir/uploadPath for testing.
24const resetBodyUploadData = (res) => {
25 res.body.uploadDir = '';
26 res.body.uploadPath = '';
27};
28
29const genUploadResult = (fileName, filePath) => {
30 const fileStat = fs.statSync(filePath);
31 const fileBuffer = fs.readFileSync(filePath);
32 return {
33 name: fileName,
34 md5: md5(fileBuffer),
35 size: fileStat.size,
36 uploadDir: '',
37 uploadPath: ''
38 };
39};
40
41describe('Test Directory Cleaning Method', function() {
42 it('emptied "uploads" directory', function(done) {
43 clearUploadsDir();
44 const filesFound = fs.readdirSync(uploadDir).length;
45 done(filesFound ? `Directory not empty. Found ${filesFound} files.` : null);
46 });
47});
48
49describe('Test Single File Upload', function() {
50 const app = server.setup();
51
52 mockFiles.forEach((fileName) => {
53 const filePath = path.join(fileDir, fileName);
54 const uploadedFilePath = path.join(uploadDir, fileName);
55 const result = genUploadResult(fileName, filePath);
56
57 it(`upload ${fileName} with POST`, function(done) {
58 clearUploadsDir();
59 request(app)
60 .post('/upload/single')
61 .attach('testFile', filePath)
62 .expect(resetBodyUploadData)
63 .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
64 });
65
66 it(`upload ${fileName} with PUT`, function(done) {
67 clearUploadsDir();
68 request(app)
69 .post('/upload/single')
70 .attach('testFile', filePath)
71 .expect(resetBodyUploadData)
72 .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
73 });
74 });
75
76 it('fail when no files were attached', function(done) {
77 request(app)
78 .post('/upload/single')
79 .expect(400)
80 .end(done);
81 });
82
83 it('fail when using GET', function(done) {
84 request(app)
85 .get('/upload/single')
86 .attach('testFile', path.join(fileDir, mockFiles[0]))
87 .expect(400)
88 .end(done);
89 });
90
91 it('fail when using HEAD', function(done) {
92 request(app)
93 .head('/upload/single')
94 .attach('testFile', path.join(fileDir, mockFiles[0]))
95 .expect(400)
96 .end(done);
97 });
98});
99
100describe('Test Single File Upload w/ .mv()', function() {
101 const app = server.setup();
102
103 mockFiles.forEach((fileName) => {
104 const filePath = path.join(fileDir, fileName);
105 const uploadedFilePath = path.join(uploadDir, fileName);
106 const result = genUploadResult(fileName, filePath);
107
108 it(`upload ${fileName} with POST w/ .mv()`, function(done) {
109 clearUploadsDir();
110 request(app)
111 .post('/upload/single')
112 .attach('testFile', filePath)
113 .expect(resetBodyUploadData)
114 .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
115 });
116
117 it(`upload ${fileName} with PUT w/ .mv()`, function(done) {
118 clearUploadsDir();
119 request(app)
120 .post('/upload/single')
121 .attach('testFile', filePath)
122 .expect(resetBodyUploadData)
123 .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
124 });
125 });
126});
127
128describe('Test Single File Upload with useTempFiles option.', function() {
129 const app = server.setup({ useTempFiles: true, tempFileDir: tempDir });
130
131 mockFiles.forEach((fileName) => {
132 const filePath = path.join(fileDir, fileName);
133 const uploadedFilePath = path.join(uploadDir, fileName);
134 const result = genUploadResult(fileName, filePath);
135
136 it(`upload ${fileName} with POST`, function(done) {
137 clearUploadsDir();
138 request(app)
139 .post('/upload/single')
140 .attach('testFile', filePath)
141 .expect(resetBodyUploadData)
142 .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
143 });
144
145 it(`upload ${fileName} with PUT`, function(done) {
146 clearUploadsDir();
147 request(app)
148 .post('/upload/single')
149 .attach('testFile', filePath)
150 .expect(resetBodyUploadData)
151 .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
152 });
153 });
154
155 it('fail when no files were attached', function(done) {
156 request(app)
157 .post('/upload/single')
158 .expect(400)
159 .end(done);
160 });
161
162 it('fail when using GET', function(done) {
163 request(app)
164 .get('/upload/single')
165 .attach('testFile', path.join(fileDir, mockFiles[0]))
166 .expect(400)
167 .end(done);
168 });
169
170 it('fail when using HEAD', function(done) {
171 request(app)
172 .head('/upload/single')
173 .attach('testFile', path.join(fileDir, mockFiles[0]))
174 .expect(400)
175 .end(done);
176 });
177});
178
179describe('Test Single File Upload with useTempFiles option and empty tempFileDir.', function() {
180 const app = server.setup({ useTempFiles: true, tempFileDir: '' });
181
182 mockFiles.forEach((fileName) => {
183 const filePath = path.join(fileDir, fileName);
184 const uploadedFilePath = path.join(uploadDir, fileName);
185 const result = genUploadResult(fileName, filePath);
186
187 it(`upload ${fileName} with POST`, function(done) {
188 clearUploadsDir();
189 request(app)
190 .post('/upload/single')
191 .attach('testFile', filePath)
192 .expect(resetBodyUploadData)
193 .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
194 });
195 });
196});
197
198describe('Test Single File Upload w/ .mv() Promise', function() {
199 const app = server.setup();
200
201 mockFiles.forEach((fileName) => {
202 const filePath = path.join(fileDir, fileName);
203 const uploadedFilePath = path.join(uploadDir, fileName);
204 const result = genUploadResult(fileName, filePath);
205
206 it(`upload ${fileName} with POST w/ .mv() Promise`, function(done) {
207 clearUploadsDir();
208 request(app)
209 .post('/upload/single/promise')
210 .attach('testFile', filePath)
211 .expect(resetBodyUploadData)
212 .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
213 });
214
215 it(`upload ${fileName} with PUT w/ .mv() Promise`, function(done) {
216 clearUploadsDir();
217 request(app)
218 .post('/upload/single/promise')
219 .attach('testFile', filePath)
220 .expect(resetBodyUploadData)
221 .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
222 });
223 });
224
225 it('fail when no files were attached', function(done) {
226 request(app)
227 .post('/upload/single')
228 .expect(400)
229 .end(done);
230 });
231
232 it('fail when using GET', function(done) {
233 request(app)
234 .get('/upload/single')
235 .attach('testFile', path.join(fileDir, mockFiles[0]))
236 .expect(400)
237 .end(done);
238 });
239
240 it('fail when using HEAD', function(done) {
241 request(app)
242 .head('/upload/single')
243 .attach('testFile', path.join(fileDir, mockFiles[0]))
244 .expect(400)
245 .end(done);
246 });
247});
248
249describe('Test Single File Upload w/ .mv() Promise and useTempFiles set to true', function() {
250 const app = server.setup({ useTempFiles: true, tempFileDir: tempDir });
251
252 mockFiles.forEach((fileName) => {
253 const filePath = path.join(fileDir, fileName);
254 const uploadedFilePath = path.join(uploadDir, fileName);
255 const result = genUploadResult(fileName, filePath);
256
257 it(`upload ${fileName} with POST w/ .mv() Promise`, function(done) {
258 clearUploadsDir();
259 request(app)
260 .post('/upload/single/promise')
261 .attach('testFile', filePath)
262 .expect(resetBodyUploadData)
263 .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
264 });
265
266 it(`upload ${fileName} with PUT w/ .mv() Promise`, function(done) {
267 clearUploadsDir();
268 request(app)
269 .post('/upload/single/promise')
270 .attach('testFile', filePath)
271 .expect(resetBodyUploadData)
272 .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
273 });
274 });
275
276 it('fail when no files were attached', (done) => {
277 request(app)
278 .post('/upload/single')
279 .expect(400)
280 .end(done);
281 });
282
283 it('fail when using GET', (done) => {
284 request(app)
285 .get('/upload/single')
286 .attach('testFile', path.join(fileDir, mockFiles[0]))
287 .expect(400)
288 .end(done);
289 });
290
291 it('fail when using HEAD', (done) => {
292 request(app)
293 .head('/upload/single')
294 .attach('testFile', path.join(fileDir, mockFiles[0]))
295 .expect(400)
296 .end(done);
297 });
298});
299
300describe('Test Multi-File Upload', function() {
301 const app = server.setup();
302
303 it('upload multiple files with POST', (done) => {
304 clearUploadsDir();
305 const req = request(app).post('/upload/multiple');
306 const expectedResult = [];
307 const expectedResultSorted = [];
308 const uploadedFilesPath = [];
309 mockFiles.forEach((fileName, index) => {
310 const filePath = path.join(fileDir, fileName);
311 req.attach(`testFile${index + 1}`, filePath);
312 uploadedFilesPath.push(path.join(uploadDir, fileName));
313 expectedResult.push(genUploadResult(fileName, filePath));
314 });
315
316 req
317 .expect((res) => {
318 res.body.forEach((fileInfo) => {
319 fileInfo.uploadDir = '';
320 fileInfo.uploadPath = '';
321 const index = mockFiles.indexOf(fileInfo.name);
322 expectedResultSorted.push(expectedResult[index]);
323 });
324 })
325 .expect(200, expectedResultSorted)
326 .end((err) => {
327 if (err) return done(err);
328 fs.stat(uploadedFilesPath[0], (err) => {
329 if (err) return done(err);
330 fs.stat(uploadedFilesPath[1], (err) => {
331 if (err) return done(err);
332 fs.stat(uploadedFilesPath[2], done);
333 });
334 });
335 });
336 });
337});
338
339describe('Test File Array Upload', function() {
340 const app = server.setup();
341
342 it('upload array of files with POST', (done) => {
343 clearUploadsDir();
344 const req = request(app).post('/upload/array');
345 const expectedResult = [];
346 const expectedResultSorted = [];
347 const uploadedFilesPath = [];
348 mockFiles.forEach((fileName) => {
349 const filePath = path.join(fileDir, fileName);
350 uploadedFilesPath.push(path.join(uploadDir, fileName));
351 expectedResult.push(genUploadResult(fileName, filePath));
352 req.attach('testFiles', filePath);
353 });
354
355 req
356 .expect((res)=>{
357 res.body.forEach((fileInfo) => {
358 fileInfo.uploadDir = '';
359 fileInfo.uploadPath = '';
360 const index = mockFiles.indexOf(fileInfo.name);
361 expectedResultSorted.push(expectedResult[index]);
362 });
363 })
364 .expect(200, expectedResultSorted)
365 .end((err) => {
366 if (err) return done(err);
367 uploadedFilesPath.forEach((uploadedFilePath) => {
368 fs.statSync(uploadedFilePath);
369 });
370 done();
371 });
372 });
373});
374
375describe('Test Upload With Fields', function() {
376 const app = server.setup();
377 mockFiles.forEach((fileName) => {
378 const filePath = path.join(fileDir, fileName);
379 const uploadedFilePath = path.join(uploadDir, fileName);
380 // Expected results
381 const result = genUploadResult(fileName, filePath);
382 result.firstName = mockUser.firstName;
383 result.lastName = mockUser.lastName;
384 result.email = mockUser.email;
385
386 it(`upload ${fileName} and submit fields at the same time with POST`, function(done) {
387 clearUploadsDir();
388 request(app)
389 .post('/upload/single/withfields')
390 .attach('testFile', filePath)
391 .field('firstName', mockUser.firstName)
392 .field('lastName', mockUser.lastName)
393 .field('email', mockUser.email)
394 .expect(resetBodyUploadData)
395 .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
396 });
397
398 it(`upload ${fileName} and submit fields at the same time with PUT`, function(done) {
399 clearUploadsDir();
400 request(app)
401 .put('/upload/single/withfields')
402 .attach('testFile', filePath)
403 .field('firstName', mockUser.firstName)
404 .field('lastName', mockUser.lastName)
405 .field('email', mockUser.email)
406 .expect(resetBodyUploadData)
407 .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
408 });
409 });
410});
411
412describe('Test Aborting/Canceling during upload', function() {
413 this.timeout(4000); // Set timeout for async tests.
414 const uploadTimeout = 1000;
415
416 const app = server.setup({
417 useTempFiles: true,
418 tempFileDir: tempDir,
419 debug: true,
420 uploadTimeout
421 });
422
423 clearTempDir();
424 clearUploadsDir();
425 mockFiles.forEach((fileName) => {
426 const filePath = path.join(fileDir, fileName);
427
428 it(`Delete temp file if ${fileName} upload was aborted`, (done) => {
429 const req = request(app)
430 .post('/upload/single')
431 .attach('testFile', filePath)
432 .on('progress', (e) => {
433 const progress = (e.loaded * 100) / e.total;
434 // Aborting request, use req.req since it is original superagent request.
435 if (progress > 50) req.req.abort();
436 })
437 .end((err) => {
438 if (!err) return done(`Connection hasn't been aborted!`);
439 if (err.code !== 'ECONNRESET') return done(err);
440 // err.code === 'ECONNRESET' that means upload has been aborted.
441 // Checking temp directory after upload timeout.
442 setTimeout(() => {
443 fs.readdir(tempDir, (err, files) => {
444 if (err) return done(err);
445 return files.length ? done(`Temporary directory contains files!`) : done();
446 });
447 }, uploadTimeout * 2);
448 });
449 });
450 });
451});