| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- should = require('chai').should()
- modulePath = "../../../../app/js/Features/Project/ProjectDetailsHandler"
- Errors = require "../../../../app/js/Features/Errors/Errors"
- SandboxedModule = require('sandboxed-module')
- sinon = require('sinon')
- assert = require("chai").assert
- expect = require("chai").expect
- require('chai').should()
- describe 'ProjectDetailsHandler', ->
- beforeEach ->
- @project_id = "321l3j1kjkjl"
- @user_id = "user-id-123"
- @project =
- name: "project"
- description: "this is a great project"
- something:"should not exist"
- compiler: "latexxxxxx"
- owner_ref: @user_id
- @user =
- features: "mock-features"
- @ProjectGetter =
- getProjectWithoutDocLines: sinon.stub().callsArgWith(1, null, @project)
- getProject: sinon.stub().callsArgWith(2, null, @project)
- @ProjectModel =
- update: sinon.stub()
- findOne: sinon.stub()
- @UserGetter =
- getUser: sinon.stub().callsArgWith(1, null, @user)
- @tpdsUpdateSender =
- moveEntity:sinon.stub().callsArgWith 1
- @handler = SandboxedModule.require modulePath, requires:
- "./ProjectGetter":@ProjectGetter
- '../../models/Project': Project:@ProjectModel
- "../User/UserGetter": @UserGetter
- '../ThirdPartyDataStore/TpdsUpdateSender':@tpdsUpdateSender
- 'logger-sharelatex':
- log:->
- err:->
- './ProjectTokenGenerator': @ProjectTokenGenerator = {}
- describe "getDetails", ->
- it "should find the project and owner", (done)->
- @handler.getDetails @project_id, (err, details)=>
- details.name.should.equal @project.name
- details.description.should.equal @project.description
- details.compiler.should.equal @project.compiler
- details.features.should.equal @user.features
- assert.equal(details.something, undefined)
- done()
- it "should find overleaf metadata if it exists", (done)->
- @project.overleaf = { id: 'id' }
- @handler.getDetails @project_id, (err, details)=>
- details.overleaf.should.equal @project.overleaf
- assert.equal(details.something, undefined)
- done()
- it "should return an error for a non-existent project", (done)->
- @ProjectGetter.getProject.callsArg(2, null, null)
- err = new Errors.NotFoundError("project not found")
- @handler.getDetails "0123456789012345678901234", (error, details) =>
- err.should.eql error
- done()
- it "should return the error", (done)->
- error = "some error"
- @ProjectGetter.getProject.callsArgWith(2, error)
- @handler.getDetails @project_id, (err)=>
- err.should.equal error
- done()
- describe "getProjectDescription", ->
- it "should make a call to mongo just for the description", (done)->
- @ProjectGetter.getProject.callsArgWith(2)
- @handler.getProjectDescription @project_id, (err, description)=>
- @ProjectGetter.getProject
- .calledWith(@project_id, description: true)
- .should.equal true
- done()
- it "should return what the mongo call returns", (done)->
- err = "error"
- description = "cool project"
- @ProjectGetter.getProject.callsArgWith(2, err, {description:description})
- @handler.getProjectDescription @project_id, (returnedErr, returnedDescription)=>
- err.should.equal returnedErr
- description.should.equal returnedDescription
- done()
- describe "setProjectDescription", ->
- beforeEach ->
- @description = "updated teh description"
- it "should update the project detials", (done)->
- @ProjectModel.update.callsArgWith(2)
- @handler.setProjectDescription @project_id, @description, =>
- @ProjectModel.update.calledWith({_id:@project_id}, {description:@description}).should.equal true
- done()
- describe "renameProject", ->
- beforeEach ->
- @handler.validateProjectName = sinon.stub().yields()
- @ProjectModel.update.callsArgWith(2)
- @newName = "new name here"
- it "should update the project with the new name", (done)->
- newName = "new name here"
- @handler.renameProject @project_id, @newName, =>
- @ProjectModel.update.calledWith({_id: @project_id}, {name: @newName}).should.equal true
- done()
- it "should tell the tpdsUpdateSender", (done)->
- @handler.renameProject @project_id, @newName, =>
- @tpdsUpdateSender.moveEntity.calledWith({project_id:@project_id, project_name:@project.name, newProjectName:@newName}).should.equal true
- done()
- it "should not do anything with an invalid name", (done) ->
- @handler.validateProjectName = sinon.stub().yields(new Error("invalid name"))
- @handler.renameProject @project_id, @newName, =>
- @tpdsUpdateSender.moveEntity.called.should.equal false
- @ProjectModel.update.called.should.equal false
- done()
- describe "validateProjectName", ->
- it "should reject undefined names", (done) ->
- @handler.validateProjectName undefined, (error) ->
- expect(error).to.exist
- done()
- it "should reject empty names", (done) ->
- @handler.validateProjectName "", (error) ->
- expect(error).to.exist
- done()
- it "should reject names with /s", (done) ->
- @handler.validateProjectName "foo/bar", (error) ->
- expect(error).to.exist
- done()
- it "should reject names with \\s", (done) ->
- @handler.validateProjectName "foo\\bar", (error) ->
- expect(error).to.exist
- done()
- it "should reject long names", (done) ->
- @handler.validateProjectName new Array(1000).join("a"), (error) ->
- expect(error).to.exist
- done()
- it "should accept normal names", (done) ->
- @handler.validateProjectName "foobar", (error) ->
- expect(error).to.not.exist
- done()
- describe "ensureProjectNameIsUnique", ->
- beforeEach ->
- @result = {
- owned: [{_id: 1, name:"name"}, {_id: 2, name: "name1"}, {_id: 3, name: "name11"}]
- readAndWrite: [{_id: 4, name:"name2"}, {_id: 5, name:"name22"}]
- readOnly: [{_id:6, name:"name3"}, {_id:7, name: "name33"}]
- tokenReadAndWrite: [{_id:8, name:"name4"}, {_id:9, name:"name44"}]
- tokenReadOnly: [{_id:10, name:"name5"}, {_id:11, name:"name55"}, {_id:12, name:"x".repeat(15)}]
- }
- @ProjectGetter.findAllUsersProjects = sinon.stub().callsArgWith(2, null, @result)
- it "should leave a unique name unchanged", (done) ->
- @handler.ensureProjectNameIsUnique @user_id, "unique-name", ["-test-suffix"], (error, name, changed) ->
- expect(name).to.equal "unique-name"
- expect(changed).to.equal false
- done()
- it "should append a suffix to an existing name", (done) ->
- @handler.ensureProjectNameIsUnique @user_id, "name1", ["-test-suffix"], (error, name, changed) ->
- expect(name).to.equal "name1-test-suffix"
- expect(changed).to.equal true
- done()
- it "should fallback to a second suffix when needed", (done) ->
- @handler.ensureProjectNameIsUnique @user_id, "name1", ["1", "-test-suffix"], (error, name, changed) ->
- expect(name).to.equal "name1-test-suffix"
- expect(changed).to.equal true
- done()
- it "should truncate the name when append a suffix if the result is too long", (done) ->
- @handler.MAX_PROJECT_NAME_LENGTH = 20
- @handler.ensureProjectNameIsUnique @user_id, "x".repeat(15), ["-test-suffix"], (error, name, changed) ->
- expect(name).to.equal "x".repeat(8) + "-test-suffix"
- expect(changed).to.equal true
- done()
- it "should return an error if the name cannot be made unique", (done) ->
- @handler.ensureProjectNameIsUnique @user_id, "name", ["1", "5", "55"], (error, name, changed) ->
- expect(error).to.eql new Errors.InvalidNameError("Project name could not be made unique")
- done()
- describe "fixProjectName", ->
- it "should change empty names to Untitled", () ->
- expect(@handler.fixProjectName "").to.equal "Untitled"
- it "should replace / with -", () ->
- expect(@handler.fixProjectName "foo/bar").to.equal "foo-bar"
- it "should replace \\ with ''", () ->
- expect(@handler.fixProjectName "foo \\ bar").to.equal "foo bar"
- it "should truncate long names", () ->
- expect(@handler.fixProjectName new Array(1000).join("a")).to.equal "a".repeat(150)
- it "should accept normal names", () ->
- expect(@handler.fixProjectName "foobar").to.equal "foobar"
- describe "setPublicAccessLevel", ->
- beforeEach ->
- @ProjectModel.update.callsArgWith(2)
- @accessLevel = "readOnly"
- it "should update the project with the new level", (done)->
- @handler.setPublicAccessLevel @project_id, @accessLevel, =>
- @ProjectModel.update.calledWith({_id: @project_id}, {publicAccesLevel: @accessLevel}).should.equal true
- done()
- it 'should not produce an error', (done) ->
- @handler.setPublicAccessLevel @project_id, @accessLevel, (err) =>
- expect(err).to.not.exist
- done()
- describe 'when update produces an error', ->
- beforeEach ->
- @ProjectModel.update.callsArgWith(2, new Error('woops'))
- it 'should produce an error', (done) ->
- @handler.setPublicAccessLevel @project_id, @accessLevel, (err) =>
- expect(err).to.exist
- expect(err).to.be.instanceof Error
- done()
- describe "ensureTokensArePresent", ->
- beforeEach ->
- describe 'when the project has tokens', ->
- beforeEach ->
- @project =
- _id: @project_id
- tokens:
- readOnly: 'aaa'
- readAndWrite: '42bbb'
- @ProjectGetter.getProject = sinon.stub()
- .callsArgWith(2, null, @project)
- @ProjectModel.update = sinon.stub()
- it 'should get the project', (done) ->
- @handler.ensureTokensArePresent @project_id, (err, tokens) =>
- expect(@ProjectGetter.getProject.callCount).to.equal 1
- expect(@ProjectGetter.getProject.calledWith(@project_id, {tokens: 1}))
- .to.equal true
- done()
- it 'should not update the project with new tokens', (done) ->
- @handler.ensureTokensArePresent @project_id, (err, tokens) =>
- expect(@ProjectModel.update.callCount).to.equal 0
- done()
- it 'should produce the tokens without error', (done) ->
- @handler.ensureTokensArePresent @project_id, (err, tokens) =>
- expect(err).to.not.exist
- expect(tokens).to.deep.equal @project.tokens
- done()
- describe 'when tokens are missing', ->
- beforeEach ->
- @project =
- _id: @project_id
- @ProjectGetter.getProject = sinon.stub()
- .callsArgWith(2, null, @project)
- @readOnlyToken = 'abc'
- @readAndWriteToken = '42def'
- @ProjectTokenGenerator.readOnlyToken = sinon.stub().returns(@readOnlyToken)
- @ProjectTokenGenerator.readAndWriteToken = sinon.stub().returns(@readAndWriteToken)
- @ProjectModel.update = sinon.stub()
- .callsArgWith(2, null)
- it 'should get the project', (done) ->
- @handler.ensureTokensArePresent @project_id, (err, tokens) =>
- expect(@ProjectGetter.getProject.callCount).to.equal 1
- expect(@ProjectGetter.getProject.calledWith(@project_id, {tokens: 1}))
- .to.equal true
- done()
- it 'should update the project with new tokens', (done) ->
- @handler.ensureTokensArePresent @project_id, (err, tokens) =>
- expect(@ProjectTokenGenerator.readOnlyToken.callCount)
- .to.equal 1
- expect(@ProjectTokenGenerator.readAndWriteToken.callCount)
- .to.equal 1
- expect(@ProjectModel.update.callCount).to.equal 1
- expect(@ProjectModel.update.calledWith(
- {_id: @project_id},
- {$set: {tokens: {readOnly: @readOnlyToken, readAndWrite: @readAndWriteToken}}}
- )).to.equal true
- done()
- it 'should produce the tokens without error', (done) ->
- @handler.ensureTokensArePresent @project_id, (err, tokens) =>
- expect(err).to.not.exist
- expect(tokens).to.deep.equal {
- readOnly: @readOnlyToken,
- readAndWrite: @readAndWriteToken
- }
- done()
|