|
|
@@ -1,444 +0,0 @@
|
|
|
-import { expect, vi } from 'vitest'
|
|
|
-import sinon from 'sinon'
|
|
|
-import Errors from '../../../../app/src/Features/Errors/Errors.js'
|
|
|
-const modulePath =
|
|
|
- '../../../../app/src/Features/References/ReferencesHandler.mjs'
|
|
|
-
|
|
|
-vi.mock('../../../../app/src/Features/Errors/Errors.js', () =>
|
|
|
- vi.importActual('../../../../app/src/Features/Errors/Errors.js')
|
|
|
-)
|
|
|
-
|
|
|
-describe('ReferencesHandler', function () {
|
|
|
- beforeEach(async function (ctx) {
|
|
|
- ctx.projectId = '222'
|
|
|
- ctx.historyId = 42
|
|
|
- ctx.fakeProject = {
|
|
|
- _id: ctx.projectId,
|
|
|
- owner_ref: (ctx.fakeOwner = {
|
|
|
- _id: 'some_owner',
|
|
|
- features: {
|
|
|
- references: false,
|
|
|
- },
|
|
|
- }),
|
|
|
- rootFolder: [
|
|
|
- {
|
|
|
- docs: [
|
|
|
- { name: 'one.bib', _id: 'aaa' },
|
|
|
- { name: 'two.txt', _id: 'bbb' },
|
|
|
- ],
|
|
|
- folders: [
|
|
|
- {
|
|
|
- docs: [{ name: 'three.bib', _id: 'ccc' }],
|
|
|
- fileRefs: [
|
|
|
- { name: 'four.bib', _id: 'fff', hash: 'abc' },
|
|
|
- { name: 'five.bib', _id: 'ggg', hash: 'def' },
|
|
|
- ],
|
|
|
- folders: [],
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
- ],
|
|
|
- overleaf: { history: { id: ctx.historyId } },
|
|
|
- }
|
|
|
- ctx.docIds = ['aaa', 'ccc']
|
|
|
-
|
|
|
- vi.doMock('@overleaf/settings', () => ({
|
|
|
- default: (ctx.settings = {
|
|
|
- apis: {
|
|
|
- references: { url: 'http://some.url/references' },
|
|
|
- docstore: { url: 'http://some.url/docstore' },
|
|
|
- filestore: { url: 'http://some.url/filestore' },
|
|
|
- project_history: { url: 'http://project-history.local' },
|
|
|
- },
|
|
|
- }),
|
|
|
- }))
|
|
|
-
|
|
|
- vi.doMock('request', () => ({
|
|
|
- default: (ctx.request = {
|
|
|
- get: sinon.stub(),
|
|
|
- post: sinon.stub(),
|
|
|
- }),
|
|
|
- }))
|
|
|
-
|
|
|
- vi.doMock('../../../../app/src/Features/Project/ProjectGetter', () => ({
|
|
|
- default: (ctx.ProjectGetter = {
|
|
|
- getProject: sinon.stub().callsArgWith(2, null, ctx.fakeProject),
|
|
|
- }),
|
|
|
- }))
|
|
|
-
|
|
|
- vi.doMock('../../../../app/src/Features/User/UserGetter', () => ({
|
|
|
- default: (ctx.UserGetter = {
|
|
|
- getUser: sinon.stub(),
|
|
|
- }),
|
|
|
- }))
|
|
|
-
|
|
|
- vi.doMock(
|
|
|
- '../../../../app/src/Features/DocumentUpdater/DocumentUpdaterHandler',
|
|
|
- () => ({
|
|
|
- default: (ctx.DocumentUpdaterHandler = {
|
|
|
- flushDocToMongo: sinon.stub().callsArgWith(2, null),
|
|
|
- }),
|
|
|
- })
|
|
|
- )
|
|
|
-
|
|
|
- vi.doMock('../../../../app/src/infrastructure/Features', () => ({
|
|
|
- default: (ctx.Features = {
|
|
|
- hasFeature: sinon.stub().returns(true),
|
|
|
- }),
|
|
|
- }))
|
|
|
-
|
|
|
- ctx.handler = (await import(modulePath)).default
|
|
|
- ctx.fakeResponseData = {
|
|
|
- projectId: ctx.projectId,
|
|
|
- keys: ['k1', 'k2'],
|
|
|
- }
|
|
|
- })
|
|
|
-
|
|
|
- describe('indexAll', function () {
|
|
|
- beforeEach(function (ctx) {
|
|
|
- sinon.stub(ctx.handler, '_findBibDocIds').returns(['aaa', 'ccc'])
|
|
|
- sinon.stub(ctx.handler, '_findBibFileRefs').returns([
|
|
|
- { _id: 'fff', hash: 'abc' },
|
|
|
- { _id: 'ggg', hash: 'def' },
|
|
|
- ])
|
|
|
- sinon.stub(ctx.handler, '_isFullIndex').callsArgWith(1, null, true)
|
|
|
- ctx.request.post.callsArgWith(
|
|
|
- 1,
|
|
|
- null,
|
|
|
- { statusCode: 200 },
|
|
|
- ctx.fakeResponseData
|
|
|
- )
|
|
|
- return (ctx.call = callback => {
|
|
|
- return ctx.handler.indexAll(ctx.projectId, callback)
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- it('should call _findBibDocIds', async function (ctx) {
|
|
|
- await new Promise(resolve => {
|
|
|
- return ctx.call((err, data) => {
|
|
|
- expect(err).to.be.null
|
|
|
- ctx.handler._findBibDocIds.callCount.should.equal(1)
|
|
|
- ctx.handler._findBibDocIds
|
|
|
- .calledWith(ctx.fakeProject)
|
|
|
- .should.equal(true)
|
|
|
- return resolve()
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- it('should call _findBibFileRefs', async function (ctx) {
|
|
|
- await new Promise(resolve => {
|
|
|
- return ctx.call((err, data) => {
|
|
|
- expect(err).to.be.null
|
|
|
- ctx.handler._findBibDocIds.callCount.should.equal(1)
|
|
|
- ctx.handler._findBibDocIds
|
|
|
- .calledWith(ctx.fakeProject)
|
|
|
- .should.equal(true)
|
|
|
- return resolve()
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- it('should call DocumentUpdaterHandler.flushDocToMongo', async function (ctx) {
|
|
|
- await new Promise(resolve => {
|
|
|
- return ctx.call((err, data) => {
|
|
|
- expect(err).to.be.null
|
|
|
- ctx.DocumentUpdaterHandler.flushDocToMongo.callCount.should.equal(2)
|
|
|
- return resolve()
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- it('should make a request to references service', async function (ctx) {
|
|
|
- await new Promise(resolve => {
|
|
|
- return ctx.call((err, data) => {
|
|
|
- expect(err).to.be.null
|
|
|
- ctx.request.post.callCount.should.equal(1)
|
|
|
- const arg = ctx.request.post.firstCall.args[0]
|
|
|
- expect(arg.json).to.have.all.keys(
|
|
|
- 'docUrls',
|
|
|
- 'sourceURLs',
|
|
|
- 'fullIndex'
|
|
|
- )
|
|
|
- expect(arg.json.docUrls.length).to.equal(4)
|
|
|
- expect(arg.json.docUrls).to.deep.equal([
|
|
|
- `${ctx.settings.apis.docstore.url}/project/${ctx.projectId}/doc/aaa/raw`,
|
|
|
- `${ctx.settings.apis.docstore.url}/project/${ctx.projectId}/doc/ccc/raw`,
|
|
|
- `${ctx.settings.apis.project_history.url}/project/${ctx.historyId}/blob/abc`,
|
|
|
- `${ctx.settings.apis.project_history.url}/project/${ctx.historyId}/blob/def`,
|
|
|
- ])
|
|
|
- expect(arg.json.sourceURLs.length).to.equal(4)
|
|
|
- expect(arg.json.sourceURLs).to.deep.equal([
|
|
|
- {
|
|
|
- url: `${ctx.settings.apis.docstore.url}/project/${ctx.projectId}/doc/aaa/raw`,
|
|
|
- },
|
|
|
- {
|
|
|
- url: `${ctx.settings.apis.docstore.url}/project/${ctx.projectId}/doc/ccc/raw`,
|
|
|
- },
|
|
|
- {
|
|
|
- url: `${ctx.settings.apis.project_history.url}/project/${ctx.historyId}/blob/abc`,
|
|
|
- },
|
|
|
- {
|
|
|
- url: `${ctx.settings.apis.project_history.url}/project/${ctx.historyId}/blob/def`,
|
|
|
- },
|
|
|
- ])
|
|
|
- expect(arg.json.fullIndex).to.equal(true)
|
|
|
- return resolve()
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- it('should not produce an error', async function (ctx) {
|
|
|
- await new Promise(resolve => {
|
|
|
- return ctx.call((err, data) => {
|
|
|
- expect(err).to.equal(null)
|
|
|
- return resolve()
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- it('should return data', async function (ctx) {
|
|
|
- await new Promise(resolve => {
|
|
|
- return ctx.call((err, data) => {
|
|
|
- expect(err).to.be.null
|
|
|
- expect(data).to.not.equal(null)
|
|
|
- expect(data).to.not.equal(undefined)
|
|
|
- expect(data).to.equal(ctx.fakeResponseData)
|
|
|
- return resolve()
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- describe('when ProjectGetter.getProject produces an error', function () {
|
|
|
- beforeEach(function (ctx) {
|
|
|
- ctx.ProjectGetter.getProject.callsArgWith(2, new Error('woops'))
|
|
|
- })
|
|
|
-
|
|
|
- it('should produce an error', async function (ctx) {
|
|
|
- await new Promise(resolve => {
|
|
|
- ctx.call((err, data) => {
|
|
|
- expect(err).to.not.equal(null)
|
|
|
- expect(err).to.be.instanceof(Error)
|
|
|
- expect(data).to.equal(undefined)
|
|
|
- resolve()
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- it('should not send request', async function (ctx) {
|
|
|
- await new Promise(resolve => {
|
|
|
- ctx.call(() => {
|
|
|
- ctx.request.post.callCount.should.equal(0)
|
|
|
- resolve()
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- describe('when ProjectGetter.getProject returns null', function () {
|
|
|
- beforeEach(function (ctx) {
|
|
|
- ctx.ProjectGetter.getProject.callsArgWith(2, null)
|
|
|
- })
|
|
|
-
|
|
|
- it('should produce an error', async function (ctx) {
|
|
|
- await new Promise(resolve => {
|
|
|
- ctx.call((err, data) => {
|
|
|
- expect(err).to.not.equal(null)
|
|
|
- expect(err).to.be.instanceof(Errors.NotFoundError)
|
|
|
- expect(data).to.equal(undefined)
|
|
|
- resolve()
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- it('should not send request', async function (ctx) {
|
|
|
- await new Promise(resolve => {
|
|
|
- ctx.call(() => {
|
|
|
- ctx.request.post.callCount.should.equal(0)
|
|
|
- resolve()
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- describe('when _isFullIndex produces an error', function () {
|
|
|
- beforeEach(function (ctx) {
|
|
|
- ctx.ProjectGetter.getProject.callsArgWith(2, null, ctx.fakeProject)
|
|
|
- ctx.handler._isFullIndex.callsArgWith(1, new Error('woops'))
|
|
|
- })
|
|
|
-
|
|
|
- it('should produce an error', async function (ctx) {
|
|
|
- await new Promise(resolve => {
|
|
|
- ctx.call((err, data) => {
|
|
|
- expect(err).to.not.equal(null)
|
|
|
- expect(err).to.be.instanceof(Error)
|
|
|
- expect(data).to.equal(undefined)
|
|
|
- resolve()
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- it('should not send request', async function (ctx) {
|
|
|
- await new Promise(resolve => {
|
|
|
- ctx.call(() => {
|
|
|
- ctx.request.post.callCount.should.equal(0)
|
|
|
- resolve()
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- describe('when flushDocToMongo produces an error', function () {
|
|
|
- beforeEach(function (ctx) {
|
|
|
- ctx.ProjectGetter.getProject.callsArgWith(2, null, ctx.fakeProject)
|
|
|
- ctx.handler._isFullIndex.callsArgWith(1, false)
|
|
|
- ctx.DocumentUpdaterHandler.flushDocToMongo.callsArgWith(
|
|
|
- 2,
|
|
|
- new Error('woops')
|
|
|
- )
|
|
|
- })
|
|
|
-
|
|
|
- it('should produce an error', async function (ctx) {
|
|
|
- await new Promise(resolve => {
|
|
|
- ctx.call((err, data) => {
|
|
|
- expect(err).to.not.equal(null)
|
|
|
- expect(err).to.be.instanceof(Error)
|
|
|
- expect(data).to.equal(undefined)
|
|
|
- resolve()
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- it('should not send request', async function (ctx) {
|
|
|
- await new Promise(resolve => {
|
|
|
- ctx.call(() => {
|
|
|
- ctx.request.post.callCount.should.equal(0)
|
|
|
- resolve()
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- describe('_findBibDocIds', function () {
|
|
|
- beforeEach(function (ctx) {
|
|
|
- ctx.fakeProject = {
|
|
|
- rootFolder: [
|
|
|
- {
|
|
|
- docs: [
|
|
|
- { name: 'one.bib', _id: 'aaa' },
|
|
|
- { name: 'two.txt', _id: 'bbb' },
|
|
|
- ],
|
|
|
- folders: [
|
|
|
- { docs: [{ name: 'three.bib', _id: 'ccc' }], folders: [] },
|
|
|
- ],
|
|
|
- },
|
|
|
- ],
|
|
|
- }
|
|
|
- ctx.expectedIds = ['aaa', 'ccc']
|
|
|
- })
|
|
|
-
|
|
|
- it('should select the correct docIds', function (ctx) {
|
|
|
- const result = ctx.handler._findBibDocIds(ctx.fakeProject)
|
|
|
- expect(result).to.deep.equal(ctx.expectedIds)
|
|
|
- })
|
|
|
-
|
|
|
- it('should not error with a non array of folders from dirty data', function (ctx) {
|
|
|
- ctx.fakeProject.rootFolder[0].folders[0].folders = {}
|
|
|
- const result = ctx.handler._findBibDocIds(ctx.fakeProject)
|
|
|
- expect(result).to.deep.equal(ctx.expectedIds)
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- describe('_findBibFileRefs', function () {
|
|
|
- beforeEach(function (ctx) {
|
|
|
- ctx.fakeProject = {
|
|
|
- rootFolder: [
|
|
|
- {
|
|
|
- docs: [
|
|
|
- { name: 'one.bib', _id: 'aaa' },
|
|
|
- { name: 'two.txt', _id: 'bbb' },
|
|
|
- ],
|
|
|
- fileRefs: [{ name: 'other.bib', _id: 'ddd' }],
|
|
|
- folders: [
|
|
|
- {
|
|
|
- docs: [{ name: 'three.bib', _id: 'ccc' }],
|
|
|
- fileRefs: [{ name: 'four.bib', _id: 'ghg' }],
|
|
|
- folders: [],
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
- ],
|
|
|
- }
|
|
|
- ctx.expectedIds = [
|
|
|
- ctx.fakeProject.rootFolder[0].fileRefs[0],
|
|
|
- ctx.fakeProject.rootFolder[0].folders[0].fileRefs[0],
|
|
|
- ]
|
|
|
- })
|
|
|
-
|
|
|
- it('should select the correct docIds', function (ctx) {
|
|
|
- const result = ctx.handler._findBibFileRefs(ctx.fakeProject)
|
|
|
- expect(result).to.deep.equal(ctx.expectedIds)
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- describe('_isFullIndex', function () {
|
|
|
- beforeEach(function (ctx) {
|
|
|
- ctx.fakeProject = { owner_ref: (ctx.owner_ref = 'owner-ref-123') }
|
|
|
- ctx.owner = {
|
|
|
- features: {
|
|
|
- references: false,
|
|
|
- },
|
|
|
- }
|
|
|
- ctx.UserGetter.getUser = sinon.stub()
|
|
|
- ctx.UserGetter.getUser
|
|
|
- .withArgs(ctx.owner_ref, { features: true })
|
|
|
- .yields(null, ctx.owner)
|
|
|
- ctx.call = callback => {
|
|
|
- ctx.handler._isFullIndex(ctx.fakeProject, callback)
|
|
|
- }
|
|
|
- })
|
|
|
-
|
|
|
- describe('with references feature on', function () {
|
|
|
- beforeEach(function (ctx) {
|
|
|
- ctx.owner.features.references = true
|
|
|
- })
|
|
|
-
|
|
|
- it('should return true', function (ctx) {
|
|
|
- ctx.call((err, isFullIndex) => {
|
|
|
- expect(err).to.equal(null)
|
|
|
- expect(isFullIndex).to.equal(true)
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- describe('with references feature off', function () {
|
|
|
- beforeEach(function (ctx) {
|
|
|
- ctx.owner.features.references = false
|
|
|
- })
|
|
|
-
|
|
|
- it('should return false', function (ctx) {
|
|
|
- ctx.call((err, isFullIndex) => {
|
|
|
- expect(err).to.equal(null)
|
|
|
- expect(isFullIndex).to.equal(false)
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- describe('with referencesSearch', function () {
|
|
|
- beforeEach(function (ctx) {
|
|
|
- ctx.owner.features = {
|
|
|
- referencesSearch: true,
|
|
|
- references: false,
|
|
|
- }
|
|
|
- })
|
|
|
-
|
|
|
- it('should return true', function (ctx) {
|
|
|
- ctx.call((err, isFullIndex) => {
|
|
|
- expect(err).to.equal(null)
|
|
|
- expect(isFullIndex).to.equal(true)
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
-})
|