/* eslint-disable handle-callback-err, no-dupe-keys, no-return-assign, no-unused-vars, */ // TODO: This file was created by bulk-decaffeinate. // Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * 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 should = chai.should(); const { expect } = chai; 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)}; 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); }); 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(); }); }); }); 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(); }); }); 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); }); 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(); }); }); 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("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 = {};}); 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(); }); }); }); 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(); }); }); }); 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(); }); }); 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(); }); }); return describe("with directory content", function() { beforeEach(function() { return this.fileList = [ {Key: 'foo'} , { Key: 'bar' , Key: 'baz' } ];}); 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 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(); }); }); }); }); 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(); }); }); 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(); }); }); 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(); }); }); }); });