2019-11-21 07:44:39 -05:00
|
|
|
const { expect } = require('chai')
|
2019-05-29 05:21:06 -04:00
|
|
|
const sinon = require('sinon')
|
|
|
|
const tk = require('timekeeper')
|
|
|
|
const Errors = require('../../../../app/src/Features/Errors/Errors')
|
2020-09-23 04:49:26 -04:00
|
|
|
const { ObjectId } = require('mongodb')
|
2019-05-29 05:21:06 -04:00
|
|
|
const SandboxedModule = require('sandboxed-module')
|
2021-02-17 06:40:56 -05:00
|
|
|
const { DeletedFile } = require('../helpers/models/DeletedFile')
|
2019-11-21 07:44:39 -05:00
|
|
|
const { Project } = require('../helpers/models/Project')
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2019-11-04 04:50:15 -05:00
|
|
|
const MODULE_PATH =
|
|
|
|
'../../../../app/src/Features/Project/ProjectEntityMongoUpdateHandler'
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('ProjectEntityMongoUpdateHandler', function () {
|
|
|
|
beforeEach(function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.doc = {
|
|
|
|
_id: ObjectId(),
|
|
|
|
name: 'test-doc.txt',
|
|
|
|
lines: ['hello', 'world'],
|
2021-04-27 03:52:58 -04:00
|
|
|
rev: 1234,
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
this.docPath = {
|
|
|
|
mongo: 'rootFolder.0.docs.0',
|
2021-04-27 03:52:58 -04:00
|
|
|
fileSystem: '/test-doc.txt',
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
this.file = {
|
|
|
|
_id: ObjectId(),
|
|
|
|
name: 'something.jpg',
|
|
|
|
linkedFileData: { provider: 'url' },
|
2021-04-27 03:52:58 -04:00
|
|
|
hash: 'some-hash',
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
this.filePath = {
|
|
|
|
fileSystem: '/something.png',
|
2021-04-27 03:52:58 -04:00
|
|
|
mongo: 'rootFolder.0.fileRefs.0',
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
this.subfolder = { _id: ObjectId(), name: 'test-subfolder' }
|
|
|
|
this.subfolderPath = {
|
|
|
|
fileSystem: '/test-folder/test-subfolder',
|
2021-04-27 03:52:58 -04:00
|
|
|
mongo: 'rootFolder.0.folders.0.folders.0',
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
this.folder = {
|
|
|
|
_id: ObjectId(),
|
|
|
|
name: 'test-folder',
|
2021-04-27 03:52:58 -04:00
|
|
|
folders: [this.subfolder],
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
this.folderPath = {
|
|
|
|
fileSystem: '/test-folder',
|
2021-04-27 03:52:58 -04:00
|
|
|
mongo: 'rootFolder.0.folders.0',
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
this.rootFolder = {
|
|
|
|
_id: ObjectId(),
|
|
|
|
folders: [this.folder],
|
|
|
|
docs: [this.doc],
|
2021-04-27 03:52:58 -04:00
|
|
|
fileRefs: [this.file],
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
this.rootFolderPath = {
|
|
|
|
fileSystem: '/',
|
2021-04-27 03:52:58 -04:00
|
|
|
mongo: 'rootFolder.0',
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
this.project = {
|
|
|
|
_id: ObjectId(),
|
|
|
|
name: 'project name',
|
2021-04-27 03:52:58 -04:00
|
|
|
rootFolder: [this.rootFolder],
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
this.Settings = { maxEntitiesPerProject: 100 }
|
|
|
|
this.CooldownManager = {}
|
|
|
|
this.LockManager = {
|
|
|
|
promises: {
|
2021-04-27 03:52:58 -04:00
|
|
|
runWithLock: sinon.spy((namespace, id, runner) => runner()),
|
|
|
|
},
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
|
|
|
|
2019-11-21 07:44:39 -05:00
|
|
|
this.FolderModel = sinon.stub()
|
2021-02-17 06:40:56 -05:00
|
|
|
this.DeletedFileMock = sinon.mock(DeletedFile)
|
2019-11-21 07:44:39 -05:00
|
|
|
this.ProjectMock = sinon.mock(Project)
|
|
|
|
this.ProjectEntityHandler = {
|
2021-12-06 10:27:12 -05:00
|
|
|
getAllEntitiesFromProject: sinon.stub(),
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
this.ProjectLocator = {
|
2022-09-12 10:59:16 -04:00
|
|
|
findElementByMongoPath: sinon.stub().throws(new Error('not found')),
|
2019-11-21 07:44:39 -05:00
|
|
|
promises: {
|
|
|
|
findElement: sinon.stub().rejects(new Error('not found')),
|
2021-04-27 03:52:58 -04:00
|
|
|
findElementByPath: sinon.stub().rejects(new Error('not found')),
|
|
|
|
},
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
this.ProjectLocator.promises.findElement
|
|
|
|
.withArgs({
|
|
|
|
project: this.project,
|
|
|
|
element_id: this.rootFolder._id,
|
2021-04-27 03:52:58 -04:00
|
|
|
type: 'folder',
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
.resolves({
|
|
|
|
element: this.rootFolder,
|
2021-04-27 03:52:58 -04:00
|
|
|
path: this.rootFolderPath,
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
this.ProjectLocator.promises.findElement
|
|
|
|
.withArgs({
|
|
|
|
project: this.project,
|
|
|
|
element_id: this.folder._id,
|
2021-04-27 03:52:58 -04:00
|
|
|
type: 'folder',
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
.resolves({
|
|
|
|
element: this.folder,
|
|
|
|
path: this.folderPath,
|
2021-04-27 03:52:58 -04:00
|
|
|
folder: this.rootFolder,
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
this.ProjectLocator.promises.findElement
|
|
|
|
.withArgs({
|
|
|
|
project: this.project,
|
|
|
|
element_id: this.subfolder._id,
|
2021-04-27 03:52:58 -04:00
|
|
|
type: 'folder',
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
.resolves({
|
|
|
|
element: this.subfolder,
|
|
|
|
path: this.subfolderPath,
|
2021-04-27 03:52:58 -04:00
|
|
|
folder: this.folder,
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
this.ProjectLocator.promises.findElement
|
|
|
|
.withArgs({
|
|
|
|
project: this.project,
|
|
|
|
element_id: this.file._id,
|
2021-04-27 03:52:58 -04:00
|
|
|
type: 'file',
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
.resolves({
|
|
|
|
element: this.file,
|
|
|
|
path: this.filePath,
|
2021-04-27 03:52:58 -04:00
|
|
|
folder: this.rootFolder,
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
this.ProjectLocator.promises.findElement
|
|
|
|
.withArgs({
|
|
|
|
project: this.project,
|
|
|
|
element_id: this.doc._id,
|
2021-04-27 03:52:58 -04:00
|
|
|
type: 'doc',
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
.resolves({
|
|
|
|
element: this.doc,
|
|
|
|
path: this.docPath,
|
2021-04-27 03:52:58 -04:00
|
|
|
folder: this.rootFolder,
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
this.ProjectLocator.promises.findElementByPath
|
|
|
|
.withArgs(
|
|
|
|
sinon.match({
|
|
|
|
project: this.project,
|
2021-04-27 03:52:58 -04:00
|
|
|
path: '/',
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
)
|
2022-09-21 08:01:56 -04:00
|
|
|
.resolves({ element: this.rootFolder, type: 'folder', folder: null })
|
2019-11-21 07:44:39 -05:00
|
|
|
this.ProjectLocator.promises.findElementByPath
|
|
|
|
.withArgs(
|
|
|
|
sinon.match({
|
|
|
|
project: this.project,
|
2021-04-27 03:52:58 -04:00
|
|
|
path: '/test-folder',
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
)
|
2022-09-21 08:01:56 -04:00
|
|
|
.resolves({
|
|
|
|
element: this.folder,
|
|
|
|
type: 'folder',
|
|
|
|
folder: this.rootFolder,
|
|
|
|
})
|
2019-11-21 07:44:39 -05:00
|
|
|
this.ProjectLocator.promises.findElementByPath
|
|
|
|
.withArgs(
|
|
|
|
sinon.match({
|
|
|
|
project: this.project,
|
2021-04-27 03:52:58 -04:00
|
|
|
path: '/test-folder/test-subfolder',
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
)
|
2022-09-21 08:01:56 -04:00
|
|
|
.resolves({
|
|
|
|
element: this.subfolder,
|
|
|
|
type: 'folder',
|
|
|
|
folder: this.folder,
|
|
|
|
})
|
2019-11-21 07:44:39 -05:00
|
|
|
|
|
|
|
this.ProjectGetter = {
|
|
|
|
promises: {
|
|
|
|
getProjectWithoutLock: sinon
|
|
|
|
.stub()
|
|
|
|
.withArgs(this.project._id)
|
|
|
|
.resolves(this.project),
|
2021-04-27 03:52:58 -04:00
|
|
|
getProjectWithOnlyFolders: sinon.stub().resolves(this.project),
|
|
|
|
},
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2019-11-21 07:44:39 -05:00
|
|
|
this.FolderStructureBuilder = {
|
2021-04-27 03:52:58 -04:00
|
|
|
buildFolderStructure: sinon.stub(),
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2019-11-04 04:50:15 -05:00
|
|
|
this.subject = SandboxedModule.require(MODULE_PATH, {
|
2019-05-29 05:21:06 -04:00
|
|
|
requires: {
|
2020-10-05 04:23:21 -04:00
|
|
|
mongodb: { ObjectId },
|
2021-07-07 05:38:56 -04:00
|
|
|
'@overleaf/settings': this.Settings,
|
2019-11-21 07:44:39 -05:00
|
|
|
'../Cooldown/CooldownManager': this.CooldownManager,
|
|
|
|
'../../models/Folder': { Folder: this.FolderModel },
|
|
|
|
'../../infrastructure/LockManager': this.LockManager,
|
2021-02-17 06:40:56 -05:00
|
|
|
'../../models/DeletedFile': { DeletedFile },
|
2019-11-21 07:44:39 -05:00
|
|
|
'../../models/Project': { Project },
|
|
|
|
'./ProjectEntityHandler': this.ProjectEntityHandler,
|
|
|
|
'./ProjectLocator': this.ProjectLocator,
|
|
|
|
'./ProjectGetter': this.ProjectGetter,
|
2021-04-27 03:52:58 -04:00
|
|
|
'./FolderStructureBuilder': this.FolderStructureBuilder,
|
|
|
|
},
|
2019-11-04 04:50:15 -05:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
afterEach(function () {
|
2021-02-17 06:40:56 -05:00
|
|
|
this.DeletedFileMock.restore()
|
2019-11-21 07:44:39 -05:00
|
|
|
this.ProjectMock.restore()
|
2019-08-07 10:04:04 -04:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
beforeEach(function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
tk.freeze(Date.now())
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
afterEach(function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
tk.reset()
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('addDoc', function () {
|
|
|
|
beforeEach(async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
const doc = { _id: ObjectId(), name: 'other.txt' }
|
|
|
|
this.ProjectMock.expects('findOneAndUpdate')
|
|
|
|
.withArgs(
|
2022-04-06 09:26:42 -04:00
|
|
|
{
|
|
|
|
_id: this.project._id,
|
|
|
|
'rootFolder.0.folders.0': { $exists: true },
|
|
|
|
},
|
2019-11-21 07:44:39 -05:00
|
|
|
{
|
|
|
|
$push: { 'rootFolder.0.folders.0.docs': doc },
|
2021-04-27 03:52:58 -04:00
|
|
|
$inc: { version: 1 },
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
)
|
|
|
|
.chain('exec')
|
|
|
|
.resolves(this.project)
|
|
|
|
this.result = await this.subject.promises.addDoc(
|
|
|
|
this.project._id,
|
|
|
|
this.folder._id,
|
|
|
|
doc
|
|
|
|
)
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('adds the document in Mongo', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.ProjectMock.verify()
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('returns path info and the project', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
expect(this.result).to.deep.equal({
|
|
|
|
result: {
|
|
|
|
path: {
|
|
|
|
mongo: 'rootFolder.0.folders.0',
|
2021-04-27 03:52:58 -04:00
|
|
|
fileSystem: '/test-folder/other.txt',
|
|
|
|
},
|
2019-11-21 07:44:39 -05:00
|
|
|
},
|
2021-04-27 03:52:58 -04:00
|
|
|
project: this.project,
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('addFile', function () {
|
|
|
|
beforeEach(function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.newFile = { _id: ObjectId(), name: 'picture.jpg' }
|
|
|
|
this.ProjectMock.expects('findOneAndUpdate')
|
|
|
|
.withArgs(
|
2022-04-06 09:26:42 -04:00
|
|
|
{
|
|
|
|
_id: this.project._id,
|
|
|
|
'rootFolder.0.folders.0': { $exists: true },
|
|
|
|
},
|
2019-11-21 07:44:39 -05:00
|
|
|
{
|
|
|
|
$push: { 'rootFolder.0.folders.0.fileRefs': this.newFile },
|
2021-04-27 03:52:58 -04:00
|
|
|
$inc: { version: 1 },
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
)
|
|
|
|
.chain('exec')
|
|
|
|
.resolves(this.project)
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('happy path', function () {
|
|
|
|
beforeEach(async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.result = await this.subject.promises.addFile(
|
|
|
|
this.project._id,
|
|
|
|
this.folder._id,
|
|
|
|
this.newFile
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('adds the file in Mongo', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.ProjectMock.verify()
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('returns path info and the project', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
expect(this.result).to.deep.equal({
|
|
|
|
result: {
|
|
|
|
path: {
|
|
|
|
mongo: 'rootFolder.0.folders.0',
|
2021-04-27 03:52:58 -04:00
|
|
|
fileSystem: '/test-folder/picture.jpg',
|
|
|
|
},
|
2019-11-21 07:44:39 -05:00
|
|
|
},
|
2021-04-27 03:52:58 -04:00
|
|
|
project: this.project,
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('when entity limit is reached', function () {
|
|
|
|
beforeEach(function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.savedMaxEntities = this.Settings.maxEntitiesPerProject
|
|
|
|
this.Settings.maxEntitiesPerProject = 3
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
afterEach(function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.Settings.maxEntitiesPerProject = this.savedMaxEntities
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should throw an error', async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
await expect(
|
|
|
|
this.subject.promises.addFile(
|
|
|
|
this.project._id,
|
|
|
|
this.folder._id,
|
|
|
|
this.newFile
|
|
|
|
)
|
|
|
|
).to.be.rejected
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('addFolder', function () {
|
|
|
|
beforeEach(async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
const folderName = 'New folder'
|
|
|
|
this.FolderModel.withArgs({ name: folderName }).returns({
|
|
|
|
_id: ObjectId(),
|
2021-04-27 03:52:58 -04:00
|
|
|
name: folderName,
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
this.ProjectMock.expects('findOneAndUpdate')
|
|
|
|
.withArgs(
|
2022-04-06 09:26:42 -04:00
|
|
|
{
|
|
|
|
_id: this.project._id,
|
|
|
|
'rootFolder.0.folders.0': { $exists: true },
|
|
|
|
},
|
2019-11-21 07:44:39 -05:00
|
|
|
{
|
|
|
|
$push: {
|
|
|
|
'rootFolder.0.folders.0.folders': sinon.match({
|
2021-04-27 03:52:58 -04:00
|
|
|
name: folderName,
|
|
|
|
}),
|
2019-11-21 07:44:39 -05:00
|
|
|
},
|
2021-04-27 03:52:58 -04:00
|
|
|
$inc: { version: 1 },
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
)
|
|
|
|
.chain('exec')
|
|
|
|
.resolves(this.project)
|
|
|
|
await this.subject.promises.addFolder(
|
|
|
|
this.project._id,
|
|
|
|
this.folder._id,
|
|
|
|
folderName
|
2019-05-29 05:21:06 -04:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('adds the folder in Mongo', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.ProjectMock.verify()
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('replaceFileWithNew', function () {
|
|
|
|
beforeEach(async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
const newFile = {
|
|
|
|
_id: ObjectId(),
|
|
|
|
name: 'some-other-file.png',
|
|
|
|
linkedFileData: { some: 'data' },
|
2021-04-27 03:52:58 -04:00
|
|
|
hash: 'some-hash',
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
// Add a deleted file record
|
2021-02-17 06:40:56 -05:00
|
|
|
this.DeletedFileMock.expects('create')
|
|
|
|
.withArgs({
|
|
|
|
projectId: this.project._id,
|
|
|
|
_id: this.file._id,
|
|
|
|
name: this.file.name,
|
|
|
|
linkedFileData: this.file.linkedFileData,
|
|
|
|
hash: this.file.hash,
|
2021-04-27 03:52:58 -04:00
|
|
|
deletedAt: sinon.match.date,
|
2021-02-17 06:40:56 -05:00
|
|
|
})
|
2019-11-21 07:44:39 -05:00
|
|
|
.resolves()
|
|
|
|
// Update the file in place
|
|
|
|
this.ProjectMock.expects('findOneAndUpdate')
|
|
|
|
.withArgs(
|
2022-04-06 09:26:42 -04:00
|
|
|
{
|
|
|
|
_id: this.project._id,
|
|
|
|
'rootFolder.0.fileRefs.0': { $exists: true },
|
|
|
|
},
|
2019-05-29 05:21:06 -04:00
|
|
|
{
|
|
|
|
$set: {
|
2019-11-21 07:44:39 -05:00
|
|
|
'rootFolder.0.fileRefs.0._id': newFile._id,
|
|
|
|
'rootFolder.0.fileRefs.0.created': sinon.match.date,
|
|
|
|
'rootFolder.0.fileRefs.0.linkedFileData': newFile.linkedFileData,
|
2021-04-27 03:52:58 -04:00
|
|
|
'rootFolder.0.fileRefs.0.hash': newFile.hash,
|
2019-11-21 07:44:39 -05:00
|
|
|
},
|
|
|
|
$inc: {
|
|
|
|
version: 1,
|
2021-04-27 03:52:58 -04:00
|
|
|
'rootFolder.0.fileRefs.0.rev': 1,
|
|
|
|
},
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
2019-05-29 05:21:06 -04:00
|
|
|
)
|
2019-11-21 07:44:39 -05:00
|
|
|
.chain('exec')
|
|
|
|
.resolves(this.project)
|
2022-09-12 10:59:16 -04:00
|
|
|
this.ProjectLocator.findElementByMongoPath
|
|
|
|
.withArgs(this.project, 'rootFolder.0.fileRefs.0')
|
|
|
|
.returns(newFile)
|
2019-11-21 07:44:39 -05:00
|
|
|
await this.subject.promises.replaceFileWithNew(
|
|
|
|
this.project._id,
|
|
|
|
this.file._id,
|
|
|
|
newFile
|
|
|
|
)
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('updates the database', function () {
|
2021-02-17 06:40:56 -05:00
|
|
|
this.DeletedFileMock.verify()
|
2019-11-21 07:44:39 -05:00
|
|
|
this.ProjectMock.verify()
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('mkdirp', function () {
|
|
|
|
describe('when the path is just a slash', function () {
|
|
|
|
beforeEach(async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.result = await this.subject.promises.mkdirp(this.project._id, '/')
|
2019-11-04 04:50:15 -05:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should return the root folder', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
expect(this.result.folder).to.deep.equal(this.rootFolder)
|
2019-11-04 04:50:15 -05:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should not report a parent folder', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
expect(this.result.folder.parentFolder_id).not.to.exist
|
2019-11-04 04:50:15 -05:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should not return new folders', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
expect(this.result.newFolders).to.have.length(0)
|
2019-11-04 04:50:15 -05:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('when the folder already exists', function () {
|
|
|
|
beforeEach(async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.result = await this.subject.promises.mkdirp(
|
|
|
|
this.project._id,
|
|
|
|
'/test-folder'
|
|
|
|
)
|
2019-11-04 04:50:15 -05:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should return the existing folder', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
expect(this.result.folder).to.deep.equal(this.folder)
|
2019-11-04 04:50:15 -05:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should report the parent folder', function () {
|
2022-09-21 08:01:56 -04:00
|
|
|
expect(this.result.folder.parentFolder_id).to.equal(this.rootFolder._id)
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should not return new folders', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
expect(this.result.newFolders).to.have.length(0)
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('when the path is a new folder at the top level', function () {
|
|
|
|
beforeEach(async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.newFolder = { _id: ObjectId(), name: 'new-folder' }
|
|
|
|
this.FolderModel.returns(this.newFolder)
|
|
|
|
this.exactCaseMatch = false
|
|
|
|
this.ProjectMock.expects('findOneAndUpdate')
|
|
|
|
.withArgs(
|
2022-04-06 09:26:42 -04:00
|
|
|
{ _id: this.project._id, 'rootFolder.0': { $exists: true } },
|
2019-11-21 07:44:39 -05:00
|
|
|
{
|
|
|
|
$push: { 'rootFolder.0.folders': this.newFolder },
|
2021-04-27 03:52:58 -04:00
|
|
|
$inc: { version: 1 },
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
)
|
|
|
|
.chain('exec')
|
|
|
|
.resolves(this.project)
|
|
|
|
this.result = await this.subject.promises.mkdirp(
|
|
|
|
this.project._id,
|
|
|
|
'/new-folder/',
|
|
|
|
{ exactCaseMatch: this.exactCaseMatch }
|
|
|
|
)
|
|
|
|
})
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should update the database', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.ProjectMock.verify()
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should make just one folder', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
expect(this.result.newFolders).to.have.length(1)
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should return the new folder', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
expect(this.result.folder.name).to.equal('new-folder')
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should return the parent folder', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
expect(this.result.folder.parentFolder_id).to.equal(this.rootFolder._id)
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should pass the exactCaseMatch option to ProjectLocator', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
expect(
|
|
|
|
this.ProjectLocator.promises.findElementByPath
|
|
|
|
).to.have.been.calledWithMatch({ exactCaseMatch: this.exactCaseMatch })
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('adding a subfolder', function () {
|
|
|
|
beforeEach(async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.newFolder = { _id: ObjectId(), name: 'new-folder' }
|
|
|
|
this.FolderModel.returns(this.newFolder)
|
|
|
|
this.ProjectMock.expects('findOneAndUpdate')
|
|
|
|
.withArgs(
|
2022-04-06 09:26:42 -04:00
|
|
|
{
|
|
|
|
_id: this.project._id,
|
|
|
|
'rootFolder.0.folders.0': { $exists: true },
|
|
|
|
},
|
2019-11-21 07:44:39 -05:00
|
|
|
{
|
|
|
|
$push: {
|
|
|
|
'rootFolder.0.folders.0.folders': sinon.match({
|
2021-04-27 03:52:58 -04:00
|
|
|
name: 'new-folder',
|
|
|
|
}),
|
2019-11-21 07:44:39 -05:00
|
|
|
},
|
2021-04-27 03:52:58 -04:00
|
|
|
$inc: { version: 1 },
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
)
|
|
|
|
.chain('exec')
|
|
|
|
.resolves(this.project)
|
|
|
|
this.result = await this.subject.promises.mkdirp(
|
|
|
|
this.project._id,
|
|
|
|
'/test-folder/new-folder'
|
2019-05-29 05:21:06 -04:00
|
|
|
)
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should update the database', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.ProjectMock.verify()
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should create one folder', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
expect(this.result.newFolders).to.have.length(1)
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should return the new folder', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
expect(this.result.folder.name).to.equal('new-folder')
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should return the parent folder', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
expect(this.result.folder.parentFolder_id).to.equal(this.folder._id)
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('when mutliple folders are missing', async function () {
|
|
|
|
beforeEach(function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.folder1 = { _id: ObjectId(), name: 'folder1' }
|
|
|
|
this.folder1Path = {
|
|
|
|
fileSystem: '/test-folder/folder1',
|
2021-04-27 03:52:58 -04:00
|
|
|
mongo: 'rootFolder.0.folders.0.folders.0',
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
this.folder2 = { _id: ObjectId(), name: 'folder2' }
|
|
|
|
this.folder2Path = {
|
|
|
|
fileSystem: '/test-folder/folder1/folder2',
|
2021-04-27 03:52:58 -04:00
|
|
|
mongo: 'rootFolder.0.folders.0.folders.0.folders.0',
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
this.FolderModel.onFirstCall().returns(this.folder1)
|
|
|
|
this.FolderModel.onSecondCall().returns(this.folder2)
|
|
|
|
this.ProjectLocator.promises.findElement
|
|
|
|
.withArgs({
|
|
|
|
project: this.project,
|
|
|
|
element_id: this.folder1._id,
|
2021-04-27 03:52:58 -04:00
|
|
|
type: 'folder',
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
.resolves({
|
|
|
|
element: this.folder1,
|
2021-04-27 03:52:58 -04:00
|
|
|
path: this.folder1Path,
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
this.ProjectLocator.promises.findElement
|
|
|
|
.withArgs({
|
|
|
|
project: this.project,
|
|
|
|
element_id: this.folder2._id,
|
2021-04-27 03:52:58 -04:00
|
|
|
type: 'folder',
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
.resolves({
|
|
|
|
element: this.folder2,
|
2021-04-27 03:52:58 -04:00
|
|
|
path: this.folder2Path,
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
this.ProjectMock.expects('findOneAndUpdate')
|
|
|
|
.withArgs(
|
2022-04-06 09:26:42 -04:00
|
|
|
{
|
|
|
|
_id: this.project._id,
|
|
|
|
'rootFolder.0.folders.0': { $exists: true },
|
|
|
|
},
|
2019-11-21 07:44:39 -05:00
|
|
|
{
|
|
|
|
$push: {
|
|
|
|
'rootFolder.0.folders.0.folders': sinon.match({
|
2021-04-27 03:52:58 -04:00
|
|
|
name: 'folder1',
|
|
|
|
}),
|
2019-11-21 07:44:39 -05:00
|
|
|
},
|
2021-04-27 03:52:58 -04:00
|
|
|
$inc: { version: 1 },
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
)
|
|
|
|
.chain('exec')
|
|
|
|
.resolves(this.project)
|
|
|
|
this.ProjectMock.expects('findOneAndUpdate')
|
|
|
|
.withArgs(
|
2022-04-06 09:26:42 -04:00
|
|
|
{
|
|
|
|
_id: this.project._id,
|
|
|
|
'rootFolder.0.folders.0.folders.0': { $exists: true },
|
|
|
|
},
|
2019-11-21 07:44:39 -05:00
|
|
|
{
|
|
|
|
$push: {
|
|
|
|
'rootFolder.0.folders.0.folders.0.folders': sinon.match({
|
2021-04-27 03:52:58 -04:00
|
|
|
name: 'folder2',
|
|
|
|
}),
|
2019-11-21 07:44:39 -05:00
|
|
|
},
|
2021-04-27 03:52:58 -04:00
|
|
|
$inc: { version: 1 },
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
)
|
|
|
|
.chain('exec')
|
|
|
|
.resolves(this.project)
|
|
|
|
})
|
|
|
|
;[
|
|
|
|
{
|
|
|
|
description: 'without a trailing slash',
|
2021-04-27 03:52:58 -04:00
|
|
|
path: '/test-folder/folder1/folder2',
|
2019-11-21 07:44:39 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
description: 'with a trailing slash',
|
2021-04-27 03:52:58 -04:00
|
|
|
path: '/test-folder/folder1/folder2/',
|
|
|
|
},
|
2019-11-21 07:44:39 -05:00
|
|
|
].forEach(({ description, path }) => {
|
2021-04-14 09:17:21 -04:00
|
|
|
describe(description, function () {
|
|
|
|
beforeEach(async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.result = await this.subject.promises.mkdirp(
|
|
|
|
this.project._id,
|
|
|
|
path
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should update the database', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.ProjectMock.verify()
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should add multiple folders', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
const newFolders = this.result.newFolders
|
|
|
|
expect(newFolders).to.have.length(2)
|
|
|
|
expect(newFolders[0].name).to.equal('folder1')
|
|
|
|
expect(newFolders[1].name).to.equal('folder2')
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should return the last folder', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
expect(this.result.folder.name).to.equal('folder2')
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should return the parent folder', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
expect(this.result.folder.parentFolder_id).to.equal(
|
|
|
|
this.folder1._id
|
|
|
|
)
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('moveEntity', function () {
|
|
|
|
describe('moving a doc into a different folder', function () {
|
|
|
|
beforeEach(async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.pathAfterMove = {
|
2021-04-27 03:52:58 -04:00
|
|
|
fileSystem: '/somewhere/else.txt',
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
this.oldDocs = ['old-doc']
|
|
|
|
this.oldFiles = ['old-file']
|
|
|
|
this.newDocs = ['new-doc']
|
|
|
|
this.newFiles = ['new-file']
|
|
|
|
|
2021-12-06 10:27:12 -05:00
|
|
|
this.ProjectEntityHandler.getAllEntitiesFromProject
|
2019-11-21 07:44:39 -05:00
|
|
|
.onFirstCall()
|
2021-12-06 10:27:12 -05:00
|
|
|
.returns({ docs: this.oldDocs, files: this.oldFiles })
|
|
|
|
this.ProjectEntityHandler.getAllEntitiesFromProject
|
2019-11-21 07:44:39 -05:00
|
|
|
.onSecondCall()
|
2021-12-06 10:27:12 -05:00
|
|
|
.returns({ docs: this.newDocs, files: this.newFiles })
|
2019-11-21 07:44:39 -05:00
|
|
|
|
|
|
|
this.ProjectMock.expects('findOneAndUpdate')
|
|
|
|
.withArgs(
|
2022-04-06 09:26:42 -04:00
|
|
|
{
|
|
|
|
_id: this.project._id,
|
|
|
|
'rootFolder.0.folders.0': { $exists: true },
|
|
|
|
},
|
2019-11-21 07:44:39 -05:00
|
|
|
{
|
|
|
|
$push: { 'rootFolder.0.folders.0.docs': this.doc },
|
2021-04-27 03:52:58 -04:00
|
|
|
$inc: { version: 1 },
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
)
|
|
|
|
.chain('exec')
|
|
|
|
.resolves(this.project)
|
|
|
|
this.ProjectMock.expects('findOneAndUpdate')
|
|
|
|
.withArgs(
|
|
|
|
{ _id: this.project._id },
|
|
|
|
{
|
|
|
|
$pull: { 'rootFolder.0.docs': { _id: this.doc._id } },
|
2021-04-27 03:52:58 -04:00
|
|
|
$inc: { version: 1 },
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
)
|
|
|
|
.chain('exec')
|
|
|
|
.resolves(this.project)
|
|
|
|
this.result = await this.subject.promises.moveEntity(
|
|
|
|
this.project._id,
|
|
|
|
this.doc._id,
|
|
|
|
this.folder._id,
|
|
|
|
'doc'
|
|
|
|
)
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should update the database', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.ProjectMock.verify()
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should report what changed', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
expect(this.result).to.deep.equal({
|
2019-05-29 05:21:06 -04:00
|
|
|
project: this.project,
|
2019-11-21 07:44:39 -05:00
|
|
|
startPath: '/test-doc.txt',
|
|
|
|
endPath: '/test-folder/test-doc.txt',
|
|
|
|
rev: this.doc.rev,
|
|
|
|
changes: {
|
|
|
|
oldDocs: this.oldDocs,
|
|
|
|
newDocs: this.newDocs,
|
|
|
|
oldFiles: this.oldFiles,
|
|
|
|
newFiles: this.newFiles,
|
2021-04-27 03:52:58 -04:00
|
|
|
newProject: this.project,
|
|
|
|
},
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('when moving a folder inside itself', function () {
|
|
|
|
it('throws an error', async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
await expect(
|
|
|
|
this.subject.promises.moveEntity(
|
|
|
|
this.project._id,
|
|
|
|
this.folder._id,
|
|
|
|
this.folder._id,
|
|
|
|
'folder'
|
|
|
|
)
|
|
|
|
).to.be.rejectedWith(Errors.InvalidNameError)
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('when moving a folder to a subfolder of itself', function () {
|
|
|
|
it('throws an error', async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
await expect(
|
|
|
|
this.subject.promises.moveEntity(
|
|
|
|
this.project._id,
|
|
|
|
this.folder._id,
|
|
|
|
this.subfolder._id,
|
|
|
|
'folder'
|
|
|
|
)
|
|
|
|
).to.be.rejectedWith(Errors.InvalidNameError)
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('deleteEntity', function () {
|
|
|
|
beforeEach(async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.ProjectMock.expects('findOneAndUpdate')
|
|
|
|
.withArgs(
|
|
|
|
{ _id: this.project._id },
|
|
|
|
{
|
|
|
|
$pull: { 'rootFolder.0.docs': { _id: this.doc._id } },
|
2021-04-27 03:52:58 -04:00
|
|
|
$inc: { version: 1 },
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
2019-05-29 05:21:06 -04:00
|
|
|
)
|
2019-11-21 07:44:39 -05:00
|
|
|
.chain('exec')
|
|
|
|
.resolves(this.project)
|
|
|
|
await this.subject.promises.deleteEntity(
|
|
|
|
this.project._id,
|
|
|
|
this.doc._id,
|
|
|
|
'doc'
|
2019-05-29 05:21:06 -04:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should update the database', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.ProjectMock.verify()
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('renameEntity', function () {
|
|
|
|
describe('happy path', function () {
|
|
|
|
beforeEach(async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.newName = 'new.tex'
|
|
|
|
this.oldDocs = ['old-doc']
|
|
|
|
this.oldFiles = ['old-file']
|
|
|
|
this.newDocs = ['new-doc']
|
|
|
|
this.newFiles = ['new-file']
|
|
|
|
|
2021-12-06 10:27:12 -05:00
|
|
|
this.ProjectEntityHandler.getAllEntitiesFromProject
|
2019-11-21 07:44:39 -05:00
|
|
|
.onFirstCall()
|
2021-12-06 10:27:12 -05:00
|
|
|
.returns({ docs: this.oldDocs, files: this.oldFiles })
|
|
|
|
this.ProjectEntityHandler.getAllEntitiesFromProject
|
2019-11-21 07:44:39 -05:00
|
|
|
.onSecondCall()
|
2021-12-06 10:27:12 -05:00
|
|
|
.returns({ docs: this.newDocs, files: this.newFiles })
|
2019-11-21 07:44:39 -05:00
|
|
|
|
|
|
|
this.ProjectMock.expects('findOneAndUpdate')
|
|
|
|
.withArgs(
|
2022-04-06 09:26:42 -04:00
|
|
|
{ _id: this.project._id, 'rootFolder.0.docs.0': { $exists: true } },
|
2019-11-21 07:44:39 -05:00
|
|
|
{
|
|
|
|
$set: { 'rootFolder.0.docs.0.name': this.newName },
|
2021-04-27 03:52:58 -04:00
|
|
|
$inc: { version: 1 },
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
)
|
|
|
|
.chain('exec')
|
|
|
|
.resolves(this.project)
|
|
|
|
this.result = await this.subject.promises.renameEntity(
|
|
|
|
this.project._id,
|
|
|
|
this.doc._id,
|
|
|
|
'doc',
|
|
|
|
this.newName
|
2019-05-29 05:21:06 -04:00
|
|
|
)
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should update the database', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.ProjectMock.verify()
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('returns info', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
expect(this.result).to.deep.equal({
|
|
|
|
project: this.project,
|
|
|
|
startPath: '/test-doc.txt',
|
|
|
|
endPath: '/new.tex',
|
|
|
|
rev: this.doc.rev,
|
|
|
|
changes: {
|
|
|
|
oldDocs: this.oldDocs,
|
|
|
|
newDocs: this.newDocs,
|
|
|
|
oldFiles: this.oldFiles,
|
|
|
|
newFiles: this.newFiles,
|
2021-04-27 03:52:58 -04:00
|
|
|
newProject: this.project,
|
|
|
|
},
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('name already exists', function () {
|
|
|
|
it('should throw an error', async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
await expect(
|
|
|
|
this.subject.promises.renameEntity(
|
|
|
|
this.project._id,
|
|
|
|
this.doc._id,
|
|
|
|
'doc',
|
|
|
|
this.folder.name
|
|
|
|
)
|
|
|
|
).to.be.rejectedWith(Errors.InvalidNameError)
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('_putElement', function () {
|
|
|
|
describe('updating the project', function () {
|
|
|
|
describe('when the parent folder is given', function () {
|
|
|
|
beforeEach(function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.newFile = { _id: ObjectId(), name: 'new file.png' }
|
|
|
|
this.ProjectMock.expects('findOneAndUpdate')
|
|
|
|
.withArgs(
|
2022-04-06 09:26:42 -04:00
|
|
|
{
|
|
|
|
_id: this.project._id,
|
|
|
|
'rootFolder.0.folders.0': { $exists: true },
|
|
|
|
},
|
2019-11-21 07:44:39 -05:00
|
|
|
{
|
|
|
|
$push: { 'rootFolder.0.folders.0.fileRefs': this.newFile },
|
2021-04-27 03:52:58 -04:00
|
|
|
$inc: { version: 1 },
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
2019-05-29 05:21:06 -04:00
|
|
|
)
|
2019-11-21 07:44:39 -05:00
|
|
|
.chain('exec')
|
|
|
|
.resolves(this.project)
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should update the database', async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
await this.subject.promises._putElement(
|
|
|
|
this.project,
|
|
|
|
this.folder._id,
|
|
|
|
this.newFile,
|
|
|
|
'files'
|
|
|
|
)
|
|
|
|
this.ProjectMock.verify()
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should add an s onto the type if not included', async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
await this.subject.promises._putElement(
|
|
|
|
this.project,
|
|
|
|
this.folder._id,
|
|
|
|
this.newFile,
|
|
|
|
'file'
|
2019-11-04 04:50:15 -05:00
|
|
|
)
|
2019-11-21 07:44:39 -05:00
|
|
|
this.ProjectMock.verify()
|
2019-11-04 04:50:15 -05:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('error cases', function () {
|
|
|
|
it('should throw an error if element is null', async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
await expect(
|
|
|
|
this.subject.promises._putElement(
|
|
|
|
this.project,
|
|
|
|
this.folder._id,
|
|
|
|
null,
|
|
|
|
'file'
|
|
|
|
)
|
|
|
|
).to.be.rejected
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should error if the element has no _id', async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
const file = { name: 'something' }
|
|
|
|
await expect(
|
|
|
|
this.subject.promises._putElement(
|
|
|
|
this.project,
|
|
|
|
this.folder._id,
|
|
|
|
file,
|
|
|
|
'file'
|
|
|
|
)
|
|
|
|
).to.be.rejected
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should error if element name contains invalid characters', async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
const file = { _id: ObjectId(), name: 'something*bad' }
|
|
|
|
await expect(
|
|
|
|
this.subject.promises._putElement(
|
|
|
|
this.project,
|
|
|
|
this.folder._id,
|
|
|
|
file,
|
|
|
|
'file'
|
|
|
|
)
|
|
|
|
).to.be.rejected
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should error if element name is too long', async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
const file = {
|
|
|
|
_id: ObjectId(),
|
2021-04-27 03:52:58 -04:00
|
|
|
name: 'long-'.repeat(1000) + 'something',
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
2019-11-21 07:44:39 -05:00
|
|
|
await expect(
|
|
|
|
this.subject.promises._putElement(
|
|
|
|
this.project,
|
|
|
|
this.folder._id,
|
|
|
|
file,
|
|
|
|
'file'
|
|
|
|
)
|
|
|
|
).to.be.rejectedWith(Errors.InvalidNameError)
|
2019-11-04 04:50:15 -05:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should error if the folder name is too long', async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
const file = {
|
|
|
|
_id: ObjectId(),
|
2021-04-27 03:52:58 -04:00
|
|
|
name: 'something',
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
this.ProjectLocator.promises.findElement
|
|
|
|
.withArgs({
|
|
|
|
project: this.project,
|
|
|
|
element_id: this.folder._id,
|
2021-04-27 03:52:58 -04:00
|
|
|
type: 'folder',
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
.resolves({
|
|
|
|
element: this.folder,
|
2021-04-27 03:52:58 -04:00
|
|
|
path: { fileSystem: 'subdir/'.repeat(1000) + 'foo' },
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
await expect(
|
|
|
|
this.subject.promises._putElement(
|
|
|
|
this.project,
|
|
|
|
this.folder._id,
|
|
|
|
file,
|
|
|
|
'file'
|
|
|
|
)
|
|
|
|
).to.be.rejectedWith(Errors.InvalidNameError)
|
2019-11-04 04:50:15 -05:00
|
|
|
})
|
2019-11-21 07:44:39 -05:00
|
|
|
;['file', 'doc', 'folder'].forEach(entityType => {
|
2021-04-14 09:17:21 -04:00
|
|
|
it(`should error if a ${entityType} already exists with the same name`, async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
const file = {
|
|
|
|
_id: ObjectId(),
|
2021-04-27 03:52:58 -04:00
|
|
|
name: this[entityType].name,
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
await expect(
|
|
|
|
this.subject.promises._putElement(
|
|
|
|
this.project,
|
|
|
|
null,
|
|
|
|
file,
|
|
|
|
'file'
|
|
|
|
)
|
|
|
|
).to.be.rejectedWith(Errors.InvalidNameError)
|
|
|
|
})
|
2019-11-04 04:50:15 -05:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('when the parent folder is not given', function () {
|
|
|
|
it('should default to root folder insert', async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.newFile = { _id: ObjectId(), name: 'new file.png' }
|
|
|
|
this.ProjectMock.expects('findOneAndUpdate')
|
|
|
|
.withArgs(
|
2022-04-06 09:26:42 -04:00
|
|
|
{ _id: this.project._id, 'rootFolder.0': { $exists: true } },
|
2019-11-21 07:44:39 -05:00
|
|
|
{
|
|
|
|
$push: { 'rootFolder.0.fileRefs': this.newFile },
|
2021-04-27 03:52:58 -04:00
|
|
|
$inc: { version: 1 },
|
2019-11-21 07:44:39 -05:00
|
|
|
}
|
|
|
|
)
|
|
|
|
.chain('exec')
|
|
|
|
.resolves(this.project)
|
|
|
|
await this.subject.promises._putElement(
|
|
|
|
this.project,
|
|
|
|
this.rootFolder._id,
|
|
|
|
this.newFile,
|
|
|
|
'file'
|
|
|
|
)
|
2019-11-18 09:37:05 -05:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('_insertDeletedFileReference', function () {
|
|
|
|
beforeEach(async function () {
|
2021-02-17 06:40:56 -05:00
|
|
|
this.DeletedFileMock.expects('create')
|
|
|
|
.withArgs({
|
|
|
|
projectId: this.project._id,
|
|
|
|
_id: this.file._id,
|
|
|
|
name: this.file.name,
|
|
|
|
linkedFileData: this.file.linkedFileData,
|
|
|
|
hash: this.file.hash,
|
2021-04-27 03:52:58 -04:00
|
|
|
deletedAt: sinon.match.date,
|
2021-02-17 06:40:56 -05:00
|
|
|
})
|
2019-11-21 07:44:39 -05:00
|
|
|
.resolves()
|
|
|
|
await this.subject.promises._insertDeletedFileReference(
|
|
|
|
this.project._id,
|
|
|
|
this.file
|
2019-05-29 05:21:06 -04:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('should update the database', function () {
|
2021-02-17 06:40:56 -05:00
|
|
|
this.DeletedFileMock.verify()
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('createNewFolderStructure', function () {
|
|
|
|
beforeEach(function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.mockRootFolder = 'MOCK_ROOT_FOLDER'
|
|
|
|
this.docUploads = ['MOCK_DOC_UPLOAD']
|
|
|
|
this.fileUploads = ['MOCK_FILE_UPLOAD']
|
|
|
|
this.FolderStructureBuilder.buildFolderStructure
|
|
|
|
.withArgs(this.docUploads, this.fileUploads)
|
|
|
|
.returns(this.mockRootFolder)
|
2020-04-23 07:51:06 -04:00
|
|
|
this.updateExpectation = this.ProjectMock.expects('findOneAndUpdate')
|
2019-11-21 07:44:39 -05:00
|
|
|
.withArgs(
|
2019-05-29 05:21:06 -04:00
|
|
|
{
|
2019-11-21 07:44:39 -05:00
|
|
|
_id: this.project._id,
|
|
|
|
'rootFolder.0.folders.0': { $exists: false },
|
|
|
|
'rootFolder.0.docs.0': { $exists: false },
|
2021-04-27 03:52:58 -04:00
|
|
|
'rootFolder.0.files.0': { $exists: false },
|
2019-05-29 05:21:06 -04:00
|
|
|
},
|
2020-04-23 07:51:06 -04:00
|
|
|
{ $set: { rootFolder: [this.mockRootFolder] }, $inc: { version: 1 } },
|
|
|
|
{ new: true, lean: true, fields: { version: 1 } }
|
2019-11-21 07:44:39 -05:00
|
|
|
)
|
|
|
|
.chain('exec')
|
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('happy path', function () {
|
|
|
|
beforeEach(async function () {
|
2020-04-23 07:51:06 -04:00
|
|
|
this.updateExpectation.resolves({ version: 1 })
|
2019-11-21 07:44:39 -05:00
|
|
|
await this.subject.promises.createNewFolderStructure(
|
|
|
|
this.project._id,
|
|
|
|
this.docUploads,
|
|
|
|
this.fileUploads
|
2019-05-29 05:21:06 -04:00
|
|
|
)
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('updates the database', function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
this.ProjectMock.verify()
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe("when the update doesn't find a matching document", function () {
|
|
|
|
beforeEach(async function () {
|
2020-04-23 07:51:06 -04:00
|
|
|
this.updateExpectation.resolves(null)
|
2019-11-21 07:44:39 -05:00
|
|
|
})
|
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
it('throws an error', async function () {
|
2019-11-21 07:44:39 -05:00
|
|
|
await expect(
|
|
|
|
this.subject.promises.createNewFolderStructure(
|
|
|
|
this.project._id,
|
|
|
|
this.docUploads,
|
|
|
|
this.fileUploads
|
|
|
|
)
|
|
|
|
).to.be.rejected
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
})
|
2020-03-04 04:37:43 -05:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('replaceDocWithFile', function () {
|
|
|
|
it('should simultaneously remove the doc and add the file', async function () {
|
2020-03-04 04:37:43 -05:00
|
|
|
this.ProjectMock.expects('findOneAndUpdate')
|
|
|
|
.withArgs(
|
2022-04-06 09:26:42 -04:00
|
|
|
{ _id: this.project._id, 'rootFolder.0': { $exists: true } },
|
2020-03-04 04:37:43 -05:00
|
|
|
{
|
|
|
|
$pull: { 'rootFolder.0.docs': { _id: this.doc._id } },
|
|
|
|
$push: { 'rootFolder.0.fileRefs': this.file },
|
2021-04-27 03:52:58 -04:00
|
|
|
$inc: { version: 1 },
|
2020-03-04 04:37:43 -05:00
|
|
|
},
|
|
|
|
{ new: true }
|
|
|
|
)
|
|
|
|
.chain('exec')
|
|
|
|
.resolves(this.project)
|
|
|
|
await this.subject.promises.replaceDocWithFile(
|
|
|
|
this.project._id,
|
|
|
|
this.doc._id,
|
|
|
|
this.file
|
|
|
|
)
|
|
|
|
this.ProjectMock.verify()
|
|
|
|
})
|
|
|
|
})
|
2020-04-27 09:00:56 -04:00
|
|
|
|
2021-04-14 09:17:21 -04:00
|
|
|
describe('replaceFileWithDoc', function () {
|
|
|
|
it('should simultaneously remove the file and add the doc', async function () {
|
2020-04-27 09:00:56 -04:00
|
|
|
this.ProjectMock.expects('findOneAndUpdate')
|
|
|
|
.withArgs(
|
2022-04-06 09:26:42 -04:00
|
|
|
{ _id: this.project._id, 'rootFolder.0': { $exists: true } },
|
2020-04-27 09:00:56 -04:00
|
|
|
{
|
|
|
|
$pull: { 'rootFolder.0.fileRefs': { _id: this.file._id } },
|
|
|
|
$push: { 'rootFolder.0.docs': this.doc },
|
2021-04-27 03:52:58 -04:00
|
|
|
$inc: { version: 1 },
|
2020-04-27 09:00:56 -04:00
|
|
|
},
|
|
|
|
{ new: true }
|
|
|
|
)
|
|
|
|
.chain('exec')
|
|
|
|
.resolves(this.project)
|
|
|
|
await this.subject.promises.replaceFileWithDoc(
|
|
|
|
this.project._id,
|
|
|
|
this.file._id,
|
|
|
|
this.doc
|
|
|
|
)
|
|
|
|
this.ProjectMock.verify()
|
|
|
|
})
|
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|