/* eslint-disable 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 * DS206: Consider reworking classes to avoid initClass * 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 modulePath = '../../../../app/js/ProjectManager.js' const SandboxedModule = require('sandboxed-module') const _ = require('lodash') describe('ProjectManager', function () { beforeEach(function () { let Timer this.ProjectManager = SandboxedModule.require(modulePath, { requires: { './RedisManager': (this.RedisManager = {}), './ProjectHistoryRedisManager': (this.ProjectHistoryRedisManager = {}), './DocumentManager': (this.DocumentManager = {}), 'logger-sharelatex': (this.logger = { log: sinon.stub(), error: sinon.stub() }), './HistoryManager': (this.HistoryManager = {}), './Metrics': (this.Metrics = { Timer: (Timer = (function () { Timer = class Timer { static initClass() { this.prototype.done = sinon.stub() } } Timer.initClass() return Timer })()) }) } }) this.project_id = 'project-id-123' this.projectHistoryId = 'history-id-123' this.user_id = 'user-id-123' this.version = 1234567 this.HistoryManager.shouldFlushHistoryOps = sinon.stub().returns(false) this.HistoryManager.flushProjectChangesAsync = sinon.stub() return (this.callback = sinon.stub()) }) return describe('updateProjectWithLocks', function () { describe('rename operations', function () { beforeEach(function () { this.firstDocUpdate = { id: 1, pathname: 'foo', newPathname: 'foo' } this.secondDocUpdate = { id: 2, pathname: 'bar', newPathname: 'bar2' } this.docUpdates = [this.firstDocUpdate, this.secondDocUpdate] this.firstFileUpdate = { id: 2, pathname: 'bar', newPathname: 'bar2' } this.fileUpdates = [this.firstFileUpdate] this.DocumentManager.renameDocWithLock = sinon.stub().yields() return (this.ProjectHistoryRedisManager.queueRenameEntity = sinon .stub() .yields()) }) describe('successfully', function () { beforeEach(function () { return this.ProjectManager.updateProjectWithLocks( this.project_id, this.projectHistoryId, this.user_id, this.docUpdates, this.fileUpdates, this.version, this.callback ) }) it('should rename the docs in the updates', function () { const firstDocUpdateWithVersion = _.extend({}, this.firstDocUpdate, { version: `${this.version}.0` }) const secondDocUpdateWithVersion = _.extend( {}, this.secondDocUpdate, { version: `${this.version}.1` } ) this.DocumentManager.renameDocWithLock .calledWith( this.project_id, this.firstDocUpdate.id, this.user_id, firstDocUpdateWithVersion, this.projectHistoryId ) .should.equal(true) return this.DocumentManager.renameDocWithLock .calledWith( this.project_id, this.secondDocUpdate.id, this.user_id, secondDocUpdateWithVersion, this.projectHistoryId ) .should.equal(true) }) it('should rename the files in the updates', function () { const firstFileUpdateWithVersion = _.extend( {}, this.firstFileUpdate, { version: `${this.version}.2` } ) return this.ProjectHistoryRedisManager.queueRenameEntity .calledWith( this.project_id, this.projectHistoryId, 'file', this.firstFileUpdate.id, this.user_id, firstFileUpdateWithVersion ) .should.equal(true) }) it('should not flush the history', function () { return this.HistoryManager.flushProjectChangesAsync .calledWith(this.project_id) .should.equal(false) }) return it('should call the callback', function () { return this.callback.called.should.equal(true) }) }) describe('when renaming a doc fails', function () { beforeEach(function () { this.error = new Error('error') this.DocumentManager.renameDocWithLock = sinon .stub() .yields(this.error) return this.ProjectManager.updateProjectWithLocks( this.project_id, this.projectHistoryId, this.user_id, this.docUpdates, this.fileUpdates, this.version, this.callback ) }) return it('should call the callback with the error', function () { return this.callback.calledWith(this.error).should.equal(true) }) }) describe('when renaming a file fails', function () { beforeEach(function () { this.error = new Error('error') this.ProjectHistoryRedisManager.queueRenameEntity = sinon .stub() .yields(this.error) return this.ProjectManager.updateProjectWithLocks( this.project_id, this.projectHistoryId, this.user_id, this.docUpdates, this.fileUpdates, this.version, this.callback ) }) return it('should call the callback with the error', function () { return this.callback.calledWith(this.error).should.equal(true) }) }) return describe('with enough ops to flush', function () { beforeEach(function () { this.HistoryManager.shouldFlushHistoryOps = sinon.stub().returns(true) return this.ProjectManager.updateProjectWithLocks( this.project_id, this.projectHistoryId, this.user_id, this.docUpdates, this.fileUpdates, this.version, this.callback ) }) return it('should flush the history', function () { return this.HistoryManager.flushProjectChangesAsync .calledWith(this.project_id) .should.equal(true) }) }) }) return describe('add operations', function () { beforeEach(function () { this.firstDocUpdate = { id: 1, docLines: 'a\nb' } this.secondDocUpdate = { id: 2, docLines: 'a\nb' } this.docUpdates = [this.firstDocUpdate, this.secondDocUpdate] this.firstFileUpdate = { id: 3, url: 'filestore.example.com/2' } this.secondFileUpdate = { id: 4, url: 'filestore.example.com/3' } this.fileUpdates = [this.firstFileUpdate, this.secondFileUpdate] return (this.ProjectHistoryRedisManager.queueAddEntity = sinon .stub() .yields()) }) describe('successfully', function () { beforeEach(function () { return this.ProjectManager.updateProjectWithLocks( this.project_id, this.projectHistoryId, this.user_id, this.docUpdates, this.fileUpdates, this.version, this.callback ) }) it('should add the docs in the updates', function () { const firstDocUpdateWithVersion = _.extend({}, this.firstDocUpdate, { version: `${this.version}.0` }) const secondDocUpdateWithVersion = _.extend( {}, this.secondDocUpdate, { version: `${this.version}.1` } ) this.ProjectHistoryRedisManager.queueAddEntity .getCall(0) .calledWith( this.project_id, this.projectHistoryId, 'doc', this.firstDocUpdate.id, this.user_id, firstDocUpdateWithVersion ) .should.equal(true) return this.ProjectHistoryRedisManager.queueAddEntity .getCall(1) .calledWith( this.project_id, this.projectHistoryId, 'doc', this.secondDocUpdate.id, this.user_id, secondDocUpdateWithVersion ) .should.equal(true) }) it('should add the files in the updates', function () { const firstFileUpdateWithVersion = _.extend( {}, this.firstFileUpdate, { version: `${this.version}.2` } ) const secondFileUpdateWithVersion = _.extend( {}, this.secondFileUpdate, { version: `${this.version}.3` } ) this.ProjectHistoryRedisManager.queueAddEntity .getCall(2) .calledWith( this.project_id, this.projectHistoryId, 'file', this.firstFileUpdate.id, this.user_id, firstFileUpdateWithVersion ) .should.equal(true) return this.ProjectHistoryRedisManager.queueAddEntity .getCall(3) .calledWith( this.project_id, this.projectHistoryId, 'file', this.secondFileUpdate.id, this.user_id, secondFileUpdateWithVersion ) .should.equal(true) }) it('should not flush the history', function () { return this.HistoryManager.flushProjectChangesAsync .calledWith(this.project_id) .should.equal(false) }) return it('should call the callback', function () { return this.callback.called.should.equal(true) }) }) describe('when adding a doc fails', function () { beforeEach(function () { this.error = new Error('error') this.ProjectHistoryRedisManager.queueAddEntity = sinon .stub() .yields(this.error) return this.ProjectManager.updateProjectWithLocks( this.project_id, this.projectHistoryId, this.user_id, this.docUpdates, this.fileUpdates, this.version, this.callback ) }) return it('should call the callback with the error', function () { return this.callback.calledWith(this.error).should.equal(true) }) }) describe('when adding a file fails', function () { beforeEach(function () { this.error = new Error('error') this.ProjectHistoryRedisManager.queueAddEntity = sinon .stub() .yields(this.error) return this.ProjectManager.updateProjectWithLocks( this.project_id, this.projectHistoryId, this.user_id, this.docUpdates, this.fileUpdates, this.version, this.callback ) }) return it('should call the callback with the error', function () { return this.callback.calledWith(this.error).should.equal(true) }) }) return describe('with enough ops to flush', function () { beforeEach(function () { this.HistoryManager.shouldFlushHistoryOps = sinon.stub().returns(true) return this.ProjectManager.updateProjectWithLocks( this.project_id, this.projectHistoryId, this.user_id, this.docUpdates, this.fileUpdates, this.version, this.callback ) }) return it('should flush the history', function () { return this.HistoryManager.flushProjectChangesAsync .calledWith(this.project_id) .should.equal(true) }) }) }) }) })