/* eslint-disable handle-callback-err, 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 * 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() { 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() this.LocalFileWriter = { writeStream: sinon.stub(), deleteFile: sinon.stub() } this.requires = { './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 })) }) describe('sendFile', function() { beforeEach(function() { return (this.Fs.createReadStream = sinon.stub().returns({ on() {}, pipe() {} })) }) it('should copy the file', function(done) { this.Fs.createWriteStream = sinon.stub().returns({ on(event, 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 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) }) } } }) 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() { 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() {} }) }) 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() } ) }) 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() { beforeEach(function() { 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() { 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) }) 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() { beforeEach(function() { 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() { beforeEach(function() { 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() } ) }) }) }) }) 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) } 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) 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 this.FSPersistorManager.getFileSize( this.location, this.name1, (err, fileSize) => { expect(err).to.equal(error) return done() } ) }) }) describe('copyFile', function() { beforeEach(function() { this.ReadStream = { on() {}, 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 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() }) }) describe('deleteFile', function() { beforeEach(function() { 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() } ) }) 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() { beforeEach(function() { 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() } ) }) 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() { beforeEach(function() { 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() } ) }) // 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 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 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() } ) }) 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() } ) }) }) })