2014-02-12 05:23:40 -05:00
|
|
|
spies = require('chai-spies')
|
|
|
|
chai = require('chai').use(spies)
|
|
|
|
sinon = require("sinon")
|
|
|
|
should = chai.should()
|
2016-01-14 11:35:42 -05:00
|
|
|
expect = chai.expect
|
2014-02-12 05:23:40 -05:00
|
|
|
modulePath = "../../../../app/js/Features/Project/ProjectCreationHandler.js"
|
|
|
|
SandboxedModule = require('sandboxed-module')
|
|
|
|
Settings = require('settings-sharelatex')
|
|
|
|
Path = require "path"
|
2014-03-06 07:28:07 -05:00
|
|
|
_ = require("underscore")
|
2014-02-12 05:23:40 -05:00
|
|
|
|
|
|
|
describe 'ProjectCreationHandler', ->
|
|
|
|
ownerId = '4eecb1c1bffa66588e0000a1'
|
2014-03-06 07:28:07 -05:00
|
|
|
projectName = 'project name goes here'
|
2014-02-12 05:23:40 -05:00
|
|
|
project_id = "4eecaffcbffa66588e000008"
|
|
|
|
docId = '4eecb17ebffa66588e00003f'
|
|
|
|
rootFolderId = "234adfa3r2afe"
|
|
|
|
|
|
|
|
beforeEach ->
|
|
|
|
@ProjectModel = class Project
|
|
|
|
constructor:(options = {})->
|
|
|
|
@._id = project_id
|
|
|
|
@owner_ref = options.owner_ref
|
|
|
|
@name = options.name
|
2017-10-27 10:24:18 -04:00
|
|
|
@overleaf =
|
|
|
|
history: {}
|
2014-02-12 05:23:40 -05:00
|
|
|
save: sinon.stub().callsArg(0)
|
|
|
|
rootFolder:[{
|
|
|
|
_id: rootFolderId
|
|
|
|
docs: []
|
|
|
|
}]
|
|
|
|
@FolderModel = class Folder
|
|
|
|
constructor:(options)->
|
|
|
|
{@name} = options
|
2018-02-01 10:31:42 -05:00
|
|
|
@ProjectEntityUpdateHandler =
|
2017-11-23 10:18:43 -05:00
|
|
|
addDoc: sinon.stub().callsArgWith(5, null, {_id: docId})
|
2018-02-20 07:52:57 -05:00
|
|
|
addFile: sinon.stub().callsArg(6)
|
2014-02-12 05:23:40 -05:00
|
|
|
setRootDoc: sinon.stub().callsArg(2)
|
2017-05-19 11:21:02 -04:00
|
|
|
@ProjectDetailsHandler =
|
|
|
|
validateProjectName: sinon.stub().yields()
|
2017-12-18 11:39:27 -05:00
|
|
|
@HistoryManager =
|
2017-10-24 06:48:21 -04:00
|
|
|
initializeProject: sinon.stub().callsArg(0)
|
2014-02-12 05:23:40 -05:00
|
|
|
|
2017-10-24 06:48:21 -04:00
|
|
|
@user =
|
2014-02-12 05:23:40 -05:00
|
|
|
first_name:"first name here"
|
|
|
|
last_name:"last name here"
|
2017-10-24 06:48:21 -04:00
|
|
|
ace:
|
2014-02-12 05:23:40 -05:00
|
|
|
spellCheckLanguage:"de"
|
|
|
|
|
|
|
|
@User = findById:sinon.stub().callsArgWith(2, null, @user)
|
|
|
|
@callback = sinon.stub()
|
2018-01-03 11:29:28 -05:00
|
|
|
|
|
|
|
@Settings = apis: { project_history: {} }
|
|
|
|
|
2018-03-12 06:50:15 -04:00
|
|
|
@AnalyticsManager = recordEvent: sinon.stub()
|
2018-02-22 16:22:55 -05:00
|
|
|
|
2014-02-12 05:23:40 -05:00
|
|
|
@handler = SandboxedModule.require modulePath, requires:
|
|
|
|
'../../models/User': User:@User
|
|
|
|
'../../models/Project':{Project:@ProjectModel}
|
|
|
|
'../../models/Folder':{Folder:@FolderModel}
|
2017-12-18 11:39:27 -05:00
|
|
|
'../History/HistoryManager': @HistoryManager
|
2018-02-01 10:31:42 -05:00
|
|
|
'./ProjectEntityUpdateHandler':@ProjectEntityUpdateHandler
|
2017-05-19 11:21:02 -04:00
|
|
|
"./ProjectDetailsHandler":@ProjectDetailsHandler
|
2018-01-03 11:29:28 -05:00
|
|
|
"settings-sharelatex": @Settings
|
2018-03-12 06:50:15 -04:00
|
|
|
"../Analytics/AnalyticsManager": @AnalyticsManager
|
2014-02-12 05:23:40 -05:00
|
|
|
'logger-sharelatex': {log:->}
|
2017-04-03 11:18:30 -04:00
|
|
|
"metrics-sharelatex": {
|
2017-03-17 10:55:41 -04:00
|
|
|
inc: ()->,
|
|
|
|
timeAsyncMethod: ()->
|
|
|
|
}
|
2014-02-12 05:23:40 -05:00
|
|
|
|
|
|
|
describe 'Creating a Blank project', ->
|
|
|
|
beforeEach ->
|
2017-10-27 09:56:16 -04:00
|
|
|
@overleaf_id = 1234
|
2017-12-18 11:39:27 -05:00
|
|
|
@HistoryManager.initializeProject = sinon.stub().callsArgWith(0, null, { @overleaf_id })
|
2014-02-12 05:23:40 -05:00
|
|
|
@ProjectModel::save = sinon.stub().callsArg(0)
|
|
|
|
|
|
|
|
describe "successfully", ->
|
|
|
|
it "should save the project", (done)->
|
|
|
|
@handler.createBlankProject ownerId, projectName, =>
|
|
|
|
@ProjectModel::save.called.should.equal true
|
|
|
|
done()
|
2017-10-24 06:48:21 -04:00
|
|
|
|
2014-02-12 05:23:40 -05:00
|
|
|
it "should return the project in the callback", (done)->
|
|
|
|
@handler.createBlankProject ownerId, projectName, (err, project)->
|
|
|
|
project.name.should.equal projectName
|
|
|
|
(project.owner_ref + "").should.equal ownerId
|
|
|
|
done()
|
|
|
|
|
2017-10-27 09:56:16 -04:00
|
|
|
it "should initialize the project overleaf if history id not provided", (done)->
|
2017-10-24 06:48:21 -04:00
|
|
|
@handler.createBlankProject ownerId, projectName, done
|
2017-12-18 11:39:27 -05:00
|
|
|
@HistoryManager.initializeProject.calledWith().should.equal true
|
2017-10-24 06:48:21 -04:00
|
|
|
|
2017-10-27 09:56:16 -04:00
|
|
|
it "should set the overleaf id if overleaf id not provided", (done)->
|
|
|
|
@handler.createBlankProject ownerId, projectName, (err, project)=>
|
2017-10-27 10:24:18 -04:00
|
|
|
project.overleaf.history.id.should.equal @overleaf_id
|
2017-10-27 09:56:16 -04:00
|
|
|
done()
|
|
|
|
|
|
|
|
it "should set the overleaf id if overleaf id provided", (done)->
|
|
|
|
overleaf_id = 2345
|
2018-05-10 06:39:23 -04:00
|
|
|
attributes =
|
|
|
|
overleaf:
|
|
|
|
history:
|
|
|
|
id: overleaf_id
|
|
|
|
@handler.createBlankProject ownerId, projectName, attributes, (err, project)->
|
2017-10-27 10:24:18 -04:00
|
|
|
project.overleaf.history.id.should.equal overleaf_id
|
2017-10-24 06:48:21 -04:00
|
|
|
done()
|
|
|
|
|
2014-02-12 05:23:40 -05:00
|
|
|
it "should set the language from the user", (done)->
|
|
|
|
@handler.createBlankProject ownerId, projectName, (err, project)->
|
|
|
|
project.spellCheckLanguage.should.equal "de"
|
|
|
|
done()
|
2017-10-24 06:48:21 -04:00
|
|
|
|
2018-08-06 11:56:44 -04:00
|
|
|
it "should set the imageName to currentImageName if set and no imageName attribute", (done) ->
|
2016-01-14 11:35:42 -05:00
|
|
|
@Settings.currentImageName = "mock-image-name"
|
|
|
|
@handler.createBlankProject ownerId, projectName, (err, project)=>
|
|
|
|
project.imageName.should.equal @Settings.currentImageName
|
|
|
|
done()
|
2017-10-24 06:48:21 -04:00
|
|
|
|
2016-01-14 11:35:42 -05:00
|
|
|
it "should not set the imageName if no currentImageName", (done) ->
|
|
|
|
@Settings.currentImageName = null
|
|
|
|
@handler.createBlankProject ownerId, projectName, (err, project)=>
|
|
|
|
expect(project.imageName).to.not.exist
|
|
|
|
done()
|
2014-02-12 05:23:40 -05:00
|
|
|
|
2018-08-06 11:56:44 -04:00
|
|
|
it "should set the imageName to the attribute value if set and not overwrite it with the currentImageName", (done) ->
|
|
|
|
@Settings.currentImageName = "mock-image-name"
|
|
|
|
attributes =
|
|
|
|
imageName: "attribute-image-name"
|
|
|
|
@handler.createBlankProject ownerId, projectName, attributes, (err, project)=>
|
|
|
|
project.imageName.should.equal attributes.imageName
|
|
|
|
done()
|
|
|
|
|
2018-01-03 11:29:28 -05:00
|
|
|
it "should not set the overleaf.history.display if not configured in settings", (done) ->
|
|
|
|
@Settings.apis.project_history.displayHistoryForNewProjects = false
|
|
|
|
@handler.createBlankProject ownerId, projectName, (err, project)=>
|
|
|
|
expect(project.overleaf.history.display).to.not.exist
|
|
|
|
done()
|
|
|
|
|
|
|
|
it "should set the overleaf.history.display if configured in settings", (done) ->
|
|
|
|
@Settings.apis.project_history.displayHistoryForNewProjects = true
|
|
|
|
@handler.createBlankProject ownerId, projectName, (err, project)=>
|
|
|
|
expect(project.overleaf.history.display).to.equal true
|
|
|
|
done()
|
|
|
|
|
2018-03-12 06:50:15 -04:00
|
|
|
it "should send a project-created event to analytics", (done) ->
|
|
|
|
@handler.createBlankProject ownerId, projectName, (err, project) =>
|
|
|
|
expect(@AnalyticsManager.recordEvent.callCount).to.equal 1
|
|
|
|
expect(
|
|
|
|
@AnalyticsManager.recordEvent.calledWith(ownerId, 'project-created')
|
|
|
|
).to.equal true
|
|
|
|
done()
|
|
|
|
|
|
|
|
it "should send a project-imported event when importing a project", (done) ->
|
|
|
|
@handler.createBlankProject ownerId, projectName, 1234, (err, project) =>
|
|
|
|
expect(@AnalyticsManager.recordEvent.callCount).to.equal 1
|
|
|
|
expect(
|
|
|
|
@AnalyticsManager.recordEvent.calledWith(ownerId, 'project-imported')
|
|
|
|
).to.equal true
|
|
|
|
done()
|
|
|
|
|
|
|
|
|
2014-02-12 05:23:40 -05:00
|
|
|
describe "with an error", ->
|
|
|
|
beforeEach ->
|
|
|
|
@ProjectModel::save = sinon.stub().callsArgWith(0, new Error("something went wrong"))
|
|
|
|
@handler.createBlankProject ownerId, projectName, @callback
|
2017-10-24 06:48:21 -04:00
|
|
|
|
2014-02-12 05:23:40 -05:00
|
|
|
it 'should return the error to the callback', ->
|
|
|
|
should.exist @callback.args[0][0]
|
2017-10-24 06:48:21 -04:00
|
|
|
|
2017-05-19 11:21:02 -04:00
|
|
|
describe "with an invalid name", ->
|
|
|
|
beforeEach ->
|
|
|
|
@ProjectDetailsHandler.validateProjectName = sinon.stub().yields(new Error("bad name"))
|
|
|
|
@handler.createBlankProject ownerId, projectName, @callback
|
2017-10-24 06:48:21 -04:00
|
|
|
|
2017-05-19 11:21:02 -04:00
|
|
|
it 'should return the error to the callback', ->
|
|
|
|
should.exist @callback.args[0][0]
|
2017-10-24 06:48:21 -04:00
|
|
|
|
2017-05-19 11:21:02 -04:00
|
|
|
it 'should not try to create the project', ->
|
|
|
|
@ProjectModel::save.called.should.equal false
|
2017-10-24 06:48:21 -04:00
|
|
|
|
2014-02-12 05:23:40 -05:00
|
|
|
|
|
|
|
describe 'Creating a basic project', ->
|
|
|
|
beforeEach ->
|
|
|
|
@project = new @ProjectModel()
|
|
|
|
@handler._buildTemplate = (template_name, user, project_name, callback) ->
|
|
|
|
if template_name == "mainbasic.tex"
|
|
|
|
return callback(null, ["mainbasic.tex", "lines"])
|
|
|
|
throw new Error("unknown template: #{template_name}")
|
|
|
|
sinon.spy @handler, "_buildTemplate"
|
|
|
|
@handler.createBlankProject = sinon.stub().callsArgWith(2, null, @project)
|
|
|
|
@handler.createBasicProject(ownerId, projectName, @callback)
|
|
|
|
|
|
|
|
it "should create a blank project first", ->
|
|
|
|
@handler.createBlankProject.calledWith(ownerId, projectName)
|
|
|
|
.should.equal true
|
|
|
|
|
|
|
|
it 'should insert main.tex', ->
|
2018-02-01 10:31:42 -05:00
|
|
|
@ProjectEntityUpdateHandler.addDoc.calledWith(project_id, rootFolderId, "main.tex", ["mainbasic.tex", "lines"], ownerId)
|
2014-02-12 05:23:40 -05:00
|
|
|
.should.equal true
|
|
|
|
|
|
|
|
it 'should set the main doc id', ->
|
2018-02-01 10:31:42 -05:00
|
|
|
@ProjectEntityUpdateHandler.setRootDoc.calledWith(project_id, docId).should.equal true
|
2014-02-12 05:23:40 -05:00
|
|
|
|
|
|
|
it 'should build the mainbasic.tex template', ->
|
|
|
|
@handler._buildTemplate
|
|
|
|
.calledWith("mainbasic.tex", ownerId, projectName)
|
|
|
|
.should.equal true
|
|
|
|
|
|
|
|
|
|
|
|
describe 'Creating an example project', ->
|
|
|
|
beforeEach ->
|
|
|
|
@project = new @ProjectModel()
|
|
|
|
@handler._buildTemplate = (template_name, user, project_name, callback) ->
|
|
|
|
if template_name == "main.tex"
|
|
|
|
return callback(null, ["main.tex", "lines"])
|
|
|
|
if template_name == "references.bib"
|
|
|
|
return callback(null, ["references.bib", "lines"])
|
|
|
|
throw new Error("unknown template: #{template_name}")
|
|
|
|
sinon.spy @handler, "_buildTemplate"
|
|
|
|
@handler.createBlankProject = sinon.stub().callsArgWith(2, null, @project)
|
|
|
|
@handler.createExampleProject(ownerId, projectName, @callback)
|
|
|
|
|
|
|
|
it "should create a blank project first", ->
|
|
|
|
@handler.createBlankProject.calledWith(ownerId, projectName)
|
|
|
|
.should.equal true
|
|
|
|
|
|
|
|
it 'should insert main.tex', ->
|
2018-02-01 10:31:42 -05:00
|
|
|
@ProjectEntityUpdateHandler.addDoc
|
2017-11-23 10:18:43 -05:00
|
|
|
.calledWith(project_id, rootFolderId, "main.tex", ["main.tex", "lines"], ownerId)
|
2014-02-12 05:23:40 -05:00
|
|
|
.should.equal true
|
|
|
|
|
|
|
|
it 'should insert references.bib', ->
|
2018-02-01 10:31:42 -05:00
|
|
|
@ProjectEntityUpdateHandler.addDoc
|
2017-11-23 10:18:43 -05:00
|
|
|
.calledWith(project_id, rootFolderId, "references.bib", ["references.bib", "lines"], ownerId)
|
2014-02-12 05:23:40 -05:00
|
|
|
.should.equal true
|
|
|
|
|
|
|
|
it 'should insert universe.jpg', ->
|
2018-02-01 10:31:42 -05:00
|
|
|
@ProjectEntityUpdateHandler.addFile
|
2014-02-12 05:23:40 -05:00
|
|
|
.calledWith(
|
|
|
|
project_id, rootFolderId, "universe.jpg",
|
2017-11-13 06:16:54 -05:00
|
|
|
Path.resolve(__dirname + "/../../../../app/templates/project_files/universe.jpg"),
|
2018-02-20 07:52:57 -05:00
|
|
|
null,
|
2017-11-13 06:16:54 -05:00
|
|
|
ownerId
|
2014-02-12 05:23:40 -05:00
|
|
|
)
|
|
|
|
.should.equal true
|
|
|
|
|
|
|
|
it 'should set the main doc id', ->
|
2018-02-01 10:31:42 -05:00
|
|
|
@ProjectEntityUpdateHandler.setRootDoc.calledWith(project_id, docId).should.equal true
|
2014-02-12 05:23:40 -05:00
|
|
|
|
|
|
|
it 'should build the main.tex template', ->
|
|
|
|
@handler._buildTemplate
|
|
|
|
.calledWith("main.tex", ownerId, projectName)
|
|
|
|
.should.equal true
|
|
|
|
|
|
|
|
it 'should build the references.bib template', ->
|
|
|
|
@handler._buildTemplate
|
|
|
|
.calledWith("references.bib", ownerId, projectName)
|
|
|
|
.should.equal true
|
2014-03-06 07:28:07 -05:00
|
|
|
|
|
|
|
|
|
|
|
describe "_buildTemplate", ->
|
|
|
|
|
|
|
|
beforeEach (done)->
|
|
|
|
@handler._buildTemplate "main.tex", @user_id, projectName, (err, templateLines)=>
|
|
|
|
@template = templateLines.reduce (singleLine, line)-> "#{singleLine}\n#{line}"
|
|
|
|
done()
|
|
|
|
|
|
|
|
it "should insert the project name into the template", (done)->
|
|
|
|
@template.indexOf(projectName).should.not.equal -1
|
|
|
|
done()
|
|
|
|
|
|
|
|
it "should insert the users name into the template", (done)->
|
|
|
|
@template.indexOf(@user.first_name).should.not.equal -1
|
|
|
|
@template.indexOf(@user.last_name).should.not.equal -1
|
|
|
|
done()
|
|
|
|
|
|
|
|
it "should not have undefined in the template", (done)->
|
|
|
|
@template.indexOf("undefined").should.equal -1
|
|
|
|
done()
|
|
|
|
|
|
|
|
it "should not have any underscore brackets in the output", (done)->
|
|
|
|
@template.indexOf("{{").should.equal -1
|
|
|
|
@template.indexOf("<%=").should.equal -1
|
|
|
|
done()
|
|
|
|
|
|
|
|
it "should put the year in", (done)->
|
|
|
|
@template.indexOf(new Date().getUTCFullYear()).should.not.equal -1
|
|
|
|
done()
|