DocstoreManagerTests.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  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. sinon.match
  90. .instanceOf(Error)
  91. .and(
  92. sinon.match.has(
  93. 'message',
  94. 'docstore api responded with non-success code: 500'
  95. )
  96. )
  97. )
  98. .should.equal(true)
  99. })
  100. })
  101. describe('with a missing (404) response code', function() {
  102. beforeEach(function() {
  103. this.request.del = sinon
  104. .stub()
  105. .callsArgWith(1, null, { statusCode: 404 }, '')
  106. return this.DocstoreManager.deleteDoc(
  107. this.project_id,
  108. this.doc_id,
  109. this.callback
  110. )
  111. })
  112. it('should call the callback with an error', function() {
  113. this.callback
  114. .calledWith(
  115. sinon.match
  116. .instanceOf(Errors.NotFoundError)
  117. .and(
  118. sinon.match.has(
  119. 'message',
  120. 'tried to delete doc not in docstore'
  121. )
  122. )
  123. )
  124. .should.equal(true)
  125. })
  126. })
  127. })
  128. describe('updateDoc', function() {
  129. beforeEach(function() {
  130. this.lines = ['mock', 'doc', 'lines']
  131. this.rev = 5
  132. this.version = 42
  133. this.ranges = { mock: 'ranges' }
  134. return (this.modified = true)
  135. })
  136. describe('with a successful response code', function() {
  137. beforeEach(function() {
  138. this.request.post = sinon
  139. .stub()
  140. .callsArgWith(
  141. 1,
  142. null,
  143. { statusCode: 204 },
  144. { modified: this.modified, rev: this.rev }
  145. )
  146. return this.DocstoreManager.updateDoc(
  147. this.project_id,
  148. this.doc_id,
  149. this.lines,
  150. this.version,
  151. this.ranges,
  152. this.callback
  153. )
  154. })
  155. it('should update the doc in the docstore api', function() {
  156. return this.request.post
  157. .calledWith({
  158. url: `${this.settings.apis.docstore.url}/project/${
  159. this.project_id
  160. }/doc/${this.doc_id}`,
  161. timeout: 30 * 1000,
  162. json: {
  163. lines: this.lines,
  164. version: this.version,
  165. ranges: this.ranges
  166. }
  167. })
  168. .should.equal(true)
  169. })
  170. it('should call the callback with the modified status and revision', function() {
  171. return this.callback
  172. .calledWith(null, this.modified, this.rev)
  173. .should.equal(true)
  174. })
  175. })
  176. describe('with a failed response code', function() {
  177. beforeEach(function() {
  178. this.request.post = sinon
  179. .stub()
  180. .callsArgWith(1, null, { statusCode: 500 }, '')
  181. return this.DocstoreManager.updateDoc(
  182. this.project_id,
  183. this.doc_id,
  184. this.lines,
  185. this.version,
  186. this.ranges,
  187. this.callback
  188. )
  189. })
  190. it('should call the callback with an error', function() {
  191. return this.callback
  192. .calledWith(
  193. sinon.match
  194. .instanceOf(Error)
  195. .and(
  196. sinon.match.has(
  197. 'message',
  198. 'docstore api responded with non-success code: 500'
  199. )
  200. )
  201. )
  202. .should.equal(true)
  203. })
  204. })
  205. })
  206. describe('getDoc', function() {
  207. beforeEach(function() {
  208. return (this.doc = {
  209. lines: (this.lines = ['mock', 'doc', 'lines']),
  210. rev: (this.rev = 5),
  211. version: (this.version = 42),
  212. ranges: (this.ranges = { mock: 'ranges' })
  213. })
  214. })
  215. describe('with a successful response code', function() {
  216. beforeEach(function() {
  217. this.request.get = sinon
  218. .stub()
  219. .callsArgWith(1, null, { statusCode: 204 }, this.doc)
  220. return this.DocstoreManager.getDoc(
  221. this.project_id,
  222. this.doc_id,
  223. this.callback
  224. )
  225. })
  226. it('should get the doc from the docstore api', function() {
  227. return this.request.get
  228. .calledWith({
  229. url: `${this.settings.apis.docstore.url}/project/${
  230. this.project_id
  231. }/doc/${this.doc_id}`,
  232. timeout: 30 * 1000,
  233. json: true
  234. })
  235. .should.equal(true)
  236. })
  237. it('should call the callback with the lines, version and rev', function() {
  238. return this.callback
  239. .calledWith(null, this.lines, this.rev, this.version, this.ranges)
  240. .should.equal(true)
  241. })
  242. })
  243. describe('with a failed response code', function() {
  244. beforeEach(function() {
  245. this.request.get = sinon
  246. .stub()
  247. .callsArgWith(1, null, { statusCode: 500 }, '')
  248. return this.DocstoreManager.getDoc(
  249. this.project_id,
  250. this.doc_id,
  251. this.callback
  252. )
  253. })
  254. it('should call the callback with an error', function() {
  255. return this.callback
  256. .calledWith(
  257. sinon.match
  258. .instanceOf(Error)
  259. .and(
  260. sinon.match.has(
  261. 'message',
  262. 'docstore api responded with non-success code: 500'
  263. )
  264. )
  265. )
  266. .should.equal(true)
  267. })
  268. })
  269. describe('with include_deleted=true', function() {
  270. beforeEach(function() {
  271. this.request.get = sinon
  272. .stub()
  273. .callsArgWith(1, null, { statusCode: 204 }, this.doc)
  274. return this.DocstoreManager.getDoc(
  275. this.project_id,
  276. this.doc_id,
  277. { include_deleted: true },
  278. this.callback
  279. )
  280. })
  281. it('should get the doc from the docstore api (including deleted)', function() {
  282. return this.request.get
  283. .calledWith({
  284. url: `${this.settings.apis.docstore.url}/project/${
  285. this.project_id
  286. }/doc/${this.doc_id}?include_deleted=true`,
  287. timeout: 30 * 1000,
  288. json: true
  289. })
  290. .should.equal(true)
  291. })
  292. it('should call the callback with the lines, version and rev', function() {
  293. return this.callback
  294. .calledWith(null, this.lines, this.rev, this.version, this.ranges)
  295. .should.equal(true)
  296. })
  297. })
  298. describe('with a missing (404) response code', function() {
  299. beforeEach(function() {
  300. this.request.get = sinon
  301. .stub()
  302. .callsArgWith(1, null, { statusCode: 404 }, '')
  303. return this.DocstoreManager.getDoc(
  304. this.project_id,
  305. this.doc_id,
  306. this.callback
  307. )
  308. })
  309. it('should call the callback with an error', function() {
  310. return this.callback
  311. .calledWith(
  312. sinon.match
  313. .instanceOf(Errors.NotFoundError)
  314. .and(sinon.match.has('message', 'doc not found in docstore'))
  315. )
  316. .should.equal(true)
  317. })
  318. })
  319. })
  320. describe('getAllDocs', function() {
  321. describe('with a successful response code', function() {
  322. beforeEach(function() {
  323. this.request.get = sinon
  324. .stub()
  325. .callsArgWith(
  326. 1,
  327. null,
  328. { statusCode: 204 },
  329. (this.docs = [{ _id: 'mock-doc-id' }])
  330. )
  331. return this.DocstoreManager.getAllDocs(this.project_id, this.callback)
  332. })
  333. it('should get all the project docs in the docstore api', function() {
  334. return this.request.get
  335. .calledWith({
  336. url: `${this.settings.apis.docstore.url}/project/${
  337. this.project_id
  338. }/doc`,
  339. timeout: 30 * 1000,
  340. json: true
  341. })
  342. .should.equal(true)
  343. })
  344. it('should call the callback with the docs', function() {
  345. return this.callback.calledWith(null, this.docs).should.equal(true)
  346. })
  347. })
  348. describe('with a failed response code', function() {
  349. beforeEach(function() {
  350. this.request.get = sinon
  351. .stub()
  352. .callsArgWith(1, null, { statusCode: 500 }, '')
  353. return this.DocstoreManager.getAllDocs(this.project_id, this.callback)
  354. })
  355. it('should call the callback with an error', function() {
  356. return this.callback
  357. .calledWith(
  358. sinon.match
  359. .instanceOf(Error)
  360. .and(
  361. sinon.match.has(
  362. 'message',
  363. 'docstore api responded with non-success code: 500'
  364. )
  365. )
  366. )
  367. .should.equal(true)
  368. })
  369. })
  370. })
  371. describe('getAllRanges', function() {
  372. describe('with a successful response code', function() {
  373. beforeEach(function() {
  374. this.request.get = sinon
  375. .stub()
  376. .callsArgWith(
  377. 1,
  378. null,
  379. { statusCode: 204 },
  380. (this.docs = [{ _id: 'mock-doc-id', ranges: 'mock-ranges' }])
  381. )
  382. return this.DocstoreManager.getAllRanges(this.project_id, this.callback)
  383. })
  384. it('should get all the project doc ranges in the docstore api', function() {
  385. return this.request.get
  386. .calledWith({
  387. url: `${this.settings.apis.docstore.url}/project/${
  388. this.project_id
  389. }/ranges`,
  390. timeout: 30 * 1000,
  391. json: true
  392. })
  393. .should.equal(true)
  394. })
  395. it('should call the callback with the docs', function() {
  396. return this.callback.calledWith(null, this.docs).should.equal(true)
  397. })
  398. })
  399. describe('with a failed response code', function() {
  400. beforeEach(function() {
  401. this.request.get = sinon
  402. .stub()
  403. .callsArgWith(1, null, { statusCode: 500 }, '')
  404. return this.DocstoreManager.getAllRanges(this.project_id, this.callback)
  405. })
  406. it('should call the callback with an error', function() {
  407. return this.callback
  408. .calledWith(
  409. sinon.match
  410. .instanceOf(Error)
  411. .and(
  412. sinon.match.has(
  413. 'message',
  414. 'docstore api responded with non-success code: 500'
  415. )
  416. )
  417. )
  418. .should.equal(true)
  419. })
  420. })
  421. })
  422. describe('archiveProject', function() {
  423. describe('with a successful response code', function() {
  424. beforeEach(function() {
  425. this.request.post = sinon
  426. .stub()
  427. .callsArgWith(1, null, { statusCode: 204 })
  428. return this.DocstoreManager.archiveProject(
  429. this.project_id,
  430. this.callback
  431. )
  432. })
  433. it('should call the callback', function() {
  434. return this.callback.called.should.equal(true)
  435. })
  436. })
  437. describe('with a failed response code', function() {
  438. beforeEach(function() {
  439. this.request.post = sinon
  440. .stub()
  441. .callsArgWith(1, null, { statusCode: 500 })
  442. return this.DocstoreManager.archiveProject(
  443. this.project_id,
  444. this.callback
  445. )
  446. })
  447. it('should call the callback with an error', function() {
  448. return this.callback
  449. .calledWith(
  450. sinon.match
  451. .instanceOf(Error)
  452. .and(
  453. sinon.match.has(
  454. 'message',
  455. 'docstore api responded with non-success code: 500'
  456. )
  457. )
  458. )
  459. .should.equal(true)
  460. })
  461. })
  462. })
  463. describe('unarchiveProject', function() {
  464. describe('with a successful response code', function() {
  465. beforeEach(function() {
  466. this.request.post = sinon
  467. .stub()
  468. .callsArgWith(1, null, { statusCode: 204 })
  469. return this.DocstoreManager.unarchiveProject(
  470. this.project_id,
  471. this.callback
  472. )
  473. })
  474. it('should call the callback', function() {
  475. return this.callback.called.should.equal(true)
  476. })
  477. })
  478. describe('with a failed response code', function() {
  479. beforeEach(function() {
  480. this.request.post = sinon
  481. .stub()
  482. .callsArgWith(1, null, { statusCode: 500 })
  483. return this.DocstoreManager.unarchiveProject(
  484. this.project_id,
  485. this.callback
  486. )
  487. })
  488. it('should call the callback with an error', function() {
  489. return this.callback
  490. .calledWith(
  491. sinon.match
  492. .instanceOf(Error)
  493. .and(
  494. sinon.match.has(
  495. 'message',
  496. 'docstore api responded with non-success code: 500'
  497. )
  498. )
  499. )
  500. .should.equal(true)
  501. })
  502. })
  503. })
  504. describe('destroyProject', 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.destroyProject(
  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.destroyProject(
  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. sinon.match
  533. .instanceOf(Error)
  534. .and(
  535. sinon.match.has(
  536. 'message',
  537. 'docstore api responded with non-success code: 500'
  538. )
  539. )
  540. )
  541. .should.equal(true)
  542. })
  543. })
  544. })
  545. })