| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550 |
- import { vi, expect } from 'vitest'
- import sinon from 'sinon'
- import Errors from '../../../../app/src/Features/Errors/Errors.js'
- const modulePath = '../../../../app/src/Features/Project/ProjectLocator'
- vi.mock('../../../../app/src/Features/Errors/Errors.js', () =>
- vi.importActual('../../../../app/src/Features/Errors/Errors.js')
- )
- const project = { _id: '1234566', rootFolder: [] }
- const rootDoc = { name: 'rootDoc', _id: 'das239djd' }
- const doc1 = { name: 'otherDoc.txt', _id: 'dsad2ddd' }
- const doc2 = { name: 'docname.txt', _id: 'dsad2ddddd' }
- const file1 = { name: 'file1', _id: 'dsa9lkdsad' }
- const subSubFile = { name: 'subSubFile', _id: 'd1d2dk' }
- const subSubDoc = { name: 'subdoc.txt', _id: '321dmdwi' }
- const firstSubFolder = {
- name: 'firstSubFolder',
- _id: 'rweq43',
- docs: [],
- fileRefs: [],
- folders: [],
- }
- const secondSubFolder = {
- name: 'secondSubFolder',
- _id: 'dsa3e23',
- docs: [subSubDoc],
- fileRefs: [subSubFile],
- folders: [],
- }
- const subFolder = {
- name: 'subFolder',
- _id: 'dsadsa93',
- folders: [secondSubFolder, null],
- docs: [],
- fileRefs: [],
- }
- const subFolder1 = {
- name: 'subFolder1',
- _id: '123asdjoij',
- folders: [firstSubFolder],
- }
- const rootFolder = {
- _id: '123sdskd',
- docs: [doc1, doc2, null, rootDoc],
- fileRefs: [file1],
- folders: [subFolder1, subFolder],
- }
- project.rootFolder[0] = rootFolder
- project.rootDoc_id = rootDoc._id
- describe('ProjectLocator', function () {
- beforeEach(async function (ctx) {
- ctx.ProjectGetter = {
- promises: {
- getProject: sinon.stub().resolves(project),
- },
- }
- ctx.ProjectHelper = {
- isArchived: sinon.stub(),
- isTrashed: sinon.stub(),
- isArchivedOrTrashed: sinon.stub(),
- }
- vi.doMock('../../../../app/src/models/User', () => ({
- default: { User: ctx.User },
- }))
- vi.doMock('../../../../app/src/Features/Project/ProjectGetter', () => ({
- default: ctx.ProjectGetter,
- }))
- vi.doMock('../../../../app/src/Features/Project/ProjectHelper', () => ({
- default: ctx.ProjectHelper,
- }))
- ctx.locator = (await import(modulePath)).default
- })
- describe('finding a doc', function () {
- it('finds one at the root level', async function (ctx) {
- const { element, path, folder } = await ctx.locator.promises.findElement({
- project_id: project._id,
- element_id: doc2._id,
- type: 'docs',
- })
- element._id.should.equal(doc2._id)
- path.fileSystem.should.equal(`/${doc2.name}`)
- folder._id.should.equal(project.rootFolder[0]._id)
- path.mongo.should.equal('rootFolder.0.docs.1')
- })
- it('when it is nested', async function (ctx) {
- const { element, path, folder } = await ctx.locator.promises.findElement({
- project_id: project._id,
- element_id: subSubDoc._id,
- type: 'doc',
- })
- expect(element._id).to.equal(subSubDoc._id)
- path.fileSystem.should.equal(
- `/${subFolder.name}/${secondSubFolder.name}/${subSubDoc.name}`
- )
- folder._id.should.equal(secondSubFolder._id)
- path.mongo.should.equal('rootFolder.0.folders.1.folders.0.docs.0')
- })
- it('should give error if element could not be found', async function (ctx) {
- await expect(
- ctx.locator.promises.findElement({
- project_id: project._id,
- element_id: 'ddsd432nj42',
- type: 'docs',
- })
- )
- .to.eventually.be.rejectedWith(Errors.NotFoundError)
- .and.eventually.have.property('message', 'entity not found')
- })
- })
- describe('finding a folder', function () {
- it('should return root folder when looking for root folder', async function (ctx) {
- const { element: foundElement } = await ctx.locator.promises.findElement({
- project_id: project._id,
- element_id: rootFolder._id,
- type: 'folder',
- })
- foundElement._id.should.equal(rootFolder._id)
- })
- it('should not return root folder when searching for docs', async function (ctx) {
- await expect(
- ctx.locator.promises.findElement({
- project_id: project._id,
- element_id: rootFolder._id,
- type: 'docs',
- })
- )
- .to.eventually.be.rejectedWith(Errors.NotFoundError)
- .and.eventually.have.property('message', 'entity not found')
- })
- it('should not return root folder when searching for files', async function (ctx) {
- await expect(
- ctx.locator.promises.findElement({
- project_id: project._id,
- element_id: rootFolder._id,
- type: 'files',
- })
- )
- .to.eventually.be.rejectedWith(Errors.NotFoundError)
- .and.eventually.have.property('message', 'entity not found')
- })
- it('when at root', async function (ctx) {
- const {
- element: foundElement,
- path,
- folder: parentFolder,
- } = await ctx.locator.promises.findElement({
- project_id: project._id,
- element_id: subFolder._id,
- type: 'folder',
- })
- foundElement._id.should.equal(subFolder._id)
- path.fileSystem.should.equal(`/${subFolder.name}`)
- parentFolder._id.should.equal(rootFolder._id)
- path.mongo.should.equal('rootFolder.0.folders.1')
- })
- it('when deeply nested', async function (ctx) {
- const {
- element: foundElement,
- path,
- folder: parentFolder,
- } = await ctx.locator.promises.findElement({
- project_id: project._id,
- element_id: secondSubFolder._id,
- type: 'folder',
- })
- foundElement._id.should.equal(secondSubFolder._id)
- path.fileSystem.should.equal(`/${subFolder.name}/${secondSubFolder.name}`)
- parentFolder._id.should.equal(subFolder._id)
- path.mongo.should.equal('rootFolder.0.folders.1.folders.0')
- })
- })
- describe('finding a file', function () {
- it('when at root', async function (ctx) {
- const {
- element: foundElement,
- path,
- folder: parentFolder,
- } = await ctx.locator.promises.findElement({
- project_id: project._id,
- element_id: file1._id,
- type: 'fileRefs',
- })
- foundElement._id.should.equal(file1._id)
- path.fileSystem.should.equal(`/${file1.name}`)
- parentFolder._id.should.equal(rootFolder._id)
- path.mongo.should.equal('rootFolder.0.fileRefs.0')
- })
- it('when deeply nested', async function (ctx) {
- const {
- element: foundElement,
- path,
- folder: parentFolder,
- } = await ctx.locator.promises.findElement({
- project_id: project._id,
- element_id: subSubFile._id,
- type: 'fileRefs',
- })
- foundElement._id.should.equal(subSubFile._id)
- path.fileSystem.should.equal(
- `/${subFolder.name}/${secondSubFolder.name}/${subSubFile.name}`
- )
- parentFolder._id.should.equal(secondSubFolder._id)
- path.mongo.should.equal('rootFolder.0.folders.1.folders.0.fileRefs.0')
- })
- })
- describe('finding an element with wrong element type', function () {
- it('should add an s onto the element type', async function (ctx) {
- const { element: foundElement } = await ctx.locator.promises.findElement({
- project_id: project._id,
- element_id: subSubDoc._id,
- type: 'doc',
- })
- foundElement._id.should.equal(subSubDoc._id)
- })
- it('should convert file to fileRefs', async function (ctx) {
- const { element: foundElement } = await ctx.locator.promises.findElement({
- project_id: project._id,
- element_id: file1._id,
- type: 'fileRefs',
- })
- foundElement._id.should.equal(file1._id)
- })
- })
- describe('should be able to take actual project as well as id', function () {
- const doc3 = {
- _id: '123dsdj3',
- name: 'doc3',
- }
- const rootFolder2 = {
- _id: '123sddedskd',
- docs: [doc3],
- }
- const project2 = {
- _id: '1234566',
- rootFolder: [rootFolder2],
- }
- it('should find doc in project', async function (ctx) {
- const {
- element: foundElement,
- path,
- folder: parentFolder,
- } = await ctx.locator.promises.findElement({
- project: project2,
- element_id: doc3._id,
- type: 'docs',
- })
- foundElement._id.should.equal(doc3._id)
- path.fileSystem.should.equal(`/${doc3.name}`)
- parentFolder._id.should.equal(project2.rootFolder[0]._id)
- path.mongo.should.equal('rootFolder.0.docs.0')
- })
- })
- describe('finding root doc', function () {
- it('should return root doc when passed project', async function (ctx) {
- const { element: doc } = await ctx.locator.promises.findRootDoc(project)
- doc._id.should.equal(rootDoc._id)
- })
- it('should return root doc when passed project_id', async function (ctx) {
- const { element: doc } = await ctx.locator.promises.findRootDoc(
- project._id
- )
- doc._id.should.equal(rootDoc._id)
- })
- it('should return null when the project has no rootDoc', async function (ctx) {
- project.rootDoc_id = null
- const { element: rootDoc } =
- await ctx.locator.promises.findRootDoc(project)
- expect(rootDoc).to.equal(null)
- })
- it('should return null when the rootDoc_id no longer exists', async function (ctx) {
- project.rootDoc_id = 'doesntexist'
- const { element: rootDoc } =
- await ctx.locator.promises.findRootDoc(project)
- expect(rootDoc).to.equal(null)
- })
- })
- describe('findElementByPath', function () {
- it('should take a doc path and return the element for a root level document', async function (ctx) {
- const path = `${doc1.name}`
- const { element, type, folder } =
- await ctx.locator.promises.findElementByPath({
- project,
- path,
- })
- element.should.deep.equal(doc1)
- expect(type).to.equal('doc')
- expect(folder).to.equal(rootFolder)
- })
- it('should take a doc path and return the element for a root level document with a starting slash', async function (ctx) {
- const path = `/${doc1.name}`
- const { element, type, folder } =
- await ctx.locator.promises.findElementByPath({
- project,
- path,
- })
- element.should.deep.equal(doc1)
- expect(type).to.equal('doc')
- expect(folder).to.equal(rootFolder)
- })
- it('should take a doc path and return the element for a nested document', async function (ctx) {
- const path = `${subFolder.name}/${secondSubFolder.name}/${subSubDoc.name}`
- const { element, type, folder } =
- await ctx.locator.promises.findElementByPath({
- project,
- path,
- })
- element.should.deep.equal(subSubDoc)
- expect(type).to.equal('doc')
- expect(folder).to.equal(secondSubFolder)
- })
- it('should take a file path and return the element for a root level document', async function (ctx) {
- const path = `${file1.name}`
- const { element, type, folder } =
- await ctx.locator.promises.findElementByPath({
- project,
- path,
- })
- element.should.deep.equal(file1)
- expect(type).to.equal('file')
- expect(folder).to.equal(rootFolder)
- })
- it('should take a file path and return the element for a nested document', async function (ctx) {
- const path = `${subFolder.name}/${secondSubFolder.name}/${subSubFile.name}`
- const { element, type, folder } =
- await ctx.locator.promises.findElementByPath({
- project,
- path,
- })
- element.should.deep.equal(subSubFile)
- expect(type).to.equal('file')
- expect(folder).to.equal(secondSubFolder)
- })
- it('should take a file path and return the element for a nested document case insenstive', async function (ctx) {
- const path = `${subFolder.name.toUpperCase()}/${secondSubFolder.name.toUpperCase()}/${subSubFile.name.toUpperCase()}`
- const { element, type, folder } =
- await ctx.locator.promises.findElementByPath({
- project,
- path,
- })
- element.should.deep.equal(subSubFile)
- expect(type).to.equal('file')
- expect(folder).to.equal(secondSubFolder)
- })
- it('should not return elements with a case-insensitive match when exactCaseMatch is true', async function (ctx) {
- const path = `${subFolder.name.toUpperCase()}/${secondSubFolder.name.toUpperCase()}/${subSubFile.name.toUpperCase()}`
- await expect(
- ctx.locator.promises.findElementByPath({
- project,
- path,
- exactCaseMatch: true,
- })
- ).to.eventually.be.rejected
- })
- it('should take a file path and return the element for a nested folder', async function (ctx) {
- const path = `${subFolder.name}/${secondSubFolder.name}`
- const { element, type, folder } =
- await ctx.locator.promises.findElementByPath({
- project,
- path,
- })
- element.should.deep.equal(secondSubFolder)
- expect(type).to.equal('folder')
- expect(folder).to.equal(subFolder)
- })
- it('should take a file path and return the root folder', async function (ctx) {
- const path = '/'
- const { element, type, folder } =
- await ctx.locator.promises.findElementByPath({
- project,
- path,
- })
- element.should.deep.equal(rootFolder)
- expect(type).to.equal('folder')
- expect(folder).to.equal(null)
- })
- it('should return an error if the file can not be found inside know folder', async function (ctx) {
- const path = `${subFolder.name}/${secondSubFolder.name}/exist.txt`
- await expect(ctx.locator.promises.findElementByPath({ project, path })).to
- .eventually.be.rejected
- })
- it('should return an error if the file can not be found inside unknown folder', async function (ctx) {
- const path = 'this/does/not/exist.txt'
- await expect(
- ctx.locator.promises.findElementByPath({
- project,
- path,
- })
- ).to.eventually.be.rejected
- })
- describe('where duplicate folder exists', function () {
- beforeEach(function (ctx) {
- ctx.duplicateFolder = {
- name: 'duplicate1',
- _id: '1234',
- folders: [
- {
- name: '1',
- docs: [{ name: 'main.tex', _id: '456' }],
- folders: [],
- fileRefs: [],
- },
- ],
- docs: [(ctx.doc = { name: 'main.tex', _id: '456' })],
- fileRefs: [],
- }
- ctx.project = {
- rootFolder: [
- {
- folders: [ctx.duplicateFolder, ctx.duplicateFolder],
- fileRefs: [],
- docs: [],
- },
- ],
- }
- })
- it('should not call the callback more than once', async function (ctx) {
- const path = `${ctx.duplicateFolder.name}/${ctx.doc.name}`
- await ctx.locator.promises.findElementByPath({
- project: ctx.project,
- path,
- })
- }) // mocha will throw exception if done called multiple times
- it('should not call the callback more than once when the path is longer than 1 level below the duplicate level', async function (ctx) {
- const path = `${ctx.duplicateFolder.name}/1/main.tex`
- await ctx.locator.promises.findElementByPath({
- project: ctx.project,
- path,
- })
- })
- }) // mocha will throw exception if done called multiple times
- describe('with a null doc', function () {
- beforeEach(function (ctx) {
- ctx.project = {
- rootFolder: [
- {
- folders: [],
- fileRefs: [],
- docs: [{ name: 'main.tex' }, null, { name: 'other.tex' }],
- },
- ],
- }
- })
- it('should not crash with a null', async function (ctx) {
- const path = '/other.tex'
- const { element } = await ctx.locator.promises.findElementByPath({
- project: ctx.project,
- path,
- })
- element.name.should.equal('other.tex')
- })
- })
- describe('with a null project', function () {
- beforeEach(function (ctx) {
- ctx.ProjectGetter = {
- promises: {
- getProject: sinon.stub().resolves(null),
- },
- }
- })
- it('should not crash with a null', async function (ctx) {
- const path = '/other.tex'
- await expect(
- ctx.locator.promises.findElementByPath({
- project_id: project._id,
- path,
- })
- ).to.be.rejected
- })
- })
- describe('with a project_id', function () {
- it('should take a doc path and return the element for a root level document', async function (ctx) {
- const path = `${doc1.name}`
- const { element, type } = await ctx.locator.promises.findElementByPath({
- project_id: project._id,
- path,
- })
- ctx.ProjectGetter.promises.getProject
- .calledWith(project._id, { rootFolder: true, rootDoc_id: true })
- .should.equal(true)
- element.should.deep.equal(doc1)
- expect(type).to.equal('doc')
- })
- })
- })
- describe('findElementByMongoPath', function () {
- it('traverses the file tree like Mongo would do', function (ctx) {
- const element = ctx.locator.findElementByMongoPath(
- project,
- 'rootFolder.0.folders.1.folders.0.fileRefs.0'
- )
- expect(element).to.equal(subSubFile)
- })
- it('throws an error if no element is found', function (ctx) {
- expect(() =>
- ctx.locator.findElementByMongoPath(
- project,
- 'rootolder.0.folders.0.folders.0.fileRefs.0'
- )
- ).to.throw
- })
- })
- })
|