mirror of
https://github.com/overleaf/overleaf.git
synced 2025-04-11 13:44:05 +00:00
Merge pull request #2168 from overleaf/pr-restrict-main-file-options
Restrict main file options based on extension. GitOrigin-RevId: f7d7a61c0454621dd8bc6ab5edce8a89721018ea
This commit is contained in:
parent
6737637b39
commit
ea0270dbdd
13 changed files with 253 additions and 65 deletions
services/web
app
src
Features/Project
infrastructure
views/project/editor
config
public/src
test/unit/src/Project
|
@ -278,6 +278,51 @@ const ProjectEntityHandler = {
|
|||
return DocstoreManager.getDoc(project_id, doc_id, options, callback)
|
||||
},
|
||||
|
||||
getDocPathByProjectIdAndDocId(project_id, doc_id, callback) {
|
||||
logger.log({ project_id, doc_id }, 'getting path for doc and project')
|
||||
return ProjectGetter.getProjectWithoutDocLines(project_id, function(
|
||||
err,
|
||||
project
|
||||
) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
if (project == null) {
|
||||
return callback(new Errors.NotFoundError('no project'))
|
||||
}
|
||||
function recursivelyFindDocInFolder(basePath, doc_id, folder) {
|
||||
let docInCurrentFolder = Array.from(folder.docs || []).find(
|
||||
currentDoc => currentDoc._id.toString() === doc_id.toString()
|
||||
)
|
||||
if (docInCurrentFolder != null) {
|
||||
return path.join(basePath, docInCurrentFolder.name)
|
||||
} else {
|
||||
let docPath, childFolder
|
||||
for (childFolder of Array.from(folder.folders || [])) {
|
||||
docPath = recursivelyFindDocInFolder(
|
||||
path.join(basePath, childFolder.name),
|
||||
doc_id,
|
||||
childFolder
|
||||
)
|
||||
if (docPath != null) {
|
||||
return docPath
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
const docPath = recursivelyFindDocInFolder(
|
||||
'/',
|
||||
doc_id,
|
||||
project.rootFolder[0]
|
||||
)
|
||||
if (docPath == null) {
|
||||
return callback(new Errors.NotFoundError('no doc'))
|
||||
}
|
||||
return callback(null, docPath)
|
||||
})
|
||||
},
|
||||
|
||||
_getAllFolders(project_id, callback) {
|
||||
logger.log({ project_id }, 'getting all folders for project')
|
||||
return ProjectGetter.getProjectWithoutDocLines(project_id, function(
|
||||
|
|
|
@ -20,6 +20,7 @@ let ProjectEntityUpdateHandler, self
|
|||
const _ = require('lodash')
|
||||
const async = require('async')
|
||||
const logger = require('logger-sharelatex')
|
||||
const Settings = require('settings-sharelatex')
|
||||
const path = require('path')
|
||||
const { Doc } = require('../../models/Doc')
|
||||
const DocstoreManager = require('../Docstore/DocstoreManager')
|
||||
|
@ -39,6 +40,12 @@ const TpdsUpdateSender = require('../ThirdPartyDataStore/TpdsUpdateSender')
|
|||
|
||||
const LOCK_NAMESPACE = 'sequentialProjectStructureUpdateLock'
|
||||
|
||||
const validRootDocExtensions = Settings.validRootDocExtensions
|
||||
const validRootDocRegExp = new RegExp(
|
||||
`^\\.(${validRootDocExtensions.join('|')})$`,
|
||||
'i'
|
||||
)
|
||||
|
||||
const wrapWithLock = function(methodWithoutLock) {
|
||||
// This lock is used to make sure that the project structure updates are made
|
||||
// sequentially. In particular the updates must be made in mongo and sent to
|
||||
|
@ -348,11 +355,33 @@ module.exports = ProjectEntityUpdateHandler = self = {
|
|||
callback = function(error) {}
|
||||
}
|
||||
logger.log({ project_id, rootDocId: newRootDocID }, 'setting root doc')
|
||||
return Project.update(
|
||||
{ _id: project_id },
|
||||
{ rootDoc_id: newRootDocID },
|
||||
{},
|
||||
callback
|
||||
if (project_id == null || newRootDocID == null) {
|
||||
return callback(
|
||||
new Errors.InvalidError('missing arguments (project or doc)')
|
||||
)
|
||||
}
|
||||
ProjectEntityHandler.getDocPathByProjectIdAndDocId(
|
||||
project_id,
|
||||
newRootDocID,
|
||||
function(err, docPath) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
if (ProjectEntityUpdateHandler.isPathValidForRootDoc(docPath)) {
|
||||
return Project.update(
|
||||
{ _id: project_id },
|
||||
{ rootDoc_id: newRootDocID },
|
||||
{},
|
||||
callback
|
||||
)
|
||||
} else {
|
||||
return callback(
|
||||
new Errors.UnsupportedFileTypeError(
|
||||
'invalid file extension for root doc'
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
|
@ -1401,6 +1430,11 @@ module.exports = ProjectEntityUpdateHandler = self = {
|
|||
)
|
||||
),
|
||||
|
||||
isPathValidForRootDoc(docPath) {
|
||||
let docExtension = path.extname(docPath)
|
||||
return validRootDocRegExp.test(docExtension)
|
||||
},
|
||||
|
||||
_cleanUpEntity(
|
||||
project,
|
||||
newProject,
|
||||
|
|
|
@ -40,7 +40,7 @@ module.exports = ProjectRootDocManager = {
|
|||
(doc, path) =>
|
||||
function(cb) {
|
||||
if (
|
||||
/\.R?tex$/.test(Path.extname(path)) &&
|
||||
ProjectEntityUpdateHandler.isPathValidForRootDoc(path) &&
|
||||
DocumentHelper.contentHasDocumentclass(doc.lines)
|
||||
) {
|
||||
return cb(doc._id)
|
||||
|
@ -232,14 +232,11 @@ module.exports = ProjectRootDocManager = {
|
|||
if (rootDocValid) {
|
||||
return callback()
|
||||
} else {
|
||||
return ProjectEntityUpdateHandler.setRootDoc(
|
||||
project_id,
|
||||
null,
|
||||
() =>
|
||||
ProjectRootDocManager.setRootDocAutomatically(
|
||||
project_id,
|
||||
callback
|
||||
)
|
||||
return ProjectEntityUpdateHandler.unsetRootDoc(project_id, () =>
|
||||
ProjectRootDocManager.setRootDocAutomatically(
|
||||
project_id,
|
||||
callback
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -533,7 +533,8 @@ module.exports = function(app, webRouter, privateApiRouter, publicApiRouter) {
|
|||
recaptchaSiteKeyV3:
|
||||
Settings.recaptcha != null ? Settings.recaptcha.siteKeyV3 : undefined,
|
||||
recaptchaDisabled:
|
||||
Settings.recaptcha != null ? Settings.recaptcha.disabled : undefined
|
||||
Settings.recaptcha != null ? Settings.recaptcha.disabled : undefined,
|
||||
validRootDocExtensions: Settings.validRootDocExtensions
|
||||
}
|
||||
return next()
|
||||
})
|
||||
|
|
|
@ -90,7 +90,7 @@ aside#left-menu.full-size(
|
|||
select(
|
||||
name="rootDoc_id",
|
||||
ng-model="project.rootDoc_id",
|
||||
ng-options="doc.doc.id as doc.path for doc in docs"
|
||||
ng-options="doc.doc.id as doc.path for doc in getValidMainDocs()"
|
||||
)
|
||||
|
||||
.form-controls
|
||||
|
|
|
@ -556,6 +556,8 @@ module.exports = settings =
|
|||
|
||||
compileBodySizeLimitMb: process.env['COMPILE_BODY_SIZE_LIMIT_MB'] or 5
|
||||
|
||||
validRootDocExtensions: ['tex', 'Rtex', 'ltx']
|
||||
|
||||
# allowedImageNames: [
|
||||
# {imageName: 'texlive-full:2017.1', imageDesc: 'TeXLive 2017'}
|
||||
# {imageName: 'wl_texlive:2018.1', imageDesc: 'Legacy OL TeXLive 2015'}
|
||||
|
|
|
@ -59,7 +59,8 @@ define([
|
|||
'services/wait-for',
|
||||
'filters/formatDate',
|
||||
'main/event',
|
||||
'main/account-upgrade'
|
||||
'main/account-upgrade',
|
||||
'main/exposed-settings'
|
||||
], function(
|
||||
App,
|
||||
FileTreeManager,
|
||||
|
|
|
@ -13,7 +13,19 @@
|
|||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
define(['base'], App =>
|
||||
App.controller('SettingsController', function($scope, settings, ide, _) {
|
||||
App.controller('SettingsController', function(
|
||||
$scope,
|
||||
ExposedSettings,
|
||||
settings,
|
||||
ide,
|
||||
_
|
||||
) {
|
||||
const validRootDocExtensions = ExposedSettings.validRootDocExtensions
|
||||
const validRootDocRegExp = new RegExp(
|
||||
`\\.(${validRootDocExtensions.join('|')})$`,
|
||||
'i'
|
||||
)
|
||||
|
||||
$scope.overallThemesList = window.overallThemes
|
||||
$scope.ui = { loadingStyleSheet: false }
|
||||
|
||||
|
@ -63,6 +75,21 @@ define(['base'], App =>
|
|||
return $scope.settings.fontSize.toString()
|
||||
}
|
||||
|
||||
$scope.getValidMainDocs = () => {
|
||||
let filteredDocs = []
|
||||
if ($scope.docs) {
|
||||
// Filter the existing docs (editable files) by accepted file extensions.
|
||||
// It's possible that an existing project has an invalid file selected as the main one.
|
||||
// To gracefully handle that case, make sure we also show the current main file (ignoring extension).
|
||||
filteredDocs = $scope.docs.filter(
|
||||
doc =>
|
||||
validRootDocRegExp.test(doc.doc.name) ||
|
||||
$scope.project.rootDoc_id === doc.doc.id
|
||||
)
|
||||
}
|
||||
return filteredDocs
|
||||
}
|
||||
|
||||
$scope.$watch('settings.editorTheme', (editorTheme, oldEditorTheme) => {
|
||||
if (editorTheme !== oldEditorTheme) {
|
||||
return settings.saveSettings({ editorTheme })
|
||||
|
@ -176,7 +203,9 @@ define(['base'], App =>
|
|||
}
|
||||
// otherwise only save changes, null values are allowed
|
||||
if (rootDoc_id !== oldRootDoc_id) {
|
||||
return settings.saveProjectSettings({ rootDocId: rootDoc_id })
|
||||
settings.saveProjectSettings({ rootDocId: rootDoc_id }).catch(() => {
|
||||
$scope.project.rootDoc_id = oldRootDoc_id
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ define([
|
|||
'main/subscription/team-invite-controller',
|
||||
'main/contact-us',
|
||||
'main/learn',
|
||||
'main/exposed-settings',
|
||||
'main/affiliations/components/affiliationForm',
|
||||
'main/affiliations/controllers/UserAffiliationsController',
|
||||
'main/affiliations/factories/UserAffiliationsDataService',
|
||||
|
|
3
services/web/public/src/main/exposed-settings.js
Normal file
3
services/web/public/src/main/exposed-settings.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
define(['base'], function(App) {
|
||||
App.constant('ExposedSettings', window.ExposedSettings)
|
||||
})
|
|
@ -57,7 +57,6 @@ describe('ProjectEntityHandler', function() {
|
|||
this.DocumentUpdaterHandler = {
|
||||
updateProjectStructure: sinon.stub().yields()
|
||||
}
|
||||
|
||||
this.callback = sinon.stub()
|
||||
|
||||
return (this.ProjectEntityHandler = SandboxedModule.require(modulePath, {
|
||||
|
@ -76,6 +75,7 @@ describe('ProjectEntityHandler', function() {
|
|||
'../../models/Project': {
|
||||
Project: this.ProjectModel
|
||||
},
|
||||
'../Errors/Errors': Errors,
|
||||
'./ProjectLocator': this.ProjectLocator,
|
||||
'./ProjectGetter': (this.ProjectGetter = {}),
|
||||
'../ThirdPartyDataStore/TpdsUpdateSender': this.TpdsUpdateSender
|
||||
|
@ -121,9 +121,9 @@ describe('ProjectEntityHandler', function() {
|
|||
]
|
||||
}
|
||||
]
|
||||
return (this.ProjectGetter.getProjectWithoutDocLines = sinon
|
||||
this.ProjectGetter.getProjectWithoutDocLines = sinon
|
||||
.stub()
|
||||
.yields(null, this.project))
|
||||
.yields(null, this.project)
|
||||
})
|
||||
|
||||
describe('getAllDocs', function() {
|
||||
|
@ -143,17 +143,17 @@ describe('ProjectEntityHandler', function() {
|
|||
this.DocstoreManager.getAllDocs = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, this.docs)
|
||||
return this.ProjectEntityHandler.getAllDocs(project_id, this.callback)
|
||||
this.ProjectEntityHandler.getAllDocs(project_id, this.callback)
|
||||
})
|
||||
|
||||
it('should get the doc lines and rev from the docstore', function() {
|
||||
return this.DocstoreManager.getAllDocs
|
||||
this.DocstoreManager.getAllDocs
|
||||
.calledWith(project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should call the callback with the docs with the lines and rev included', function() {
|
||||
return this.callback
|
||||
this.callback
|
||||
.calledWith(null, {
|
||||
'/doc1': {
|
||||
_id: this.doc1._id,
|
||||
|
@ -175,11 +175,11 @@ describe('ProjectEntityHandler', function() {
|
|||
describe('getAllFiles', function() {
|
||||
beforeEach(function() {
|
||||
this.callback = sinon.stub()
|
||||
return this.ProjectEntityHandler.getAllFiles(project_id, this.callback)
|
||||
this.ProjectEntityHandler.getAllFiles(project_id, this.callback)
|
||||
})
|
||||
|
||||
it('should call the callback with the files', function() {
|
||||
return this.callback
|
||||
this.callback
|
||||
.calledWith(null, {
|
||||
'/file1': this.file1,
|
||||
'/folder1/file2': this.file2
|
||||
|
@ -203,7 +203,7 @@ describe('ProjectEntityHandler', function() {
|
|||
}
|
||||
]
|
||||
this.callback = sinon.stub()
|
||||
return this.ProjectEntityHandler.getAllDocPathsFromProject(
|
||||
this.ProjectEntityHandler.getAllDocPathsFromProject(
|
||||
this.project,
|
||||
this.callback
|
||||
)
|
||||
|
@ -213,27 +213,71 @@ describe('ProjectEntityHandler', function() {
|
|||
this.expected = {}
|
||||
this.expected[this.doc1._id] = `/${this.doc1.name}`
|
||||
this.expected[this.doc2._id] = `/folder1/${this.doc2.name}`
|
||||
return this.callback.calledWith(null, this.expected).should.equal(true)
|
||||
this.callback.calledWith(null, this.expected).should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('getDocPathByProjectIdAndDocId', function() {
|
||||
beforeEach(function() {
|
||||
this.callback = sinon.stub()
|
||||
})
|
||||
it('should call the callback with the path for an existing doc id at the root level', function() {
|
||||
this.ProjectEntityHandler.getDocPathByProjectIdAndDocId(
|
||||
project_id,
|
||||
this.doc1._id,
|
||||
this.callback
|
||||
)
|
||||
this.callback.calledWith(null, `/${this.doc1.name}`).should.equal(true)
|
||||
})
|
||||
|
||||
it('should call the callback with the path for an existing doc id nested within a folder', function() {
|
||||
this.ProjectEntityHandler.getDocPathByProjectIdAndDocId(
|
||||
project_id,
|
||||
this.doc2._id,
|
||||
this.callback
|
||||
)
|
||||
this.callback
|
||||
.calledWith(null, `/folder1/${this.doc2.name}`)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should call the callback with a NotFoundError for a non-existing doc', function() {
|
||||
this.ProjectEntityHandler.getDocPathByProjectIdAndDocId(
|
||||
project_id,
|
||||
'non-existing-id',
|
||||
this.callback
|
||||
)
|
||||
expect(this.callback.firstCall.args[0]).to.be.an.instanceof(
|
||||
Errors.NotFoundError
|
||||
)
|
||||
})
|
||||
|
||||
it('should call the callback with a NotFoundError for an existing file', function() {
|
||||
this.ProjectEntityHandler.getDocPathByProjectIdAndDocId(
|
||||
project_id,
|
||||
this.file1._id,
|
||||
this.callback
|
||||
)
|
||||
expect(this.callback.firstCall.args[0]).to.be.an.instanceof(
|
||||
Errors.NotFoundError
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('_getAllFolders', function() {
|
||||
beforeEach(function() {
|
||||
this.callback = sinon.stub()
|
||||
return this.ProjectEntityHandler._getAllFolders(
|
||||
project_id,
|
||||
this.callback
|
||||
)
|
||||
this.ProjectEntityHandler._getAllFolders(project_id, this.callback)
|
||||
})
|
||||
|
||||
it('should get the project without the docs lines', function() {
|
||||
return this.ProjectGetter.getProjectWithoutDocLines
|
||||
this.ProjectGetter.getProjectWithoutDocLines
|
||||
.calledWith(project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should call the callback with the folders', function() {
|
||||
return this.callback
|
||||
this.callback
|
||||
.calledWith(null, {
|
||||
'/': this.project.rootFolder[0],
|
||||
'/folder1': this.folder1
|
||||
|
@ -245,14 +289,14 @@ describe('ProjectEntityHandler', function() {
|
|||
describe('_getAllFoldersFromProject', function() {
|
||||
beforeEach(function() {
|
||||
this.callback = sinon.stub()
|
||||
return this.ProjectEntityHandler._getAllFoldersFromProject(
|
||||
this.ProjectEntityHandler._getAllFoldersFromProject(
|
||||
this.project,
|
||||
this.callback
|
||||
)
|
||||
})
|
||||
|
||||
it('should call the callback with the folders', function() {
|
||||
return this.callback
|
||||
this.callback
|
||||
.calledWith(null, {
|
||||
'/': this.project.rootFolder[0],
|
||||
'/folder1': this.folder1
|
||||
|
@ -286,32 +330,30 @@ describe('ProjectEntityHandler', function() {
|
|||
|
||||
this.ProjectGetter.getProject = sinon.stub().yields(null, this.project)
|
||||
|
||||
return this.ProjectEntityHandler.flushProjectToThirdPartyDataStore(
|
||||
this.ProjectEntityHandler.flushProjectToThirdPartyDataStore(
|
||||
project_id,
|
||||
() => done()
|
||||
)
|
||||
})
|
||||
|
||||
it('should flush the project from the doc updater', function() {
|
||||
return this.DocumentUpdaterHandler.flushProjectToMongo
|
||||
this.DocumentUpdaterHandler.flushProjectToMongo
|
||||
.calledWith(project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should look up the project in mongo', function() {
|
||||
return this.ProjectGetter.getProject
|
||||
.calledWith(project_id)
|
||||
.should.equal(true)
|
||||
this.ProjectGetter.getProject.calledWith(project_id).should.equal(true)
|
||||
})
|
||||
|
||||
it('should get all the docs in the project', function() {
|
||||
return this.ProjectEntityHandler.getAllDocs
|
||||
this.ProjectEntityHandler.getAllDocs
|
||||
.calledWith(project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should get all the files in the project', function() {
|
||||
return this.ProjectEntityHandler.getAllFiles
|
||||
this.ProjectEntityHandler.getAllFiles
|
||||
.calledWith(project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
@ -369,17 +411,17 @@ describe('ProjectEntityHandler', function() {
|
|||
this.DocstoreManager.getDoc = sinon
|
||||
.stub()
|
||||
.callsArgWith(3, null, this.lines, this.rev, this.version, this.ranges)
|
||||
return this.ProjectEntityHandler.getDoc(project_id, doc_id, this.callback)
|
||||
this.ProjectEntityHandler.getDoc(project_id, doc_id, this.callback)
|
||||
})
|
||||
|
||||
it('should call the docstore', function() {
|
||||
return this.DocstoreManager.getDoc
|
||||
this.DocstoreManager.getDoc
|
||||
.calledWith(project_id, doc_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should call the callback with the lines, version and rev', function() {
|
||||
return this.callback
|
||||
this.callback
|
||||
.calledWith(null, this.lines, this.rev, this.version, this.ranges)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
|
|
@ -493,14 +493,50 @@ describe('ProjectEntityUpdateHandler', function() {
|
|||
})
|
||||
|
||||
describe('setRootDoc', function() {
|
||||
it('should call Project.update', function() {
|
||||
const rootDoc_id = 'root-doc-id-123123'
|
||||
beforeEach(function() {
|
||||
this.rootDoc_id = 'root-doc-id-123123'
|
||||
this.callback = sinon.stub()
|
||||
})
|
||||
|
||||
it('should call Project.update when the doc exists and has a valid extension', function() {
|
||||
this.ProjectModel.update = sinon.stub()
|
||||
this.ProjectEntityUpdateHandler.setRootDoc(project_id, rootDoc_id)
|
||||
this.ProjectEntityHandler.getDocPathByProjectIdAndDocId = sinon
|
||||
.stub()
|
||||
.yields(null, `/main.tex`)
|
||||
|
||||
this.ProjectEntityUpdateHandler.setRootDoc(project_id, this.rootDoc_id)
|
||||
return this.ProjectModel.update
|
||||
.calledWith({ _id: project_id }, { rootDoc_id })
|
||||
.calledWith({ _id: project_id }, { rootDoc_id: this.rootDoc_id })
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it("should not call Project.update when the doc doesn't exist", function() {
|
||||
this.ProjectModel.update = sinon.stub()
|
||||
this.ProjectEntityHandler.getDocPathByProjectIdAndDocId = sinon
|
||||
.stub()
|
||||
.yields(Errors.NotFoundError)
|
||||
|
||||
this.ProjectEntityUpdateHandler.setRootDoc(project_id, this.rootDoc_id)
|
||||
return this.ProjectModel.update
|
||||
.calledWith({ _id: project_id }, { rootDoc_id: this.rootDoc_id })
|
||||
.should.equal(false)
|
||||
})
|
||||
|
||||
it('should call the callback with an UnsupportedFileTypeError when the doc has an unaccepted file extension', function() {
|
||||
this.ProjectModel.update = sinon.stub()
|
||||
this.ProjectEntityHandler.getDocPathByProjectIdAndDocId = sinon
|
||||
.stub()
|
||||
.yields(null, `/foo/bar.baz`)
|
||||
|
||||
this.ProjectEntityUpdateHandler.setRootDoc(
|
||||
project_id,
|
||||
this.rootDoc_id,
|
||||
this.callback
|
||||
)
|
||||
return expect(this.callback.firstCall.args[0]).to.be.an.instanceof(
|
||||
Errors.UnsupportedFileTypeError
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('unsetRootDoc', function() {
|
||||
|
|
|
@ -55,6 +55,12 @@ describe('ProjectRootDocManager', function() {
|
|||
})
|
||||
|
||||
describe('setRootDocAutomatically', function() {
|
||||
beforeEach(function() {
|
||||
this.ProjectEntityUpdateHandler.setRootDoc = sinon.stub().callsArgWith(2)
|
||||
this.ProjectEntityUpdateHandler.isPathValidForRootDoc = sinon
|
||||
.stub()
|
||||
.returns(true)
|
||||
})
|
||||
describe('when there is a suitable root doc', function() {
|
||||
beforeEach(function(done) {
|
||||
this.docs = {
|
||||
|
@ -84,14 +90,10 @@ describe('ProjectRootDocManager', function() {
|
|||
lines: ['Hello world']
|
||||
}
|
||||
}
|
||||
|
||||
this.ProjectEntityHandler.getAllDocs = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, this.docs)
|
||||
this.ProjectEntityUpdateHandler.setRootDoc = sinon
|
||||
.stub()
|
||||
.callsArgWith(2)
|
||||
return this.ProjectRootDocManager.setRootDocAutomatically(
|
||||
this.ProjectRootDocManager.setRootDocAutomatically(
|
||||
this.project_id,
|
||||
done
|
||||
)
|
||||
|
@ -125,9 +127,6 @@ describe('ProjectRootDocManager', function() {
|
|||
this.ProjectEntityHandler.getAllDocs = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, this.docs)
|
||||
this.ProjectEntityUpdateHandler.setRootDoc = sinon
|
||||
.stub()
|
||||
.callsArgWith(2)
|
||||
return this.ProjectRootDocManager.setRootDocAutomatically(
|
||||
this.project_id,
|
||||
this.callback
|
||||
|
@ -156,9 +155,6 @@ describe('ProjectRootDocManager', function() {
|
|||
this.ProjectEntityHandler.getAllDocs = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, this.docs)
|
||||
this.ProjectEntityUpdateHandler.setRootDoc = sinon
|
||||
.stub()
|
||||
.callsArgWith(2)
|
||||
return this.ProjectRootDocManager.setRootDocAutomatically(
|
||||
this.project_id,
|
||||
done
|
||||
|
@ -580,6 +576,7 @@ describe('ProjectRootDocManager', function() {
|
|||
.stub()
|
||||
.callsArgWith(2, null, this.project)
|
||||
this.ProjectEntityUpdateHandler.setRootDoc = sinon.stub().yields()
|
||||
this.ProjectEntityUpdateHandler.unsetRootDoc = sinon.stub().yields()
|
||||
this.ProjectEntityHandler.getAllDocPathsFromProjectById = sinon
|
||||
.stub()
|
||||
.callsArgWith(1, null, this.docPaths)
|
||||
|
@ -630,9 +627,9 @@ describe('ProjectRootDocManager', function() {
|
|||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should null the rootDoc_id field', function() {
|
||||
return this.ProjectEntityUpdateHandler.setRootDoc
|
||||
.calledWith(this.project_id, null)
|
||||
it('should unset the root doc', function() {
|
||||
return this.ProjectEntityUpdateHandler.unsetRootDoc
|
||||
.calledWith(this.project_id)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue