123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451 |
- 'use strict';
- const fs = require('fs');
- const md5 = require('md5');
- const path = require('path');
- const request = require('supertest');
- const server = require('./server');
- const fileDir = server.fileDir;
- const tempDir = server.tempDir;
- const uploadDir = server.uploadDir;
- const clearTempDir = server.clearTempDir;
- const clearUploadsDir = server.clearUploadsDir;
- const mockFiles = ['car.png', 'tree.png', 'basketball.png', 'emptyfile.txt'];
- const mockUser = {
- firstName: 'Joe',
- lastName: 'Schmo',
- email: 'joe@mailinator.com'
- };
- // Reset response body.uploadDir/uploadPath for testing.
- const resetBodyUploadData = (res) => {
- res.body.uploadDir = '';
- res.body.uploadPath = '';
- };
- const genUploadResult = (fileName, filePath) => {
- const fileStat = fs.statSync(filePath);
- const fileBuffer = fs.readFileSync(filePath);
- return {
- name: fileName,
- md5: md5(fileBuffer),
- size: fileStat.size,
- uploadDir: '',
- uploadPath: ''
- };
- };
- describe('Test Directory Cleaning Method', function() {
- it('emptied "uploads" directory', function(done) {
- clearUploadsDir();
- const filesFound = fs.readdirSync(uploadDir).length;
- done(filesFound ? `Directory not empty. Found ${filesFound} files.` : null);
- });
- });
- describe('Test Single File Upload', function() {
- const app = server.setup();
- mockFiles.forEach((fileName) => {
- const filePath = path.join(fileDir, fileName);
- const uploadedFilePath = path.join(uploadDir, fileName);
- const result = genUploadResult(fileName, filePath);
- it(`upload ${fileName} with POST`, function(done) {
- clearUploadsDir();
- request(app)
- .post('/upload/single')
- .attach('testFile', filePath)
- .expect(resetBodyUploadData)
- .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
- });
- it(`upload ${fileName} with PUT`, function(done) {
- clearUploadsDir();
- request(app)
- .post('/upload/single')
- .attach('testFile', filePath)
- .expect(resetBodyUploadData)
- .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
- });
- });
- it('fail when no files were attached', function(done) {
- request(app)
- .post('/upload/single')
- .expect(400)
- .end(done);
- });
- it('fail when using GET', function(done) {
- request(app)
- .get('/upload/single')
- .attach('testFile', path.join(fileDir, mockFiles[0]))
- .expect(400)
- .end(done);
- });
- it('fail when using HEAD', function(done) {
- request(app)
- .head('/upload/single')
- .attach('testFile', path.join(fileDir, mockFiles[0]))
- .expect(400)
- .end(done);
- });
- });
- describe('Test Single File Upload w/ .mv()', function() {
- const app = server.setup();
- mockFiles.forEach((fileName) => {
- const filePath = path.join(fileDir, fileName);
- const uploadedFilePath = path.join(uploadDir, fileName);
- const result = genUploadResult(fileName, filePath);
- it(`upload ${fileName} with POST w/ .mv()`, function(done) {
- clearUploadsDir();
- request(app)
- .post('/upload/single')
- .attach('testFile', filePath)
- .expect(resetBodyUploadData)
- .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
- });
- it(`upload ${fileName} with PUT w/ .mv()`, function(done) {
- clearUploadsDir();
- request(app)
- .post('/upload/single')
- .attach('testFile', filePath)
- .expect(resetBodyUploadData)
- .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
- });
- });
- });
- describe('Test Single File Upload with useTempFiles option.', function() {
- const app = server.setup({ useTempFiles: true, tempFileDir: tempDir });
- mockFiles.forEach((fileName) => {
- const filePath = path.join(fileDir, fileName);
- const uploadedFilePath = path.join(uploadDir, fileName);
- const result = genUploadResult(fileName, filePath);
-
- it(`upload ${fileName} with POST`, function(done) {
- clearUploadsDir();
- request(app)
- .post('/upload/single')
- .attach('testFile', filePath)
- .expect(resetBodyUploadData)
- .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
- });
- it(`upload ${fileName} with PUT`, function(done) {
- clearUploadsDir();
- request(app)
- .post('/upload/single')
- .attach('testFile', filePath)
- .expect(resetBodyUploadData)
- .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
- });
- });
- it('fail when no files were attached', function(done) {
- request(app)
- .post('/upload/single')
- .expect(400)
- .end(done);
- });
- it('fail when using GET', function(done) {
- request(app)
- .get('/upload/single')
- .attach('testFile', path.join(fileDir, mockFiles[0]))
- .expect(400)
- .end(done);
- });
- it('fail when using HEAD', function(done) {
- request(app)
- .head('/upload/single')
- .attach('testFile', path.join(fileDir, mockFiles[0]))
- .expect(400)
- .end(done);
- });
- });
- describe('Test Single File Upload with useTempFiles option and empty tempFileDir.', function() {
- const app = server.setup({ useTempFiles: true, tempFileDir: '' });
- mockFiles.forEach((fileName) => {
- const filePath = path.join(fileDir, fileName);
- const uploadedFilePath = path.join(uploadDir, fileName);
- const result = genUploadResult(fileName, filePath);
- it(`upload ${fileName} with POST`, function(done) {
- clearUploadsDir();
- request(app)
- .post('/upload/single')
- .attach('testFile', filePath)
- .expect(resetBodyUploadData)
- .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
- });
- });
- });
- describe('Test Single File Upload w/ .mv() Promise', function() {
- const app = server.setup();
- mockFiles.forEach((fileName) => {
- const filePath = path.join(fileDir, fileName);
- const uploadedFilePath = path.join(uploadDir, fileName);
- const result = genUploadResult(fileName, filePath);
-
- it(`upload ${fileName} with POST w/ .mv() Promise`, function(done) {
- clearUploadsDir();
- request(app)
- .post('/upload/single/promise')
- .attach('testFile', filePath)
- .expect(resetBodyUploadData)
- .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
- });
- it(`upload ${fileName} with PUT w/ .mv() Promise`, function(done) {
- clearUploadsDir();
- request(app)
- .post('/upload/single/promise')
- .attach('testFile', filePath)
- .expect(resetBodyUploadData)
- .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
- });
- });
- it('fail when no files were attached', function(done) {
- request(app)
- .post('/upload/single')
- .expect(400)
- .end(done);
- });
- it('fail when using GET', function(done) {
- request(app)
- .get('/upload/single')
- .attach('testFile', path.join(fileDir, mockFiles[0]))
- .expect(400)
- .end(done);
- });
- it('fail when using HEAD', function(done) {
- request(app)
- .head('/upload/single')
- .attach('testFile', path.join(fileDir, mockFiles[0]))
- .expect(400)
- .end(done);
- });
- });
- describe('Test Single File Upload w/ .mv() Promise and useTempFiles set to true', function() {
- const app = server.setup({ useTempFiles: true, tempFileDir: tempDir });
- mockFiles.forEach((fileName) => {
- const filePath = path.join(fileDir, fileName);
- const uploadedFilePath = path.join(uploadDir, fileName);
- const result = genUploadResult(fileName, filePath);
-
- it(`upload ${fileName} with POST w/ .mv() Promise`, function(done) {
- clearUploadsDir();
- request(app)
- .post('/upload/single/promise')
- .attach('testFile', filePath)
- .expect(resetBodyUploadData)
- .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
- });
- it(`upload ${fileName} with PUT w/ .mv() Promise`, function(done) {
- clearUploadsDir();
- request(app)
- .post('/upload/single/promise')
- .attach('testFile', filePath)
- .expect(resetBodyUploadData)
- .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
- });
- });
- it('fail when no files were attached', (done) => {
- request(app)
- .post('/upload/single')
- .expect(400)
- .end(done);
- });
- it('fail when using GET', (done) => {
- request(app)
- .get('/upload/single')
- .attach('testFile', path.join(fileDir, mockFiles[0]))
- .expect(400)
- .end(done);
- });
- it('fail when using HEAD', (done) => {
- request(app)
- .head('/upload/single')
- .attach('testFile', path.join(fileDir, mockFiles[0]))
- .expect(400)
- .end(done);
- });
- });
- describe('Test Multi-File Upload', function() {
- const app = server.setup();
- it('upload multiple files with POST', (done) => {
- clearUploadsDir();
- const req = request(app).post('/upload/multiple');
- const expectedResult = [];
- const expectedResultSorted = [];
- const uploadedFilesPath = [];
- mockFiles.forEach((fileName, index) => {
- const filePath = path.join(fileDir, fileName);
- req.attach(`testFile${index + 1}`, filePath);
- uploadedFilesPath.push(path.join(uploadDir, fileName));
- expectedResult.push(genUploadResult(fileName, filePath));
- });
- req
- .expect((res) => {
- res.body.forEach((fileInfo) => {
- fileInfo.uploadDir = '';
- fileInfo.uploadPath = '';
- const index = mockFiles.indexOf(fileInfo.name);
- expectedResultSorted.push(expectedResult[index]);
- });
- })
- .expect(200, expectedResultSorted)
- .end((err) => {
- if (err) return done(err);
- fs.stat(uploadedFilesPath[0], (err) => {
- if (err) return done(err);
- fs.stat(uploadedFilesPath[1], (err) => {
- if (err) return done(err);
- fs.stat(uploadedFilesPath[2], done);
- });
- });
- });
- });
- });
- describe('Test File Array Upload', function() {
- const app = server.setup();
- it('upload array of files with POST', (done) => {
- clearUploadsDir();
- const req = request(app).post('/upload/array');
- const expectedResult = [];
- const expectedResultSorted = [];
- const uploadedFilesPath = [];
- mockFiles.forEach((fileName) => {
- const filePath = path.join(fileDir, fileName);
- uploadedFilesPath.push(path.join(uploadDir, fileName));
- expectedResult.push(genUploadResult(fileName, filePath));
- req.attach('testFiles', filePath);
- });
- req
- .expect((res)=>{
- res.body.forEach((fileInfo) => {
- fileInfo.uploadDir = '';
- fileInfo.uploadPath = '';
- const index = mockFiles.indexOf(fileInfo.name);
- expectedResultSorted.push(expectedResult[index]);
- });
- })
- .expect(200, expectedResultSorted)
- .end((err) => {
- if (err) return done(err);
- uploadedFilesPath.forEach((uploadedFilePath) => {
- fs.statSync(uploadedFilePath);
- });
- done();
- });
- });
- });
- describe('Test Upload With Fields', function() {
- const app = server.setup();
- mockFiles.forEach((fileName) => {
- const filePath = path.join(fileDir, fileName);
- const uploadedFilePath = path.join(uploadDir, fileName);
- // Expected results
- const result = genUploadResult(fileName, filePath);
- result.firstName = mockUser.firstName;
- result.lastName = mockUser.lastName;
- result.email = mockUser.email;
- it(`upload ${fileName} and submit fields at the same time with POST`, function(done) {
- clearUploadsDir();
- request(app)
- .post('/upload/single/withfields')
- .attach('testFile', filePath)
- .field('firstName', mockUser.firstName)
- .field('lastName', mockUser.lastName)
- .field('email', mockUser.email)
- .expect(resetBodyUploadData)
- .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
- });
- it(`upload ${fileName} and submit fields at the same time with PUT`, function(done) {
- clearUploadsDir();
- request(app)
- .put('/upload/single/withfields')
- .attach('testFile', filePath)
- .field('firstName', mockUser.firstName)
- .field('lastName', mockUser.lastName)
- .field('email', mockUser.email)
- .expect(resetBodyUploadData)
- .expect(200, result, err => (err ? done(err) : fs.stat(uploadedFilePath, done)));
- });
- });
- });
- describe('Test Aborting/Canceling during upload', function() {
- this.timeout(4000); // Set timeout for async tests.
- const uploadTimeout = 1000;
- const app = server.setup({
- useTempFiles: true,
- tempFileDir: tempDir,
- debug: true,
- uploadTimeout
- });
- clearTempDir();
- clearUploadsDir();
- mockFiles.forEach((fileName) => {
- const filePath = path.join(fileDir, fileName);
- it(`Delete temp file if ${fileName} upload was aborted`, (done) => {
- const req = request(app)
- .post('/upload/single')
- .attach('testFile', filePath)
- .on('progress', (e) => {
- const progress = (e.loaded * 100) / e.total;
- // Aborting request, use req.req since it is original superagent request.
- if (progress > 50) req.req.abort();
- })
- .end((err) => {
- if (!err) return done(`Connection hasn't been aborted!`);
- if (err.code !== 'ECONNRESET') return done(err);
- // err.code === 'ECONNRESET' that means upload has been aborted.
- // Checking temp directory after upload timeout.
- setTimeout(() => {
- fs.readdir(tempDir, (err, files) => {
- if (err) return done(err);
- return files.length ? done(`Temporary directory contains files!`) : done();
- });
- }, uploadTimeout * 2);
- });
- });
- });
- });
|