| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019 |
- /* eslint-disable
- camelcase,
- max-len,
- 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 chai = require('chai')
- const { assert } = require('chai')
- const should = chai.should()
- const { expect } = chai
- const modulePath =
- '../../../../app/src/Features/Project/ProjectEntityUpdateHandler'
- const sinon = require('sinon')
- const Errors = require('../../../../app/src/Features/Errors/Errors')
- const SandboxedModule = require('sandboxed-module')
- const { ObjectId } = require('mongoose').Types
- describe('ProjectEntityUpdateHandler', function() {
- const project_id = '4eecb1c1bffa66588e0000a1'
- const projectHistoryId = '123456'
- const doc_id = '4eecb1c1bffa66588e0000a2'
- const file_id = '4eecaffcbffa66588e000009'
- const folder_id = '4eecaffcbffa66588e000008'
- const rootFolderId = '4eecaffcbffa66588e000007'
- const new_file_id = '4eecaffcbffa66588e000099'
- const userId = 1234
- beforeEach(function() {
- let Doc, File
- this.project = {
- _id: project_id,
- name: 'project name',
- overleaf: {
- history: {
- id: projectHistoryId
- }
- }
- }
- this.fileUrl = 'filestore.example.com/file'
- this.FileStoreHandler = {}
- this.DocModel = Doc = class Doc {
- constructor(options) {
- ;({ name: this.name, lines: this.lines } = options)
- this._id = doc_id
- this.rev = 0
- }
- }
- this.FileModel = File = class File {
- constructor(options) {
- ;({ name: this.name } = options)
- // use a new id for replacement files
- if (this.name === 'dummy-upload-filename') {
- this._id = new_file_id
- } else {
- this._id = file_id
- }
- this.rev = 0
- if (options.linkedFileData != null) {
- this.linkedFileData = options.linkedFileData
- }
- if (options.hash != null) {
- this.hash = options.hash
- }
- }
- }
- this.docName = 'doc-name'
- this.docLines = ['1234', 'abc']
- this.fileName = 'something.jpg'
- this.fileSystemPath = 'somehintg'
- this.linkedFileData = { provider: 'url' }
- this.source = 'editor'
- this.callback = sinon.stub()
- return (this.ProjectEntityUpdateHandler = SandboxedModule.require(
- modulePath,
- {
- globals: {
- console: console
- },
- requires: {
- 'logger-sharelatex': (this.logger = {
- log: sinon.stub(),
- warn: sinon.stub(),
- error: sinon.stub(),
- err() {}
- }),
- '../../models/Doc': {
- Doc: this.DocModel
- },
- '../Docstore/DocstoreManager': (this.DocstoreManager = {}),
- '../Errors/Errors': Errors,
- '../../Features/DocumentUpdater/DocumentUpdaterHandler': (this.DocumentUpdaterHandler = {
- updateProjectStructure: sinon.stub().yields()
- }),
- '../../models/File': {
- File: this.FileModel
- },
- '../FileStore/FileStoreHandler': this.FileStoreHandler,
- '../../infrastructure/LockManager': (this.LockManager = {
- runWithLock: sinon.spy((namespace, id, runner, callback) =>
- runner(callback)
- )
- }),
- '../../models/Project': {
- Project: (this.ProjectModel = {})
- },
- './ProjectGetter': (this.ProjectGetter = {}),
- './ProjectLocator': (this.ProjectLocator = {}),
- './ProjectUpdateHandler': (this.ProjectUpdater = {}),
- './ProjectEntityHandler': (this.ProjectEntityHandler = {}),
- './ProjectEntityMongoUpdateHandler': (this.ProjectEntityMongoUpdateHandler = {}),
- '../ThirdPartyDataStore/TpdsUpdateSender': (this.TpdsUpdateSender = {
- addFile: sinon.stub().yields()
- })
- }
- }
- ))
- })
- describe('copyFileFromExistingProjectWithProject', function() {
- beforeEach(function() {
- this.oldProject_id = '123kljadas'
- this.oldFileRef = { name: this.fileName, _id: 'oldFileRef' }
- this.ProjectEntityMongoUpdateHandler._confirmFolder = sinon
- .stub()
- .yields(folder_id)
- this.ProjectEntityMongoUpdateHandler._putElement = sinon
- .stub()
- .yields(null, { path: { fileSystem: this.fileSystemPath } })
- this.FileStoreHandler.copyFile = sinon.stub().yields(null, this.fileUrl)
- return this.ProjectEntityUpdateHandler.copyFileFromExistingProjectWithProject(
- this.project._id,
- this.project,
- folder_id,
- this.oldProject_id,
- this.oldFileRef,
- userId,
- this.callback
- )
- })
- it('should copy the file in FileStoreHandler', function() {
- return this.FileStoreHandler.copyFile
- .calledWith(
- this.oldProject_id,
- this.oldFileRef._id,
- project_id,
- file_id
- )
- .should.equal(true)
- })
- it('should put file into folder by calling put element', function() {
- return this.ProjectEntityMongoUpdateHandler._putElement
- .calledWithMatch(
- this.project,
- folder_id,
- { _id: file_id, name: this.fileName },
- 'file'
- )
- .should.equal(true)
- })
- it('should return doc and parent folder', function() {
- return this.callback
- .calledWithMatch(null, { _id: file_id, name: this.fileName }, folder_id)
- .should.equal(true)
- })
- it('should call third party data store if versioning is enabled', function() {
- return this.TpdsUpdateSender.addFile
- .calledWith({
- project_id,
- file_id,
- path: this.fileSystemPath,
- rev: 0,
- project_name: this.project.name
- })
- .should.equal(true)
- })
- it('should should send the change in project structure to the doc updater', function() {
- const changesMatcher = sinon.match(changes => {
- const { newFiles } = changes
- if (newFiles.length !== 1) {
- return false
- }
- const newFile = newFiles[0]
- return (
- newFile.file._id === file_id &&
- newFile.path === this.fileSystemPath &&
- newFile.url === this.fileUrl
- )
- })
- return this.DocumentUpdaterHandler.updateProjectStructure
- .calledWithMatch(project_id, projectHistoryId, userId, changesMatcher)
- .should.equal(true)
- })
- })
- describe('copyFileFromExistingProjectWithProject, with linkedFileData and hash', function() {
- beforeEach(function() {
- this.oldProject_id = '123kljadas'
- this.oldFileRef = {
- _id: 'oldFileRef',
- name: this.fileName,
- linkedFileData: this.linkedFileData,
- hash: '123456'
- }
- this.ProjectEntityMongoUpdateHandler._confirmFolder = sinon
- .stub()
- .yields(folder_id)
- this.ProjectEntityMongoUpdateHandler._putElement = sinon
- .stub()
- .yields(null, { path: { fileSystem: this.fileSystemPath } })
- this.FileStoreHandler.copyFile = sinon.stub().yields(null, this.fileUrl)
- return this.ProjectEntityUpdateHandler.copyFileFromExistingProjectWithProject(
- this.project._id,
- this.project,
- folder_id,
- this.oldProject_id,
- this.oldFileRef,
- userId,
- this.callback
- )
- })
- it('should copy the file in FileStoreHandler', function() {
- return this.FileStoreHandler.copyFile
- .calledWith(
- this.oldProject_id,
- this.oldFileRef._id,
- project_id,
- file_id
- )
- .should.equal(true)
- })
- it('should put file into folder by calling put element, with the linkedFileData and hash', function() {
- return this.ProjectEntityMongoUpdateHandler._putElement
- .calledWithMatch(
- this.project,
- folder_id,
- {
- _id: file_id,
- name: this.fileName,
- linkedFileData: this.linkedFileData,
- hash: '123456'
- },
- 'file'
- )
- .should.equal(true)
- })
- })
- describe('updateDocLines', function() {
- beforeEach(function() {
- this.path = '/somewhere/something.tex'
- this.doc = {
- _id: doc_id
- }
- this.version = 42
- this.ranges = { mock: 'ranges' }
- this.lastUpdatedAt = new Date().getTime()
- this.lastUpdatedBy = 'fake-last-updater-id'
- this.ProjectGetter.getProjectWithoutDocLines = sinon
- .stub()
- .yields(null, this.project)
- this.ProjectLocator.findElement = sinon
- .stub()
- .yields(null, this.doc, { fileSystem: this.path })
- this.TpdsUpdateSender.addDoc = sinon.stub().yields()
- this.ProjectUpdater.markAsUpdated = sinon.stub()
- return (this.callback = sinon.stub())
- })
- describe('when the doc has been modified', function() {
- beforeEach(function() {
- this.DocstoreManager.updateDoc = sinon
- .stub()
- .yields(null, true, (this.rev = 5))
- return this.ProjectEntityUpdateHandler.updateDocLines(
- project_id,
- doc_id,
- this.docLines,
- this.version,
- this.ranges,
- this.lastUpdatedAt,
- this.lastUpdatedBy,
- this.callback
- )
- })
- it('should get the project without doc lines', function() {
- return this.ProjectGetter.getProjectWithoutDocLines
- .calledWith(project_id)
- .should.equal(true)
- })
- it('should find the doc', function() {
- return this.ProjectLocator.findElement
- .calledWith({
- project: this.project,
- type: 'docs',
- element_id: doc_id
- })
- .should.equal(true)
- })
- it('should update the doc in the docstore', function() {
- return this.DocstoreManager.updateDoc
- .calledWith(
- project_id,
- doc_id,
- this.docLines,
- this.version,
- this.ranges
- )
- .should.equal(true)
- })
- it('should mark the project as updated', function() {
- return sinon.assert.calledWith(
- this.ProjectUpdater.markAsUpdated,
- project_id,
- this.lastUpdatedAt,
- this.lastUpdatedBy
- )
- })
- it('should send the doc the to the TPDS', function() {
- return this.TpdsUpdateSender.addDoc
- .calledWith({
- project_id,
- project_name: this.project.name,
- doc_id,
- rev: this.rev,
- path: this.path
- })
- .should.equal(true)
- })
- it('should call the callback', function() {
- return this.callback.called.should.equal(true)
- })
- })
- describe('when the doc has not been modified', function() {
- beforeEach(function() {
- this.DocstoreManager.updateDoc = sinon
- .stub()
- .yields(null, false, (this.rev = 5))
- return this.ProjectEntityUpdateHandler.updateDocLines(
- project_id,
- doc_id,
- this.docLines,
- this.version,
- this.ranges,
- this.lastUpdatedAt,
- this.lastUpdatedBy,
- this.callback
- )
- })
- it('should not mark the project as updated', function() {
- return this.ProjectUpdater.markAsUpdated.called.should.equal(false)
- })
- it('should not send the doc the to the TPDS', function() {
- return this.TpdsUpdateSender.addDoc.called.should.equal(false)
- })
- it('should call the callback', function() {
- return this.callback.called.should.equal(true)
- })
- })
- describe('when the doc has been deleted', function() {
- beforeEach(function() {
- this.project.deletedDocs = [{ _id: doc_id }]
- this.ProjectGetter.getProjectWithoutDocLines = sinon
- .stub()
- .yields(null, this.project)
- this.ProjectLocator.findElement = sinon
- .stub()
- .yields(new Errors.NotFoundError())
- this.DocstoreManager.updateDoc = sinon.stub().yields()
- return this.ProjectEntityUpdateHandler.updateDocLines(
- project_id,
- doc_id,
- this.docLines,
- this.version,
- this.ranges,
- this.lastUpdatedAt,
- this.lastUpdatedBy,
- this.callback
- )
- })
- it('should update the doc in the docstore', function() {
- return this.DocstoreManager.updateDoc
- .calledWith(
- project_id,
- doc_id,
- this.docLines,
- this.version,
- this.ranges
- )
- .should.equal(true)
- })
- it('should not mark the project as updated', function() {
- return this.ProjectUpdater.markAsUpdated.called.should.equal(false)
- })
- it('should not send the doc the to the TPDS', function() {
- return this.TpdsUpdateSender.addDoc.called.should.equal(false)
- })
- it('should call the callback', function() {
- return this.callback.called.should.equal(true)
- })
- })
- describe('when the doc is not related to the project', function() {
- beforeEach(function() {
- this.ProjectLocator.findElement = sinon.stub().yields()
- return this.ProjectEntityUpdateHandler.updateDocLines(
- project_id,
- doc_id,
- this.docLines,
- this.version,
- this.ranges,
- this.lastUpdatedAt,
- this.lastUpdatedBy,
- this.callback
- )
- })
- it('should log out the error', function() {
- return this.logger.warn
- .calledWith(
- {
- project_id,
- doc_id,
- lines: this.docLines
- },
- 'doc not found while updating doc lines'
- )
- .should.equal(true)
- })
- it('should return a not found error', function() {
- return this.callback
- .calledWith(new Errors.NotFoundError())
- .should.equal(true)
- })
- })
- describe('when the project is not found', function() {
- beforeEach(function() {
- this.ProjectGetter.getProjectWithoutDocLines = sinon.stub().yields()
- return this.ProjectEntityUpdateHandler.updateDocLines(
- project_id,
- doc_id,
- this.docLines,
- this.version,
- this.ranges,
- this.lastUpdatedAt,
- this.lastUpdatedBy,
- this.callback
- )
- })
- it('should return a not found error', function() {
- return this.callback
- .calledWith(new Errors.NotFoundError())
- .should.equal(true)
- })
- })
- })
- describe('setRootDoc', function() {
- it('should call Project.update', function() {
- const rootDoc_id = 'root-doc-id-123123'
- this.ProjectModel.update = sinon.stub()
- this.ProjectEntityUpdateHandler.setRootDoc(project_id, rootDoc_id)
- return this.ProjectModel.update
- .calledWith({ _id: project_id }, { rootDoc_id })
- .should.equal(true)
- })
- })
- describe('unsetRootDoc', function() {
- it('should call Project.update', function() {
- this.ProjectModel.update = sinon.stub()
- this.ProjectEntityUpdateHandler.unsetRootDoc(project_id)
- return this.ProjectModel.update
- .calledWith({ _id: project_id }, { $unset: { rootDoc_id: true } })
- .should.equal(true)
- })
- })
- describe('addDoc', function() {
- describe('adding a doc', function() {
- beforeEach(function() {
- this.path = '/path/to/doc'
- this.newDoc = {
- name: this.docName,
- lines: undefined,
- _id: doc_id,
- rev: 0
- }
- this.DocstoreManager.updateDoc = sinon
- .stub()
- .yields(null, false, (this.rev = 5))
- this.TpdsUpdateSender.addDoc = sinon.stub().yields()
- this.ProjectEntityMongoUpdateHandler.addDoc = sinon
- .stub()
- .yields(null, { path: { fileSystem: this.path } }, this.project)
- return this.ProjectEntityUpdateHandler.addDoc(
- project_id,
- doc_id,
- this.docName,
- this.docLines,
- userId,
- this.callback
- )
- })
- it('creates the doc without history', function() {
- return this.DocstoreManager.updateDoc
- .calledWith(project_id, doc_id, this.docLines, 0, {})
- .should.equal(true)
- })
- it('sends the change in project structure to the doc updater', function() {
- const newDocs = [
- {
- doc: this.newDoc,
- path: this.path,
- docLines: this.docLines.join('\n')
- }
- ]
- return this.DocumentUpdaterHandler.updateProjectStructure
- .calledWith(project_id, projectHistoryId, userId, {
- newDocs,
- newProject: this.project
- })
- .should.equal(true)
- })
- })
- describe('adding a doc with an invalid name', function() {
- beforeEach(function() {
- this.path = '/path/to/doc'
- this.newDoc = { _id: doc_id }
- return this.ProjectEntityUpdateHandler.addDoc(
- project_id,
- folder_id,
- `*${this.docName}`,
- this.docLines,
- userId,
- this.callback
- )
- })
- it('returns an error', function() {
- const errorMatcher = sinon.match.instanceOf(Errors.InvalidNameError)
- return this.callback.calledWithMatch(errorMatcher).should.equal(true)
- })
- })
- })
- describe('addFile', function() {
- describe('adding a file', function() {
- beforeEach(function() {
- this.path = '/path/to/file'
- this.newFile = {
- _id: file_id,
- rev: 0,
- name: this.fileName,
- linkedFileData: this.linkedFileData
- }
- this.FileStoreHandler.uploadFileFromDisk = sinon
- .stub()
- .yields(null, this.fileUrl, this.newFile)
- this.TpdsUpdateSender.addFile = sinon.stub().yields()
- this.ProjectEntityMongoUpdateHandler.addFile = sinon
- .stub()
- .yields(null, { path: { fileSystem: this.path } }, this.project)
- return this.ProjectEntityUpdateHandler.addFile(
- project_id,
- folder_id,
- this.fileName,
- this.fileSystemPath,
- this.linkedFileData,
- userId,
- this.callback
- )
- })
- it('updates the file in the filestore', function() {
- return this.FileStoreHandler.uploadFileFromDisk
- .calledWith(
- project_id,
- { name: this.fileName, linkedFileData: this.linkedFileData },
- this.fileSystemPath
- )
- .should.equal(true)
- })
- it('updates the file in mongo', function() {
- const fileMatcher = sinon.match(file => {
- return file.name === this.fileName
- })
- return this.ProjectEntityMongoUpdateHandler.addFile
- .calledWithMatch(project_id, folder_id, fileMatcher)
- .should.equal(true)
- })
- it('notifies the tpds', function() {
- return this.TpdsUpdateSender.addFile
- .calledWith({
- project_id,
- project_name: this.project.name,
- file_id,
- rev: 0,
- path: this.path
- })
- .should.equal(true)
- })
- it('sends the change in project structure to the doc updater', function() {
- const newFiles = [
- {
- file: this.newFile,
- path: this.path,
- url: this.fileUrl
- }
- ]
- return this.DocumentUpdaterHandler.updateProjectStructure
- .calledWith(project_id, projectHistoryId, userId, {
- newFiles,
- newProject: this.project
- })
- .should.equal(true)
- })
- })
- describe('adding a file with an invalid name', function() {
- beforeEach(function() {
- this.path = '/path/to/file'
- this.newFile = {
- _id: file_id,
- rev: 0,
- name: this.fileName,
- linkedFileData: this.linkedFileData
- }
- this.TpdsUpdateSender.addFile = sinon.stub().yields()
- this.ProjectEntityMongoUpdateHandler.addFile = sinon
- .stub()
- .yields(null, { path: { fileSystem: this.path } }, this.project)
- return this.ProjectEntityUpdateHandler.addFile(
- project_id,
- folder_id,
- `*${this.fileName}`,
- this.fileSystemPath,
- this.linkedFileData,
- userId,
- this.callback
- )
- })
- it('returns an error', function() {
- const errorMatcher = sinon.match.instanceOf(Errors.InvalidNameError)
- return this.callback.calledWithMatch(errorMatcher).should.equal(true)
- })
- })
- })
- describe('replaceFile', function() {
- beforeEach(function() {
- // replacement file now creates a new file object
- this.newFileUrl = 'new-file-url'
- this.FileStoreHandler.uploadFileFromDisk = sinon
- .stub()
- .yields(null, this.newFileUrl, this.newFile)
- this.newFile = {
- _id: new_file_id,
- name: 'dummy-upload-filename',
- rev: 0,
- linkedFileData: this.linkedFileData
- }
- this.oldFile = { _id: file_id, rev: 3 }
- this.path = '/path/to/file'
- this.newProject = 'new project'
- this.FileStoreHandler.uploadFileFromDisk = sinon
- .stub()
- .yields(null, this.newFileUrl, this.newFile)
- this.ProjectEntityMongoUpdateHandler._insertDeletedFileReference = sinon
- .stub()
- .yields()
- this.ProjectEntityMongoUpdateHandler.replaceFileWithNew = sinon
- .stub()
- .yields(
- null,
- this.oldFile,
- this.project,
- { fileSystem: this.path },
- this.newProject
- )
- return this.ProjectEntityUpdateHandler.replaceFile(
- project_id,
- file_id,
- this.fileSystemPath,
- this.linkedFileData,
- userId,
- this.callback
- )
- })
- it('uploads a new version of the file', function() {
- return this.FileStoreHandler.uploadFileFromDisk
- .calledWith(
- project_id,
- {
- name: 'dummy-upload-filename',
- linkedFileData: this.linkedFileData
- },
- this.fileSystemPath
- )
- .should.equal(true)
- })
- it('replaces the file in mongo', function() {
- return this.ProjectEntityMongoUpdateHandler.replaceFileWithNew
- .calledWith(project_id, file_id, this.newFile)
- .should.equal(true)
- })
- it('notifies the tpds', function() {
- return this.TpdsUpdateSender.addFile
- .calledWith({
- project_id,
- project_name: this.project.name,
- file_id: new_file_id,
- rev: this.oldFile.rev + 1,
- path: this.path
- })
- .should.equal(true)
- })
- it('updates the project structure in the doc updater', function() {
- const oldFiles = [
- {
- file: this.oldFile,
- path: this.path
- }
- ]
- const newFiles = [
- {
- file: this.newFile,
- path: this.path,
- url: this.newFileUrl
- }
- ]
- return this.DocumentUpdaterHandler.updateProjectStructure
- .calledWith(project_id, projectHistoryId, userId, {
- oldFiles,
- newFiles,
- newProject: this.newProject
- })
- .should.equal(true)
- })
- })
- describe('upsertDoc', function() {
- describe('upserting into an invalid folder', function() {
- beforeEach(function() {
- this.ProjectLocator.findElement = sinon.stub().yields()
- return this.ProjectEntityUpdateHandler.upsertDoc(
- project_id,
- folder_id,
- this.docName,
- this.docLines,
- this.source,
- userId,
- this.callback
- )
- })
- it('returns an error', function() {
- const errorMatcher = sinon.match.instanceOf(Error)
- return this.callback.calledWithMatch(errorMatcher).should.equal(true)
- })
- })
- describe('updating an existing doc', function() {
- beforeEach(function() {
- this.existingDoc = { _id: doc_id, name: this.docName }
- this.folder = { _id: folder_id, docs: [this.existingDoc] }
- this.ProjectLocator.findElement = sinon.stub().yields(null, this.folder)
- this.DocumentUpdaterHandler.setDocument = sinon.stub().yields()
- this.DocumentUpdaterHandler.flushDocToMongo = sinon.stub().yields()
- return this.ProjectEntityUpdateHandler.upsertDoc(
- project_id,
- folder_id,
- this.docName,
- this.docLines,
- this.source,
- userId,
- this.callback
- )
- })
- it('tries to find the folder', function() {
- return this.ProjectLocator.findElement
- .calledWith({ project_id, element_id: folder_id, type: 'folder' })
- .should.equal(true)
- })
- it('updates the doc contents', function() {
- return this.DocumentUpdaterHandler.setDocument
- .calledWith(
- project_id,
- this.existingDoc._id,
- userId,
- this.docLines,
- this.source
- )
- .should.equal(true)
- })
- it('flushes the doc contents', function() {
- return this.DocumentUpdaterHandler.flushDocToMongo
- .calledWith(project_id, this.existingDoc._id)
- .should.equal(true)
- })
- it('returns the doc', function() {
- return this.callback.calledWith(null, this.existingDoc, false)
- })
- })
- describe('creating a new doc', function() {
- beforeEach(function() {
- this.folder = { _id: folder_id, docs: [] }
- this.newDoc = { _id: doc_id }
- this.ProjectLocator.findElement = sinon.stub().yields(null, this.folder)
- this.ProjectEntityUpdateHandler.addDocWithRanges = {
- withoutLock: sinon.stub().yields(null, this.newDoc)
- }
- return this.ProjectEntityUpdateHandler.upsertDoc(
- project_id,
- folder_id,
- this.docName,
- this.docLines,
- this.source,
- userId,
- this.callback
- )
- })
- it('tries to find the folder', function() {
- return this.ProjectLocator.findElement
- .calledWith({ project_id, element_id: folder_id, type: 'folder' })
- .should.equal(true)
- })
- it('adds the doc', function() {
- return this.ProjectEntityUpdateHandler.addDocWithRanges.withoutLock
- .calledWith(
- project_id,
- folder_id,
- this.docName,
- this.docLines,
- {},
- userId
- )
- .should.equal(true)
- })
- it('returns the doc', function() {
- return this.callback.calledWith(null, this.newDoc, true)
- })
- })
- describe('upserting a new doc with an invalid name', function() {
- beforeEach(function() {
- this.folder = { _id: folder_id, docs: [] }
- this.newDoc = { _id: doc_id }
- this.ProjectLocator.findElement = sinon.stub().yields(null, this.folder)
- this.ProjectEntityUpdateHandler.addDocWithRanges = {
- withoutLock: sinon.stub().yields(null, this.newDoc)
- }
- return this.ProjectEntityUpdateHandler.upsertDoc(
- project_id,
- folder_id,
- `*${this.docName}`,
- this.docLines,
- this.source,
- userId,
- this.callback
- )
- })
- it('returns an error', function() {
- const errorMatcher = sinon.match.instanceOf(Errors.InvalidNameError)
- return this.callback.calledWithMatch(errorMatcher).should.equal(true)
- })
- })
- })
- describe('upsertFile', function() {
- beforeEach(function() {
- return (this.FileStoreHandler.uploadFileFromDisk = sinon
- .stub()
- .yields(null, this.fileUrl, this.newFile))
- })
- describe('upserting into an invalid folder', function() {
- beforeEach(function() {
- this.ProjectLocator.findElement = sinon.stub().yields()
- return this.ProjectEntityUpdateHandler.upsertFile(
- project_id,
- folder_id,
- this.fileName,
- this.fileSystemPath,
- this.linkedFileData,
- userId,
- this.callback
- )
- })
- it('returns an error', function() {
- const errorMatcher = sinon.match.instanceOf(Error)
- return this.callback.calledWithMatch(errorMatcher).should.equal(true)
- })
- })
- describe('updating an existing file', function() {
- beforeEach(function() {
- this.existingFile = { _id: file_id, name: this.fileName }
- this.folder = { _id: folder_id, fileRefs: [this.existingFile] }
- this.ProjectLocator.findElement = sinon.stub().yields(null, this.folder)
- this.ProjectEntityUpdateHandler.replaceFile = {
- mainTask: sinon.stub().yields(null, this.newFile)
- }
- return this.ProjectEntityUpdateHandler.upsertFile(
- project_id,
- folder_id,
- this.fileName,
- this.fileSystemPath,
- this.linkedFileData,
- userId,
- this.callback
- )
- })
- it('replaces the file', function() {
- return this.ProjectEntityUpdateHandler.replaceFile.mainTask
- .calledWith(
- project_id,
- file_id,
- this.fileSystemPath,
- this.linkedFileData,
- userId
- )
- .should.equal(true)
- })
- it('returns the file', function() {
- return this.callback.calledWith(null, this.existingFile, false)
- })
- })
- describe('creating a new file', function() {
- beforeEach(function() {
- this.folder = { _id: folder_id, fileRefs: [] }
- this.newFile = { _id: file_id }
- this.ProjectLocator.findElement = sinon.stub().yields(null, this.folder)
- this.ProjectEntityUpdateHandler.addFile = {
- mainTask: sinon.stub().yields(null, this.newFile)
- }
- return this.ProjectEntityUpdateHandler.upsertFile(
- project_id,
- folder_id,
- this.fileName,
- this.fileSystemPath,
- this.linkedFileData,
- userId,
- this.callback
- )
- })
- it('tries to find the folder', function() {
- return this.ProjectLocator.findElement
- .calledWith({ project_id, element_id: folder_id, type: 'folder' })
- .should.equal(true)
- })
- it('adds the file', function() {
- return this.ProjectEntityUpdateHandler.addFile.mainTask
- .calledWith(
- project_id,
- folder_id,
- this.fileName,
- this.fileSystemPath,
- this.linkedFileData,
- userId
- )
- .should.equal(true)
- })
- it('returns the file', function() {
- return this.callback.calledWith(null, this.newFile, true)
- })
- })
- describe('upserting a new file with an invalid name', function() {
- beforeEach(function() {
- this.folder = { _id: folder_id, fileRefs: [] }
- this.newFile = { _id: file_id }
- this.ProjectLocator.findElement = sinon.stub().yields(null, this.folder)
- this.ProjectEntityUpdateHandler.addFile = {
- mainTask: sinon.stub().yields(null, this.newFile)
- }
- return this.ProjectEntityUpdateHandler.upsertFile(
- project_id,
- folder_id,
- `*${this.fileName}`,
- this.fileSystemPath,
- this.linkedFileData,
- userId,
- this.callback
- )
- })
- it('returns an error', function() {
- const errorMatcher = sinon.match.instanceOf(Errors.InvalidNameError)
- return this.callback.calledWithMatch(errorMatcher).should.equal(true)
- })
- })
- })
- describe('upsertDocWithPath', function() {
- describe('upserting a doc', function() {
- beforeEach(function() {
- this.path = '/folder/doc.tex'
- this.newFolders = ['mock-a', 'mock-b']
- this.folder = { _id: folder_id }
- this.doc = { _id: doc_id }
- this.isNewDoc = true
- this.ProjectEntityUpdateHandler.mkdirp = {
- withoutLock: sinon.stub().yields(null, this.newFolders, this.folder)
- }
- this.ProjectEntityUpdateHandler.upsertDoc = {
- withoutLock: sinon.stub().yields(null, this.doc, this.isNewDoc)
- }
- return this.ProjectEntityUpdateHandler.upsertDocWithPath(
- project_id,
- this.path,
- this.docLines,
- this.source,
- userId,
- this.callback
- )
- })
- it('creates any necessary folders', function() {
- return this.ProjectEntityUpdateHandler.mkdirp.withoutLock
- .calledWith(project_id, '/folder')
- .should.equal(true)
- })
- it('upserts the doc', function() {
- return this.ProjectEntityUpdateHandler.upsertDoc.withoutLock
- .calledWith(
- project_id,
- this.folder._id,
- 'doc.tex',
- this.docLines,
- this.source,
- userId
- )
- .should.equal(true)
- })
- it('calls the callback', function() {
- return this.callback
- .calledWith(
- null,
- this.doc,
- this.isNewDoc,
- this.newFolders,
- this.folder
- )
- .should.equal(true)
- })
- })
- describe('upserting a doc with an invalid path', function() {
- beforeEach(function() {
- this.path = '/*folder/doc.tex'
- this.newFolders = ['mock-a', 'mock-b']
- this.folder = { _id: folder_id }
- this.doc = { _id: doc_id }
- this.isNewDoc = true
- this.ProjectEntityUpdateHandler.mkdirp = {
- withoutLock: sinon.stub().yields(null, this.newFolders, this.folder)
- }
- this.ProjectEntityUpdateHandler.upsertDoc = {
- withoutLock: sinon.stub().yields(null, this.doc, this.isNewDoc)
- }
- return this.ProjectEntityUpdateHandler.upsertDocWithPath(
- project_id,
- this.path,
- this.docLines,
- this.source,
- userId,
- this.callback
- )
- })
- it('returns an error', function() {
- const errorMatcher = sinon.match.instanceOf(Errors.InvalidNameError)
- return this.callback.calledWithMatch(errorMatcher).should.equal(true)
- })
- })
- describe('upserting a doc with an invalid name', function() {
- beforeEach(function() {
- this.path = '/folder/*doc.tex'
- this.newFolders = ['mock-a', 'mock-b']
- this.folder = { _id: folder_id }
- this.doc = { _id: doc_id }
- this.isNewDoc = true
- this.ProjectEntityUpdateHandler.mkdirp = {
- withoutLock: sinon.stub().yields(null, this.newFolders, this.folder)
- }
- this.ProjectEntityUpdateHandler.upsertDoc = {
- withoutLock: sinon.stub().yields(null, this.doc, this.isNewDoc)
- }
- return this.ProjectEntityUpdateHandler.upsertDocWithPath(
- project_id,
- this.path,
- this.docLines,
- this.source,
- userId,
- this.callback
- )
- })
- it('returns an error', function() {
- const errorMatcher = sinon.match.instanceOf(Errors.InvalidNameError)
- return this.callback.calledWithMatch(errorMatcher).should.equal(true)
- })
- })
- })
- describe('upsertFileWithPath', function() {
- describe('upserting a file', function() {
- beforeEach(function() {
- this.path = '/folder/file.png'
- this.newFolders = ['mock-a', 'mock-b']
- this.folder = { _id: folder_id }
- this.file = { _id: file_id }
- this.isNewFile = true
- this.FileStoreHandler.uploadFileFromDisk = sinon
- .stub()
- .yields(null, this.fileUrl, this.newFile)
- this.ProjectEntityUpdateHandler.mkdirp = {
- withoutLock: sinon.stub().yields(null, this.newFolders, this.folder)
- }
- this.ProjectEntityUpdateHandler.upsertFile = {
- mainTask: sinon.stub().yields(null, this.file, this.isNewFile)
- }
- return this.ProjectEntityUpdateHandler.upsertFileWithPath(
- project_id,
- this.path,
- this.fileSystemPath,
- this.linkedFileData,
- userId,
- this.callback
- )
- })
- it('creates any necessary folders', function() {
- return this.ProjectEntityUpdateHandler.mkdirp.withoutLock
- .calledWith(project_id, '/folder')
- .should.equal(true)
- })
- it('upserts the file', function() {
- return this.ProjectEntityUpdateHandler.upsertFile.mainTask
- .calledWith(
- project_id,
- this.folder._id,
- 'file.png',
- this.fileSystemPath,
- this.linkedFileData,
- userId
- )
- .should.equal(true)
- })
- it('calls the callback', function() {
- return this.callback
- .calledWith(
- null,
- this.file,
- this.isNewFile,
- undefined,
- this.newFolders,
- this.folder
- )
- .should.equal(true)
- })
- })
- describe('upserting a file with an invalid path', function() {
- beforeEach(function() {
- this.path = '/*folder/file.png'
- this.newFolders = ['mock-a', 'mock-b']
- this.folder = { _id: folder_id }
- this.file = { _id: file_id }
- this.isNewFile = true
- this.ProjectEntityUpdateHandler.mkdirp = {
- withoutLock: sinon.stub().yields(null, this.newFolders, this.folder)
- }
- this.ProjectEntityUpdateHandler.upsertFile = {
- mainTask: sinon.stub().yields(null, this.file, this.isNewFile)
- }
- return this.ProjectEntityUpdateHandler.upsertFileWithPath(
- project_id,
- this.path,
- this.fileSystemPath,
- this.linkedFileData,
- userId,
- this.callback
- )
- })
- it('returns an error', function() {
- const errorMatcher = sinon.match.instanceOf(Errors.InvalidNameError)
- return this.callback.calledWithMatch(errorMatcher).should.equal(true)
- })
- })
- describe('upserting a file with an invalid name', function() {
- beforeEach(function() {
- this.path = '/folder/*file.png'
- this.newFolders = ['mock-a', 'mock-b']
- this.folder = { _id: folder_id }
- this.file = { _id: file_id }
- this.isNewFile = true
- this.ProjectEntityUpdateHandler.mkdirp = {
- withoutLock: sinon.stub().yields(null, this.newFolders, this.folder)
- }
- this.ProjectEntityUpdateHandler.upsertFile = {
- mainTask: sinon.stub().yields(null, this.file, this.isNewFile)
- }
- return this.ProjectEntityUpdateHandler.upsertFileWithPath(
- project_id,
- this.path,
- this.fileSystemPath,
- this.linkedFileData,
- userId,
- this.callback
- )
- })
- it('returns an error', function() {
- const errorMatcher = sinon.match.instanceOf(Errors.InvalidNameError)
- return this.callback.calledWithMatch(errorMatcher).should.equal(true)
- })
- })
- })
- describe('deleteEntity', function() {
- beforeEach(function() {
- this.path = '/path/to/doc.tex'
- this.doc = { _id: doc_id }
- this.projectBeforeDeletion = { _id: project_id, name: 'project' }
- this.newProject = 'new-project'
- this.ProjectEntityMongoUpdateHandler.deleteEntity = sinon
- .stub()
- .yields(
- null,
- this.doc,
- { fileSystem: this.path },
- this.projectBeforeDeletion,
- this.newProject
- )
- this.ProjectEntityUpdateHandler._cleanUpEntity = sinon.stub().yields()
- this.TpdsUpdateSender.deleteEntity = sinon.stub().yields()
- return this.ProjectEntityUpdateHandler.deleteEntity(
- project_id,
- doc_id,
- 'doc',
- userId,
- this.callback
- )
- })
- it('deletes the entity in mongo', function() {
- return this.ProjectEntityMongoUpdateHandler.deleteEntity
- .calledWith(project_id, doc_id, 'doc')
- .should.equal(true)
- })
- it('cleans up the doc in the docstore', function() {
- return this.ProjectEntityUpdateHandler._cleanUpEntity
- .calledWith(
- this.projectBeforeDeletion,
- this.newProject,
- this.doc,
- 'doc',
- this.path,
- userId
- )
- .should.equal(true)
- })
- it('it notifies the tpds', function() {
- return this.TpdsUpdateSender.deleteEntity
- .calledWith({
- project_id,
- path: this.path,
- project_name: this.projectBeforeDeletion.name
- })
- .should.equal(true)
- })
- it('retuns the entity_id', function() {
- return this.callback.calledWith(null, doc_id).should.equal(true)
- })
- })
- describe('deleteEntityWithPath', function() {
- describe('when the entity exists', function() {
- beforeEach(function() {
- this.doc = { _id: doc_id }
- this.ProjectLocator.findElementByPath = sinon
- .stub()
- .yields(null, this.doc, 'doc')
- this.ProjectEntityUpdateHandler.deleteEntity = {
- withoutLock: sinon.stub().yields()
- }
- this.path = '/path/to/doc.tex'
- return this.ProjectEntityUpdateHandler.deleteEntityWithPath(
- project_id,
- this.path,
- userId,
- this.callback
- )
- })
- it('finds the entity', function() {
- return this.ProjectLocator.findElementByPath
- .calledWith({ project_id, path: this.path })
- .should.equal(true)
- })
- it('deletes the entity', function() {
- return this.ProjectEntityUpdateHandler.deleteEntity.withoutLock
- .calledWith(project_id, this.doc._id, 'doc', userId, this.callback)
- .should.equal(true)
- })
- })
- describe('when the entity does not exist', function() {
- beforeEach(function() {
- this.ProjectLocator.findElementByPath = sinon.stub().yields()
- this.path = '/doc.tex'
- return this.ProjectEntityUpdateHandler.deleteEntityWithPath(
- project_id,
- this.path,
- userId,
- this.callback
- )
- })
- it('returns an error', function() {
- return this.callback
- .calledWith(new Errors.NotFoundError())
- .should.equal(true)
- })
- })
- })
- describe('mkdirp', function() {
- beforeEach(function() {
- this.docPath = '/folder/doc.tex'
- this.ProjectEntityMongoUpdateHandler.mkdirp = sinon.stub().yields()
- return this.ProjectEntityUpdateHandler.mkdirp(
- project_id,
- this.docPath,
- this.callback
- )
- })
- it('calls ProjectEntityMongoUpdateHandler', function() {
- return this.ProjectEntityMongoUpdateHandler.mkdirp
- .calledWith(project_id, this.docPath)
- .should.equal(true)
- })
- })
- describe('mkdirpWithExactCase', function() {
- beforeEach(function() {
- this.docPath = '/folder/doc.tex'
- this.ProjectEntityMongoUpdateHandler.mkdirp = sinon.stub().yields()
- return this.ProjectEntityUpdateHandler.mkdirpWithExactCase(
- project_id,
- this.docPath,
- this.callback
- )
- })
- it('calls ProjectEntityMongoUpdateHandler', function() {
- return this.ProjectEntityMongoUpdateHandler.mkdirp
- .calledWith(project_id, this.docPath, { exactCaseMatch: true })
- .should.equal(true)
- })
- })
- describe('addFolder', function() {
- describe('adding a folder', function() {
- beforeEach(function() {
- this.parentFolder_id = '123asdf'
- this.folderName = 'new-folder'
- this.ProjectEntityMongoUpdateHandler.addFolder = sinon.stub().yields()
- return this.ProjectEntityUpdateHandler.addFolder(
- project_id,
- this.parentFolder_id,
- this.folderName,
- this.callback
- )
- })
- it('calls ProjectEntityMongoUpdateHandler', function() {
- return this.ProjectEntityMongoUpdateHandler.addFolder
- .calledWith(project_id, this.parentFolder_id, this.folderName)
- .should.equal(true)
- })
- })
- describe('adding a folder with an invalid name', function() {
- beforeEach(function() {
- this.parentFolder_id = '123asdf'
- this.folderName = '*new-folder'
- this.ProjectEntityMongoUpdateHandler.addFolder = sinon.stub().yields()
- return this.ProjectEntityUpdateHandler.addFolder(
- project_id,
- this.parentFolder_id,
- this.folderName,
- this.callback
- )
- })
- it('returns an error', function() {
- const errorMatcher = sinon.match.instanceOf(Errors.InvalidNameError)
- return this.callback.calledWithMatch(errorMatcher).should.equal(true)
- })
- })
- })
- describe('moveEntity', function() {
- beforeEach(function() {
- this.project_name = 'project name'
- this.startPath = '/a.tex'
- this.endPath = '/folder/b.tex'
- this.rev = 2
- this.changes = { newDocs: ['old-doc'], newFiles: ['old-file'] }
- this.ProjectEntityMongoUpdateHandler.moveEntity = sinon
- .stub()
- .yields(
- null,
- this.project,
- this.startPath,
- this.endPath,
- this.rev,
- this.changes
- )
- this.TpdsUpdateSender.moveEntity = sinon.stub()
- this.DocumentUpdaterHandler.updateProjectStructure = sinon.stub()
- return this.ProjectEntityUpdateHandler.moveEntity(
- project_id,
- doc_id,
- folder_id,
- 'doc',
- userId,
- this.callback
- )
- })
- it('moves the entity in mongo', function() {
- return this.ProjectEntityMongoUpdateHandler.moveEntity
- .calledWith(project_id, doc_id, folder_id, 'doc')
- .should.equal(true)
- })
- it('notifies tpds', function() {
- return this.TpdsUpdateSender.moveEntity
- .calledWith({
- project_id,
- project_name: this.project_name,
- startPath: this.startPath,
- endPath: this.endPath,
- rev: this.rev
- })
- .should.equal(true)
- })
- it('sends the changes in project structure to the doc updater', function() {
- return this.DocumentUpdaterHandler.updateProjectStructure
- .calledWith(
- project_id,
- projectHistoryId,
- userId,
- this.changes,
- this.callback
- )
- .should.equal(true)
- })
- })
- describe('renameEntity', function() {
- describe('renaming an entity', function() {
- beforeEach(function() {
- this.project_name = 'project name'
- this.startPath = '/folder/a.tex'
- this.endPath = '/folder/b.tex'
- this.rev = 2
- this.changes = { newDocs: ['old-doc'], newFiles: ['old-file'] }
- this.newDocName = 'b.tex'
- this.ProjectEntityMongoUpdateHandler.renameEntity = sinon
- .stub()
- .yields(
- null,
- this.project,
- this.startPath,
- this.endPath,
- this.rev,
- this.changes
- )
- this.TpdsUpdateSender.moveEntity = sinon.stub()
- this.DocumentUpdaterHandler.updateProjectStructure = sinon.stub()
- return this.ProjectEntityUpdateHandler.renameEntity(
- project_id,
- doc_id,
- 'doc',
- this.newDocName,
- userId,
- this.callback
- )
- })
- it('moves the entity in mongo', function() {
- return this.ProjectEntityMongoUpdateHandler.renameEntity
- .calledWith(project_id, doc_id, 'doc', this.newDocName)
- .should.equal(true)
- })
- it('notifies tpds', function() {
- return this.TpdsUpdateSender.moveEntity
- .calledWith({
- project_id,
- project_name: this.project_name,
- startPath: this.startPath,
- endPath: this.endPath,
- rev: this.rev
- })
- .should.equal(true)
- })
- it('sends the changes in project structure to the doc updater', function() {
- return this.DocumentUpdaterHandler.updateProjectStructure
- .calledWith(
- project_id,
- projectHistoryId,
- userId,
- this.changes,
- this.callback
- )
- .should.equal(true)
- })
- })
- describe('renaming an entity to an invalid name', function() {
- beforeEach(function() {
- this.project_name = 'project name'
- this.startPath = '/folder/a.tex'
- this.endPath = '/folder/b.tex'
- this.rev = 2
- this.changes = { newDocs: ['old-doc'], newFiles: ['old-file'] }
- this.newDocName = '*b.tex'
- this.ProjectEntityMongoUpdateHandler.renameEntity = sinon
- .stub()
- .yields(
- null,
- this.project,
- this.startPath,
- this.endPath,
- this.rev,
- this.changes
- )
- this.TpdsUpdateSender.moveEntity = sinon.stub()
- this.DocumentUpdaterHandler.updateProjectStructure = sinon.stub()
- return this.ProjectEntityUpdateHandler.renameEntity(
- project_id,
- doc_id,
- 'doc',
- this.newDocName,
- userId,
- this.callback
- )
- })
- it('returns an error', function() {
- const errorMatcher = sinon.match.instanceOf(Errors.InvalidNameError)
- return this.callback.calledWithMatch(errorMatcher).should.equal(true)
- })
- })
- })
- describe('resyncProjectHistory', function() {
- describe('a deleted project', function() {
- beforeEach(function() {
- this.ProjectGetter.getProject = sinon.stub().yields()
- return this.ProjectEntityUpdateHandler.resyncProjectHistory(
- project_id,
- this.callback
- )
- })
- it('should return an error', function() {
- const error = new Errors.ProjectHistoryDisabledError(
- `project history not enabled for ${project_id}`
- )
- return this.callback.calledWith(error).should.equal(true)
- })
- })
- describe('a project without project-history enabled', function() {
- beforeEach(function() {
- this.project.overleaf = {}
- this.ProjectGetter.getProject = sinon.stub().yields(null, this.project)
- return this.ProjectEntityUpdateHandler.resyncProjectHistory(
- project_id,
- this.callback
- )
- })
- it('should return an error', function() {
- const error = new Errors.ProjectHistoryDisabledError(
- `project history not enabled for ${project_id}`
- )
- return this.callback.calledWith(error).should.equal(true)
- })
- })
- describe('a project with project-history enabled', function() {
- beforeEach(function() {
- this.ProjectGetter.getProject = sinon.stub().yields(null, this.project)
- const docs = [
- {
- doc: {
- _id: doc_id
- },
- path: 'main.tex'
- }
- ]
- const files = [
- {
- file: {
- _id: file_id
- },
- path: 'universe.png'
- }
- ]
- this.ProjectEntityHandler.getAllEntitiesFromProject = sinon
- .stub()
- .yields(null, docs, files)
- this.FileStoreHandler._buildUrl = (project_id, file_id) =>
- `www.filestore.test/${project_id}/${file_id}`
- this.DocumentUpdaterHandler.resyncProjectHistory = sinon.stub().yields()
- return this.ProjectEntityUpdateHandler.resyncProjectHistory(
- project_id,
- this.callback
- )
- })
- it('gets the project', function() {
- return this.ProjectGetter.getProject
- .calledWith(project_id)
- .should.equal(true)
- })
- it('gets the entities for the project', function() {
- return this.ProjectEntityHandler.getAllEntitiesFromProject
- .calledWith(this.project)
- .should.equal(true)
- })
- it('tells the doc updater to sync the project', function() {
- const docs = [
- {
- doc: doc_id,
- path: 'main.tex'
- }
- ]
- const files = [
- {
- file: file_id,
- path: 'universe.png',
- url: `www.filestore.test/${project_id}/${file_id}`
- }
- ]
- return this.DocumentUpdaterHandler.resyncProjectHistory
- .calledWith(project_id, projectHistoryId, docs, files)
- .should.equal(true)
- })
- it('calls the callback', function() {
- return this.callback.called.should.equal(true)
- })
- })
- })
- describe('_cleanUpEntity', function() {
- beforeEach(function() {
- this.entity_id = '4eecaffcbffa66588e000009'
- this.FileStoreHandler.deleteFile = sinon.stub().yields()
- this.DocumentUpdaterHandler.deleteDoc = sinon.stub().yields()
- this.ProjectEntityUpdateHandler.unsetRootDoc = sinon.stub().yields()
- return (this.ProjectEntityMongoUpdateHandler._insertDeletedFileReference = sinon
- .stub()
- .yields())
- })
- describe('a file', function() {
- beforeEach(function(done) {
- this.path = '/file/system/path.png'
- this.entity = { _id: this.entity_id }
- this.newProject = 'new-project'
- return this.ProjectEntityUpdateHandler._cleanUpEntity(
- this.project,
- this.newProject,
- this.entity,
- 'file',
- this.path,
- userId,
- done
- )
- })
- it('should insert the file into the deletedFiles array', function() {
- return this.ProjectEntityMongoUpdateHandler._insertDeletedFileReference
- .calledWith(this.project._id, this.entity)
- .should.equal(true)
- })
- it('should not delete the file from FileStoreHandler', function() {
- return this.FileStoreHandler.deleteFile
- .calledWith(project_id, this.entity_id)
- .should.equal(false)
- })
- it('should not attempt to delete from the document updater', function() {
- return this.DocumentUpdaterHandler.deleteDoc.called.should.equal(false)
- })
- it('should should send the update to the doc updater', function() {
- const oldFiles = [{ file: this.entity, path: this.path }]
- return this.DocumentUpdaterHandler.updateProjectStructure
- .calledWith(project_id, projectHistoryId, userId, {
- oldFiles,
- newProject: this.newProject
- })
- .should.equal(true)
- })
- })
- describe('a doc', function() {
- beforeEach(function(done) {
- this.path = '/file/system/path.tex'
- this.ProjectEntityUpdateHandler._cleanUpDoc = sinon.stub().yields()
- this.entity = { _id: this.entity_id }
- this.newProject = 'new-project'
- return this.ProjectEntityUpdateHandler._cleanUpEntity(
- this.project,
- this.newProject,
- this.entity,
- 'doc',
- this.path,
- userId,
- done
- )
- })
- it('should clean up the doc', function() {
- return this.ProjectEntityUpdateHandler._cleanUpDoc
- .calledWith(this.project, this.entity, this.path, userId)
- .should.equal(true)
- })
- it('should should send the update to the doc updater', function() {
- const oldDocs = [{ doc: this.entity, path: this.path }]
- return this.DocumentUpdaterHandler.updateProjectStructure
- .calledWith(project_id, projectHistoryId, userId, {
- oldDocs,
- newProject: this.newProject
- })
- .should.equal(true)
- })
- })
- describe('a folder', function() {
- beforeEach(function(done) {
- this.folder = {
- folders: [
- {
- name: 'subfolder',
- fileRefs: [
- (this.file1 = { _id: 'file-id-1', name: 'file-name-1' })
- ],
- docs: [(this.doc1 = { _id: 'doc-id-1', name: 'doc-name-1' })],
- folders: []
- }
- ],
- fileRefs: [(this.file2 = { _id: 'file-id-2', name: 'file-name-2' })],
- docs: [(this.doc2 = { _id: 'doc-id-2', name: 'doc-name-2' })]
- }
- this.ProjectEntityUpdateHandler._cleanUpDoc = sinon.stub().yields()
- this.ProjectEntityUpdateHandler._cleanUpFile = sinon.stub().yields()
- const path = '/folder'
- this.newProject = 'new-project'
- return this.ProjectEntityUpdateHandler._cleanUpEntity(
- this.project,
- this.newProject,
- this.folder,
- 'folder',
- path,
- userId,
- done
- )
- })
- it('should clean up all sub files', function() {
- this.ProjectEntityUpdateHandler._cleanUpFile
- .calledWith(
- this.project,
- this.file1,
- '/folder/subfolder/file-name-1',
- userId
- )
- .should.equal(true)
- return this.ProjectEntityUpdateHandler._cleanUpFile
- .calledWith(this.project, this.file2, '/folder/file-name-2', userId)
- .should.equal(true)
- })
- it('should clean up all sub docs', function() {
- this.ProjectEntityUpdateHandler._cleanUpDoc
- .calledWith(
- this.project,
- this.doc1,
- '/folder/subfolder/doc-name-1',
- userId
- )
- .should.equal(true)
- return this.ProjectEntityUpdateHandler._cleanUpDoc
- .calledWith(this.project, this.doc2, '/folder/doc-name-2', userId)
- .should.equal(true)
- })
- it('should should send one update to the doc updater for all docs and files', function() {
- const oldFiles = [
- { file: this.file2, path: '/folder/file-name-2' },
- { file: this.file1, path: '/folder/subfolder/file-name-1' }
- ]
- const oldDocs = [
- { doc: this.doc2, path: '/folder/doc-name-2' },
- { doc: this.doc1, path: '/folder/subfolder/doc-name-1' }
- ]
- return this.DocumentUpdaterHandler.updateProjectStructure
- .calledWith(project_id, projectHistoryId, userId, {
- oldFiles,
- oldDocs,
- newProject: this.newProject
- })
- .should.equal(true)
- })
- })
- })
- describe('_cleanUpDoc', function() {
- beforeEach(function() {
- this.doc = {
- _id: ObjectId(),
- name: 'test.tex'
- }
- this.path = '/path/to/doc'
- this.ProjectEntityUpdateHandler.unsetRootDoc = sinon.stub().yields()
- this.ProjectEntityMongoUpdateHandler._insertDeletedDocReference = sinon
- .stub()
- .yields()
- this.DocumentUpdaterHandler.deleteDoc = sinon.stub().yields()
- this.DocstoreManager.deleteDoc = sinon.stub().yields()
- return (this.callback = sinon.stub())
- })
- describe('when the doc is the root doc', function() {
- beforeEach(function() {
- this.project.rootDoc_id = this.doc._id
- return this.ProjectEntityUpdateHandler._cleanUpDoc(
- this.project,
- this.doc,
- this.path,
- userId,
- this.callback
- )
- })
- it('should unset the root doc', function() {
- return this.ProjectEntityUpdateHandler.unsetRootDoc
- .calledWith(project_id)
- .should.equal(true)
- })
- it('should delete the doc in the doc updater', function() {
- return this.DocumentUpdaterHandler.deleteDoc.calledWith(
- project_id,
- this.doc._id.toString()
- )
- })
- it('should insert the doc into the deletedDocs array', function() {
- return this.ProjectEntityMongoUpdateHandler._insertDeletedDocReference
- .calledWith(this.project._id, this.doc)
- .should.equal(true)
- })
- it('should delete the doc in the doc store', function() {
- return this.DocstoreManager.deleteDoc
- .calledWith(project_id, this.doc._id.toString())
- .should.equal(true)
- })
- it('should call the callback', function() {
- return this.callback.called.should.equal(true)
- })
- })
- describe('when the doc is not the root doc', function() {
- beforeEach(function() {
- this.project.rootDoc_id = ObjectId()
- return this.ProjectEntityUpdateHandler._cleanUpDoc(
- this.project,
- this.doc,
- this.path,
- userId,
- this.callback
- )
- })
- it('should not unset the root doc', function() {
- return this.ProjectEntityUpdateHandler.unsetRootDoc.called.should.equal(
- false
- )
- })
- it('should call the callback', function() {
- return this.callback.called.should.equal(true)
- })
- })
- })
- })
|