You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
452 lines
14 KiB
452 lines
14 KiB
4 years ago
|
'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);
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|