DocstoreManagerTests.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. /* eslint-disable
  2. max-len,
  3. no-return-assign,
  4. */
  5. // TODO: This file was created by bulk-decaffeinate.
  6. // Fix any style issues and re-enable lint.
  7. /*
  8. * decaffeinate suggestions:
  9. * DS102: Remove unnecessary code created because of implicit returns
  10. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  11. */
  12. const chai = require('chai')
  13. chai.should()
  14. const sinon = require('sinon')
  15. const modulePath = '../../../../app/src/Features/Docstore/DocstoreManager'
  16. const SandboxedModule = require('sandboxed-module')
  17. const Errors = require('../../../../app/src/Features/Errors/Errors.js')
  18. describe('DocstoreManager', function() {
  19. beforeEach(function() {
  20. this.requestDefaults = sinon.stub().returns((this.request = sinon.stub()))
  21. this.DocstoreManager = SandboxedModule.require(modulePath, {
  22. globals: {
  23. console: console
  24. },
  25. requires: {
  26. request: {
  27. defaults: this.requestDefaults
  28. },
  29. 'settings-sharelatex': (this.settings = {
  30. apis: {
  31. docstore: {
  32. url: 'docstore.sharelatex.com'
  33. }
  34. }
  35. }),
  36. 'logger-sharelatex': (this.logger = {
  37. log: sinon.stub(),
  38. warn: sinon.stub(),
  39. error: sinon.stub(),
  40. err() {}
  41. })
  42. }
  43. })
  44. this.requestDefaults.calledWith({ jar: false }).should.equal(true)
  45. this.project_id = 'project-id-123'
  46. this.doc_id = 'doc-id-123'
  47. return (this.callback = sinon.stub())
  48. })
  49. describe('deleteDoc', function() {
  50. describe('with a successful response code', function() {
  51. beforeEach(function() {
  52. this.request.del = sinon
  53. .stub()
  54. .callsArgWith(1, null, { statusCode: 204 }, '')
  55. return this.DocstoreManager.deleteDoc(
  56. this.project_id,
  57. this.doc_id,
  58. this.callback
  59. )
  60. })
  61. it('should delete the doc in the docstore api', function() {
  62. return this.request.del
  63. .calledWith({
  64. url: `${this.settings.apis.docstore.url}/project/${
  65. this.project_id
  66. }/doc/${this.doc_id}`,
  67. timeout: 30 * 1000
  68. })
  69. .should.equal(true)
  70. })
  71. it('should call the callback without an error', function() {
  72. return this.callback.calledWith(null).should.equal(true)
  73. })
  74. })
  75. describe('with a failed response code', function() {
  76. beforeEach(function() {
  77. this.request.del = sinon
  78. .stub()
  79. .callsArgWith(1, null, { statusCode: 500 }, '')
  80. return this.DocstoreManager.deleteDoc(
  81. this.project_id,
  82. this.doc_id,
  83. this.callback
  84. )
  85. })
  86. it('should call the callback with an error', function() {
  87. return this.callback
  88. .calledWith(
  89. new Error('docstore api responded with non-success code: 500')
  90. )
  91. .should.equal(true)
  92. })
  93. it('should log the error', function() {
  94. return this.logger.warn
  95. .calledWith(
  96. {
  97. err: new Error(
  98. 'docstore api responded with a non-success code: 500'
  99. ),
  100. project_id: this.project_id,
  101. doc_id: this.doc_id
  102. },
  103. 'error deleting doc in docstore'
  104. )
  105. .should.equal(true)
  106. })
  107. })
  108. describe('with a missing (404) response code', function() {
  109. beforeEach(function() {
  110. this.request.del = sinon
  111. .stub()
  112. .callsArgWith(1, null, { statusCode: 404 }, '')
  113. return this.DocstoreManager.deleteDoc(
  114. this.project_id,
  115. this.doc_id,
  116. this.callback
  117. )
  118. })
  119. it('should call the callback with an error', function() {
  120. return this.callback
  121. .calledWith(
  122. new Errors.NotFoundError('tried to delete doc not in docstore')
  123. )
  124. .should.equal(true)
  125. })
  126. it('should log the error', function() {
  127. return this.logger.warn
  128. .calledWith(
  129. {
  130. err: new Errors.NotFoundError(
  131. 'tried to delete doc not in docstore'
  132. ),
  133. project_id: this.project_id,
  134. doc_id: this.doc_id
  135. },
  136. 'tried to delete doc not in docstore'
  137. )
  138. .should.equal(true)
  139. })
  140. })
  141. })
  142. describe('updateDoc', function() {
  143. beforeEach(function() {
  144. this.lines = ['mock', 'doc', 'lines']
  145. this.rev = 5
  146. this.version = 42
  147. this.ranges = { mock: 'ranges' }
  148. return (this.modified = true)
  149. })
  150. describe('with a successful response code', function() {
  151. beforeEach(function() {
  152. this.request.post = sinon
  153. .stub()
  154. .callsArgWith(
  155. 1,
  156. null,
  157. { statusCode: 204 },
  158. { modified: this.modified, rev: this.rev }
  159. )
  160. return this.DocstoreManager.updateDoc(
  161. this.project_id,
  162. this.doc_id,
  163. this.lines,
  164. this.version,
  165. this.ranges,
  166. this.callback
  167. )
  168. })
  169. it('should update the doc in the docstore api', function() {
  170. return this.request.post
  171. .calledWith({
  172. url: `${this.settings.apis.docstore.url}/project/${
  173. this.project_id
  174. }/doc/${this.doc_id}`,
  175. timeout: 30 * 1000,
  176. json: {
  177. lines: this.lines,
  178. version: this.version,
  179. ranges: this.ranges
  180. }
  181. })
  182. .should.equal(true)
  183. })
  184. it('should call the callback with the modified status and revision', function() {
  185. return this.callback
  186. .calledWith(null, this.modified, this.rev)
  187. .should.equal(true)
  188. })
  189. })
  190. describe('with a failed response code', function() {
  191. beforeEach(function() {
  192. this.request.post = sinon
  193. .stub()
  194. .callsArgWith(1, null, { statusCode: 500 }, '')
  195. return this.DocstoreManager.updateDoc(
  196. this.project_id,
  197. this.doc_id,
  198. this.lines,
  199. this.version,
  200. this.ranges,
  201. this.callback
  202. )
  203. })
  204. it('should call the callback with an error', function() {
  205. return this.callback
  206. .calledWith(
  207. new Error('docstore api responded with non-success code: 500')
  208. )
  209. .should.equal(true)
  210. })
  211. it('should log the error', function() {
  212. return this.logger.warn
  213. .calledWith(
  214. {
  215. err: new Error(
  216. 'docstore api responded with a non-success code: 500'
  217. ),
  218. project_id: this.project_id,
  219. doc_id: this.doc_id
  220. },
  221. 'error updating doc in docstore'
  222. )
  223. .should.equal(true)
  224. })
  225. })
  226. })
  227. describe('getDoc', function() {
  228. beforeEach(function() {
  229. return (this.doc = {
  230. lines: (this.lines = ['mock', 'doc', 'lines']),
  231. rev: (this.rev = 5),
  232. version: (this.version = 42),
  233. ranges: (this.ranges = { mock: 'ranges' })
  234. })
  235. })
  236. describe('with a successful response code', function() {
  237. beforeEach(function() {
  238. this.request.get = sinon
  239. .stub()
  240. .callsArgWith(1, null, { statusCode: 204 }, this.doc)
  241. return this.DocstoreManager.getDoc(
  242. this.project_id,
  243. this.doc_id,
  244. this.callback
  245. )
  246. })
  247. it('should get the doc from the docstore api', function() {
  248. return this.request.get
  249. .calledWith({
  250. url: `${this.settings.apis.docstore.url}/project/${
  251. this.project_id
  252. }/doc/${this.doc_id}`,
  253. timeout: 30 * 1000,
  254. json: true
  255. })
  256. .should.equal(true)
  257. })
  258. it('should call the callback with the lines, version and rev', function() {
  259. return this.callback
  260. .calledWith(null, this.lines, this.rev, this.version, this.ranges)
  261. .should.equal(true)
  262. })
  263. })
  264. describe('with a failed response code', function() {
  265. beforeEach(function() {
  266. this.request.get = sinon
  267. .stub()
  268. .callsArgWith(1, null, { statusCode: 500 }, '')
  269. return this.DocstoreManager.getDoc(
  270. this.project_id,
  271. this.doc_id,
  272. this.callback
  273. )
  274. })
  275. it('should call the callback with an error', function() {
  276. return this.callback
  277. .calledWith(
  278. new Error('docstore api responded with non-success code: 500')
  279. )
  280. .should.equal(true)
  281. })
  282. it('should log the error', function() {
  283. return this.logger.warn
  284. .calledWith(
  285. {
  286. err: new Error(
  287. 'docstore api responded with a non-success code: 500'
  288. ),
  289. project_id: this.project_id,
  290. doc_id: this.doc_id
  291. },
  292. 'error getting doc from docstore'
  293. )
  294. .should.equal(true)
  295. })
  296. })
  297. describe('with include_deleted=true', function() {
  298. beforeEach(function() {
  299. this.request.get = sinon
  300. .stub()
  301. .callsArgWith(1, null, { statusCode: 204 }, this.doc)
  302. return this.DocstoreManager.getDoc(
  303. this.project_id,
  304. this.doc_id,
  305. { include_deleted: true },
  306. this.callback
  307. )
  308. })
  309. it('should get the doc from the docstore api (including deleted)', function() {
  310. return this.request.get
  311. .calledWith({
  312. url: `${this.settings.apis.docstore.url}/project/${
  313. this.project_id
  314. }/doc/${this.doc_id}?include_deleted=true`,
  315. timeout: 30 * 1000,
  316. json: true
  317. })
  318. .should.equal(true)
  319. })
  320. it('should call the callback with the lines, version and rev', function() {
  321. return this.callback
  322. .calledWith(null, this.lines, this.rev, this.version, this.ranges)
  323. .should.equal(true)
  324. })
  325. })
  326. describe('with a missing (404) response code', function() {
  327. beforeEach(function() {
  328. this.request.get = sinon
  329. .stub()
  330. .callsArgWith(1, null, { statusCode: 404 }, '')
  331. return this.DocstoreManager.getDoc(
  332. this.project_id,
  333. this.doc_id,
  334. this.callback
  335. )
  336. })
  337. it('should call the callback with an error', function() {
  338. return this.callback
  339. .calledWith(new Errors.NotFoundError('doc not found in docstore'))
  340. .should.equal(true)
  341. })
  342. it('should log the error', function() {
  343. return this.logger.warn
  344. .calledWith(
  345. {
  346. err: new Errors.NotFoundError('doc not found in docstore'),
  347. project_id: this.project_id,
  348. doc_id: this.doc_id
  349. },
  350. 'doc not found in docstore'
  351. )
  352. .should.equal(true)
  353. })
  354. })
  355. })
  356. describe('getAllDocs', function() {
  357. describe('with a successful response code', function() {
  358. beforeEach(function() {
  359. this.request.get = sinon
  360. .stub()
  361. .callsArgWith(
  362. 1,
  363. null,
  364. { statusCode: 204 },
  365. (this.docs = [{ _id: 'mock-doc-id' }])
  366. )
  367. return this.DocstoreManager.getAllDocs(this.project_id, this.callback)
  368. })
  369. it('should get all the project docs in the docstore api', function() {
  370. return this.request.get
  371. .calledWith({
  372. url: `${this.settings.apis.docstore.url}/project/${
  373. this.project_id
  374. }/doc`,
  375. timeout: 30 * 1000,
  376. json: true
  377. })
  378. .should.equal(true)
  379. })
  380. it('should call the callback with the docs', function() {
  381. return this.callback.calledWith(null, this.docs).should.equal(true)
  382. })
  383. })
  384. describe('with a failed response code', function() {
  385. beforeEach(function() {
  386. this.request.get = sinon
  387. .stub()
  388. .callsArgWith(1, null, { statusCode: 500 }, '')
  389. return this.DocstoreManager.getAllDocs(this.project_id, this.callback)
  390. })
  391. it('should call the callback with an error', function() {
  392. return this.callback
  393. .calledWith(
  394. new Error('docstore api responded with non-success code: 500')
  395. )
  396. .should.equal(true)
  397. })
  398. it('should log the error', function() {
  399. return this.logger.warn
  400. .calledWith(
  401. {
  402. err: new Error(
  403. 'docstore api responded with a non-success code: 500'
  404. ),
  405. project_id: this.project_id
  406. },
  407. 'error getting all docs from docstore'
  408. )
  409. .should.equal(true)
  410. })
  411. })
  412. })
  413. describe('getAllRanges', function() {
  414. describe('with a successful response code', function() {
  415. beforeEach(function() {
  416. this.request.get = sinon
  417. .stub()
  418. .callsArgWith(
  419. 1,
  420. null,
  421. { statusCode: 204 },
  422. (this.docs = [{ _id: 'mock-doc-id', ranges: 'mock-ranges' }])
  423. )
  424. return this.DocstoreManager.getAllRanges(this.project_id, this.callback)
  425. })
  426. it('should get all the project doc ranges in the docstore api', function() {
  427. return this.request.get
  428. .calledWith({
  429. url: `${this.settings.apis.docstore.url}/project/${
  430. this.project_id
  431. }/ranges`,
  432. timeout: 30 * 1000,
  433. json: true
  434. })
  435. .should.equal(true)
  436. })
  437. it('should call the callback with the docs', function() {
  438. return this.callback.calledWith(null, this.docs).should.equal(true)
  439. })
  440. })
  441. describe('with a failed response code', function() {
  442. beforeEach(function() {
  443. this.request.get = sinon
  444. .stub()
  445. .callsArgWith(1, null, { statusCode: 500 }, '')
  446. return this.DocstoreManager.getAllRanges(this.project_id, this.callback)
  447. })
  448. it('should call the callback with an error', function() {
  449. return this.callback
  450. .calledWith(
  451. new Error('docstore api responded with non-success code: 500')
  452. )
  453. .should.equal(true)
  454. })
  455. it('should log the error', function() {
  456. return this.logger.warn
  457. .calledWith(
  458. {
  459. err: new Error(
  460. 'docstore api responded with a non-success code: 500'
  461. ),
  462. project_id: this.project_id
  463. },
  464. 'error getting all doc ranges from docstore'
  465. )
  466. .should.equal(true)
  467. })
  468. })
  469. })
  470. describe('archiveProject', function() {
  471. describe('with a successful response code', function() {
  472. beforeEach(function() {
  473. this.request.post = sinon
  474. .stub()
  475. .callsArgWith(1, null, { statusCode: 204 })
  476. return this.DocstoreManager.archiveProject(
  477. this.project_id,
  478. this.callback
  479. )
  480. })
  481. it('should call the callback', function() {
  482. return this.callback.called.should.equal(true)
  483. })
  484. })
  485. describe('with a failed response code', function() {
  486. beforeEach(function() {
  487. this.request.post = sinon
  488. .stub()
  489. .callsArgWith(1, null, { statusCode: 500 })
  490. return this.DocstoreManager.archiveProject(
  491. this.project_id,
  492. this.callback
  493. )
  494. })
  495. it('should call the callback with an error', function() {
  496. return this.callback
  497. .calledWith(
  498. new Error('docstore api responded with non-success code: 500')
  499. )
  500. .should.equal(true)
  501. })
  502. })
  503. })
  504. describe('unarchiveProject', function() {
  505. describe('with a successful response code', function() {
  506. beforeEach(function() {
  507. this.request.post = sinon
  508. .stub()
  509. .callsArgWith(1, null, { statusCode: 204 })
  510. return this.DocstoreManager.unarchiveProject(
  511. this.project_id,
  512. this.callback
  513. )
  514. })
  515. it('should call the callback', function() {
  516. return this.callback.called.should.equal(true)
  517. })
  518. })
  519. describe('with a failed response code', function() {
  520. beforeEach(function() {
  521. this.request.post = sinon
  522. .stub()
  523. .callsArgWith(1, null, { statusCode: 500 })
  524. return this.DocstoreManager.unarchiveProject(
  525. this.project_id,
  526. this.callback
  527. )
  528. })
  529. it('should call the callback with an error', function() {
  530. return this.callback
  531. .calledWith(
  532. new Error('docstore api responded with non-success code: 500')
  533. )
  534. .should.equal(true)
  535. })
  536. })
  537. })
  538. describe('destroyProject', function() {
  539. describe('with a successful response code', function() {
  540. beforeEach(function() {
  541. this.request.post = sinon
  542. .stub()
  543. .callsArgWith(1, null, { statusCode: 204 })
  544. return this.DocstoreManager.destroyProject(
  545. this.project_id,
  546. this.callback
  547. )
  548. })
  549. it('should call the callback', function() {
  550. return this.callback.called.should.equal(true)
  551. })
  552. })
  553. describe('with a failed response code', function() {
  554. beforeEach(function() {
  555. this.request.post = sinon
  556. .stub()
  557. .callsArgWith(1, null, { statusCode: 500 })
  558. return this.DocstoreManager.destroyProject(
  559. this.project_id,
  560. this.callback
  561. )
  562. })
  563. it('should call the callback with an error', function() {
  564. return this.callback
  565. .calledWith(
  566. new Error('docstore api responded with non-success code: 500')
  567. )
  568. .should.equal(true)
  569. })
  570. })
  571. })
  572. })