diff --git a/core/test/integration/api/api_upload_spec.js b/core/test/integration/api/api_upload_spec.js index 8c35a36dcd..67377c69f7 100644 --- a/core/test/integration/api/api_upload_spec.js +++ b/core/test/integration/api/api_upload_spec.js @@ -1,117 +1,163 @@ -/*globals describe, beforeEach, afterEach, it*/ -var fs = require('fs-extra'), +/*globals describe, afterEach, it*/ +var tmp = require('tmp'), should = require('should'), - sinon = require('sinon'), Promise = require('bluebird'), - storage = require('../../../server/storage'), + configUtils = require('../../utils/configUtils'), + extname = require('path').extname, // Stuff we are testing UploadAPI = require('../../../server/api/upload'), - store; + uploadimage = { + name: '', + type: '', + path: '' + }; + +function setupAndTestUpload(filename, mimeType) { + return new Promise(function (resolve, reject) { + // create a temp file (the uploaded file) + tmp.file({keep: true}, function (err, path/*, fd, cleanupFile*/) { + if (err) { + return reject(err); + } + + uploadimage.path = path; + uploadimage.name = filename; + uploadimage.type = mimeType; + + // create a temp directory (the directory that the API saves the file to) + tmp.dir({keep: true, unsafeCleanup: true}, function (err, path, cleanupDir) { + if (err) { + return reject(err); + } + + configUtils.set({ + paths: { + contentPath: path + } + }); + + UploadAPI.add({uploadimage: uploadimage}) + .then(resolve) + .catch(reject) + .finally(function () { + // remove the temporary directory (file is unlinked by the API) + cleanupDir(); + }); + }); + }); + }); +} + +function testResult(filename, result) { + var base = filename, + ext = extname(base), + regex; + + if (ext) { + base = base.split(ext)[0]; + } + + regex = new RegExp('^/content/images/[0-9]{4}/[0-9]{2}/' + base + '.*' + ext + '$'); + regex.test(result).should.be.true(); +} describe('Upload API', function () { - // Doesn't test the DB - afterEach(function () { - storage.getStorage.restore(); - fs.unlink.restore(); - }); + uploadimage = { + name: '', + type: 'application/octet-stream', + path: '' + }; - beforeEach(function () { - store = sinon.stub(); - store.save = sinon.stub().returns(Promise.resolve('URL')); - store.exists = sinon.stub().returns(Promise.resolve(true)); - store.destroy = sinon.stub().returns(Promise.resolve()); - sinon.stub(storage, 'getStorage').returns(store); - sinon.stub(fs, 'unlink').yields(); + configUtils.restore(); }); should.exist(UploadAPI); - describe('invalid file', function () { - it('should return 415 for invalid file type', function (done) { - var uploadimage = { - name: 'INVALID.FILE', - type: 'application/octet-stream', - path: '/tmp/TMPFILEID' - }; - UploadAPI.add({uploadimage: uploadimage}).then(function () { - done(new Error('Upload suceeded with invalid file.')); - }, function (result) { - result.statusCode.should.equal(415); - result.errorType.should.equal('UnsupportedMediaTypeError'); + describe('invalid file extension and mime-type', function () { + it('should return 415 for invalid file extension', function (done) { + setupAndTestUpload('test.invalid', 'application/octet-stream').then(function () { + done(new Error('Upload succeeded with invalid extension and mime-type')); + }).catch(function (err) { + should.exist(err); + err.statusCode.should.equal(415); + err.errorType.should.equal('UnsupportedMediaTypeError'); + done(); - }); + }).catch(done); }); }); describe('valid extension but invalid type', function () { - it('should return 415 for invalid file type', function (done) { - var uploadimage = { - name: 'INVALID.jpg', - type: 'application/octet-stream', - path: '/tmp/TMPFILEID' - }; - UploadAPI.add({uploadimage: uploadimage}).then(function () { - done(new Error('Upload suceeded with invalid file.')); - }, function (result) { - result.statusCode.should.equal(415); - result.errorType.should.equal('UnsupportedMediaTypeError'); + it('should return 415 for mime-type', function (done) { + setupAndTestUpload('test.jpg', 'application/octet-stream').then(function () { + done(new Error('Upload succeeded with invalid mime-type')); + }).catch(function (err) { + should.exist(err); + err.statusCode.should.equal(415); + err.errorType.should.equal('UnsupportedMediaTypeError'); + done(); - }); + }).catch(done); }); }); describe('valid file', function () { it('can upload jpg', function (done) { - var uploadimage = { - name: 'INVALID.jpg', - type: 'image/jpeg', - path: '/tmp/TMPFILEID' - }; - UploadAPI.add({uploadimage: uploadimage}).then(function (result) { - result.should.equal('URL'); + var filename = 'test.jpg'; + + setupAndTestUpload(filename, 'image/jpeg').then(function (url) { + testResult(filename, url); + done(); - }); + }).catch(done); }); it('cannot upload jpg with incorrect extension', function (done) { - var uploadimage = { - name: 'INVALID.xjpg', - type: 'image/jpeg', - path: '/tmp/TMPFILEID' - }; - UploadAPI.add({uploadimage: uploadimage}).then(function () { - done(new Error('Upload suceeded with invalid file.')); - }, function (result) { - result.statusCode.should.equal(415); - result.errorType.should.equal('UnsupportedMediaTypeError'); + setupAndTestUpload('invalid.xjpg', 'image/jpeg').then(function () { + done(new Error('Upload succeeded with invalid extension')); + }).catch(function (err) { + should.exist(err); + err.statusCode.should.equal(415); + err.errorType.should.equal('UnsupportedMediaTypeError'); + done(); - }); + }).catch(done); }); it('can upload png', function (done) { - var uploadimage = { - name: 'INVALID.png', - type: 'image/png', - path: '/tmp/TMPFILEID' - }; - UploadAPI.add({uploadimage: uploadimage}).then(function (result) { - result.should.equal('URL'); + var filename = 'test.png'; + + setupAndTestUpload(filename, 'image/png').then(function (url) { + testResult(filename, url); + done(); - }); + }).catch(done); }); it('can upload gif', function (done) { - var uploadimage = { - name: 'INVALID.gif', - type: 'image/gif', - path: '/tmp/TMPFILEID' - }; - UploadAPI.add({uploadimage: uploadimage}).then(function (result) { - result.should.equal('URL'); + var filename = 'test.gif'; + + setupAndTestUpload(filename, 'image/gif').then(function (url) { + testResult(filename, url); + done(); - }); + }).catch(done); + }); + }); + + describe('missing file', function () { + it('throws an error if no file is provided', function (done) { + UploadAPI.add({}).then(function () { + done(new Error('Upload succeeded with invalid extension')); + }).catch(function (err) { + should.exist(err); + err.statusCode.should.equal(403); + err.errorType.should.equal('NoPermissionError'); + + done(); + }).catch(done); }); }); }); diff --git a/package.json b/package.json index e91ebbb905..cc5271311d 100644 --- a/package.json +++ b/package.json @@ -100,9 +100,20 @@ "should-http": "0.0.4", "sinon": "1.17.3", "supertest": "1.1.0", + "tmp": "0.0.28", "top-gh-contribs": "2.0.2" }, "greenkeeper": { - "ignore": ["bower", "bluebird", "glob", "lodash", "mysql", "nodemailer", "pg", "showdown-ghost", "validator"] + "ignore": [ + "bower", + "bluebird", + "glob", + "lodash", + "mysql", + "nodemailer", + "pg", + "showdown-ghost", + "validator" + ] } }