ReferencesHandlerTests.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. /* eslint-disable
  2. n/handle-callback-err,
  3. max-len,
  4. mocha/no-identical-title,
  5. no-return-assign,
  6. no-unused-vars,
  7. */
  8. // TODO: This file was created by bulk-decaffeinate.
  9. // Fix any style issues and re-enable lint.
  10. /*
  11. * decaffeinate suggestions:
  12. * DS102: Remove unnecessary code created because of implicit returns
  13. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  14. */
  15. const SandboxedModule = require('sandboxed-module')
  16. const { assert, expect } = require('chai')
  17. const sinon = require('sinon')
  18. const Errors = require('../../../../app/src/Features/Errors/Errors')
  19. const modulePath = '../../../../app/src/Features/References/ReferencesHandler'
  20. describe('ReferencesHandler', function () {
  21. beforeEach(function () {
  22. this.projectId = '222'
  23. this.fakeProject = {
  24. _id: this.projectId,
  25. owner_ref: (this.fakeOwner = {
  26. _id: 'some_owner',
  27. features: {
  28. references: false,
  29. },
  30. }),
  31. rootFolder: [
  32. {
  33. docs: [
  34. { name: 'one.bib', _id: 'aaa' },
  35. { name: 'two.txt', _id: 'bbb' },
  36. ],
  37. folders: [
  38. {
  39. docs: [{ name: 'three.bib', _id: 'ccc' }],
  40. fileRefs: [{ name: 'four.bib', _id: 'ghg' }],
  41. folders: [],
  42. },
  43. ],
  44. },
  45. ],
  46. }
  47. this.docIds = ['aaa', 'ccc']
  48. this.handler = SandboxedModule.require(modulePath, {
  49. requires: {
  50. '@overleaf/settings': (this.settings = {
  51. apis: {
  52. references: { url: 'http://some.url/references' },
  53. docstore: { url: 'http://some.url/docstore' },
  54. filestore: { url: 'http://some.url/filestore' },
  55. },
  56. }),
  57. request: (this.request = {
  58. get: sinon.stub(),
  59. post: sinon.stub(),
  60. }),
  61. '../Project/ProjectGetter': (this.ProjectGetter = {
  62. getProject: sinon.stub().callsArgWith(2, null, this.fakeProject),
  63. }),
  64. '../User/UserGetter': (this.UserGetter = {
  65. getUser: sinon.stub(),
  66. }),
  67. '../DocumentUpdater/DocumentUpdaterHandler':
  68. (this.DocumentUpdaterHandler = {
  69. flushDocToMongo: sinon.stub().callsArgWith(2, null),
  70. }),
  71. '../../infrastructure/Features': (this.Features = {
  72. hasFeature: sinon.stub().returns(true),
  73. }),
  74. },
  75. })
  76. return (this.fakeResponseData = {
  77. projectId: this.projectId,
  78. keys: ['k1', 'k2'],
  79. })
  80. })
  81. describe('indexAll', function () {
  82. beforeEach(function () {
  83. sinon.stub(this.handler, '_findBibDocIds').returns(['aaa', 'ccc'])
  84. sinon.stub(this.handler, '_findBibFileIds').returns(['fff', 'ggg'])
  85. sinon.stub(this.handler, '_isFullIndex').callsArgWith(1, null, true)
  86. this.request.post.callsArgWith(
  87. 1,
  88. null,
  89. { statusCode: 200 },
  90. this.fakeResponseData
  91. )
  92. return (this.call = callback => {
  93. return this.handler.indexAll(this.projectId, callback)
  94. })
  95. })
  96. it('should call _findBibDocIds', function (done) {
  97. return this.call((err, data) => {
  98. this.handler._findBibDocIds.callCount.should.equal(1)
  99. this.handler._findBibDocIds
  100. .calledWith(this.fakeProject)
  101. .should.equal(true)
  102. return done()
  103. })
  104. })
  105. it('should call _findBibFileIds', function (done) {
  106. return this.call((err, data) => {
  107. this.handler._findBibDocIds.callCount.should.equal(1)
  108. this.handler._findBibDocIds
  109. .calledWith(this.fakeProject)
  110. .should.equal(true)
  111. return done()
  112. })
  113. })
  114. it('should call DocumentUpdaterHandler.flushDocToMongo', function (done) {
  115. return this.call((err, data) => {
  116. this.DocumentUpdaterHandler.flushDocToMongo.callCount.should.equal(2)
  117. return done()
  118. })
  119. })
  120. it('should make a request to references service', function (done) {
  121. return this.call((err, data) => {
  122. this.request.post.callCount.should.equal(1)
  123. const arg = this.request.post.firstCall.args[0]
  124. expect(arg.json).to.have.all.keys('docUrls', 'fullIndex')
  125. expect(arg.json.docUrls.length).to.equal(4)
  126. expect(arg.json.fullIndex).to.equal(true)
  127. return done()
  128. })
  129. })
  130. it('should not produce an error', function (done) {
  131. return this.call((err, data) => {
  132. expect(err).to.equal(null)
  133. return done()
  134. })
  135. })
  136. it('should return data', function (done) {
  137. return this.call((err, data) => {
  138. expect(data).to.not.equal(null)
  139. expect(data).to.not.equal(undefined)
  140. expect(data).to.equal(this.fakeResponseData)
  141. return done()
  142. })
  143. })
  144. describe('when ProjectGetter.getProject produces an error', function () {
  145. beforeEach(function () {
  146. return this.ProjectGetter.getProject.callsArgWith(2, new Error('woops'))
  147. })
  148. it('should produce an error', function (done) {
  149. return this.call((err, data) => {
  150. expect(err).to.not.equal(null)
  151. expect(err).to.be.instanceof(Error)
  152. expect(data).to.equal(undefined)
  153. return done()
  154. })
  155. })
  156. it('should not send request', function (done) {
  157. return this.call((err, data) => {
  158. this.request.post.callCount.should.equal(0)
  159. return done()
  160. })
  161. })
  162. })
  163. describe('when ProjectGetter.getProject returns null', function () {
  164. beforeEach(function () {
  165. return this.ProjectGetter.getProject.callsArgWith(2, null)
  166. })
  167. it('should produce an error', function (done) {
  168. return this.call((err, data) => {
  169. expect(err).to.not.equal(null)
  170. expect(err).to.be.instanceof(Errors.NotFoundError)
  171. expect(data).to.equal(undefined)
  172. return done()
  173. })
  174. })
  175. it('should not send request', function (done) {
  176. return this.call((err, data) => {
  177. this.request.post.callCount.should.equal(0)
  178. return done()
  179. })
  180. })
  181. })
  182. describe('when _isFullIndex produces an error', function () {
  183. beforeEach(function () {
  184. this.ProjectGetter.getProject.callsArgWith(2, null, this.fakeProject)
  185. return this.handler._isFullIndex.callsArgWith(1, new Error('woops'))
  186. })
  187. it('should produce an error', function (done) {
  188. return this.call((err, data) => {
  189. expect(err).to.not.equal(null)
  190. expect(err).to.be.instanceof(Error)
  191. expect(data).to.equal(undefined)
  192. return done()
  193. })
  194. })
  195. it('should not send request', function (done) {
  196. return this.call((err, data) => {
  197. this.request.post.callCount.should.equal(0)
  198. return done()
  199. })
  200. })
  201. })
  202. describe('when flushDocToMongo produces an error', function () {
  203. beforeEach(function () {
  204. this.ProjectGetter.getProject.callsArgWith(2, null, this.fakeProject)
  205. this.handler._isFullIndex.callsArgWith(1, false)
  206. return this.DocumentUpdaterHandler.flushDocToMongo.callsArgWith(
  207. 2,
  208. new Error('woops')
  209. )
  210. })
  211. it('should produce an error', function (done) {
  212. return this.call((err, data) => {
  213. expect(err).to.not.equal(null)
  214. expect(err).to.be.instanceof(Error)
  215. expect(data).to.equal(undefined)
  216. return done()
  217. })
  218. })
  219. it('should not send request', function (done) {
  220. return this.call((err, data) => {
  221. this.request.post.callCount.should.equal(0)
  222. return done()
  223. })
  224. })
  225. })
  226. })
  227. describe('_findBibDocIds', function () {
  228. beforeEach(function () {
  229. this.fakeProject = {
  230. rootFolder: [
  231. {
  232. docs: [
  233. { name: 'one.bib', _id: 'aaa' },
  234. { name: 'two.txt', _id: 'bbb' },
  235. ],
  236. folders: [
  237. { docs: [{ name: 'three.bib', _id: 'ccc' }], folders: [] },
  238. ],
  239. },
  240. ],
  241. }
  242. return (this.expectedIds = ['aaa', 'ccc'])
  243. })
  244. it('should select the correct docIds', function () {
  245. const result = this.handler._findBibDocIds(this.fakeProject)
  246. return expect(result).to.deep.equal(this.expectedIds)
  247. })
  248. it('should not error with a non array of folders from dirty data', function () {
  249. this.fakeProject.rootFolder[0].folders[0].folders = {}
  250. const result = this.handler._findBibDocIds(this.fakeProject)
  251. return expect(result).to.deep.equal(this.expectedIds)
  252. })
  253. })
  254. describe('_findBibFileIds', function () {
  255. beforeEach(function () {
  256. this.fakeProject = {
  257. rootFolder: [
  258. {
  259. docs: [
  260. { name: 'one.bib', _id: 'aaa' },
  261. { name: 'two.txt', _id: 'bbb' },
  262. ],
  263. fileRefs: [{ name: 'other.bib', _id: 'ddd' }],
  264. folders: [
  265. {
  266. docs: [{ name: 'three.bib', _id: 'ccc' }],
  267. fileRefs: [{ name: 'four.bib', _id: 'ghg' }],
  268. folders: [],
  269. },
  270. ],
  271. },
  272. ],
  273. }
  274. return (this.expectedIds = ['ddd', 'ghg'])
  275. })
  276. it('should select the correct docIds', function () {
  277. const result = this.handler._findBibFileIds(this.fakeProject)
  278. return expect(result).to.deep.equal(this.expectedIds)
  279. })
  280. })
  281. describe('_isFullIndex', function () {
  282. beforeEach(function () {
  283. this.fakeProject = { owner_ref: (this.owner_ref = 'owner-ref-123') }
  284. this.owner = {
  285. features: {
  286. references: false,
  287. },
  288. }
  289. this.UserGetter.getUser = sinon.stub()
  290. this.UserGetter.getUser
  291. .withArgs(this.owner_ref, { features: true })
  292. .yields(null, this.owner)
  293. return (this.call = callback => {
  294. return this.handler._isFullIndex(this.fakeProject, callback)
  295. })
  296. })
  297. describe('with references feature on', function () {
  298. beforeEach(function () {
  299. return (this.owner.features.references = true)
  300. })
  301. it('should return true', function () {
  302. return this.call((err, isFullIndex) => {
  303. expect(err).to.equal(null)
  304. return expect(isFullIndex).to.equal(true)
  305. })
  306. })
  307. })
  308. describe('with references feature off', function () {
  309. beforeEach(function () {
  310. return (this.owner.features.references = false)
  311. })
  312. it('should return false', function () {
  313. return this.call((err, isFullIndex) => {
  314. expect(err).to.equal(null)
  315. return expect(isFullIndex).to.equal(false)
  316. })
  317. })
  318. })
  319. describe('with referencesSearch', function () {
  320. beforeEach(function () {
  321. return (this.owner.features = {
  322. referencesSearch: true,
  323. references: false,
  324. })
  325. })
  326. it('should return true', function () {
  327. return this.call((err, isFullIndex) => {
  328. expect(err).to.equal(null)
  329. return expect(isFullIndex).to.equal(true)
  330. })
  331. })
  332. })
  333. })
  334. })