diff --git a/services/filestore/test/unit/js/AWSSDKPersistorManagerTests.js b/services/filestore/test/unit/js/AWSSDKPersistorManagerTests.js index da31ee399a..ea88da71c3 100644 --- a/services/filestore/test/unit/js/AWSSDKPersistorManagerTests.js +++ b/services/filestore/test/unit/js/AWSSDKPersistorManagerTests.js @@ -11,351 +11,499 @@ * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const sinon = require('sinon'); -const chai = require('chai'); +const sinon = require('sinon') +const chai = require('chai') -const should = chai.should(); -const { - expect -} = chai; +const should = chai.should() +const { expect } = chai -const modulePath = "../../../app/js/AWSSDKPersistorManager.js"; -const SandboxedModule = require('sandboxed-module'); +const modulePath = '../../../app/js/AWSSDKPersistorManager.js' +const SandboxedModule = require('sandboxed-module') -describe("AWSSDKPersistorManager", function() { - beforeEach(function() { - this.settings = { - filestore: { - backend: "aws-sdk" - } - }; - this.s3 = { - upload: sinon.stub(), - getObject: sinon.stub(), - copyObject: sinon.stub(), - deleteObject: sinon.stub(), - listObjects: sinon.stub(), - deleteObjects: sinon.stub(), - headObject: sinon.stub() - }; - this.awssdk = - {S3: sinon.stub().returns(this.s3)}; +describe('AWSSDKPersistorManager', function() { + beforeEach(function() { + this.settings = { + filestore: { + backend: 'aws-sdk' + } + } + this.s3 = { + upload: sinon.stub(), + getObject: sinon.stub(), + copyObject: sinon.stub(), + deleteObject: sinon.stub(), + listObjects: sinon.stub(), + deleteObjects: sinon.stub(), + headObject: sinon.stub() + } + this.awssdk = { S3: sinon.stub().returns(this.s3) } - this.requires = { - "aws-sdk": this.awssdk, - "settings-sharelatex": this.settings, - "logger-sharelatex": { - log() {}, - err() {} - }, - "fs": (this.fs = - {createReadStream: sinon.stub()}), - "./Errors": (this.Errors = - {NotFoundError: sinon.stub()}) - }; - this.key = "my/key"; - this.bucketName = "my-bucket"; - this.error = "my error"; - return this.AWSSDKPersistorManager = SandboxedModule.require(modulePath, {requires: this.requires}); - }); + this.requires = { + 'aws-sdk': this.awssdk, + 'settings-sharelatex': this.settings, + 'logger-sharelatex': { + log() {}, + err() {} + }, + fs: (this.fs = { createReadStream: sinon.stub() }), + './Errors': (this.Errors = { NotFoundError: sinon.stub() }) + } + this.key = 'my/key' + this.bucketName = 'my-bucket' + this.error = 'my error' + return (this.AWSSDKPersistorManager = SandboxedModule.require(modulePath, { + requires: this.requires + })) + }) - describe("sendFile", function() { - beforeEach(function() { - this.stream = {}; - this.fsPath = "/usr/local/some/file"; - return this.fs.createReadStream.returns(this.stream); - }); + describe('sendFile', function() { + beforeEach(function() { + this.stream = {} + this.fsPath = '/usr/local/some/file' + return this.fs.createReadStream.returns(this.stream) + }) - it("should put the file with s3.upload", function(done) { - this.s3.upload.callsArgWith(1); - return this.AWSSDKPersistorManager.sendFile(this.bucketName, this.key, this.fsPath, err => { - expect(err).to.not.be.ok; - expect(this.s3.upload.calledOnce, "called only once").to.be.true; - expect((this.s3.upload.calledWith({Bucket: this.bucketName, Key: this.key, Body: this.stream})) - , "called with correct arguments").to.be.true; - return done(); - }); - }); + it('should put the file with s3.upload', function(done) { + this.s3.upload.callsArgWith(1) + return this.AWSSDKPersistorManager.sendFile( + this.bucketName, + this.key, + this.fsPath, + err => { + expect(err).to.not.be.ok + expect(this.s3.upload.calledOnce, 'called only once').to.be.true + expect( + this.s3.upload.calledWith({ + Bucket: this.bucketName, + Key: this.key, + Body: this.stream + }), + 'called with correct arguments' + ).to.be.true + return done() + } + ) + }) - return it("should dispatch the error from s3.upload", function(done) { - this.s3.upload.callsArgWith(1, this.error); - return this.AWSSDKPersistorManager.sendFile(this.bucketName, this.key, this.fsPath, err => { - expect(err).to.equal(this.error); - return done(); - }); - }); - }); + return it('should dispatch the error from s3.upload', function(done) { + this.s3.upload.callsArgWith(1, this.error) + return this.AWSSDKPersistorManager.sendFile( + this.bucketName, + this.key, + this.fsPath, + err => { + expect(err).to.equal(this.error) + return done() + } + ) + }) + }) + describe('sendStream', function() { + beforeEach(function() { + return (this.stream = {}) + }) - describe("sendStream", function() { - beforeEach(function() { - return this.stream = {};}); + it('should put the file with s3.upload', function(done) { + this.s3.upload.callsArgWith(1) + return this.AWSSDKPersistorManager.sendStream( + this.bucketName, + this.key, + this.stream, + err => { + expect(err).to.not.be.ok + expect(this.s3.upload.calledOnce, 'called only once').to.be.true + expect( + this.s3.upload.calledWith({ + Bucket: this.bucketName, + Key: this.key, + Body: this.stream + }), + 'called with correct arguments' + ).to.be.true + return done() + } + ) + }) - it("should put the file with s3.upload", function(done) { - this.s3.upload.callsArgWith(1); - return this.AWSSDKPersistorManager.sendStream(this.bucketName, this.key, this.stream, err => { - expect(err).to.not.be.ok; - expect(this.s3.upload.calledOnce, "called only once").to.be.true; - expect((this.s3.upload.calledWith({Bucket: this.bucketName, Key: this.key, Body: this.stream})), - "called with correct arguments").to.be.true; - return done(); - }); - }); + return it('should dispatch the error from s3.upload', function(done) { + this.s3.upload.callsArgWith(1, this.error) + return this.AWSSDKPersistorManager.sendStream( + this.bucketName, + this.key, + this.stream, + err => { + expect(err).to.equal(this.error) + return done() + } + ) + }) + }) - return it("should dispatch the error from s3.upload", function(done) { - this.s3.upload.callsArgWith(1, this.error); - return this.AWSSDKPersistorManager.sendStream(this.bucketName, this.key, this.stream, err => { - expect(err).to.equal(this.error); - return done(); - }); - }); - }); + describe('getFileStream', function() { + beforeEach(function() { + this.opts = {} + this.stream = {} + this.read_stream = { on: (this.read_stream_on = sinon.stub()) } + this.object = { createReadStream: sinon.stub().returns(this.read_stream) } + return this.s3.getObject.returns(this.object) + }) - describe("getFileStream", function() { - beforeEach(function() { - this.opts = {}; - this.stream = {}; - this.read_stream = - {on: (this.read_stream_on = sinon.stub())}; - this.object = - {createReadStream: sinon.stub().returns(this.read_stream)}; - return this.s3.getObject.returns(this.object); - }); + it('should return a stream from s3.getObject', function(done) { + this.read_stream_on.withArgs('readable').callsArgWith(1) - it("should return a stream from s3.getObject", function(done) { - this.read_stream_on.withArgs('readable').callsArgWith(1); + return this.AWSSDKPersistorManager.getFileStream( + this.bucketName, + this.key, + this.opts, + (err, stream) => { + expect(this.read_stream_on.calledTwice) + expect(err).to.not.be.ok + expect(stream, 'returned the stream').to.equal(this.read_stream) + expect( + this.s3.getObject.calledWith({ + Bucket: this.bucketName, + Key: this.key + }), + 'called with correct arguments' + ).to.be.true + return done() + } + ) + }) - return this.AWSSDKPersistorManager.getFileStream(this.bucketName, this.key, this.opts, (err, stream) => { - expect(this.read_stream_on.calledTwice); - expect(err).to.not.be.ok; - expect(stream, "returned the stream").to.equal(this.read_stream); - expect((this.s3.getObject.calledWith({Bucket: this.bucketName, Key: this.key})), - "called with correct arguments").to.be.true; - return done(); - }); - }); + describe('with start and end options', function() { + beforeEach(function() { + return (this.opts = { + start: 0, + end: 8 + }) + }) + return it('should pass headers to the s3.GetObject', function(done) { + this.read_stream_on.withArgs('readable').callsArgWith(1) + this.AWSSDKPersistorManager.getFileStream( + this.bucketName, + this.key, + this.opts, + (err, stream) => { + return expect( + this.s3.getObject.calledWith({ + Bucket: this.bucketName, + Key: this.key, + Range: 'bytes=0-8' + }), + 'called with correct arguments' + ).to.be.true + } + ) + return done() + }) + }) - describe("with start and end options", function() { - beforeEach(function() { - return this.opts = { - start: 0, - end: 8 - }; - }); - return it("should pass headers to the s3.GetObject", function(done) { - this.read_stream_on.withArgs('readable').callsArgWith(1); - this.AWSSDKPersistorManager.getFileStream(this.bucketName, this.key, this.opts, (err, stream) => { - return expect((this.s3.getObject.calledWith({Bucket: this.bucketName, Key: this.key, Range: 'bytes=0-8'})), - "called with correct arguments").to.be.true; - }); - return done(); - }); - }); + return describe('error conditions', function() { + describe("when the file doesn't exist", function() { + beforeEach(function() { + this.error = new Error() + return (this.error.code = 'NoSuchKey') + }) + return it('should produce a NotFoundError', function(done) { + this.read_stream_on.withArgs('error').callsArgWith(1, this.error) + return this.AWSSDKPersistorManager.getFileStream( + this.bucketName, + this.key, + this.opts, + (err, stream) => { + expect(stream).to.not.be.ok + expect(err).to.be.ok + expect( + err instanceof this.Errors.NotFoundError, + 'error is a correct instance' + ).to.equal(true) + return done() + } + ) + }) + }) - return describe("error conditions", function() { - describe("when the file doesn't exist", function() { - beforeEach(function() { - this.error = new Error(); - return this.error.code = 'NoSuchKey'; - }); - return it("should produce a NotFoundError", function(done) { - this.read_stream_on.withArgs('error').callsArgWith(1, this.error); - return this.AWSSDKPersistorManager.getFileStream(this.bucketName, this.key, this.opts, (err, stream) => { - expect(stream).to.not.be.ok; - expect(err).to.be.ok; - expect(err instanceof this.Errors.NotFoundError, "error is a correct instance").to.equal(true); - return done(); - }); - }); - }); + return describe('when there is some other error', function() { + beforeEach(function() { + return (this.error = new Error()) + }) + return it('should dispatch the error from s3 object stream', function(done) { + this.read_stream_on.withArgs('error').callsArgWith(1, this.error) + return this.AWSSDKPersistorManager.getFileStream( + this.bucketName, + this.key, + this.opts, + (err, stream) => { + expect(stream).to.not.be.ok + expect(err).to.be.ok + expect(err).to.equal(this.error) + return done() + } + ) + }) + }) + }) + }) - return describe("when there is some other error", function() { - beforeEach(function() { - return this.error = new Error(); - }); - return it("should dispatch the error from s3 object stream", function(done) { - this.read_stream_on.withArgs('error').callsArgWith(1, this.error); - return this.AWSSDKPersistorManager.getFileStream(this.bucketName, this.key, this.opts, (err, stream) => { - expect(stream).to.not.be.ok; - expect(err).to.be.ok; - expect(err).to.equal(this.error); - return done(); - }); - }); - }); - }); - }); + describe('copyFile', function() { + beforeEach(function() { + this.destKey = 'some/key' + return (this.stream = {}) + }) - describe("copyFile", function() { - beforeEach(function() { - this.destKey = "some/key"; - return this.stream = {};}); + it('should copy the file with s3.copyObject', function(done) { + this.s3.copyObject.callsArgWith(1) + return this.AWSSDKPersistorManager.copyFile( + this.bucketName, + this.key, + this.destKey, + err => { + expect(err).to.not.be.ok + expect(this.s3.copyObject.calledOnce, 'called only once').to.be.true + expect( + this.s3.copyObject.calledWith({ + Bucket: this.bucketName, + Key: this.destKey, + CopySource: this.bucketName + '/' + this.key + }), + 'called with correct arguments' + ).to.be.true + return done() + } + ) + }) - it("should copy the file with s3.copyObject", function(done) { - this.s3.copyObject.callsArgWith(1); - return this.AWSSDKPersistorManager.copyFile(this.bucketName, this.key, this.destKey, err => { - expect(err).to.not.be.ok; - expect(this.s3.copyObject.calledOnce, "called only once").to.be.true; - expect((this.s3.copyObject.calledWith({Bucket: this.bucketName, Key: this.destKey, CopySource: this.bucketName + '/' + this.key})), - "called with correct arguments").to.be.true; - return done(); - }); - }); + return it('should dispatch the error from s3.copyObject', function(done) { + this.s3.copyObject.callsArgWith(1, this.error) + return this.AWSSDKPersistorManager.copyFile( + this.bucketName, + this.key, + this.destKey, + err => { + expect(err).to.equal(this.error) + return done() + } + ) + }) + }) - return it("should dispatch the error from s3.copyObject", function(done) { - this.s3.copyObject.callsArgWith(1, this.error); - return this.AWSSDKPersistorManager.copyFile(this.bucketName, this.key, this.destKey, err => { - expect(err).to.equal(this.error); - return done(); - }); - }); - }); + describe('deleteFile', function() { + it('should delete the file with s3.deleteObject', function(done) { + this.s3.deleteObject.callsArgWith(1) + return this.AWSSDKPersistorManager.deleteFile( + this.bucketName, + this.key, + err => { + expect(err).to.not.be.ok + expect(this.s3.deleteObject.calledOnce, 'called only once').to.be.true + expect( + this.s3.deleteObject.calledWith({ + Bucket: this.bucketName, + Key: this.key + }), + 'called with correct arguments' + ).to.be.true + return done() + } + ) + }) - describe("deleteFile", function() { - it("should delete the file with s3.deleteObject", function(done) { - this.s3.deleteObject.callsArgWith(1); - return this.AWSSDKPersistorManager.deleteFile(this.bucketName, this.key, err => { - expect(err).to.not.be.ok; - expect(this.s3.deleteObject.calledOnce, "called only once").to.be.true; - expect((this.s3.deleteObject.calledWith({Bucket: this.bucketName, Key: this.key})), - "called with correct arguments").to.be.true; - return done(); - }); - }); + return it('should dispatch the error from s3.deleteObject', function(done) { + this.s3.deleteObject.callsArgWith(1, this.error) + return this.AWSSDKPersistorManager.deleteFile( + this.bucketName, + this.key, + err => { + expect(err).to.equal(this.error) + return done() + } + ) + }) + }) - return it("should dispatch the error from s3.deleteObject", function(done) { - this.s3.deleteObject.callsArgWith(1, this.error); - return this.AWSSDKPersistorManager.deleteFile(this.bucketName, this.key, err => { - expect(err).to.equal(this.error); - return done(); - }); - }); - }); + describe('deleteDirectory', function() { + it('should list the directory content using s3.listObjects', function(done) { + this.s3.listObjects.callsArgWith(1, null, { Contents: [] }) + return this.AWSSDKPersistorManager.deleteDirectory( + this.bucketName, + this.key, + err => { + expect(err).to.not.be.ok + expect(this.s3.listObjects.calledOnce, 'called only once').to.be.true + expect( + this.s3.listObjects.calledWith({ + Bucket: this.bucketName, + Prefix: this.key + }), + 'called with correct arguments' + ).to.be.true + return done() + } + ) + }) - describe("deleteDirectory", function() { + it('should dispatch the error from s3.listObjects', function(done) { + this.s3.listObjects.callsArgWith(1, this.error) + return this.AWSSDKPersistorManager.deleteDirectory( + this.bucketName, + this.key, + err => { + expect(err).to.equal(this.error) + return done() + } + ) + }) - it("should list the directory content using s3.listObjects", function(done) { - this.s3.listObjects.callsArgWith(1, null, {Contents: []}); - return this.AWSSDKPersistorManager.deleteDirectory(this.bucketName, this.key, err => { - expect(err).to.not.be.ok; - expect(this.s3.listObjects.calledOnce, "called only once").to.be.true; - expect((this.s3.listObjects.calledWith({Bucket: this.bucketName, Prefix: this.key})), - "called with correct arguments").to.be.true; - return done(); - }); - }); + return describe('with directory content', function() { + beforeEach(function() { + return (this.fileList = [{ Key: 'foo' }, { Key: 'bar', Key: 'baz' }]) + }) - it("should dispatch the error from s3.listObjects", function(done) { - this.s3.listObjects.callsArgWith(1, this.error); - return this.AWSSDKPersistorManager.deleteDirectory(this.bucketName, this.key, err => { - expect(err).to.equal(this.error); - return done(); - }); - }); + it('should forward the file keys to s3.deleteObjects', function(done) { + this.s3.listObjects.callsArgWith(1, null, { Contents: this.fileList }) + this.s3.deleteObjects.callsArgWith(1) + return this.AWSSDKPersistorManager.deleteDirectory( + this.bucketName, + this.key, + err => { + expect(err).to.not.be.ok + expect(this.s3.deleteObjects.calledOnce, 'called only once').to.be + .true + expect( + this.s3.deleteObjects.calledWith({ + Bucket: this.bucketName, + Delete: { + Quiet: true, + Objects: this.fileList + } + }), + 'called with correct arguments' + ).to.be.true + return done() + } + ) + }) - return describe("with directory content", function() { - beforeEach(function() { - return this.fileList = [ - {Key: 'foo'} - , { Key: 'bar' - , Key: 'baz' - } - ];}); + return it('should dispatch the error from s3.deleteObjects', function(done) { + this.s3.listObjects.callsArgWith(1, null, { Contents: this.fileList }) + this.s3.deleteObjects.callsArgWith(1, this.error) + return this.AWSSDKPersistorManager.deleteDirectory( + this.bucketName, + this.key, + err => { + expect(err).to.equal(this.error) + return done() + } + ) + }) + }) + }) - it("should forward the file keys to s3.deleteObjects", function(done) { - this.s3.listObjects.callsArgWith(1, null, {Contents: this.fileList}); - this.s3.deleteObjects.callsArgWith(1); - return this.AWSSDKPersistorManager.deleteDirectory(this.bucketName, this.key, err => { - expect(err).to.not.be.ok; - expect(this.s3.deleteObjects.calledOnce, "called only once").to.be.true; - expect((this.s3.deleteObjects.calledWith({ - Bucket: this.bucketName, - Delete: { - Quiet: true, - Objects: this.fileList - }})), - "called with correct arguments").to.be.true; - return done(); - }); - }); + describe('checkIfFileExists', function() { + it('should check for the file with s3.headObject', function(done) { + this.s3.headObject.callsArgWith(1, null, {}) + return this.AWSSDKPersistorManager.checkIfFileExists( + this.bucketName, + this.key, + (err, exists) => { + expect(err).to.not.be.ok + expect(this.s3.headObject.calledOnce, 'called only once').to.be.true + expect( + this.s3.headObject.calledWith({ + Bucket: this.bucketName, + Key: this.key + }), + 'called with correct arguments' + ).to.be.true + return done() + } + ) + }) - return it("should dispatch the error from s3.deleteObjects", function(done) { - this.s3.listObjects.callsArgWith(1, null, {Contents: this.fileList}); - this.s3.deleteObjects.callsArgWith(1, this.error); - return this.AWSSDKPersistorManager.deleteDirectory(this.bucketName, this.key, err => { - expect(err).to.equal(this.error); - return done(); - }); - }); - }); - }); + it('should return false on an inexistant file', function(done) { + this.s3.headObject.callsArgWith(1, null, {}) + return this.AWSSDKPersistorManager.checkIfFileExists( + this.bucketName, + this.key, + (err, exists) => { + expect(exists).to.be.false + return done() + } + ) + }) + it('should return true on an existing file', function(done) { + this.s3.headObject.callsArgWith(1, null, { ETag: 'etag' }) + return this.AWSSDKPersistorManager.checkIfFileExists( + this.bucketName, + this.key, + (err, exists) => { + expect(exists).to.be.true + return done() + } + ) + }) - describe("checkIfFileExists", function() { + return it('should dispatch the error from s3.headObject', function(done) { + this.s3.headObject.callsArgWith(1, this.error) + return this.AWSSDKPersistorManager.checkIfFileExists( + this.bucketName, + this.key, + (err, exists) => { + expect(err).to.equal(this.error) + return done() + } + ) + }) + }) - it("should check for the file with s3.headObject", function(done) { - this.s3.headObject.callsArgWith(1, null, {}); - return this.AWSSDKPersistorManager.checkIfFileExists(this.bucketName, this.key, (err, exists) => { - expect(err).to.not.be.ok; - expect(this.s3.headObject.calledOnce, "called only once").to.be.true; - expect((this.s3.headObject.calledWith({Bucket: this.bucketName, Key: this.key})), - "called with correct arguments").to.be.true; - return done(); - }); - }); + return describe('directorySize', function() { + it('should list the directory content using s3.listObjects', function(done) { + this.s3.listObjects.callsArgWith(1, null, { Contents: [] }) + return this.AWSSDKPersistorManager.directorySize( + this.bucketName, + this.key, + err => { + expect(err).to.not.be.ok + expect(this.s3.listObjects.calledOnce, 'called only once').to.be.true + expect( + this.s3.listObjects.calledWith({ + Bucket: this.bucketName, + Prefix: this.key + }), + 'called with correct arguments' + ).to.be.true + return done() + } + ) + }) - it("should return false on an inexistant file", function(done) { - this.s3.headObject.callsArgWith(1, null, {}); - return this.AWSSDKPersistorManager.checkIfFileExists(this.bucketName, this.key, (err, exists) => { - expect(exists).to.be.false; - return done(); - }); - }); + it('should dispatch the error from s3.listObjects', function(done) { + this.s3.listObjects.callsArgWith(1, this.error) + return this.AWSSDKPersistorManager.directorySize( + this.bucketName, + this.key, + err => { + expect(err).to.equal(this.error) + return done() + } + ) + }) - it("should return true on an existing file", function(done) { - this.s3.headObject.callsArgWith(1, null, {ETag: "etag"}); - return this.AWSSDKPersistorManager.checkIfFileExists(this.bucketName, this.key, (err, exists) => { - expect(exists).to.be.true; - return done(); - }); - }); - - return it("should dispatch the error from s3.headObject", function(done) { - this.s3.headObject.callsArgWith(1, this.error); - return this.AWSSDKPersistorManager.checkIfFileExists(this.bucketName, this.key, (err, exists) => { - expect(err).to.equal(this.error); - return done(); - }); - }); - }); - - return describe("directorySize", function() { - - it("should list the directory content using s3.listObjects", function(done) { - this.s3.listObjects.callsArgWith(1, null, {Contents: []}); - return this.AWSSDKPersistorManager.directorySize(this.bucketName, this.key, err => { - expect(err).to.not.be.ok; - expect(this.s3.listObjects.calledOnce, "called only once").to.be.true; - expect((this.s3.listObjects.calledWith({Bucket: this.bucketName, Prefix: this.key})), - "called with correct arguments").to.be.true; - return done(); - }); - }); - - it("should dispatch the error from s3.listObjects", function(done) { - this.s3.listObjects.callsArgWith(1, this.error); - return this.AWSSDKPersistorManager.directorySize(this.bucketName, this.key, err => { - expect(err).to.equal(this.error); - return done(); - }); - }); - - return it("should sum directory files sizes", function(done) { - this.s3.listObjects.callsArgWith(1, null, {Contents: [ { Size: 1024 }, { Size: 2048 }]}); - return this.AWSSDKPersistorManager.directorySize(this.bucketName, this.key, (err, size) => { - expect(size).to.equal(3072); - return done(); - }); - }); - }); -}); + return it('should sum directory files sizes', function(done) { + this.s3.listObjects.callsArgWith(1, null, { + Contents: [{ Size: 1024 }, { Size: 2048 }] + }) + return this.AWSSDKPersistorManager.directorySize( + this.bucketName, + this.key, + (err, size) => { + expect(size).to.equal(3072) + return done() + } + ) + }) + }) +}) diff --git a/services/filestore/test/unit/js/BucketControllerTests.js b/services/filestore/test/unit/js/BucketControllerTests.js index 86db19da1b..ef74b3f6c0 100644 --- a/services/filestore/test/unit/js/BucketControllerTests.js +++ b/services/filestore/test/unit/js/BucketControllerTests.js @@ -9,98 +9,92 @@ * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const { - assert -} = require("chai"); -const sinon = require('sinon'); -const chai = require('chai'); -const should = chai.should(); -const { - expect -} = chai; -const modulePath = "../../../app/js/BucketController.js"; -const SandboxedModule = require('sandboxed-module'); +const { assert } = require('chai') +const sinon = require('sinon') +const chai = require('chai') +const should = chai.should() +const { expect } = chai +const modulePath = '../../../app/js/BucketController.js' +const SandboxedModule = require('sandboxed-module') -describe("BucketController", function() { +describe('BucketController', function() { + beforeEach(function() { + this.PersistorManager = { + sendStream: sinon.stub(), + copyFile: sinon.stub(), + deleteFile: sinon.stub() + } - beforeEach(function() { - this.PersistorManager = { - sendStream: sinon.stub(), - copyFile: sinon.stub(), - deleteFile:sinon.stub() - }; + this.settings = { + s3: { + buckets: { + user_files: 'user_files' + } + }, + filestore: { + backend: 's3', + s3: { + secret: 'secret', + key: 'this_key' + } + } + } - this.settings = { - s3: { - buckets: { - user_files:"user_files" - } - }, - filestore: { - backend: "s3", - s3: { - secret: "secret", - key: "this_key" - } - } - }; + this.FileHandler = { + getFile: sinon.stub(), + deleteFile: sinon.stub(), + insertFile: sinon.stub(), + getDirectorySize: sinon.stub() + } + this.LocalFileWriter = {} + this.controller = SandboxedModule.require(modulePath, { + requires: { + './LocalFileWriter': this.LocalFileWriter, + './FileHandler': this.FileHandler, + './PersistorManager': this.PersistorManager, + 'settings-sharelatex': this.settings, + 'metrics-sharelatex': { + inc() {} + }, + 'logger-sharelatex': { + log() {}, + err() {} + } + } + }) + this.project_id = 'project_id' + this.file_id = 'file_id' + this.bucket = 'user_files' + this.key = `${this.project_id}/${this.file_id}` + this.req = { + query: {}, + params: { + bucket: this.bucket, + 0: this.key + }, + headers: {} + } + this.res = { setHeader() {} } + return (this.fileStream = {}) + }) - this.FileHandler = { - getFile: sinon.stub(), - deleteFile: sinon.stub(), - insertFile: sinon.stub(), - getDirectorySize: sinon.stub() - }; - this.LocalFileWriter = {}; - this.controller = SandboxedModule.require(modulePath, { requires: { - "./LocalFileWriter":this.LocalFileWriter, - "./FileHandler": this.FileHandler, - "./PersistorManager":this.PersistorManager, - "settings-sharelatex": this.settings, - "metrics-sharelatex": { - inc() {} - }, - "logger-sharelatex": { - log() {}, - err() {} - } - } - } - ); - this.project_id = "project_id"; - this.file_id = "file_id"; - this.bucket = "user_files"; - this.key = `${this.project_id}/${this.file_id}`; - this.req = { - query:{}, - params: { - bucket: this.bucket, - 0: this.key - }, - headers: {} - }; - this.res = - {setHeader() {}}; - return this.fileStream = {};}); + return describe('getFile', function() { + it('should pipe the stream', function(done) { + this.FileHandler.getFile.callsArgWith(3, null, this.fileStream) + this.fileStream.pipe = res => { + res.should.equal(this.res) + return done() + } + return this.controller.getFile(this.req, this.res) + }) - return describe("getFile", function() { - - it("should pipe the stream", function(done){ - this.FileHandler.getFile.callsArgWith(3, null, this.fileStream); - this.fileStream.pipe = res=> { - res.should.equal(this.res); - return done(); - }; - return this.controller.getFile(this.req, this.res); - }); - - return it("should send a 500 if there is a problem", function(done){ - this.FileHandler.getFile.callsArgWith(3, "error"); - this.res.send = code=> { - code.should.equal(500); - return done(); - }; - return this.controller.getFile(this.req, this.res); - }); - }); -}); + return it('should send a 500 if there is a problem', function(done) { + this.FileHandler.getFile.callsArgWith(3, 'error') + this.res.send = code => { + code.should.equal(500) + return done() + } + return this.controller.getFile(this.req, this.res) + }) + }) +}) diff --git a/services/filestore/test/unit/js/FSPersistorManagerTests.js b/services/filestore/test/unit/js/FSPersistorManagerTests.js index b3c2842b46..9e9018c17b 100644 --- a/services/filestore/test/unit/js/FSPersistorManagerTests.js +++ b/services/filestore/test/unit/js/FSPersistorManagerTests.js @@ -11,369 +11,492 @@ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const { - assert -} = require("chai"); -const sinon = require('sinon'); -const chai = require('chai'); -const { - should -} = chai; -const { - expect -} = chai; -const modulePath = "../../../app/js/FSPersistorManager.js"; -const SandboxedModule = require('sandboxed-module'); -const fs = require("fs"); -const response = require("response"); - -describe("FSPersistorManagerTests", function() { +const { assert } = require('chai') +const sinon = require('sinon') +const chai = require('chai') +const { should } = chai +const { expect } = chai +const modulePath = '../../../app/js/FSPersistorManager.js' +const SandboxedModule = require('sandboxed-module') +const fs = require('fs') +const response = require('response') +describe('FSPersistorManagerTests', function() { beforeEach(function() { this.Fs = { - rename:sinon.stub(), - createReadStream:sinon.stub(), - createWriteStream:sinon.stub(), - unlink:sinon.stub(), - rmdir:sinon.stub(), - exists:sinon.stub(), - readdir:sinon.stub(), - open:sinon.stub(), - openSync:sinon.stub(), - fstatSync:sinon.stub(), - closeSync:sinon.stub(), - stat:sinon.stub() - }; - this.Rimraf = sinon.stub(); + rename: sinon.stub(), + createReadStream: sinon.stub(), + createWriteStream: sinon.stub(), + unlink: sinon.stub(), + rmdir: sinon.stub(), + exists: sinon.stub(), + readdir: sinon.stub(), + open: sinon.stub(), + openSync: sinon.stub(), + fstatSync: sinon.stub(), + closeSync: sinon.stub(), + stat: sinon.stub() + } + this.Rimraf = sinon.stub() this.LocalFileWriter = { writeStream: sinon.stub(), deleteFile: sinon.stub() - }; + } this.requires = { - "./LocalFileWriter":this.LocalFileWriter, - "fs":this.Fs, - "logger-sharelatex": { + './LocalFileWriter': this.LocalFileWriter, + fs: this.Fs, + 'logger-sharelatex': { log() {}, err() {} }, - "response":response, - "rimraf":this.Rimraf, - "./Errors": (this.Errors = - {NotFoundError: sinon.stub()}) - }; - this.location = "/tmp"; - this.name1 = "530f2407e7ef165704000007/530f838b46d9a9e859000008"; - this.name1Filtered ="530f2407e7ef165704000007_530f838b46d9a9e859000008"; - this.name2 = "second_file"; - this.error = "error_message"; - return this.FSPersistorManager = SandboxedModule.require(modulePath, {requires: this.requires}); - }); + response: response, + rimraf: this.Rimraf, + './Errors': (this.Errors = { NotFoundError: sinon.stub() }) + } + this.location = '/tmp' + this.name1 = '530f2407e7ef165704000007/530f838b46d9a9e859000008' + this.name1Filtered = '530f2407e7ef165704000007_530f838b46d9a9e859000008' + this.name2 = 'second_file' + this.error = 'error_message' + return (this.FSPersistorManager = SandboxedModule.require(modulePath, { + requires: this.requires + })) + }) - describe("sendFile", function() { + describe('sendFile', function() { beforeEach(function() { - return this.Fs.createReadStream = sinon.stub().returns({ + return (this.Fs.createReadStream = sinon.stub().returns({ on() {}, pipe() {} - }); - }); + })) + }) - it("should copy the file", function(done) { - this.Fs.createWriteStream =sinon.stub().returns({ + it('should copy the file', function(done) { + this.Fs.createWriteStream = sinon.stub().returns({ on(event, handler) { - if (event === 'finish') { return process.nextTick(handler); } + if (event === 'finish') { + return process.nextTick(handler) + } } - }); - return this.FSPersistorManager.sendFile(this.location, this.name1, this.name2, err=> { - this.Fs.createReadStream.calledWith(this.name2).should.equal(true); - this.Fs.createWriteStream.calledWith(`${this.location}/${this.name1Filtered}` ).should.equal(true); - return done(); - }); - }); + }) + return this.FSPersistorManager.sendFile( + this.location, + this.name1, + this.name2, + err => { + this.Fs.createReadStream.calledWith(this.name2).should.equal(true) + this.Fs.createWriteStream + .calledWith(`${this.location}/${this.name1Filtered}`) + .should.equal(true) + return done() + } + ) + }) - return it("should return an error if the file cannot be stored", function(done) { - this.Fs.createWriteStream =sinon.stub().returns({ + return it('should return an error if the file cannot be stored', function(done) { + this.Fs.createWriteStream = sinon.stub().returns({ on: (event, handler) => { - if (event === 'error') { - return process.nextTick(() => { - return handler(this.error); - }); + if (event === 'error') { + return process.nextTick(() => { + return handler(this.error) + }) + } } - } - }); - return this.FSPersistorManager.sendFile(this.location, this.name1, this.name2, err=> { - this.Fs.createReadStream.calledWith(this.name2).should.equal(true); - this.Fs.createWriteStream.calledWith(`${this.location}/${this.name1Filtered}` ).should.equal(true); - err.should.equal(this.error); - return done(); - }); - }); - }); + }) + return this.FSPersistorManager.sendFile( + this.location, + this.name1, + this.name2, + err => { + this.Fs.createReadStream.calledWith(this.name2).should.equal(true) + this.Fs.createWriteStream + .calledWith(`${this.location}/${this.name1Filtered}`) + .should.equal(true) + err.should.equal(this.error) + return done() + } + ) + }) + }) - describe("sendStream", function() { + describe('sendStream', function() { beforeEach(function() { - this.FSPersistorManager.sendFile = sinon.stub().callsArgWith(3); - this.LocalFileWriter.writeStream.callsArgWith(2, null, this.name1); - this.LocalFileWriter.deleteFile.callsArg(1); - return this.SourceStream = - {on() {}}; - }); + this.FSPersistorManager.sendFile = sinon.stub().callsArgWith(3) + this.LocalFileWriter.writeStream.callsArgWith(2, null, this.name1) + this.LocalFileWriter.deleteFile.callsArg(1) + return (this.SourceStream = { on() {} }) + }) - it("should sent stream to LocalFileWriter", function(done){ - return this.FSPersistorManager.sendStream(this.location, this.name1, this.SourceStream, () => { - this.LocalFileWriter.writeStream.calledWith(this.SourceStream).should.equal(true); - return done(); - }); - }); + it('should sent stream to LocalFileWriter', function(done) { + return this.FSPersistorManager.sendStream( + this.location, + this.name1, + this.SourceStream, + () => { + this.LocalFileWriter.writeStream + .calledWith(this.SourceStream) + .should.equal(true) + return done() + } + ) + }) - it("should return the error from LocalFileWriter", function(done){ - this.LocalFileWriter.writeStream.callsArgWith(2, this.error); - return this.FSPersistorManager.sendStream(this.location, this.name1, this.SourceStream, err=> { - err.should.equal(this.error); - return done(); - }); - }); + it('should return the error from LocalFileWriter', function(done) { + this.LocalFileWriter.writeStream.callsArgWith(2, this.error) + return this.FSPersistorManager.sendStream( + this.location, + this.name1, + this.SourceStream, + err => { + err.should.equal(this.error) + return done() + } + ) + }) - return it("should send the file to the filestore", function(done){ - this.LocalFileWriter.writeStream.callsArgWith(2); - return this.FSPersistorManager.sendStream(this.location, this.name1, this.SourceStream, err=> { - this.FSPersistorManager.sendFile.called.should.equal(true); - return done(); - }); - }); - }); + return it('should send the file to the filestore', function(done) { + this.LocalFileWriter.writeStream.callsArgWith(2) + return this.FSPersistorManager.sendStream( + this.location, + this.name1, + this.SourceStream, + err => { + this.FSPersistorManager.sendFile.called.should.equal(true) + return done() + } + ) + }) + }) - describe("getFileStream", function() { + describe('getFileStream', function() { beforeEach(function() { - return this.opts = {};}); + return (this.opts = {}) + }) - it("should use correct file location", function(done) { - this.FSPersistorManager.getFileStream(this.location, this.name1, this.opts, (err,res) => {}); - this.Fs.open.calledWith(`${this.location}/${this.name1Filtered}`).should.equal(true); - return done(); - }); - - describe("with start and end options", function() { + it('should use correct file location', function(done) { + this.FSPersistorManager.getFileStream( + this.location, + this.name1, + this.opts, + (err, res) => {} + ) + this.Fs.open + .calledWith(`${this.location}/${this.name1Filtered}`) + .should.equal(true) + return done() + }) + describe('with start and end options', function() { beforeEach(function() { - this.fd = 2019; - this.opts_in = {start: 0, end: 8}; - this.opts = {start: 0, end: 8, fd: this.fd}; - return this.Fs.open.callsArgWith(2, null, this.fd); - }); + this.fd = 2019 + this.opts_in = { start: 0, end: 8 } + this.opts = { start: 0, end: 8, fd: this.fd } + return this.Fs.open.callsArgWith(2, null, this.fd) + }) return it('should pass the options to createReadStream', function(done) { - this.FSPersistorManager.getFileStream(this.location, this.name1, this.opts_in, (err,res)=> {}); - this.Fs.createReadStream.calledWith(null, this.opts).should.equal(true); - return done(); - }); - }); - - return describe("error conditions", function() { - - describe("when the file does not exist", function() { + this.FSPersistorManager.getFileStream( + this.location, + this.name1, + this.opts_in, + (err, res) => {} + ) + this.Fs.createReadStream.calledWith(null, this.opts).should.equal(true) + return done() + }) + }) + return describe('error conditions', function() { + describe('when the file does not exist', function() { beforeEach(function() { - this.fakeCode = 'ENOENT'; - const err = new Error(); - err.code = this.fakeCode; - return this.Fs.open.callsArgWith(2, err, null); - }); + this.fakeCode = 'ENOENT' + const err = new Error() + err.code = this.fakeCode + return this.Fs.open.callsArgWith(2, err, null) + }) - return it("should give a NotFoundError", function(done) { - return this.FSPersistorManager.getFileStream(this.location, this.name1, this.opts, (err,res)=> { - expect(res).to.equal(null); - expect(err).to.not.equal(null); - expect(err instanceof this.Errors.NotFoundError).to.equal(true); - return done(); - }); - }); - }); - - return describe("when some other error happens", function() { + return it('should give a NotFoundError', function(done) { + return this.FSPersistorManager.getFileStream( + this.location, + this.name1, + this.opts, + (err, res) => { + expect(res).to.equal(null) + expect(err).to.not.equal(null) + expect(err instanceof this.Errors.NotFoundError).to.equal(true) + return done() + } + ) + }) + }) + return describe('when some other error happens', function() { beforeEach(function() { - this.fakeCode = 'SOMETHINGHORRIBLE'; - const err = new Error(); - err.code = this.fakeCode; - return this.Fs.open.callsArgWith(2, err, null); - }); + this.fakeCode = 'SOMETHINGHORRIBLE' + const err = new Error() + err.code = this.fakeCode + return this.Fs.open.callsArgWith(2, err, null) + }) - return it("should give an Error", function(done) { - return this.FSPersistorManager.getFileStream(this.location, this.name1, this.opts, (err,res)=> { - expect(res).to.equal(null); - expect(err).to.not.equal(null); - expect(err instanceof Error).to.equal(true); - return done(); - }); - }); - }); - }); - }); + return it('should give an Error', function(done) { + return this.FSPersistorManager.getFileStream( + this.location, + this.name1, + this.opts, + (err, res) => { + expect(res).to.equal(null) + expect(err).to.not.equal(null) + expect(err instanceof Error).to.equal(true) + return done() + } + ) + }) + }) + }) + }) - describe("getFileSize", function() { - it("should return the file size", function(done) { - const expectedFileSize = 75382; - this.Fs.stat.yields(new Error("fs.stat got unexpected arguments")); - this.Fs.stat.withArgs(`${this.location}/${this.name1Filtered}`) - .yields(null, { size: expectedFileSize }); + describe('getFileSize', function() { + it('should return the file size', function(done) { + const expectedFileSize = 75382 + this.Fs.stat.yields(new Error('fs.stat got unexpected arguments')) + this.Fs.stat + .withArgs(`${this.location}/${this.name1Filtered}`) + .yields(null, { size: expectedFileSize }) - return this.FSPersistorManager.getFileSize(this.location, this.name1, (err, fileSize) => { - if (err != null) { - return done(err); + return this.FSPersistorManager.getFileSize( + this.location, + this.name1, + (err, fileSize) => { + if (err != null) { + return done(err) + } + expect(fileSize).to.equal(expectedFileSize) + return done() } - expect(fileSize).to.equal(expectedFileSize); - return done(); - }); - }); + ) + }) - it("should throw a NotFoundError if the file does not exist", function(done) { - const error = new Error(); - error.code = "ENOENT"; - this.Fs.stat.yields(error); + it('should throw a NotFoundError if the file does not exist', function(done) { + const error = new Error() + error.code = 'ENOENT' + this.Fs.stat.yields(error) - return this.FSPersistorManager.getFileSize(this.location, this.name1, (err, fileSize) => { - expect(err).to.be.instanceof(this.Errors.NotFoundError); - return done(); - }); - }); + return this.FSPersistorManager.getFileSize( + this.location, + this.name1, + (err, fileSize) => { + expect(err).to.be.instanceof(this.Errors.NotFoundError) + return done() + } + ) + }) - return it("should rethrow any other error", function(done) { - const error = new Error(); - this.Fs.stat.yields(error); + return it('should rethrow any other error', function(done) { + const error = new Error() + this.Fs.stat.yields(error) - return this.FSPersistorManager.getFileSize(this.location, this.name1, (err, fileSize) => { - expect(err).to.equal(error); - return done(); - }); - }); - }); + return this.FSPersistorManager.getFileSize( + this.location, + this.name1, + (err, fileSize) => { + expect(err).to.equal(error) + return done() + } + ) + }) + }) - describe("copyFile", function() { + describe('copyFile', function() { beforeEach(function() { - this.ReadStream= { + this.ReadStream = { on() {}, - pipe:sinon.stub() - }; - this.WriteStream= - {on() {}}; - this.Fs.createReadStream.returns(this.ReadStream); - return this.Fs.createWriteStream.returns(this.WriteStream); - }); + pipe: sinon.stub() + } + this.WriteStream = { on() {} } + this.Fs.createReadStream.returns(this.ReadStream) + return this.Fs.createWriteStream.returns(this.WriteStream) + }) - it("Should open the source for reading", function(done) { - this.FSPersistorManager.copyFile(this.location, this.name1, this.name2, function() {}); - this.Fs.createReadStream.calledWith(`${this.location}/${this.name1Filtered}`).should.equal(true); - return done(); - }); + it('Should open the source for reading', function(done) { + this.FSPersistorManager.copyFile( + this.location, + this.name1, + this.name2, + function() {} + ) + this.Fs.createReadStream + .calledWith(`${this.location}/${this.name1Filtered}`) + .should.equal(true) + return done() + }) - it("Should open the target for writing", function(done) { - this.FSPersistorManager.copyFile(this.location, this.name1, this.name2, function() {}); - this.Fs.createWriteStream.calledWith(`${this.location}/${this.name2}`).should.equal(true); - return done(); - }); + it('Should open the target for writing', function(done) { + this.FSPersistorManager.copyFile( + this.location, + this.name1, + this.name2, + function() {} + ) + this.Fs.createWriteStream + .calledWith(`${this.location}/${this.name2}`) + .should.equal(true) + return done() + }) - return it("Should pipe the source to the target", function(done) { - this.FSPersistorManager.copyFile(this.location, this.name1, this.name2, function() {}); - this.ReadStream.pipe.calledWith(this.WriteStream).should.equal(true); - return done(); - }); - }); + return it('Should pipe the source to the target', function(done) { + this.FSPersistorManager.copyFile( + this.location, + this.name1, + this.name2, + function() {} + ) + this.ReadStream.pipe.calledWith(this.WriteStream).should.equal(true) + return done() + }) + }) - describe("deleteFile", function() { + describe('deleteFile', function() { beforeEach(function() { - return this.Fs.unlink.callsArgWith(1,this.error); - }); + return this.Fs.unlink.callsArgWith(1, this.error) + }) - it("Should call unlink with correct options", function(done) { - return this.FSPersistorManager.deleteFile(this.location, this.name1, err => { - this.Fs.unlink.calledWith(`${this.location}/${this.name1Filtered}`).should.equal(true); - return done(); - }); - }); + it('Should call unlink with correct options', function(done) { + return this.FSPersistorManager.deleteFile( + this.location, + this.name1, + err => { + this.Fs.unlink + .calledWith(`${this.location}/${this.name1Filtered}`) + .should.equal(true) + return done() + } + ) + }) - return it("Should propogate the error", function(done) { - return this.FSPersistorManager.deleteFile(this.location, this.name1, err => { - err.should.equal(this.error); - return done(); - }); - }); - }); + return it('Should propogate the error', function(done) { + return this.FSPersistorManager.deleteFile( + this.location, + this.name1, + err => { + err.should.equal(this.error) + return done() + } + ) + }) + }) - - describe("deleteDirectory", function() { + describe('deleteDirectory', function() { beforeEach(function() { - return this.Rimraf.callsArgWith(1,this.error); - }); + return this.Rimraf.callsArgWith(1, this.error) + }) - it("Should call rmdir(rimraf) with correct options", function(done) { - return this.FSPersistorManager.deleteDirectory(this.location, this.name1, err => { - this.Rimraf.calledWith(`${this.location}/${this.name1Filtered}`).should.equal(true); - return done(); - }); - }); + it('Should call rmdir(rimraf) with correct options', function(done) { + return this.FSPersistorManager.deleteDirectory( + this.location, + this.name1, + err => { + this.Rimraf.calledWith( + `${this.location}/${this.name1Filtered}` + ).should.equal(true) + return done() + } + ) + }) - return it("Should propogate the error", function(done) { - return this.FSPersistorManager.deleteDirectory(this.location, this.name1, err => { - err.should.equal(this.error); - return done(); - }); - }); - }); + return it('Should propogate the error', function(done) { + return this.FSPersistorManager.deleteDirectory( + this.location, + this.name1, + err => { + err.should.equal(this.error) + return done() + } + ) + }) + }) - describe("checkIfFileExists", function() { + describe('checkIfFileExists', function() { beforeEach(function() { - return this.Fs.exists.callsArgWith(1,true); - }); + return this.Fs.exists.callsArgWith(1, true) + }) - it("Should call exists with correct options", function(done) { - return this.FSPersistorManager.checkIfFileExists(this.location, this.name1, exists => { - this.Fs.exists.calledWith(`${this.location}/${this.name1Filtered}`).should.equal(true); - return done(); - }); - }); + it('Should call exists with correct options', function(done) { + return this.FSPersistorManager.checkIfFileExists( + this.location, + this.name1, + exists => { + this.Fs.exists + .calledWith(`${this.location}/${this.name1Filtered}`) + .should.equal(true) + return done() + } + ) + }) // fs.exists simply returns false on any error, so... - it("should not return an error", function(done) { - return this.FSPersistorManager.checkIfFileExists(this.location, this.name1, (err,exists) => { - expect(err).to.be.null; - return done(); - }); - }); + it('should not return an error', function(done) { + return this.FSPersistorManager.checkIfFileExists( + this.location, + this.name1, + (err, exists) => { + expect(err).to.be.null + return done() + } + ) + }) - it("Should return true for existing files", function(done) { - this.Fs.exists.callsArgWith(1,true); - return this.FSPersistorManager.checkIfFileExists(this.location, this.name1, (err,exists) => { - exists.should.be.true; - return done(); - }); - }); + it('Should return true for existing files', function(done) { + this.Fs.exists.callsArgWith(1, true) + return this.FSPersistorManager.checkIfFileExists( + this.location, + this.name1, + (err, exists) => { + exists.should.be.true + return done() + } + ) + }) - return it("Should return false for non-existing files", function(done) { - this.Fs.exists.callsArgWith(1,false); - return this.FSPersistorManager.checkIfFileExists(this.location, this.name1, (err,exists) => { - exists.should.be.false; - return done(); - }); - }); - }); + return it('Should return false for non-existing files', function(done) { + this.Fs.exists.callsArgWith(1, false) + return this.FSPersistorManager.checkIfFileExists( + this.location, + this.name1, + (err, exists) => { + exists.should.be.false + return done() + } + ) + }) + }) - return describe("directorySize", function() { + return describe('directorySize', function() { + it('should propogate the error', function(done) { + this.Fs.readdir.callsArgWith(1, this.error) + return this.FSPersistorManager.directorySize( + this.location, + this.name1, + (err, totalsize) => { + err.should.equal(this.error) + return done() + } + ) + }) - it("should propogate the error", function(done) { - this.Fs.readdir.callsArgWith(1, this.error); - return this.FSPersistorManager.directorySize(this.location, this.name1, (err, totalsize) => { - err.should.equal(this.error); - return done(); - }); - }); - - return it("should sum directory files size", function(done) { - this.Fs.readdir.callsArgWith(1, null, [ {'file1': 'file1'}, {'file2': 'file2'} ]); - this.Fs.fstatSync.returns({size : 1024}); - return this.FSPersistorManager.directorySize(this.location, this.name1, (err, totalsize) => { - expect(totalsize).to.equal(2048); - return done(); - }); - }); - }); -}); + return it('should sum directory files size', function(done) { + this.Fs.readdir.callsArgWith(1, null, [ + { file1: 'file1' }, + { file2: 'file2' } + ]) + this.Fs.fstatSync.returns({ size: 1024 }) + return this.FSPersistorManager.directorySize( + this.location, + this.name1, + (err, totalsize) => { + expect(totalsize).to.equal(2048) + return done() + } + ) + }) + }) +}) diff --git a/services/filestore/test/unit/js/FileControllerTests.js b/services/filestore/test/unit/js/FileControllerTests.js index d60ca5fbd1..2505e87c9b 100644 --- a/services/filestore/test/unit/js/FileControllerTests.js +++ b/services/filestore/test/unit/js/FileControllerTests.js @@ -9,281 +9,289 @@ * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const { - assert -} = require("chai"); -const sinon = require('sinon'); -const chai = require('chai'); -const should = chai.should(); -const { - expect -} = chai; -const modulePath = "../../../app/js/FileController.js"; -const SandboxedModule = require('sandboxed-module'); +const { assert } = require('chai') +const sinon = require('sinon') +const chai = require('chai') +const should = chai.should() +const { expect } = chai +const modulePath = '../../../app/js/FileController.js' +const SandboxedModule = require('sandboxed-module') -describe("FileController", function() { +describe('FileController', function() { + beforeEach(function() { + this.PersistorManager = { + sendStream: sinon.stub(), + copyFile: sinon.stub(), + deleteFile: sinon.stub() + } - beforeEach(function() { - this.PersistorManager = { - sendStream: sinon.stub(), - copyFile: sinon.stub(), - deleteFile:sinon.stub() - }; + this.settings = { + s3: { + buckets: { + user_files: 'user_files' + } + } + } + this.FileHandler = { + getFile: sinon.stub(), + getFileSize: sinon.stub(), + deleteFile: sinon.stub(), + insertFile: sinon.stub(), + getDirectorySize: sinon.stub() + } + this.LocalFileWriter = {} + this.controller = SandboxedModule.require(modulePath, { + requires: { + './LocalFileWriter': this.LocalFileWriter, + './FileHandler': this.FileHandler, + './PersistorManager': this.PersistorManager, + './Errors': (this.Errors = { NotFoundError: sinon.stub() }), + 'settings-sharelatex': this.settings, + 'metrics-sharelatex': { + inc() {} + }, + 'logger-sharelatex': { + log() {}, + err() {} + } + } + }) + this.project_id = 'project_id' + this.file_id = 'file_id' + this.bucket = 'user_files' + this.key = `${this.project_id}/${this.file_id}` + this.req = { + key: this.key, + bucket: this.bucket, + query: {}, + params: { + project_id: this.project_id, + file_id: this.file_id + }, + headers: {} + } + this.res = { + set: sinon.stub().returnsThis(), + status: sinon.stub().returnsThis() + } + return (this.fileStream = {}) + }) - this.settings = { - s3: { - buckets: { - user_files:"user_files" - } - } - }; - this.FileHandler = { - getFile: sinon.stub(), - getFileSize: sinon.stub(), - deleteFile: sinon.stub(), - insertFile: sinon.stub(), - getDirectorySize: sinon.stub() - }; - this.LocalFileWriter = {}; - this.controller = SandboxedModule.require(modulePath, { requires: { - "./LocalFileWriter":this.LocalFileWriter, - "./FileHandler": this.FileHandler, - "./PersistorManager":this.PersistorManager, - "./Errors": (this.Errors = - {NotFoundError: sinon.stub()}), - "settings-sharelatex": this.settings, - "metrics-sharelatex": { - inc() {} - }, - "logger-sharelatex": { - log() {}, - err() {} - } - } - } - ); - this.project_id = "project_id"; - this.file_id = "file_id"; - this.bucket = "user_files"; - this.key = `${this.project_id}/${this.file_id}`; - this.req = { - key:this.key, - bucket:this.bucket, - query:{}, - params: { - project_id:this.project_id, - file_id:this.file_id - }, - headers: {} - }; - this.res = { - set: sinon.stub().returnsThis(), - status: sinon.stub().returnsThis() - }; - return this.fileStream = {};}); + describe('getFile', function() { + it('should pipe the stream', function(done) { + this.FileHandler.getFile.callsArgWith(3, null, this.fileStream) + this.fileStream.pipe = res => { + res.should.equal(this.res) + return done() + } + return this.controller.getFile(this.req, this.res) + }) - describe("getFile", function() { + it('should send a 200 if the cacheWarm param is true', function(done) { + this.req.query.cacheWarm = true + this.FileHandler.getFile.callsArgWith(3, null, this.fileStream) + this.res.send = statusCode => { + statusCode.should.equal(200) + return done() + } + return this.controller.getFile(this.req, this.res) + }) - it("should pipe the stream", function(done){ - this.FileHandler.getFile.callsArgWith(3, null, this.fileStream); - this.fileStream.pipe = res=> { - res.should.equal(this.res); - return done(); - }; - return this.controller.getFile(this.req, this.res); - }); + it('should send a 500 if there is a problem', function(done) { + this.FileHandler.getFile.callsArgWith(3, 'error') + this.res.send = code => { + code.should.equal(500) + return done() + } + return this.controller.getFile(this.req, this.res) + }) - it("should send a 200 if the cacheWarm param is true", function(done){ - this.req.query.cacheWarm = true; - this.FileHandler.getFile.callsArgWith(3, null, this.fileStream); - this.res.send = statusCode=> { - statusCode.should.equal(200); - return done(); - }; - return this.controller.getFile(this.req, this.res); - }); + return describe("with a 'Range' header set", function() { + beforeEach(function() { + return (this.req.headers.range = 'bytes=0-8') + }) - it("should send a 500 if there is a problem", function(done){ - this.FileHandler.getFile.callsArgWith(3, "error"); - this.res.send = code=> { - code.should.equal(500); - return done(); - }; - return this.controller.getFile(this.req, this.res); - }); + return it("should pass 'start' and 'end' options to FileHandler", function(done) { + this.FileHandler.getFile.callsArgWith(3, null, this.fileStream) + this.fileStream.pipe = res => { + expect(this.FileHandler.getFile.lastCall.args[2].start).to.equal(0) + expect(this.FileHandler.getFile.lastCall.args[2].end).to.equal(8) + return done() + } + return this.controller.getFile(this.req, this.res) + }) + }) + }) - return describe("with a 'Range' header set", function() { + describe('getFileHead', function() { + it('should return the file size in a Content-Length header', function(done) { + const expectedFileSize = 84921 + this.FileHandler.getFileSize.yields( + new Error('FileHandler.getFileSize: unexpected arguments') + ) + this.FileHandler.getFileSize + .withArgs(this.bucket, this.key) + .yields(null, expectedFileSize) - beforeEach(function() { - return this.req.headers.range = 'bytes=0-8'; - }); + this.res.end = () => { + expect(this.res.status.lastCall.args[0]).to.equal(200) + expect( + this.res.set.calledWith('Content-Length', expectedFileSize) + ).to.equal(true) + return done() + } - return it("should pass 'start' and 'end' options to FileHandler", function(done) { - this.FileHandler.getFile.callsArgWith(3, null, this.fileStream); - this.fileStream.pipe = res=> { - expect(this.FileHandler.getFile.lastCall.args[2].start).to.equal(0); - expect(this.FileHandler.getFile.lastCall.args[2].end).to.equal(8); - return done(); - }; - return this.controller.getFile(this.req, this.res); - }); - }); - }); + return this.controller.getFileHead(this.req, this.res) + }) - describe("getFileHead", function() { - it("should return the file size in a Content-Length header", function(done) { - const expectedFileSize = 84921; - this.FileHandler.getFileSize.yields( - new Error("FileHandler.getFileSize: unexpected arguments") - ); - this.FileHandler.getFileSize.withArgs(this.bucket, this.key).yields(null, expectedFileSize); + it('should return a 404 is the file is not found', function(done) { + this.FileHandler.getFileSize.yields(new this.Errors.NotFoundError()) - this.res.end = () => { - expect(this.res.status.lastCall.args[0]).to.equal(200); - expect(this.res.set.calledWith("Content-Length", expectedFileSize)).to.equal(true); - return done(); - }; + this.res.end = () => { + expect(this.res.status.lastCall.args[0]).to.equal(404) + return done() + } - return this.controller.getFileHead(this.req, this.res); - }); + return this.controller.getFileHead(this.req, this.res) + }) - it("should return a 404 is the file is not found", function(done) { - this.FileHandler.getFileSize.yields(new this.Errors.NotFoundError()); + return it('should return a 500 on internal errors', function(done) { + this.FileHandler.getFileSize.yields(new Error()) - this.res.end = () => { - expect(this.res.status.lastCall.args[0]).to.equal(404); - return done(); - }; + this.res.end = () => { + expect(this.res.status.lastCall.args[0]).to.equal(500) + return done() + } - return this.controller.getFileHead(this.req, this.res); - }); + return this.controller.getFileHead(this.req, this.res) + }) + }) - return it("should return a 500 on internal errors", function(done) { - this.FileHandler.getFileSize.yields(new Error()); + describe('insertFile', () => + it('should send bucket name key and res to PersistorManager', function(done) { + this.FileHandler.insertFile.callsArgWith(3) + this.res.send = () => { + this.FileHandler.insertFile + .calledWith(this.bucket, this.key, this.req) + .should.equal(true) + return done() + } + return this.controller.insertFile(this.req, this.res) + })) - this.res.end = () => { - expect(this.res.status.lastCall.args[0]).to.equal(500); - return done(); - }; + describe('copyFile', function() { + beforeEach(function() { + this.oldFile_id = 'old_file_id' + this.oldProject_id = 'old_project_id' + return (this.req.body = { + source: { + project_id: this.oldProject_id, + file_id: this.oldFile_id + } + }) + }) - return this.controller.getFileHead(this.req, this.res); - }); - }); + it('should send bucket name and both keys to PersistorManager', function(done) { + this.PersistorManager.copyFile.callsArgWith(3) + this.res.send = code => { + code.should.equal(200) + this.PersistorManager.copyFile + .calledWith( + this.bucket, + `${this.oldProject_id}/${this.oldFile_id}`, + this.key + ) + .should.equal(true) + return done() + } + return this.controller.copyFile(this.req, this.res) + }) - describe("insertFile", () => it("should send bucket name key and res to PersistorManager", function(done){ - this.FileHandler.insertFile.callsArgWith(3); - this.res.send = () => { - this.FileHandler.insertFile.calledWith(this.bucket, this.key, this.req).should.equal(true); - return done(); - }; - return this.controller.insertFile(this.req, this.res); - })); + it('should send a 404 if the original file was not found', function(done) { + this.PersistorManager.copyFile.callsArgWith( + 3, + new this.Errors.NotFoundError() + ) + this.res.send = code => { + code.should.equal(404) + return done() + } + return this.controller.copyFile(this.req, this.res) + }) - describe("copyFile", function() { - beforeEach(function() { - this.oldFile_id = "old_file_id"; - this.oldProject_id = "old_project_id"; - return this.req.body = { - source: { - project_id: this.oldProject_id, - file_id: this.oldFile_id - } - }; - }); + return it('should send a 500 if there was an error', function(done) { + this.PersistorManager.copyFile.callsArgWith(3, 'error') + this.res.send = code => { + code.should.equal(500) + return done() + } + return this.controller.copyFile(this.req, this.res) + }) + }) - it("should send bucket name and both keys to PersistorManager", function(done){ - this.PersistorManager.copyFile.callsArgWith(3); - this.res.send = code=> { - code.should.equal(200); - this.PersistorManager.copyFile.calledWith(this.bucket, `${this.oldProject_id}/${this.oldFile_id}`, this.key).should.equal(true); - return done(); - }; - return this.controller.copyFile(this.req, this.res); - }); + describe('delete file', function() { + it('should tell the file handler', function(done) { + this.FileHandler.deleteFile.callsArgWith(2) + this.res.send = code => { + code.should.equal(204) + this.FileHandler.deleteFile + .calledWith(this.bucket, this.key) + .should.equal(true) + return done() + } + return this.controller.deleteFile(this.req, this.res) + }) - it("should send a 404 if the original file was not found", function(done) { - this.PersistorManager.copyFile.callsArgWith(3, new this.Errors.NotFoundError()); - this.res.send = code=> { - code.should.equal(404); - return done(); - }; - return this.controller.copyFile(this.req, this.res); - }); + return it('should send a 500 if there was an error', function(done) { + this.FileHandler.deleteFile.callsArgWith(2, 'error') + this.res.send = function(code) { + code.should.equal(500) + return done() + } + return this.controller.deleteFile(this.req, this.res) + }) + }) - return it("should send a 500 if there was an error", function(done){ - this.PersistorManager.copyFile.callsArgWith(3, "error"); - this.res.send = code=> { - code.should.equal(500); - return done(); - }; - return this.controller.copyFile(this.req, this.res); - }); - }); + describe('_get_range', function() { + it('should parse a valid Range header', function(done) { + const result = this.controller._get_range('bytes=0-200') + expect(result).to.not.equal(null) + expect(result.start).to.equal(0) + expect(result.end).to.equal(200) + return done() + }) - describe("delete file", function() { + it('should return null for an invalid Range header', function(done) { + const result = this.controller._get_range('wat') + expect(result).to.equal(null) + return done() + }) - it("should tell the file handler", function(done){ - this.FileHandler.deleteFile.callsArgWith(2); - this.res.send = code=> { - code.should.equal(204); - this.FileHandler.deleteFile.calledWith(this.bucket, this.key).should.equal(true); - return done(); - }; - return this.controller.deleteFile(this.req, this.res); - }); + return it("should return null for any type other than 'bytes'", function(done) { + const result = this.controller._get_range('carrots=0-200') + expect(result).to.equal(null) + return done() + }) + }) - return it("should send a 500 if there was an error", function(done){ - this.FileHandler.deleteFile.callsArgWith(2, "error"); - this.res.send = function(code){ - code.should.equal(500); - return done(); - }; - return this.controller.deleteFile(this.req, this.res); - }); - }); + return describe('directorySize', function() { + it('should return total directory size bytes', function(done) { + this.FileHandler.getDirectorySize.callsArgWith(2, null, 1024) + return this.controller.directorySize(this.req, { + json: result => { + expect(result['total bytes']).to.equal(1024) + return done() + } + }) + }) - describe("_get_range", function() { - - it("should parse a valid Range header", function(done) { - const result = this.controller._get_range('bytes=0-200'); - expect(result).to.not.equal(null); - expect(result.start).to.equal(0); - expect(result.end).to.equal(200); - return done(); - }); - - it("should return null for an invalid Range header", function(done) { - const result = this.controller._get_range('wat'); - expect(result).to.equal(null); - return done(); - }); - - return it("should return null for any type other than 'bytes'", function(done) { - const result = this.controller._get_range('carrots=0-200'); - expect(result).to.equal(null); - return done(); - }); - }); - - return describe("directorySize", function() { - - it("should return total directory size bytes", function(done) { - this.FileHandler.getDirectorySize.callsArgWith(2, null, 1024); - return this.controller.directorySize(this.req, { json:result=> { - expect(result['total bytes']).to.equal(1024); - return done(); - } - } - ); - }); - - return it("should send a 500 if there was an error", function(done){ - this.FileHandler.getDirectorySize.callsArgWith(2, "error"); - this.res.send = function(code){ - code.should.equal(500); - return done(); - }; - return this.controller.directorySize(this.req, this.res); - }); - }); -}); + return it('should send a 500 if there was an error', function(done) { + this.FileHandler.getDirectorySize.callsArgWith(2, 'error') + this.res.send = function(code) { + code.should.equal(500) + return done() + } + return this.controller.directorySize(this.req, this.res) + }) + }) +}) diff --git a/services/filestore/test/unit/js/FileConverterTests.js b/services/filestore/test/unit/js/FileConverterTests.js index 96cb0ee53a..1b548d592e 100644 --- a/services/filestore/test/unit/js/FileConverterTests.js +++ b/services/filestore/test/unit/js/FileConverterTests.js @@ -10,110 +10,110 @@ * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const { - assert -} = require("chai"); -const sinon = require('sinon'); -const chai = require('chai'); -const should = chai.should(); -const { - expect -} = chai; -const modulePath = "../../../app/js/FileConverter.js"; -const SandboxedModule = require('sandboxed-module'); +const { assert } = require('chai') +const sinon = require('sinon') +const chai = require('chai') +const should = chai.should() +const { expect } = chai +const modulePath = '../../../app/js/FileConverter.js' +const SandboxedModule = require('sandboxed-module') -describe("FileConverter", function() { +describe('FileConverter', function() { + beforeEach(function() { + this.safe_exec = sinon.stub() + this.converter = SandboxedModule.require(modulePath, { + requires: { + './SafeExec': this.safe_exec, + 'logger-sharelatex': { + log() {}, + err() {} + }, + 'metrics-sharelatex': { + inc() {}, + Timer() { + return { done() {} } + } + }, + 'settings-sharelatex': (this.Settings = { + commands: { + convertCommandPrefix: [] + } + }) + } + }) - beforeEach(function() { + this.sourcePath = '/this/path/here.eps' + this.format = 'png' + return (this.error = 'Error') + }) - this.safe_exec = sinon.stub(); - this.converter = SandboxedModule.require(modulePath, { requires: { - "./SafeExec": this.safe_exec, - "logger-sharelatex": { - log() {}, - err() {} - }, - "metrics-sharelatex": { - inc() {}, - Timer() { - return {done() {}}; - } - }, - "settings-sharelatex": (this.Settings = { - commands: { - convertCommandPrefix: [] - } - }) - } - }); + describe('convert', function() { + it('should convert the source to the requested format', function(done) { + this.safe_exec.callsArgWith(2) + return this.converter.convert(this.sourcePath, this.format, err => { + const args = this.safe_exec.args[0][0] + args.indexOf(`${this.sourcePath}[0]`).should.not.equal(-1) + args.indexOf(`${this.sourcePath}.${this.format}`).should.not.equal(-1) + return done() + }) + }) - this.sourcePath = "/this/path/here.eps"; - this.format = "png"; - return this.error = "Error"; - }); + it('should return the dest path', function(done) { + this.safe_exec.callsArgWith(2) + return this.converter.convert( + this.sourcePath, + this.format, + (err, destPath) => { + destPath.should.equal(`${this.sourcePath}.${this.format}`) + return done() + } + ) + }) - describe("convert", function() { + it('should return the error from convert', function(done) { + this.safe_exec.callsArgWith(2, this.error) + return this.converter.convert(this.sourcePath, this.format, err => { + err.should.equal(this.error) + return done() + }) + }) - it("should convert the source to the requested format", function(done){ - this.safe_exec.callsArgWith(2); - return this.converter.convert(this.sourcePath, this.format, err=> { - const args = this.safe_exec.args[0][0]; - args.indexOf(`${this.sourcePath}[0]`).should.not.equal(-1); - args.indexOf(`${this.sourcePath}.${this.format}`).should.not.equal(-1); - return done(); - }); - }); + it('should not accapt an non aproved format', function(done) { + this.safe_exec.callsArgWith(2) + return this.converter.convert(this.sourcePath, 'ahhhhh', err => { + expect(err).to.exist + return done() + }) + }) - it("should return the dest path", function(done){ - this.safe_exec.callsArgWith(2); - return this.converter.convert(this.sourcePath, this.format, (err, destPath)=> { - destPath.should.equal(`${this.sourcePath}.${this.format}`); - return done(); - }); - }); + return it('should prefix the command with Settings.commands.convertCommandPrefix', function(done) { + this.safe_exec.callsArgWith(2) + this.Settings.commands.convertCommandPrefix = ['nice'] + return this.converter.convert(this.sourcePath, this.format, err => { + const command = this.safe_exec.args[0][0] + command[0].should.equal('nice') + return done() + }) + }) + }) - it("should return the error from convert", function(done){ - this.safe_exec.callsArgWith(2, this.error); - return this.converter.convert(this.sourcePath, this.format, err=> { - err.should.equal(this.error); - return done(); - }); - }); + describe('thumbnail', () => + it('should call converter resize with args', function(done) { + this.safe_exec.callsArgWith(2) + return this.converter.thumbnail(this.sourcePath, err => { + const args = this.safe_exec.args[0][0] + args.indexOf(`${this.sourcePath}[0]`).should.not.equal(-1) + return done() + }) + })) - it("should not accapt an non aproved format", function(done){ - this.safe_exec.callsArgWith(2); - return this.converter.convert(this.sourcePath, "ahhhhh", err=> { - expect(err).to.exist; - return done(); - }); - }); - - return it("should prefix the command with Settings.commands.convertCommandPrefix", function(done) { - this.safe_exec.callsArgWith(2); - this.Settings.commands.convertCommandPrefix = ["nice"]; - return this.converter.convert(this.sourcePath, this.format, err=> { - const command = this.safe_exec.args[0][0]; - command[0].should.equal("nice"); - return done(); - }); - }); - }); - - describe("thumbnail", () => it("should call converter resize with args", function(done){ - this.safe_exec.callsArgWith(2); - return this.converter.thumbnail(this.sourcePath, err=> { - const args = this.safe_exec.args[0][0]; - args.indexOf(`${this.sourcePath}[0]`).should.not.equal(-1); - return done(); - }); - })); - - return describe("preview", () => it("should call converter resize with args", function(done){ - this.safe_exec.callsArgWith(2); - return this.converter.preview(this.sourcePath, err=> { - const args = this.safe_exec.args[0][0]; - args.indexOf(`${this.sourcePath}[0]`).should.not.equal(-1); - return done(); - }); - })); -}); + return describe('preview', () => + it('should call converter resize with args', function(done) { + this.safe_exec.callsArgWith(2) + return this.converter.preview(this.sourcePath, err => { + const args = this.safe_exec.args[0][0] + args.indexOf(`${this.sourcePath}[0]`).should.not.equal(-1) + return done() + }) + })) +}) diff --git a/services/filestore/test/unit/js/FileHandlerTests.js b/services/filestore/test/unit/js/FileHandlerTests.js index 13c60f08da..e641ffdd16 100644 --- a/services/filestore/test/unit/js/FileHandlerTests.js +++ b/services/filestore/test/unit/js/FileHandlerTests.js @@ -10,273 +10,359 @@ * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const { - assert -} = require("chai"); -const sinon = require('sinon'); -const chai = require('chai'); -const should = chai.should(); -const { - expect -} = chai; -const modulePath = "../../../app/js/FileHandler.js"; -const SandboxedModule = require('sandboxed-module'); +const { assert } = require('chai') +const sinon = require('sinon') +const chai = require('chai') +const should = chai.should() +const { expect } = chai +const modulePath = '../../../app/js/FileHandler.js' +const SandboxedModule = require('sandboxed-module') -describe("FileHandler", function() { +describe('FileHandler', function() { + beforeEach(function() { + this.settings = { + s3: { + buckets: { + user_files: 'user_files' + } + } + } + this.PersistorManager = { + getFileStream: sinon.stub(), + checkIfFileExists: sinon.stub(), + deleteFile: sinon.stub(), + deleteDirectory: sinon.stub(), + sendStream: sinon.stub(), + insertFile: sinon.stub(), + directorySize: sinon.stub() + } + this.LocalFileWriter = { + writeStream: sinon.stub(), + getStream: sinon.stub(), + deleteFile: sinon.stub() + } + this.FileConverter = { + convert: sinon.stub(), + thumbnail: sinon.stub(), + preview: sinon.stub() + } + this.keyBuilder = { + addCachingToKey: sinon.stub(), + getConvertedFolderKey: sinon.stub() + } + this.ImageOptimiser = { compressPng: sinon.stub() } + this.handler = SandboxedModule.require(modulePath, { + requires: { + 'settings-sharelatex': this.settings, + './PersistorManager': this.PersistorManager, + './LocalFileWriter': this.LocalFileWriter, + './FileConverter': this.FileConverter, + './KeyBuilder': this.keyBuilder, + './ImageOptimiser': this.ImageOptimiser, + 'logger-sharelatex': { + log() {}, + err() {} + } + } + }) + this.bucket = 'my_bucket' + this.key = 'key/here' + this.stubbedPath = '/var/somewhere/path' + this.format = 'png' + return (this.formattedStubbedPath = `${this.stubbedPath}.${this.format}`) + }) - beforeEach(function() { - this.settings = { - s3: { - buckets: { - user_files:"user_files" - } - } - }; - this.PersistorManager = { - getFileStream: sinon.stub(), - checkIfFileExists: sinon.stub(), - deleteFile: sinon.stub(), - deleteDirectory: sinon.stub(), - sendStream: sinon.stub(), - insertFile: sinon.stub(), - directorySize: sinon.stub() - }; - this.LocalFileWriter = { - writeStream: sinon.stub(), - getStream: sinon.stub(), - deleteFile: sinon.stub() - }; - this.FileConverter = { - convert: sinon.stub(), - thumbnail: sinon.stub(), - preview: sinon.stub() - }; - this.keyBuilder = { - addCachingToKey: sinon.stub(), - getConvertedFolderKey: sinon.stub() - }; - this.ImageOptimiser = - {compressPng: sinon.stub()}; - this.handler = SandboxedModule.require(modulePath, { requires: { - "settings-sharelatex": this.settings, - "./PersistorManager":this.PersistorManager, - "./LocalFileWriter":this.LocalFileWriter, - "./FileConverter":this.FileConverter, - "./KeyBuilder": this.keyBuilder, - "./ImageOptimiser":this.ImageOptimiser, - "logger-sharelatex": { - log() {}, - err() {} - } - } - } - ); - this.bucket = "my_bucket"; - this.key = "key/here"; - this.stubbedPath = "/var/somewhere/path"; - this.format = "png"; - return this.formattedStubbedPath = `${this.stubbedPath}.${this.format}`; - }); + describe('insertFile', function() { + beforeEach(function() { + this.stream = {} + this.PersistorManager.deleteDirectory.callsArgWith(2) + return this.PersistorManager.sendStream.callsArgWith(3) + }) - describe("insertFile", function() { - beforeEach(function() { - this.stream = {}; - this.PersistorManager.deleteDirectory.callsArgWith(2); - return this.PersistorManager.sendStream.callsArgWith(3); - }); + it('should send file to the filestore', function(done) { + return this.handler.insertFile(this.bucket, this.key, this.stream, () => { + this.PersistorManager.sendStream + .calledWith(this.bucket, this.key, this.stream) + .should.equal(true) + return done() + }) + }) - it("should send file to the filestore", function(done){ - return this.handler.insertFile(this.bucket, this.key, this.stream, () => { - this.PersistorManager.sendStream.calledWith(this.bucket, this.key, this.stream).should.equal(true); - return done(); - }); - }); + return it('should delete the convetedKey folder', function(done) { + this.keyBuilder.getConvertedFolderKey.returns(this.stubbedConvetedKey) + return this.handler.insertFile(this.bucket, this.key, this.stream, () => { + this.PersistorManager.deleteDirectory + .calledWith(this.bucket, this.stubbedConvetedKey) + .should.equal(true) + return done() + }) + }) + }) - return it("should delete the convetedKey folder", function(done){ - this.keyBuilder.getConvertedFolderKey.returns(this.stubbedConvetedKey); - return this.handler.insertFile(this.bucket, this.key, this.stream, () => { - this.PersistorManager.deleteDirectory.calledWith(this.bucket, this.stubbedConvetedKey).should.equal(true); - return done(); - }); - }); - }); + describe('deleteFile', function() { + beforeEach(function() { + this.keyBuilder.getConvertedFolderKey.returns(this.stubbedConvetedKey) + this.PersistorManager.deleteFile.callsArgWith(2) + return this.PersistorManager.deleteDirectory.callsArgWith(2) + }) - describe("deleteFile", function() { - beforeEach(function() { - this.keyBuilder.getConvertedFolderKey.returns(this.stubbedConvetedKey); - this.PersistorManager.deleteFile.callsArgWith(2); - return this.PersistorManager.deleteDirectory.callsArgWith(2); - }); + it('should tell the filestore manager to delete the file', function(done) { + return this.handler.deleteFile(this.bucket, this.key, () => { + this.PersistorManager.deleteFile + .calledWith(this.bucket, this.key) + .should.equal(true) + return done() + }) + }) - it("should tell the filestore manager to delete the file", function(done){ - return this.handler.deleteFile(this.bucket, this.key, () => { - this.PersistorManager.deleteFile.calledWith(this.bucket, this.key).should.equal(true); - return done(); - }); - }); + return it('should tell the filestore manager to delete the cached foler', function(done) { + return this.handler.deleteFile(this.bucket, this.key, () => { + this.PersistorManager.deleteDirectory + .calledWith(this.bucket, this.stubbedConvetedKey) + .should.equal(true) + return done() + }) + }) + }) - return it("should tell the filestore manager to delete the cached foler", function(done){ - return this.handler.deleteFile(this.bucket, this.key, () => { - this.PersistorManager.deleteDirectory.calledWith(this.bucket, this.stubbedConvetedKey).should.equal(true); - return done(); - }); - }); - }); + describe('getFile', function() { + beforeEach(function() { + this.handler._getStandardFile = sinon.stub().callsArgWith(3) + return (this.handler._getConvertedFile = sinon.stub().callsArgWith(3)) + }) - describe("getFile", function() { - beforeEach(function() { - this.handler._getStandardFile = sinon.stub().callsArgWith(3); - return this.handler._getConvertedFile = sinon.stub().callsArgWith(3); - }); + it('should call _getStandardFile if no format or style are defined', function(done) { + return this.handler.getFile(this.bucket, this.key, null, () => { + this.handler._getStandardFile.called.should.equal(true) + this.handler._getConvertedFile.called.should.equal(false) + return done() + }) + }) - it("should call _getStandardFile if no format or style are defined", function(done){ + it('should pass options to _getStandardFile', function(done) { + const options = { start: 0, end: 8 } + return this.handler.getFile(this.bucket, this.key, options, () => { + expect(this.handler._getStandardFile.lastCall.args[2].start).to.equal(0) + expect(this.handler._getStandardFile.lastCall.args[2].end).to.equal(8) + return done() + }) + }) - return this.handler.getFile(this.bucket, this.key, null, () => { - this.handler._getStandardFile.called.should.equal(true); - this.handler._getConvertedFile.called.should.equal(false); - return done(); - }); - }); + return it('should call _getConvertedFile if a format is defined', function(done) { + return this.handler.getFile( + this.bucket, + this.key, + { format: 'png' }, + () => { + this.handler._getStandardFile.called.should.equal(false) + this.handler._getConvertedFile.called.should.equal(true) + return done() + } + ) + }) + }) - it("should pass options to _getStandardFile", function(done) { - const options = {start: 0, end: 8}; - return this.handler.getFile(this.bucket, this.key, options, () => { - expect(this.handler._getStandardFile.lastCall.args[2].start).to.equal(0); - expect(this.handler._getStandardFile.lastCall.args[2].end).to.equal(8); - return done(); - }); - }); + describe('_getStandardFile', function() { + beforeEach(function() { + this.fileStream = { on() {} } + return this.PersistorManager.getFileStream.callsArgWith( + 3, + 'err', + this.fileStream + ) + }) - return it("should call _getConvertedFile if a format is defined", function(done){ - return this.handler.getFile(this.bucket, this.key, {format:"png"}, () => { - this.handler._getStandardFile.called.should.equal(false); - this.handler._getConvertedFile.called.should.equal(true); - return done(); - }); - }); - }); + it('should get the stream', function(done) { + return this.handler.getFile(this.bucket, this.key, null, () => { + this.PersistorManager.getFileStream + .calledWith(this.bucket, this.key) + .should.equal(true) + return done() + }) + }) - describe("_getStandardFile", function() { + it('should return the stream and error', function(done) { + return this.handler.getFile( + this.bucket, + this.key, + null, + (err, stream) => { + err.should.equal('err') + stream.should.equal(this.fileStream) + return done() + } + ) + }) - beforeEach(function() { - this.fileStream = {on() {}}; - return this.PersistorManager.getFileStream.callsArgWith(3, "err", this.fileStream); - }); + return it('should pass options to PersistorManager', function(done) { + return this.handler.getFile( + this.bucket, + this.key, + { start: 0, end: 8 }, + () => { + expect( + this.PersistorManager.getFileStream.lastCall.args[2].start + ).to.equal(0) + expect( + this.PersistorManager.getFileStream.lastCall.args[2].end + ).to.equal(8) + return done() + } + ) + }) + }) - it("should get the stream", function(done){ - return this.handler.getFile(this.bucket, this.key, null, () => { - this.PersistorManager.getFileStream.calledWith(this.bucket, this.key).should.equal(true); - return done(); - }); - }); + describe('_getConvertedFile', function() { + it('should getFileStream if it does exists', function(done) { + this.PersistorManager.checkIfFileExists.callsArgWith(2, null, true) + this.PersistorManager.getFileStream.callsArgWith(3) + return this.handler._getConvertedFile(this.bucket, this.key, {}, () => { + this.PersistorManager.getFileStream + .calledWith(this.bucket) + .should.equal(true) + return done() + }) + }) - it("should return the stream and error", function(done){ - return this.handler.getFile(this.bucket, this.key, null, (err, stream)=> { - err.should.equal("err"); - stream.should.equal(this.fileStream); - return done(); - }); - }); + return it('should call _getConvertedFileAndCache if it does exists', function(done) { + this.PersistorManager.checkIfFileExists.callsArgWith(2, null, false) + this.handler._getConvertedFileAndCache = sinon.stub().callsArgWith(4) + return this.handler._getConvertedFile(this.bucket, this.key, {}, () => { + this.handler._getConvertedFileAndCache + .calledWith(this.bucket, this.key) + .should.equal(true) + return done() + }) + }) + }) - return it("should pass options to PersistorManager", function(done) { - return this.handler.getFile(this.bucket, this.key, {start: 0, end: 8}, () => { - expect(this.PersistorManager.getFileStream.lastCall.args[2].start).to.equal(0); - expect(this.PersistorManager.getFileStream.lastCall.args[2].end).to.equal(8); - return done(); - }); - }); - }); + describe('_getConvertedFileAndCache', () => + it('should _convertFile ', function(done) { + this.stubbedStream = { something: 'here' } + this.localStream = { + on() {} + } + this.PersistorManager.sendFile = sinon.stub().callsArgWith(3) + this.LocalFileWriter.getStream = sinon + .stub() + .callsArgWith(1, null, this.localStream) + this.convetedKey = this.key + 'converted' + this.handler._convertFile = sinon + .stub() + .callsArgWith(3, null, this.stubbedPath) + this.ImageOptimiser.compressPng = sinon.stub().callsArgWith(1) + return this.handler._getConvertedFileAndCache( + this.bucket, + this.key, + this.convetedKey, + {}, + (err, fsStream) => { + this.handler._convertFile.called.should.equal(true) + this.PersistorManager.sendFile + .calledWith(this.bucket, this.convetedKey, this.stubbedPath) + .should.equal(true) + this.ImageOptimiser.compressPng + .calledWith(this.stubbedPath) + .should.equal(true) + this.LocalFileWriter.getStream + .calledWith(this.stubbedPath) + .should.equal(true) + fsStream.should.equal(this.localStream) + return done() + } + ) + })) + describe('_convertFile', function() { + beforeEach(function() { + this.FileConverter.convert.callsArgWith( + 2, + null, + this.formattedStubbedPath + ) + this.FileConverter.thumbnail.callsArgWith( + 1, + null, + this.formattedStubbedPath + ) + this.FileConverter.preview.callsArgWith( + 1, + null, + this.formattedStubbedPath + ) + this.handler._writeS3FileToDisk = sinon + .stub() + .callsArgWith(3, null, this.stubbedPath) + return this.LocalFileWriter.deleteFile.callsArgWith(1) + }) - describe("_getConvertedFile", function() { + it('should call thumbnail on the writer path if style was thumbnail was specified', function(done) { + return this.handler._convertFile( + this.bucket, + this.key, + { style: 'thumbnail' }, + (err, path) => { + path.should.equal(this.formattedStubbedPath) + this.FileConverter.thumbnail + .calledWith(this.stubbedPath) + .should.equal(true) + this.LocalFileWriter.deleteFile + .calledWith(this.stubbedPath) + .should.equal(true) + return done() + } + ) + }) - it("should getFileStream if it does exists", function(done){ - this.PersistorManager.checkIfFileExists.callsArgWith(2, null, true); - this.PersistorManager.getFileStream.callsArgWith(3); - return this.handler._getConvertedFile(this.bucket, this.key, {}, () => { - this.PersistorManager.getFileStream.calledWith(this.bucket).should.equal(true); - return done(); - }); - }); + it('should call preview on the writer path if style was preview was specified', function(done) { + return this.handler._convertFile( + this.bucket, + this.key, + { style: 'preview' }, + (err, path) => { + path.should.equal(this.formattedStubbedPath) + this.FileConverter.preview + .calledWith(this.stubbedPath) + .should.equal(true) + this.LocalFileWriter.deleteFile + .calledWith(this.stubbedPath) + .should.equal(true) + return done() + } + ) + }) - return it("should call _getConvertedFileAndCache if it does exists", function(done){ - this.PersistorManager.checkIfFileExists.callsArgWith(2, null, false); - this.handler._getConvertedFileAndCache = sinon.stub().callsArgWith(4); - return this.handler._getConvertedFile(this.bucket, this.key, {}, () => { - this.handler._getConvertedFileAndCache.calledWith(this.bucket, this.key).should.equal(true); - return done(); - }); - }); - }); + return it('should call convert on the writer path if a format was specified', function(done) { + return this.handler._convertFile( + this.bucket, + this.key, + { format: this.format }, + (err, path) => { + path.should.equal(this.formattedStubbedPath) + this.FileConverter.convert + .calledWith(this.stubbedPath, this.format) + .should.equal(true) + this.LocalFileWriter.deleteFile + .calledWith(this.stubbedPath) + .should.equal(true) + return done() + } + ) + }) + }) - describe("_getConvertedFileAndCache", () => it("should _convertFile ", function(done){ - this.stubbedStream = {"something":"here"}; - this.localStream = { - on() {} - }; - this.PersistorManager.sendFile = sinon.stub().callsArgWith(3); - this.LocalFileWriter.getStream = sinon.stub().callsArgWith(1, null, this.localStream); - this.convetedKey = this.key+"converted"; - this.handler._convertFile = sinon.stub().callsArgWith(3, null, this.stubbedPath); - this.ImageOptimiser.compressPng = sinon.stub().callsArgWith(1); - return this.handler._getConvertedFileAndCache(this.bucket, this.key, this.convetedKey, {}, (err, fsStream)=> { - this.handler._convertFile.called.should.equal(true); - this.PersistorManager.sendFile.calledWith(this.bucket, this.convetedKey, this.stubbedPath).should.equal(true); - this.ImageOptimiser.compressPng.calledWith(this.stubbedPath).should.equal(true); - this.LocalFileWriter.getStream.calledWith(this.stubbedPath).should.equal(true); - fsStream.should.equal(this.localStream); - return done(); - }); - })); + return describe('getDirectorySize', function() { + beforeEach(function() { + return this.PersistorManager.directorySize.callsArgWith(2) + }) - describe("_convertFile", function() { - beforeEach(function() { - this.FileConverter.convert.callsArgWith(2, null, this.formattedStubbedPath); - this.FileConverter.thumbnail.callsArgWith(1, null, this.formattedStubbedPath); - this.FileConverter.preview.callsArgWith(1, null, this.formattedStubbedPath); - this.handler._writeS3FileToDisk = sinon.stub().callsArgWith(3, null, this.stubbedPath); - return this.LocalFileWriter.deleteFile.callsArgWith(1); - }); - - it("should call thumbnail on the writer path if style was thumbnail was specified", function(done){ - return this.handler._convertFile(this.bucket, this.key, {style:"thumbnail"}, (err, path)=> { - path.should.equal(this.formattedStubbedPath); - this.FileConverter.thumbnail.calledWith(this.stubbedPath).should.equal(true); - this.LocalFileWriter.deleteFile.calledWith(this.stubbedPath).should.equal(true); - return done(); - }); - }); - - it("should call preview on the writer path if style was preview was specified", function(done){ - return this.handler._convertFile(this.bucket, this.key, {style:"preview"}, (err, path)=> { - path.should.equal(this.formattedStubbedPath); - this.FileConverter.preview.calledWith(this.stubbedPath).should.equal(true); - this.LocalFileWriter.deleteFile.calledWith(this.stubbedPath).should.equal(true); - return done(); - }); - }); - - return it("should call convert on the writer path if a format was specified", function(done){ - return this.handler._convertFile(this.bucket, this.key, {format:this.format}, (err, path)=> { - path.should.equal(this.formattedStubbedPath); - this.FileConverter.convert.calledWith(this.stubbedPath, this.format).should.equal(true); - this.LocalFileWriter.deleteFile.calledWith(this.stubbedPath).should.equal(true); - return done(); - }); - }); - }); - - return describe("getDirectorySize", function() { - - beforeEach(function() { - return this.PersistorManager.directorySize.callsArgWith(2); - }); - - return it("should call the filestore manager to get directory size", function(done){ - return this.handler.getDirectorySize(this.bucket, this.key, () => { - this.PersistorManager.directorySize.calledWith(this.bucket, this.key).should.equal(true); - return done(); - }); - }); - }); -}); + return it('should call the filestore manager to get directory size', function(done) { + return this.handler.getDirectorySize(this.bucket, this.key, () => { + this.PersistorManager.directorySize + .calledWith(this.bucket, this.key) + .should.equal(true) + return done() + }) + }) + }) +}) diff --git a/services/filestore/test/unit/js/ImageOptimiserTests.js b/services/filestore/test/unit/js/ImageOptimiserTests.js index 4e6cb858f4..6fdb09f89d 100644 --- a/services/filestore/test/unit/js/ImageOptimiserTests.js +++ b/services/filestore/test/unit/js/ImageOptimiserTests.js @@ -10,82 +10,72 @@ * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const { - assert -} = require("chai"); -const sinon = require('sinon'); -const chai = require('chai'); -const should = chai.should(); -const { - expect -} = chai; -const modulePath = "../../../app/js/ImageOptimiser.js"; -const SandboxedModule = require('sandboxed-module'); +const { assert } = require('chai') +const sinon = require('sinon') +const chai = require('chai') +const should = chai.should() +const { expect } = chai +const modulePath = '../../../app/js/ImageOptimiser.js' +const SandboxedModule = require('sandboxed-module') -describe("ImageOptimiser", function() { +describe('ImageOptimiser', function() { + beforeEach(function() { + this.child_process = { exec: sinon.stub() } + this.settings = { enableConversions: true } + this.optimiser = SandboxedModule.require(modulePath, { + requires: { + child_process: this.child_process, + 'logger-sharelatex': { + log() {}, + err() {}, + warn() {} + }, + 'settings-sharelatex': this.settings + } + }) - beforeEach(function() { - this.child_process = - {exec : sinon.stub()}; - this.settings = - {enableConversions:true}; - this.optimiser = SandboxedModule.require(modulePath, { requires: { - 'child_process': this.child_process, - "logger-sharelatex": { - log() {}, - err() {}, - warn() {} - }, - "settings-sharelatex": this.settings - } - } - ); - + this.sourcePath = '/this/path/here.eps' + return (this.error = 'Error') + }) - this.sourcePath = "/this/path/here.eps"; - return this.error = "Error"; - }); + describe('compressPng', function() { + it('convert the file', function(done) { + this.child_process.exec.callsArgWith(2) + return this.optimiser.compressPng(this.sourcePath, err => { + const args = this.child_process.exec.args[0][0] + args.should.equal(`optipng ${this.sourcePath}`) + return done() + }) + }) - describe("compressPng", function() { - + return it('should return the error', function(done) { + this.child_process.exec.callsArgWith(2, this.error) + return this.optimiser.compressPng(this.sourcePath, err => { + err.should.equal(this.error) + return done() + }) + }) + }) - it("convert the file", function(done){ - this.child_process.exec.callsArgWith(2); - return this.optimiser.compressPng(this.sourcePath, err=> { - const args = this.child_process.exec.args[0][0]; - args.should.equal(`optipng ${this.sourcePath}`); - return done(); - }); - }); + describe('when enableConversions is disabled', () => + it('should produce an error', function(done) { + this.settings.enableConversions = false + this.child_process.exec.callsArgWith(2) + return this.optimiser.compressPng(this.sourcePath, err => { + this.child_process.exec.called.should.equal(false) + expect(err).to.exist + return done() + }) + })) - - return it("should return the error", function(done){ - this.child_process.exec.callsArgWith(2, this.error); - return this.optimiser.compressPng(this.sourcePath, err=> { - err.should.equal(this.error); - return done(); - }); - }); - }); - - describe('when enableConversions is disabled', () => it('should produce an error', function(done) { - this.settings.enableConversions = false; - this.child_process.exec.callsArgWith(2); - return this.optimiser.compressPng(this.sourcePath, err=> { - this.child_process.exec.called.should.equal(false); - expect(err).to.exist; - return done(); - }); - })); - - - return describe('when optimiser is sigkilled', () => it('should not produce an error', function(done) { - this.error = new Error('woops'); - this.error.signal = 'SIGKILL'; - this.child_process.exec.callsArgWith(2, this.error); - return this.optimiser.compressPng(this.sourcePath, err=> { - expect(err).to.equal(null); - return done(); - }); - })); -}); + return describe('when optimiser is sigkilled', () => + it('should not produce an error', function(done) { + this.error = new Error('woops') + this.error.signal = 'SIGKILL' + this.child_process.exec.callsArgWith(2, this.error) + return this.optimiser.compressPng(this.sourcePath, err => { + expect(err).to.equal(null) + return done() + }) + })) +}) diff --git a/services/filestore/test/unit/js/KeybuilderTests.js b/services/filestore/test/unit/js/KeybuilderTests.js index 1e99899be7..09a0ea8717 100644 --- a/services/filestore/test/unit/js/KeybuilderTests.js +++ b/services/filestore/test/unit/js/KeybuilderTests.js @@ -10,56 +10,49 @@ * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const { - assert -} = require("chai"); -const sinon = require('sinon'); -const chai = require('chai'); -const should = chai.should(); -const { - expect -} = chai; -const modulePath = "../../../app/js/KeyBuilder.js"; -const SandboxedModule = require('sandboxed-module'); +const { assert } = require('chai') +const sinon = require('sinon') +const chai = require('chai') +const should = chai.should() +const { expect } = chai +const modulePath = '../../../app/js/KeyBuilder.js' +const SandboxedModule = require('sandboxed-module') -describe("LocalFileWriter", function() { +describe('LocalFileWriter', function() { + beforeEach(function() { + this.keyBuilder = SandboxedModule.require(modulePath, { + requires: { + 'logger-sharelatex': { + log() {}, + err() {} + } + } + }) + return (this.key = '123/456') + }) - beforeEach(function() { + return describe('cachedKey', function() { + it('should add the fomat on', function() { + const opts = { format: 'png' } + const newKey = this.keyBuilder.addCachingToKey(this.key, opts) + return newKey.should.equal(`${this.key}-converted-cache/format-png`) + }) - this.keyBuilder = SandboxedModule.require(modulePath, { requires: { - "logger-sharelatex": { - log() {}, - err() {} - } - } - } - ); - return this.key = "123/456"; - }); - - return describe("cachedKey", function() { + it('should add the style on', function() { + const opts = { style: 'thumbnail' } + const newKey = this.keyBuilder.addCachingToKey(this.key, opts) + return newKey.should.equal(`${this.key}-converted-cache/style-thumbnail`) + }) - it("should add the fomat on", function() { - const opts = - {format: "png"}; - const newKey = this.keyBuilder.addCachingToKey(this.key, opts); - return newKey.should.equal(`${this.key}-converted-cache/format-png`); - }); - - it("should add the style on", function() { - const opts = - {style: "thumbnail"}; - const newKey = this.keyBuilder.addCachingToKey(this.key, opts); - return newKey.should.equal(`${this.key}-converted-cache/style-thumbnail`); - }); - - return it("should add format on first", function() { - const opts = { - style: "thumbnail", - format: "png" - }; - const newKey = this.keyBuilder.addCachingToKey(this.key, opts); - return newKey.should.equal(`${this.key}-converted-cache/format-png-style-thumbnail`); - }); - }); -}); + return it('should add format on first', function() { + const opts = { + style: 'thumbnail', + format: 'png' + } + const newKey = this.keyBuilder.addCachingToKey(this.key, opts) + return newKey.should.equal( + `${this.key}-converted-cache/format-png-style-thumbnail` + ) + }) + }) +}) diff --git a/services/filestore/test/unit/js/LocalFileWriterTests.js b/services/filestore/test/unit/js/LocalFileWriterTests.js index 1bf131a3c4..e7ea993ab9 100644 --- a/services/filestore/test/unit/js/LocalFileWriterTests.js +++ b/services/filestore/test/unit/js/LocalFileWriterTests.js @@ -11,118 +11,112 @@ * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const { - assert -} = require("chai"); -const sinon = require('sinon'); -const chai = require('chai'); -const should = chai.should(); -const { - expect -} = chai; -const modulePath = "../../../app/js/LocalFileWriter.js"; -const SandboxedModule = require('sandboxed-module'); +const { assert } = require('chai') +const sinon = require('sinon') +const chai = require('chai') +const should = chai.should() +const { expect } = chai +const modulePath = '../../../app/js/LocalFileWriter.js' +const SandboxedModule = require('sandboxed-module') -describe("LocalFileWriter", function() { +describe('LocalFileWriter', function() { + beforeEach(function() { + this.writeStream = { + on(type, cb) { + if (type === 'finish') { + return cb() + } + } + } + this.readStream = { on() {} } + this.fs = { + createWriteStream: sinon.stub().returns(this.writeStream), + createReadStream: sinon.stub().returns(this.readStream), + unlink: sinon.stub() + } + this.settings = { + path: { + uploadFolder: 'somewhere' + } + } + this.writer = SandboxedModule.require(modulePath, { + requires: { + fs: this.fs, + 'logger-sharelatex': { + log() {}, + err() {} + }, + 'settings-sharelatex': this.settings, + 'metrics-sharelatex': { + inc() {}, + Timer() { + return { done() {} } + } + } + } + }) - beforeEach(function() { + return (this.stubbedFsPath = 'something/uploads/eio2k1j3') + }) - this.writeStream = { - on(type, cb){ - if (type === "finish") { - return cb(); - } - } - }; - this.readStream = - {on() {}}; - this.fs = { - createWriteStream : sinon.stub().returns(this.writeStream), - createReadStream: sinon.stub().returns(this.readStream), - unlink: sinon.stub() - }; - this.settings = { - path: { - uploadFolder:"somewhere" - } - }; - this.writer = SandboxedModule.require(modulePath, { requires: { - "fs": this.fs, - "logger-sharelatex": { - log() {}, - err() {} - }, - "settings-sharelatex":this.settings, - "metrics-sharelatex": { - inc() {}, - Timer() { - return {done() {}}; - } - } - } - } - ); + describe('writeStrem', function() { + beforeEach(function() { + return (this.writer._getPath = sinon.stub().returns(this.stubbedFsPath)) + }) - return this.stubbedFsPath = "something/uploads/eio2k1j3"; - }); + it('write the stream to ./uploads', function(done) { + const stream = { + pipe: dest => { + dest.should.equal(this.writeStream) + return done() + }, + on() {} + } + return this.writer.writeStream(stream, null, () => {}) + }) - describe("writeStrem", function() { - beforeEach(function() { - return this.writer._getPath = sinon.stub().returns(this.stubbedFsPath); - }); + return it('should send the path in the callback', function(done) { + const stream = { + pipe: dest => {}, + on(type, cb) { + if (type === 'end') { + return cb() + } + } + } + return this.writer.writeStream(stream, null, (err, fsPath) => { + fsPath.should.equal(this.stubbedFsPath) + return done() + }) + }) + }) - it("write the stream to ./uploads", function(done){ - const stream = { - pipe: dest=> { - dest.should.equal(this.writeStream); - return done(); - }, - on() {} - }; - return this.writer.writeStream(stream, null, ()=> {}); - }); + describe('getStream', function() { + it('should read the stream from the file ', function(done) { + return this.writer.getStream(this.stubbedFsPath, (err, stream) => { + this.fs.createReadStream + .calledWith(this.stubbedFsPath) + .should.equal(true) + return done() + }) + }) - return it("should send the path in the callback", function(done){ - const stream = { - pipe: dest=> {}, - on(type, cb){ - if (type === "end") { - return cb(); - } - } - }; - return this.writer.writeStream(stream, null, (err, fsPath)=> { - fsPath.should.equal(this.stubbedFsPath); - return done(); - }); - }); - }); - - describe("getStream", function() { - - it("should read the stream from the file ", function(done){ - return this.writer.getStream(this.stubbedFsPath, (err, stream)=> { - this.fs.createReadStream.calledWith(this.stubbedFsPath).should.equal(true); - return done(); - }); - }); - - return it("should send the stream in the callback", function(done){ - return this.writer.getStream(this.stubbedFsPath, (err, readStream)=> { - readStream.should.equal(this.readStream); - return done(); - }); - }); - }); - - return describe("delete file", () => it("should unlink the file", function(done){ - const error = "my error"; - this.fs.unlink.callsArgWith(1, error); - return this.writer.deleteFile(this.stubbedFsPath, err=> { - this.fs.unlink.calledWith(this.stubbedFsPath).should.equal(true); - err.should.equal(error); - return done(); - }); - })); -}); + return it('should send the stream in the callback', function(done) { + return this.writer.getStream(this.stubbedFsPath, (err, readStream) => { + readStream.should.equal(this.readStream) + return done() + }) + }) + }) + return describe('delete file', () => + it('should unlink the file', function(done) { + const error = 'my error' + this.fs.unlink.callsArgWith(1, error) + return this.writer.deleteFile(this.stubbedFsPath, err => { + this.fs.unlink.calledWith(this.stubbedFsPath).should.equal(true) + err.should.equal(error) + return done() + }) + })) +}) diff --git a/services/filestore/test/unit/js/PersistorManagerTests.js b/services/filestore/test/unit/js/PersistorManagerTests.js index 620d6f0083..ff49c05ce9 100644 --- a/services/filestore/test/unit/js/PersistorManagerTests.js +++ b/services/filestore/test/unit/js/PersistorManagerTests.js @@ -9,129 +9,129 @@ * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const logger = require("logger-sharelatex"); -const { - assert -} = require("chai"); -const sinon = require('sinon'); -const chai = require('chai'); -const should = chai.should(); -const { - expect -} = chai; -const modulePath = "../../../app/js/PersistorManager.js"; -const SandboxedModule = require('sandboxed-module'); +const logger = require('logger-sharelatex') +const { assert } = require('chai') +const sinon = require('sinon') +const chai = require('chai') +const should = chai.should() +const { expect } = chai +const modulePath = '../../../app/js/PersistorManager.js' +const SandboxedModule = require('sandboxed-module') +describe('PersistorManagerTests', function() { + beforeEach(function() { + return (this.S3PersistorManager = { + getFileStream: sinon.stub(), + checkIfFileExists: sinon.stub(), + deleteFile: sinon.stub(), + deleteDirectory: sinon.stub(), + sendStream: sinon.stub(), + insertFile: sinon.stub() + }) + }) -describe("PersistorManagerTests", function() { - - beforeEach(function() { - return this.S3PersistorManager = { - getFileStream: sinon.stub(), - checkIfFileExists: sinon.stub(), - deleteFile: sinon.stub(), - deleteDirectory: sinon.stub(), - sendStream: sinon.stub(), - insertFile: sinon.stub() - }; - }); - - describe("test s3 mixin", function() { - beforeEach(function() { - this.settings = { - filestore: { - backend: "s3" - } - }; - this.requires = { - "./S3PersistorManager": this.S3PersistorManager, - "settings-sharelatex": this.settings, - "logger-sharelatex": { - log() {}, - err() {} - } - }; - return this.PersistorManager = SandboxedModule.require(modulePath, {requires: this.requires}); - }); - - it("should load getFileStream", function(done) { - this.PersistorManager.should.respondTo("getFileStream"); - this.PersistorManager.getFileStream(); - this.S3PersistorManager.getFileStream.calledOnce.should.equal(true); - return done(); - }); - - it("should load checkIfFileExists", function(done) { - this.PersistorManager.checkIfFileExists(); - this.S3PersistorManager.checkIfFileExists.calledOnce.should.equal(true); - return done(); - }); - - it("should load deleteFile", function(done) { - this.PersistorManager.deleteFile(); - this.S3PersistorManager.deleteFile.calledOnce.should.equal(true); - return done(); - }); - - it("should load deleteDirectory", function(done) { - this.PersistorManager.deleteDirectory(); - this.S3PersistorManager.deleteDirectory.calledOnce.should.equal(true); - return done(); - }); - - it("should load sendStream", function(done) { - this.PersistorManager.sendStream(); - this.S3PersistorManager.sendStream.calledOnce.should.equal(true); - return done(); - }); - - return it("should load insertFile", function(done) { - this.PersistorManager.insertFile(); - this.S3PersistorManager.insertFile.calledOnce.should.equal(true); - return done(); - }); - }); - - describe("test unspecified mixins", () => it("should load s3 when no wrapper specified", function(done) { - this.settings = {filestore:{}}; - this.requires = { - "./S3PersistorManager": this.S3PersistorManager, - "settings-sharelatex": this.settings, - "logger-sharelatex": { - log() {}, - err() {} - } - }; - this.PersistorManager = SandboxedModule.require(modulePath, {requires: this.requires}); - this.PersistorManager.should.respondTo("getFileStream"); - this.PersistorManager.getFileStream(); - this.S3PersistorManager.getFileStream.calledOnce.should.equal(true); - return done(); - })); - - return describe("test invalid mixins", () => it("should not load an invalid wrapper", function(done) { - this.settings = { - filestore: { - backend:"magic" - } - }; - this.requires = { - "./S3PersistorManager": this.S3PersistorManager, - "settings-sharelatex": this.settings, - "logger-sharelatex": { - log() {}, - err() {} - } - }; - this.fsWrapper=null; - try { - this.PersistorManager=SandboxedModule.require(modulePath, {requires: this.requires}); - } catch (error) { - assert.equal("Unknown filestore backend: magic",error.message); + describe('test s3 mixin', function() { + beforeEach(function() { + this.settings = { + filestore: { + backend: 's3' } - assert.isNull(this.fsWrapper); - return done(); - })); -}); + } + this.requires = { + './S3PersistorManager': this.S3PersistorManager, + 'settings-sharelatex': this.settings, + 'logger-sharelatex': { + log() {}, + err() {} + } + } + return (this.PersistorManager = SandboxedModule.require(modulePath, { + requires: this.requires + })) + }) + it('should load getFileStream', function(done) { + this.PersistorManager.should.respondTo('getFileStream') + this.PersistorManager.getFileStream() + this.S3PersistorManager.getFileStream.calledOnce.should.equal(true) + return done() + }) + it('should load checkIfFileExists', function(done) { + this.PersistorManager.checkIfFileExists() + this.S3PersistorManager.checkIfFileExists.calledOnce.should.equal(true) + return done() + }) + + it('should load deleteFile', function(done) { + this.PersistorManager.deleteFile() + this.S3PersistorManager.deleteFile.calledOnce.should.equal(true) + return done() + }) + + it('should load deleteDirectory', function(done) { + this.PersistorManager.deleteDirectory() + this.S3PersistorManager.deleteDirectory.calledOnce.should.equal(true) + return done() + }) + + it('should load sendStream', function(done) { + this.PersistorManager.sendStream() + this.S3PersistorManager.sendStream.calledOnce.should.equal(true) + return done() + }) + + return it('should load insertFile', function(done) { + this.PersistorManager.insertFile() + this.S3PersistorManager.insertFile.calledOnce.should.equal(true) + return done() + }) + }) + + describe('test unspecified mixins', () => + it('should load s3 when no wrapper specified', function(done) { + this.settings = { filestore: {} } + this.requires = { + './S3PersistorManager': this.S3PersistorManager, + 'settings-sharelatex': this.settings, + 'logger-sharelatex': { + log() {}, + err() {} + } + } + this.PersistorManager = SandboxedModule.require(modulePath, { + requires: this.requires + }) + this.PersistorManager.should.respondTo('getFileStream') + this.PersistorManager.getFileStream() + this.S3PersistorManager.getFileStream.calledOnce.should.equal(true) + return done() + })) + + return describe('test invalid mixins', () => + it('should not load an invalid wrapper', function(done) { + this.settings = { + filestore: { + backend: 'magic' + } + } + this.requires = { + './S3PersistorManager': this.S3PersistorManager, + 'settings-sharelatex': this.settings, + 'logger-sharelatex': { + log() {}, + err() {} + } + } + this.fsWrapper = null + try { + this.PersistorManager = SandboxedModule.require(modulePath, { + requires: this.requires + }) + } catch (error) { + assert.equal('Unknown filestore backend: magic', error.message) + } + assert.isNull(this.fsWrapper) + return done() + })) +}) diff --git a/services/filestore/test/unit/js/S3PersistorManagerTests.js b/services/filestore/test/unit/js/S3PersistorManagerTests.js index a3a7d16825..c0a03696a8 100644 --- a/services/filestore/test/unit/js/S3PersistorManagerTests.js +++ b/services/filestore/test/unit/js/S3PersistorManagerTests.js @@ -11,444 +11,609 @@ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const { - assert -} = require("chai"); -const sinon = require('sinon'); -const chai = require('chai'); -const should = chai.should(); -const { - expect -} = chai; -const modulePath = "../../../app/js/S3PersistorManager.js"; -const SandboxedModule = require('sandboxed-module'); +const { assert } = require('chai') +const sinon = require('sinon') +const chai = require('chai') +const should = chai.should() +const { expect } = chai +const modulePath = '../../../app/js/S3PersistorManager.js' +const SandboxedModule = require('sandboxed-module') -describe("S3PersistorManagerTests", function() { +describe('S3PersistorManagerTests', function() { + beforeEach(function() { + this.settings = { + filestore: { + backend: 's3', + s3: { + secret: 'secret', + key: 'this_key' + }, + stores: { + user_files: 'sl_user_files' + } + } + } + this.knoxClient = { + putFile: sinon.stub(), + copyFile: sinon.stub(), + list: sinon.stub(), + deleteMultiple: sinon.stub(), + get: sinon.stub() + } + this.knox = { createClient: sinon.stub().returns(this.knoxClient) } + this.s3EventHandlers = {} + this.s3Request = { + on: sinon.stub().callsFake((event, callback) => { + return (this.s3EventHandlers[event] = callback) + }), + send: sinon.stub() + } + this.s3Response = { + httpResponse: { + createUnbufferedStream: sinon.stub() + } + } + this.s3Client = { + copyObject: sinon.stub(), + headObject: sinon.stub(), + getObject: sinon.stub().returns(this.s3Request) + } + this.awsS3 = sinon.stub().returns(this.s3Client) + this.LocalFileWriter = { + writeStream: sinon.stub(), + deleteFile: sinon.stub() + } + this.request = sinon.stub() + this.requires = { + knox: this.knox, + 'aws-sdk/clients/s3': this.awsS3, + 'settings-sharelatex': this.settings, + './LocalFileWriter': this.LocalFileWriter, + 'logger-sharelatex': { + log() {}, + err() {} + }, + request: this.request, + './Errors': (this.Errors = { NotFoundError: sinon.stub() }) + } + this.key = 'my/key' + this.bucketName = 'my-bucket' + this.error = 'my errror' + return (this.S3PersistorManager = SandboxedModule.require(modulePath, { + requires: this.requires + })) + }) - beforeEach(function() { - this.settings = { - filestore: { - backend: "s3", - s3: { - secret: "secret", - key: "this_key" - }, - stores: { - user_files:"sl_user_files" - } - } - }; - this.knoxClient = { - putFile:sinon.stub(), - copyFile:sinon.stub(), - list: sinon.stub(), - deleteMultiple: sinon.stub(), - get: sinon.stub() - }; - this.knox = - {createClient: sinon.stub().returns(this.knoxClient)}; - this.s3EventHandlers = {}; - this.s3Request = { - on: sinon.stub().callsFake((event, callback) => { - return this.s3EventHandlers[event] = callback; - }), - send: sinon.stub() - }; - this.s3Response = { - httpResponse: { - createUnbufferedStream: sinon.stub() - } - }; - this.s3Client = { - copyObject: sinon.stub(), - headObject: sinon.stub(), - getObject: sinon.stub().returns(this.s3Request) - }; - this.awsS3 = sinon.stub().returns(this.s3Client); - this.LocalFileWriter = { - writeStream: sinon.stub(), - deleteFile: sinon.stub() - }; - this.request = sinon.stub(); - this.requires = { - "knox": this.knox, - "aws-sdk/clients/s3": this.awsS3, - "settings-sharelatex": this.settings, - "./LocalFileWriter":this.LocalFileWriter, - "logger-sharelatex": { - log() {}, - err() {} - }, - "request": this.request, - "./Errors": (this.Errors = - {NotFoundError: sinon.stub()}) - }; - this.key = "my/key"; - this.bucketName = "my-bucket"; - this.error = "my errror"; - return this.S3PersistorManager = SandboxedModule.require(modulePath, {requires: this.requires}); - }); + describe('getFileStream', function() { + describe('success', function() { + beforeEach(function() { + this.expectedStream = { expectedStream: true } + this.expectedStream.on = sinon.stub() + this.s3Request.send.callsFake(() => { + return this.s3EventHandlers.httpHeaders( + 200, + {}, + this.s3Response, + 'OK' + ) + }) + return this.s3Response.httpResponse.createUnbufferedStream.returns( + this.expectedStream + ) + }) - describe("getFileStream", function() { - describe("success", function() { - beforeEach(function() { - this.expectedStream = { expectedStream: true }; - this.expectedStream.on = sinon.stub(); - this.s3Request.send.callsFake(() => { - return this.s3EventHandlers.httpHeaders(200, {}, this.s3Response, "OK"); - }); - return this.s3Response.httpResponse.createUnbufferedStream.returns(this.expectedStream); - }); + it('returns a stream', function(done) { + return this.S3PersistorManager.getFileStream( + this.bucketName, + this.key, + {}, + (err, stream) => { + if (err != null) { + return done(err) + } + expect(stream).to.equal(this.expectedStream) + return done() + } + ) + }) - it("returns a stream", function(done) { - return this.S3PersistorManager.getFileStream(this.bucketName, this.key, {}, (err, stream) => { - if (err != null) { - return done(err); - } - expect(stream).to.equal(this.expectedStream); - return done(); - }); - }); + it('sets the AWS client up with credentials from settings', function(done) { + return this.S3PersistorManager.getFileStream( + this.bucketName, + this.key, + {}, + (err, stream) => { + if (err != null) { + return done(err) + } + expect(this.awsS3.lastCall.args).to.deep.equal([ + { + credentials: { + accessKeyId: this.settings.filestore.s3.key, + secretAccessKey: this.settings.filestore.s3.secret + } + } + ]) + return done() + } + ) + }) - it("sets the AWS client up with credentials from settings", function(done) { - return this.S3PersistorManager.getFileStream(this.bucketName, this.key, {}, (err, stream) => { - if (err != null) { - return done(err); - } - expect(this.awsS3.lastCall.args).to.deep.equal([{ - credentials: { - accessKeyId: this.settings.filestore.s3.key, - secretAccessKey: this.settings.filestore.s3.secret - } - }]); - return done(); - }); - }); + it('fetches the right key from the right bucket', function(done) { + return this.S3PersistorManager.getFileStream( + this.bucketName, + this.key, + {}, + (err, stream) => { + if (err != null) { + return done(err) + } + expect(this.s3Client.getObject.lastCall.args).to.deep.equal([ + { + Bucket: this.bucketName, + Key: this.key + } + ]) + return done() + } + ) + }) - it("fetches the right key from the right bucket", function(done) { - return this.S3PersistorManager.getFileStream(this.bucketName, this.key, {}, (err, stream) => { - if (err != null) { - return done(err); - } - expect(this.s3Client.getObject.lastCall.args).to.deep.equal([{ - Bucket: this.bucketName, - Key: this.key - }]); - return done(); - }); - }); + it('accepts alternative credentials', function(done) { + const accessKeyId = 'that_key' + const secret = 'that_secret' + const opts = { + credentials: { + auth_key: accessKeyId, + auth_secret: secret + } + } + return this.S3PersistorManager.getFileStream( + this.bucketName, + this.key, + opts, + (err, stream) => { + if (err != null) { + return done(err) + } + expect(this.awsS3.lastCall.args).to.deep.equal([ + { + credentials: { + accessKeyId, + secretAccessKey: secret + } + } + ]) + expect(stream).to.equal(this.expectedStream) + return done() + } + ) + }) - it("accepts alternative credentials", function(done) { - const accessKeyId = "that_key"; - const secret = "that_secret"; - const opts = { - credentials: { - auth_key: accessKeyId, - auth_secret: secret - } - }; - return this.S3PersistorManager.getFileStream(this.bucketName, this.key, opts, (err, stream) => { - if (err != null) { - return done(err); - } - expect(this.awsS3.lastCall.args).to.deep.equal([{ - credentials: { - accessKeyId, - secretAccessKey: secret - } - }]); - expect(stream).to.equal(this.expectedStream); - return done(); - }); - }); + return it('accepts byte range', function(done) { + const start = 0 + const end = 8 + const opts = { start, end } + return this.S3PersistorManager.getFileStream( + this.bucketName, + this.key, + opts, + (err, stream) => { + if (err != null) { + return done(err) + } + expect(this.s3Client.getObject.lastCall.args).to.deep.equal([ + { + Bucket: this.bucketName, + Key: this.key, + Range: `bytes=${start}-${end}` + } + ]) + expect(stream).to.equal(this.expectedStream) + return done() + } + ) + }) + }) - return it("accepts byte range", function(done) { - const start = 0; - const end = 8; - const opts = { start, end }; - return this.S3PersistorManager.getFileStream(this.bucketName, this.key, opts, (err, stream) => { - if (err != null) { - return done(err); - } - expect(this.s3Client.getObject.lastCall.args).to.deep.equal([{ - Bucket: this.bucketName, - Key: this.key, - Range: `bytes=${start}-${end}` - }]); - expect(stream).to.equal(this.expectedStream); - return done(); - }); - }); - }); + return describe('errors', function() { + describe("when the file doesn't exist", function() { + beforeEach(function() { + return this.s3Request.send.callsFake(() => { + return this.s3EventHandlers.httpHeaders( + 404, + {}, + this.s3Response, + 'Not found' + ) + }) + }) - return describe("errors", function() { - describe("when the file doesn't exist", function() { - beforeEach(function() { - return this.s3Request.send.callsFake(() => { - return this.s3EventHandlers.httpHeaders(404, {}, this.s3Response, "Not found"); - }); - }); + return it('returns a NotFoundError that indicates the bucket and key', function(done) { + return this.S3PersistorManager.getFileStream( + this.bucketName, + this.key, + {}, + (err, stream) => { + expect(err).to.be.instanceof(this.Errors.NotFoundError) + const errMsg = this.Errors.NotFoundError.lastCall.args[0] + expect(errMsg).to.match(new RegExp(`.*${this.bucketName}.*`)) + expect(errMsg).to.match(new RegExp(`.*${this.key}.*`)) + return done() + } + ) + }) + }) - return it("returns a NotFoundError that indicates the bucket and key", function(done) { - return this.S3PersistorManager.getFileStream(this.bucketName, this.key, {}, (err, stream) => { - expect(err).to.be.instanceof(this.Errors.NotFoundError); - const errMsg = this.Errors.NotFoundError.lastCall.args[0]; - expect(errMsg).to.match(new RegExp(`.*${this.bucketName}.*`)); - expect(errMsg).to.match(new RegExp(`.*${this.key}.*`)); - return done(); - }); - }); - }); + describe('when S3 encounters an unkown error', function() { + beforeEach(function() { + return this.s3Request.send.callsFake(() => { + return this.s3EventHandlers.httpHeaders( + 500, + {}, + this.s3Response, + 'Internal server error' + ) + }) + }) - describe("when S3 encounters an unkown error", function() { - beforeEach(function() { - return this.s3Request.send.callsFake(() => { - return this.s3EventHandlers.httpHeaders(500, {}, this.s3Response, "Internal server error"); - }); - }); + return it('returns an error', function(done) { + return this.S3PersistorManager.getFileStream( + this.bucketName, + this.key, + {}, + (err, stream) => { + expect(err).to.be.instanceof(Error) + return done() + } + ) + }) + }) - return it("returns an error", function(done) { - return this.S3PersistorManager.getFileStream(this.bucketName, this.key, {}, (err, stream) => { - expect(err).to.be.instanceof(Error); - return done(); - }); - }); - }); + return describe('when the S3 request errors out before receiving HTTP headers', function() { + beforeEach(function() { + return this.s3Request.send.callsFake(() => { + return this.s3EventHandlers.error(new Error('connection failed')) + }) + }) - return describe("when the S3 request errors out before receiving HTTP headers", function() { - beforeEach(function() { - return this.s3Request.send.callsFake(() => { - return this.s3EventHandlers.error(new Error("connection failed")); - }); - }); + return it('returns an error', function(done) { + return this.S3PersistorManager.getFileStream( + this.bucketName, + this.key, + {}, + (err, stream) => { + expect(err).to.be.instanceof(Error) + return done() + } + ) + }) + }) + }) + }) - return it("returns an error", function(done) { - return this.S3PersistorManager.getFileStream(this.bucketName, this.key, {}, (err, stream) => { - expect(err).to.be.instanceof(Error); - return done(); - }); - }); - }); - }); - }); + describe('getFileSize', function() { + it('should obtain the file size from S3', function(done) { + const expectedFileSize = 123 + this.s3Client.headObject.yields( + new Error('s3Client.headObject got unexpected arguments') + ) + this.s3Client.headObject + .withArgs({ + Bucket: this.bucketName, + Key: this.key + }) + .yields(null, { ContentLength: expectedFileSize }) - describe("getFileSize", function() { - it("should obtain the file size from S3", function(done) { - const expectedFileSize = 123; - this.s3Client.headObject.yields(new Error( - "s3Client.headObject got unexpected arguments" - )); - this.s3Client.headObject.withArgs({ - Bucket: this.bucketName, - Key: this.key - }).yields(null, { ContentLength: expectedFileSize }); + return this.S3PersistorManager.getFileSize( + this.bucketName, + this.key, + (err, fileSize) => { + if (err != null) { + return done(err) + } + expect(fileSize).to.equal(expectedFileSize) + return done() + } + ) + }) - return this.S3PersistorManager.getFileSize(this.bucketName, this.key, (err, fileSize) => { - if (err != null) { - return done(err); - } - expect(fileSize).to.equal(expectedFileSize); - return done(); - }); - }); + ;[403, 404].forEach(statusCode => + it(`should throw NotFoundError when S3 responds with ${statusCode}`, function(done) { + const error = new Error() + error.statusCode = statusCode + this.s3Client.headObject.yields(error) - [403, 404].forEach(statusCode => it(`should throw NotFoundError when S3 responds with ${statusCode}`, function(done) { - const error = new Error(); - error.statusCode = statusCode; - this.s3Client.headObject.yields(error); + return this.S3PersistorManager.getFileSize( + this.bucketName, + this.key, + (err, fileSize) => { + expect(err).to.be.an.instanceof(this.Errors.NotFoundError) + return done() + } + ) + }) + ) - return this.S3PersistorManager.getFileSize(this.bucketName, this.key, (err, fileSize) => { - expect(err).to.be.an.instanceof(this.Errors.NotFoundError); - return done(); - }); - })); + return it('should rethrow any other error', function(done) { + const error = new Error() + this.s3Client.headObject.yields(error) + this.s3Client.headObject.yields(error) - return it("should rethrow any other error", function(done) { - const error = new Error(); - this.s3Client.headObject.yields(error); - this.s3Client.headObject.yields(error); + return this.S3PersistorManager.getFileSize( + this.bucketName, + this.key, + (err, fileSize) => { + expect(err).to.equal(error) + return done() + } + ) + }) + }) - return this.S3PersistorManager.getFileSize(this.bucketName, this.key, (err, fileSize) => { - expect(err).to.equal(error); - return done(); - }); - }); - }); + describe('sendFile', function() { + beforeEach(function() { + return this.knoxClient.putFile.returns({ on() {} }) + }) - describe("sendFile", function() { + it('should put file with knox', function(done) { + this.LocalFileWriter.deleteFile.callsArgWith(1) + this.knoxClient.putFile.callsArgWith(2, this.error) + return this.S3PersistorManager.sendFile( + this.bucketName, + this.key, + this.fsPath, + err => { + this.knoxClient.putFile + .calledWith(this.fsPath, this.key) + .should.equal(true) + err.should.equal(this.error) + return done() + } + ) + }) - beforeEach(function() { - return this.knoxClient.putFile.returns({on() {}}); - }); + return it('should delete the file and pass the error with it', function(done) { + this.LocalFileWriter.deleteFile.callsArgWith(1) + this.knoxClient.putFile.callsArgWith(2, this.error) + return this.S3PersistorManager.sendFile( + this.bucketName, + this.key, + this.fsPath, + err => { + this.knoxClient.putFile + .calledWith(this.fsPath, this.key) + .should.equal(true) + err.should.equal(this.error) + return done() + } + ) + }) + }) - it("should put file with knox", function(done){ - this.LocalFileWriter.deleteFile.callsArgWith(1); - this.knoxClient.putFile.callsArgWith(2, this.error); - return this.S3PersistorManager.sendFile(this.bucketName, this.key, this.fsPath, err=> { - this.knoxClient.putFile.calledWith(this.fsPath, this.key).should.equal(true); - err.should.equal(this.error); - return done(); - }); - }); + describe('sendStream', function() { + beforeEach(function() { + this.fsPath = 'to/some/where' + this.origin = { on() {} } + return (this.S3PersistorManager.sendFile = sinon.stub().callsArgWith(3)) + }) - return it("should delete the file and pass the error with it", function(done){ - this.LocalFileWriter.deleteFile.callsArgWith(1); - this.knoxClient.putFile.callsArgWith(2, this.error); - return this.S3PersistorManager.sendFile(this.bucketName, this.key, this.fsPath, err=> { - this.knoxClient.putFile.calledWith(this.fsPath, this.key).should.equal(true); - err.should.equal(this.error); - return done(); - }); - }); - }); + it('should send stream to LocalFileWriter', function(done) { + this.LocalFileWriter.deleteFile.callsArgWith(1) + this.LocalFileWriter.writeStream.callsArgWith(2, null, this.fsPath) + return this.S3PersistorManager.sendStream( + this.bucketName, + this.key, + this.origin, + () => { + this.LocalFileWriter.writeStream + .calledWith(this.origin) + .should.equal(true) + return done() + } + ) + }) - describe("sendStream", function() { - beforeEach(function() { - this.fsPath = "to/some/where"; - this.origin = - {on() {}}; - return this.S3PersistorManager.sendFile = sinon.stub().callsArgWith(3); - }); + it('should return the error from LocalFileWriter', function(done) { + this.LocalFileWriter.deleteFile.callsArgWith(1) + this.LocalFileWriter.writeStream.callsArgWith(2, this.error) + return this.S3PersistorManager.sendStream( + this.bucketName, + this.key, + this.origin, + err => { + err.should.equal(this.error) + return done() + } + ) + }) - it("should send stream to LocalFileWriter", function(done){ - this.LocalFileWriter.deleteFile.callsArgWith(1); - this.LocalFileWriter.writeStream.callsArgWith(2, null, this.fsPath); - return this.S3PersistorManager.sendStream(this.bucketName, this.key, this.origin, () => { - this.LocalFileWriter.writeStream.calledWith(this.origin).should.equal(true); - return done(); - }); - }); + return it('should send the file to the filestore', function(done) { + this.LocalFileWriter.deleteFile.callsArgWith(1) + this.LocalFileWriter.writeStream.callsArgWith(2) + return this.S3PersistorManager.sendStream( + this.bucketName, + this.key, + this.origin, + err => { + this.S3PersistorManager.sendFile.called.should.equal(true) + return done() + } + ) + }) + }) - it("should return the error from LocalFileWriter", function(done){ - this.LocalFileWriter.deleteFile.callsArgWith(1); - this.LocalFileWriter.writeStream.callsArgWith(2, this.error); - return this.S3PersistorManager.sendStream(this.bucketName, this.key, this.origin, err=> { - err.should.equal(this.error); - return done(); - }); - }); + describe('copyFile', function() { + beforeEach(function() { + this.sourceKey = 'my/key' + return (this.destKey = 'my/dest/key') + }) - return it("should send the file to the filestore", function(done){ - this.LocalFileWriter.deleteFile.callsArgWith(1); - this.LocalFileWriter.writeStream.callsArgWith(2); - return this.S3PersistorManager.sendStream(this.bucketName, this.key, this.origin, err=> { - this.S3PersistorManager.sendFile.called.should.equal(true); - return done(); - }); - }); - }); + it('should use AWS SDK to copy file', function(done) { + this.s3Client.copyObject.callsArgWith(1, this.error) + return this.S3PersistorManager.copyFile( + this.bucketName, + this.sourceKey, + this.destKey, + err => { + err.should.equal(this.error) + this.s3Client.copyObject + .calledWith({ + Bucket: this.bucketName, + Key: this.destKey, + CopySource: this.bucketName + '/' + this.key + }) + .should.equal(true) + return done() + } + ) + }) - describe("copyFile", function() { - beforeEach(function() { - this.sourceKey = "my/key"; - return this.destKey = "my/dest/key"; - }); + return it('should return a NotFoundError object if the original file does not exist', function(done) { + const NoSuchKeyError = { code: 'NoSuchKey' } + this.s3Client.copyObject.callsArgWith(1, NoSuchKeyError) + return this.S3PersistorManager.copyFile( + this.bucketName, + this.sourceKey, + this.destKey, + err => { + expect(err instanceof this.Errors.NotFoundError).to.equal(true) + return done() + } + ) + }) + }) - it("should use AWS SDK to copy file", function(done){ - this.s3Client.copyObject.callsArgWith(1, this.error); - return this.S3PersistorManager.copyFile(this.bucketName, this.sourceKey, this.destKey, err=> { - err.should.equal(this.error); - this.s3Client.copyObject.calledWith({Bucket: this.bucketName, Key: this.destKey, CopySource: this.bucketName + '/' + this.key}).should.equal(true); - return done(); - }); - }); + describe('deleteDirectory', () => + it('should list the contents passing them onto multi delete', function(done) { + const data = { Contents: [{ Key: '1234' }, { Key: '456' }] } + this.knoxClient.list.callsArgWith(1, null, data) + this.knoxClient.deleteMultiple.callsArgWith(1) + return this.S3PersistorManager.deleteDirectory( + this.bucketName, + this.key, + err => { + this.knoxClient.deleteMultiple + .calledWith(['1234', '456']) + .should.equal(true) + return done() + } + ) + })) - return it("should return a NotFoundError object if the original file does not exist", function(done){ - const NoSuchKeyError = {code: "NoSuchKey"}; - this.s3Client.copyObject.callsArgWith(1, NoSuchKeyError); - return this.S3PersistorManager.copyFile(this.bucketName, this.sourceKey, this.destKey, err=> { - expect(err instanceof this.Errors.NotFoundError).to.equal(true); - return done(); - }); - }); - }); + describe('deleteFile', function() { + it('should use correct options', function(done) { + this.request.callsArgWith(1) - describe("deleteDirectory", () => it("should list the contents passing them onto multi delete", function(done){ - const data = - {Contents: [{Key:"1234"}, {Key: "456"}]}; - this.knoxClient.list.callsArgWith(1, null, data); - this.knoxClient.deleteMultiple.callsArgWith(1); - return this.S3PersistorManager.deleteDirectory(this.bucketName, this.key, err=> { - this.knoxClient.deleteMultiple.calledWith(["1234","456"]).should.equal(true); - return done(); - }); - })); + return this.S3PersistorManager.deleteFile( + this.bucketName, + this.key, + err => { + const opts = this.request.args[0][0] + assert.deepEqual(opts.aws, { + key: this.settings.filestore.s3.key, + secret: this.settings.filestore.s3.secret, + bucket: this.bucketName + }) + opts.method.should.equal('delete') + opts.timeout.should.equal(30 * 1000) + opts.uri.should.equal( + `https://${this.bucketName}.s3.amazonaws.com/${this.key}` + ) + return done() + } + ) + }) - describe("deleteFile", function() { + return it('should return the error', function(done) { + this.request.callsArgWith(1, this.error) - it("should use correct options", function(done){ - this.request.callsArgWith(1); + return this.S3PersistorManager.deleteFile( + this.bucketName, + this.key, + err => { + err.should.equal(this.error) + return done() + } + ) + }) + }) - return this.S3PersistorManager.deleteFile(this.bucketName, this.key, err=> { - const opts = this.request.args[0][0]; - assert.deepEqual(opts.aws, {key:this.settings.filestore.s3.key, secret:this.settings.filestore.s3.secret, bucket:this.bucketName}); - opts.method.should.equal("delete"); - opts.timeout.should.equal((30*1000)); - opts.uri.should.equal(`https://${this.bucketName}.s3.amazonaws.com/${this.key}`); - return done(); - }); - }); + describe('checkIfFileExists', function() { + it('should use correct options', function(done) { + this.request.callsArgWith(1, null, { statusCode: 200 }) - return it("should return the error", function(done){ - this.request.callsArgWith(1, this.error); + return this.S3PersistorManager.checkIfFileExists( + this.bucketName, + this.key, + err => { + const opts = this.request.args[0][0] + assert.deepEqual(opts.aws, { + key: this.settings.filestore.s3.key, + secret: this.settings.filestore.s3.secret, + bucket: this.bucketName + }) + opts.method.should.equal('head') + opts.timeout.should.equal(30 * 1000) + opts.uri.should.equal( + `https://${this.bucketName}.s3.amazonaws.com/${this.key}` + ) + return done() + } + ) + }) - return this.S3PersistorManager.deleteFile(this.bucketName, this.key, err=> { - err.should.equal(this.error); - return done(); - }); - }); - }); + it('should return true for a 200', function(done) { + this.request.callsArgWith(1, null, { statusCode: 200 }) - describe("checkIfFileExists", function() { + return this.S3PersistorManager.checkIfFileExists( + this.bucketName, + this.key, + (err, exists) => { + exists.should.equal(true) + return done() + } + ) + }) - it("should use correct options", function(done){ - this.request.callsArgWith(1, null, {statusCode:200}); + it('should return false for a non 200', function(done) { + this.request.callsArgWith(1, null, { statusCode: 404 }) - return this.S3PersistorManager.checkIfFileExists(this.bucketName, this.key, err=> { - const opts = this.request.args[0][0]; - assert.deepEqual(opts.aws, {key:this.settings.filestore.s3.key, secret:this.settings.filestore.s3.secret, bucket:this.bucketName}); - opts.method.should.equal("head"); - opts.timeout.should.equal((30*1000)); - opts.uri.should.equal(`https://${this.bucketName}.s3.amazonaws.com/${this.key}`); - return done(); - }); - }); + return this.S3PersistorManager.checkIfFileExists( + this.bucketName, + this.key, + (err, exists) => { + exists.should.equal(false) + return done() + } + ) + }) - it("should return true for a 200", function(done){ - this.request.callsArgWith(1, null, {statusCode:200}); + return it('should return the error', function(done) { + this.request.callsArgWith(1, this.error, {}) - return this.S3PersistorManager.checkIfFileExists(this.bucketName, this.key, (err, exists)=> { - exists.should.equal(true); - return done(); - }); - }); + return this.S3PersistorManager.checkIfFileExists( + this.bucketName, + this.key, + err => { + err.should.equal(this.error) + return done() + } + ) + }) + }) - it("should return false for a non 200", function(done){ - this.request.callsArgWith(1, null, {statusCode:404}); - - return this.S3PersistorManager.checkIfFileExists(this.bucketName, this.key, (err, exists)=> { - exists.should.equal(false); - return done(); - }); - }); - - return it("should return the error", function(done){ - this.request.callsArgWith(1, this.error, {}); - - return this.S3PersistorManager.checkIfFileExists(this.bucketName, this.key, err=> { - err.should.equal(this.error); - return done(); - }); - }); - }); - - return describe("directorySize", () => it("should sum directory files size", function(done) { - const data = - {Contents: [ {Size: 1024}, {Size: 2048} ]}; - this.knoxClient.list.callsArgWith(1, null, data); - return this.S3PersistorManager.directorySize(this.bucketName, this.key, (err, totalSize)=> { - totalSize.should.equal(3072); - return done(); - }); - })); -}); + return describe('directorySize', () => + it('should sum directory files size', function(done) { + const data = { Contents: [{ Size: 1024 }, { Size: 2048 }] } + this.knoxClient.list.callsArgWith(1, null, data) + return this.S3PersistorManager.directorySize( + this.bucketName, + this.key, + (err, totalSize) => { + totalSize.should.equal(3072) + return done() + } + ) + })) +}) diff --git a/services/filestore/test/unit/js/SafeExecTests.js b/services/filestore/test/unit/js/SafeExecTests.js index f9a0e51ca8..2b629947f5 100644 --- a/services/filestore/test/unit/js/SafeExecTests.js +++ b/services/filestore/test/unit/js/SafeExecTests.js @@ -9,73 +9,87 @@ * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const { - assert -} = require("chai"); -const sinon = require('sinon'); -const chai = require('chai'); -const should = chai.should(); -const { - expect -} = chai; -const modulePath = "../../../app/js/SafeExec.js"; -const SandboxedModule = require('sandboxed-module'); +const { assert } = require('chai') +const sinon = require('sinon') +const chai = require('chai') +const should = chai.should() +const { expect } = chai +const modulePath = '../../../app/js/SafeExec.js' +const SandboxedModule = require('sandboxed-module') -describe("SafeExec", function() { +describe('SafeExec', function() { + beforeEach(function() { + this.settings = { enableConversions: true } + this.safe_exec = SandboxedModule.require(modulePath, { + requires: { + 'logger-sharelatex': { + log() {}, + err() {} + }, + 'settings-sharelatex': this.settings + } + }) + return (this.options = { timeout: 10 * 1000, killSignal: 'SIGTERM' }) + }) - beforeEach(function() { - this.settings = - {enableConversions:true}; - this.safe_exec = SandboxedModule.require(modulePath, { requires: { - "logger-sharelatex": { - log() {}, - err() {} - }, - "settings-sharelatex": this.settings - } - } - ); - return this.options = {timeout: 10*1000, killSignal: "SIGTERM" };}); + return describe('safe_exec', function() { + it('should execute a valid command', function(done) { + return this.safe_exec( + ['/bin/echo', 'hello'], + this.options, + (err, stdout, stderr) => { + stdout.should.equal('hello\n') + should.not.exist(err) + return done() + } + ) + }) - return describe("safe_exec", function() { + it('should error when conversions are disabled', function(done) { + this.settings.enableConversions = false + return this.safe_exec( + ['/bin/echo', 'hello'], + this.options, + (err, stdout, stderr) => { + expect(err).to.exist + return done() + } + ) + }) - it("should execute a valid command", function(done) { - return this.safe_exec(["/bin/echo", "hello"], this.options, (err, stdout, stderr) => { - stdout.should.equal("hello\n"); - should.not.exist(err); - return done(); - }); - }); + it('should execute a command with non-zero exit status', function(done) { + return this.safe_exec( + ['/usr/bin/env', 'false'], + this.options, + (err, stdout, stderr) => { + stdout.should.equal('') + stderr.should.equal('') + err.message.should.equal('exit status 1') + return done() + } + ) + }) - it("should error when conversions are disabled", function(done) { - this.settings.enableConversions = false; - return this.safe_exec(["/bin/echo", "hello"], this.options, (err, stdout, stderr) => { - expect(err).to.exist; - return done(); - }); - }); + it('should handle an invalid command', function(done) { + return this.safe_exec( + ['/bin/foobar'], + this.options, + (err, stdout, stderr) => { + err.code.should.equal('ENOENT') + return done() + } + ) + }) - it("should execute a command with non-zero exit status", function(done) { - return this.safe_exec(["/usr/bin/env", "false"], this.options, (err, stdout, stderr) => { - stdout.should.equal(""); - stderr.should.equal(""); - err.message.should.equal("exit status 1"); - return done(); - }); - }); - - it("should handle an invalid command", function(done) { - return this.safe_exec(["/bin/foobar"], this.options, (err, stdout, stderr) => { - err.code.should.equal("ENOENT"); - return done(); - }); - }); - - return it("should handle a command that runs too long", function(done) { - return this.safe_exec(["/bin/sleep", "10"], {timeout: 500, killSignal: "SIGTERM"}, (err, stdout, stderr) => { - err.should.equal("SIGTERM"); - return done(); - }); - }); - }); -}); + return it('should handle a command that runs too long', function(done) { + return this.safe_exec( + ['/bin/sleep', '10'], + { timeout: 500, killSignal: 'SIGTERM' }, + (err, stdout, stderr) => { + err.should.equal('SIGTERM') + return done() + } + ) + }) + }) +}) diff --git a/services/filestore/test/unit/js/SettingsTests.js b/services/filestore/test/unit/js/SettingsTests.js index 98d17723a9..472c6d1179 100644 --- a/services/filestore/test/unit/js/SettingsTests.js +++ b/services/filestore/test/unit/js/SettingsTests.js @@ -9,27 +9,25 @@ * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const { - assert -} = require("chai"); -const sinon = require('sinon'); -const chai = require('chai'); -const should = chai.should(); -const { - expect -} = chai; -const modulePath = "../../../app/js/BucketController.js"; +const { assert } = require('chai') +const sinon = require('sinon') +const chai = require('chai') +const should = chai.should() +const { expect } = chai +const modulePath = '../../../app/js/BucketController.js' -describe("Settings", () => describe("s3", () => it("should use JSONified env var if present", function(done){ - const s3_settings = { +describe('Settings', () => + describe('s3', () => + it('should use JSONified env var if present', function(done) { + const s3_settings = { bucket1: { - auth_key: 'bucket1_key', - auth_secret: 'bucket1_secret' + auth_key: 'bucket1_key', + auth_secret: 'bucket1_secret' } - }; - process.env.S3_BUCKET_CREDENTIALS = JSON.stringify(s3_settings); + } + process.env.S3_BUCKET_CREDENTIALS = JSON.stringify(s3_settings) - const settings = require("settings-sharelatex"); - expect(settings.filestore.s3BucketCreds).to.deep.equal(s3_settings); - return done(); -}))); + const settings = require('settings-sharelatex') + expect(settings.filestore.s3BucketCreds).to.deep.equal(s3_settings) + return done() + })))