| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453 |
- const sinon = require('sinon')
- const { expect } = require('chai')
- const modulePath = '../../../../app/src/Features/Project/ProjectGetter.js'
- const SandboxedModule = require('sandboxed-module')
- const { ObjectId } = require('mongodb-legacy')
- describe('ProjectGetter', function () {
- beforeEach(function () {
- this.project = { _id: new ObjectId() }
- this.projectIdStr = this.project._id.toString()
- this.deletedProject = { deleterData: { wombat: 'potato' } }
- this.userId = new ObjectId()
- this.DeletedProject = {
- find: sinon.stub().returns({
- exec: sinon.stub().resolves([this.deletedProject]),
- }),
- }
- this.Project = {
- find: sinon.stub().returns({
- exec: sinon.stub().resolves(),
- }),
- findOne: sinon.stub().returns({
- exec: sinon.stub().resolves(this.project),
- }),
- }
- this.CollaboratorsGetter = {
- promises: {
- getProjectsUserIsMemberOf: sinon.stub().resolves({
- readAndWrite: [],
- readOnly: [],
- tokenReadAndWrite: [],
- tokenReadOnly: [],
- }),
- },
- }
- this.LockManager = {
- promises: {
- runWithLock: sinon
- .stub()
- .callsFake((namespace, id, runner) => runner()),
- },
- }
- this.db = {
- projects: {
- findOne: sinon.stub().resolves(this.project),
- },
- users: {},
- }
- this.ProjectEntityMongoUpdateHandler = {
- lockKey: sinon.stub().returnsArg(0),
- }
- this.ProjectGetter = SandboxedModule.require(modulePath, {
- requires: {
- '../../infrastructure/mongodb': { db: this.db, ObjectId },
- '../../models/Project': {
- Project: this.Project,
- },
- '../../models/DeletedProject': {
- DeletedProject: this.DeletedProject,
- },
- '../Collaborators/CollaboratorsGetter': this.CollaboratorsGetter,
- '../../infrastructure/LockManager': this.LockManager,
- './ProjectEntityMongoUpdateHandler':
- this.ProjectEntityMongoUpdateHandler,
- },
- })
- })
- describe('getProjectWithoutDocLines', function () {
- beforeEach(function () {
- this.ProjectGetter.promises.getProject = sinon.stub().resolves()
- })
- describe('passing an id', function () {
- beforeEach(async function () {
- await this.ProjectGetter.promises.getProjectWithoutDocLines(
- this.project._id
- )
- })
- it('should call find with the project id', function () {
- this.ProjectGetter.promises.getProject
- .calledWith(this.project._id)
- .should.equal(true)
- })
- it('should exclude the doc lines', function () {
- const excludes = {
- 'rootFolder.docs.lines': 0,
- 'rootFolder.folders.docs.lines': 0,
- 'rootFolder.folders.folders.docs.lines': 0,
- 'rootFolder.folders.folders.folders.docs.lines': 0,
- 'rootFolder.folders.folders.folders.folders.docs.lines': 0,
- 'rootFolder.folders.folders.folders.folders.folders.docs.lines': 0,
- 'rootFolder.folders.folders.folders.folders.folders.folders.docs.lines': 0,
- 'rootFolder.folders.folders.folders.folders.folders.folders.folders.docs.lines': 0,
- }
- this.ProjectGetter.promises.getProject
- .calledWith(this.project._id, excludes)
- .should.equal(true)
- })
- })
- })
- describe('getProjectWithOnlyFolders', function () {
- beforeEach(function () {
- this.ProjectGetter.promises.getProject = sinon.stub().resolves()
- })
- describe('passing an id', function () {
- beforeEach(async function () {
- await this.ProjectGetter.promises.getProjectWithOnlyFolders(
- this.project._id
- )
- })
- it('should call find with the project id', function () {
- this.ProjectGetter.promises.getProject
- .calledWith(this.project._id)
- .should.equal(true)
- })
- it('should exclude the docs and files lines', function () {
- const excludes = {
- 'rootFolder.docs': 0,
- 'rootFolder.fileRefs': 0,
- 'rootFolder.folders.docs': 0,
- 'rootFolder.folders.fileRefs': 0,
- 'rootFolder.folders.folders.docs': 0,
- 'rootFolder.folders.folders.fileRefs': 0,
- 'rootFolder.folders.folders.folders.docs': 0,
- 'rootFolder.folders.folders.folders.fileRefs': 0,
- 'rootFolder.folders.folders.folders.folders.docs': 0,
- 'rootFolder.folders.folders.folders.folders.fileRefs': 0,
- 'rootFolder.folders.folders.folders.folders.folders.docs': 0,
- 'rootFolder.folders.folders.folders.folders.folders.fileRefs': 0,
- 'rootFolder.folders.folders.folders.folders.folders.folders.docs': 0,
- 'rootFolder.folders.folders.folders.folders.folders.folders.fileRefs': 0,
- 'rootFolder.folders.folders.folders.folders.folders.folders.folders.docs': 0,
- 'rootFolder.folders.folders.folders.folders.folders.folders.folders.fileRefs': 0,
- }
- this.ProjectGetter.promises.getProject
- .calledWith(this.project._id, excludes)
- .should.equal(true)
- })
- })
- })
- describe('getProject', function () {
- describe('without projection', function () {
- describe('with project id', function () {
- beforeEach(async function () {
- await this.ProjectGetter.promises.getProject(this.projectIdStr)
- })
- it('should call findOne with the project id', function () {
- expect(this.db.projects.findOne.callCount).to.equal(1)
- expect(
- this.db.projects.findOne.lastCall.args[0]._id.toString()
- ).to.equal(this.projectIdStr)
- })
- })
- describe('without project id', function () {
- it('should be rejected', function () {
- expect(
- this.ProjectGetter.promises.getProject(null)
- ).to.be.rejectedWith('no project id provided')
- expect(this.db.projects.findOne.callCount).to.equal(0)
- })
- })
- })
- describe('with projection', function () {
- beforeEach(function () {
- this.projection = { _id: 1 }
- })
- describe('with project id', function () {
- beforeEach(async function () {
- await this.ProjectGetter.promises.getProject(
- this.projectIdStr,
- this.projection
- )
- })
- it('should call findOne with the project id', function () {
- expect(this.db.projects.findOne.callCount).to.equal(1)
- expect(
- this.db.projects.findOne.lastCall.args[0]._id.toString()
- ).to.equal(this.projectIdStr)
- expect(this.db.projects.findOne.lastCall.args[1]).to.deep.equal({
- projection: this.projection,
- })
- })
- })
- describe('without project id', function () {
- it('should be rejected', function () {
- expect(
- this.ProjectGetter.promises.getProject(null)
- ).to.be.rejectedWith('no project id provided')
- expect(this.db.projects.findOne.callCount).to.equal(0)
- })
- })
- })
- })
- describe('getProjectWithoutLock', function () {
- describe('without projection', function () {
- describe('with project id', function () {
- beforeEach(async function () {
- await this.ProjectGetter.promises.getProjectWithoutLock(
- this.projectIdStr
- )
- })
- it('should call findOne with the project id', function () {
- expect(this.db.projects.findOne.callCount).to.equal(1)
- expect(
- this.db.projects.findOne.lastCall.args[0]._id.toString()
- ).to.equal(this.projectIdStr)
- })
- })
- describe('without project id', function () {
- it('should be rejected', function () {
- expect(
- this.ProjectGetter.promises.getProjectWithoutLock(null)
- ).to.be.rejectedWith('no project id provided')
- expect(this.db.projects.findOne.callCount).to.equal(0)
- })
- })
- })
- describe('with projection', function () {
- beforeEach(function () {
- this.projection = { _id: 1 }
- })
- describe('with project id', function () {
- beforeEach(async function () {
- await this.ProjectGetter.promises.getProjectWithoutLock(
- this.project._id,
- this.projection
- )
- })
- it('should call findOne with the project id', function () {
- expect(this.db.projects.findOne.callCount).to.equal(1)
- expect(
- this.db.projects.findOne.lastCall.args[0]._id.toString()
- ).to.equal(this.projectIdStr)
- expect(this.db.projects.findOne.lastCall.args[1]).to.deep.equal({
- projection: this.projection,
- })
- })
- })
- describe('without project id', function () {
- it('should be rejected', function () {
- expect(
- this.ProjectGetter.promises.getProjectWithoutLock(null)
- ).to.be.rejectedWith('no project id provided')
- expect(this.db.projects.findOne.callCount).to.equal(0)
- })
- })
- })
- })
- describe('findAllUsersProjects', function () {
- beforeEach(function () {
- this.fields = { mock: 'fields' }
- this.projectOwned = { _id: 'mock-owned-projects' }
- this.projectRW = { _id: 'mock-rw-projects' }
- this.projectReview = { _id: 'mock-review-projects' }
- this.projectRO = { _id: 'mock-ro-projects' }
- this.projectTokenRW = { _id: 'mock-token-rw-projects' }
- this.projectTokenRO = { _id: 'mock-token-ro-projects' }
- this.Project.find
- .withArgs({ owner_ref: this.userId }, this.fields)
- .returns({ exec: sinon.stub().resolves([this.projectOwned]) })
- })
- it('should return a promise with all the projects', async function () {
- this.CollaboratorsGetter.promises.getProjectsUserIsMemberOf.resolves({
- readAndWrite: [this.projectRW],
- readOnly: [this.projectRO],
- tokenReadAndWrite: [this.projectTokenRW],
- tokenReadOnly: [this.projectTokenRO],
- review: [this.projectReview],
- })
- const projects = await this.ProjectGetter.promises.findAllUsersProjects(
- this.userId,
- this.fields
- )
- expect(projects).to.deep.equal({
- owned: [this.projectOwned],
- readAndWrite: [this.projectRW],
- readOnly: [this.projectRO],
- tokenReadAndWrite: [this.projectTokenRW],
- tokenReadOnly: [this.projectTokenRO],
- review: [this.projectReview],
- })
- })
- it('should remove duplicate projects', async function () {
- this.CollaboratorsGetter.promises.getProjectsUserIsMemberOf.resolves({
- readAndWrite: [this.projectRW, this.projectOwned],
- readOnly: [this.projectRO, this.projectRW],
- tokenReadAndWrite: [this.projectTokenRW, this.projectRO],
- tokenReadOnly: [
- this.projectTokenRW,
- this.projectTokenRO,
- this.projectRO,
- ],
- review: [this.projectReview],
- })
- const projects = await this.ProjectGetter.promises.findAllUsersProjects(
- this.userId,
- this.fields
- )
- expect(projects).to.deep.equal({
- owned: [this.projectOwned],
- readAndWrite: [this.projectRW],
- readOnly: [this.projectRO],
- tokenReadAndWrite: [this.projectTokenRW],
- tokenReadOnly: [this.projectTokenRO],
- review: [this.projectReview],
- })
- })
- })
- describe('getProjectIdByReadAndWriteToken', function () {
- describe('when project find returns project', function () {
- this.beforeEach(async function () {
- this.projectIdFound =
- await this.ProjectGetter.promises.getProjectIdByReadAndWriteToken(
- 'token'
- )
- })
- it('should find project with token', function () {
- this.Project.findOne
- .calledWithMatch({ 'tokens.readAndWrite': 'token' })
- .should.equal(true)
- })
- it('should return the project id', function () {
- expect(this.projectIdFound).to.equal(this.project._id)
- })
- })
- describe('when project not found', function () {
- it('should return undefined', async function () {
- this.Project.findOne.returns({ exec: sinon.stub().resolves(null) })
- const projectId =
- await this.ProjectGetter.promises.getProjectIdByReadAndWriteToken(
- 'token'
- )
- expect(projectId).to.equal(undefined)
- })
- })
- describe('when project find returns error', function () {
- this.beforeEach(async function () {
- this.Project.findOne.returns({ exec: sinon.stub().rejects() })
- })
- it('should be rejected', function () {
- expect(
- this.ProjectGetter.promises.getProjectIdByReadAndWriteToken('token')
- ).to.be.rejected
- })
- })
- })
- describe('findUsersProjectsByName', function () {
- it('should perform a case-insensitive search', async function () {
- this.project1 = { _id: 1, name: 'find me!' }
- this.project2 = { _id: 2, name: 'not me!' }
- this.project3 = { _id: 3, name: 'FIND ME!' }
- this.project4 = { _id: 4, name: 'Find Me!' }
- this.Project.find.withArgs({ owner_ref: this.userId }).returns({
- exec: sinon
- .stub()
- .resolves([
- this.project1,
- this.project2,
- this.project3,
- this.project4,
- ]),
- })
- const projects =
- await this.ProjectGetter.promises.findUsersProjectsByName(
- this.userId,
- this.project1.name
- )
- const projectNames = projects.map(project => project.name)
- expect(projectNames).to.have.members([
- this.project1.name,
- this.project3.name,
- this.project4.name,
- ])
- })
- it('should search collaborations as well', async function () {
- this.project1 = { _id: 1, name: 'find me!' }
- this.project2 = { _id: 2, name: 'FIND ME!' }
- this.project3 = { _id: 3, name: 'Find Me!' }
- this.project4 = { _id: 4, name: 'find ME!' }
- this.project5 = { _id: 5, name: 'FIND me!' }
- this.Project.find
- .withArgs({ owner_ref: this.userId })
- .returns({ exec: sinon.stub().resolves([this.project1]) })
- this.CollaboratorsGetter.promises.getProjectsUserIsMemberOf.resolves({
- readAndWrite: [this.project2],
- readOnly: [this.project3],
- tokenReadAndWrite: [this.project4],
- tokenReadOnly: [this.project5],
- })
- const projects =
- await this.ProjectGetter.promises.findUsersProjectsByName(
- this.userId,
- this.project1.name
- )
- expect(projects.map(project => project.name)).to.have.members([
- this.project1.name,
- this.project2.name,
- ])
- })
- })
- describe('getUsersDeletedProjects', function () {
- it('should look up the deleted projects by deletedProjectOwnerId', async function () {
- await this.ProjectGetter.promises.getUsersDeletedProjects('giraffe')
- sinon.assert.calledWith(this.DeletedProject.find, {
- 'deleterData.deletedProjectOwnerId': 'giraffe',
- })
- })
- it('should pass the found projects to the callback', async function () {
- const docs =
- await this.ProjectGetter.promises.getUsersDeletedProjects('giraffe')
- expect(docs).to.deep.equal([this.deletedProject])
- })
- })
- })
|