CompileControllerTests.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. /* eslint-disable
  2. camelcase,
  3. max-len,
  4. no-return-assign,
  5. no-unused-vars,
  6. */
  7. // TODO: This file was created by bulk-decaffeinate.
  8. // Fix any style issues and re-enable lint.
  9. /*
  10. * decaffeinate suggestions:
  11. * DS102: Remove unnecessary code created because of implicit returns
  12. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  13. */
  14. const sinon = require('sinon')
  15. const { assert, expect } = require('chai')
  16. const modulePath = '../../../../app/src/Features/Compile/CompileController.js'
  17. const SandboxedModule = require('sandboxed-module')
  18. const MockRequest = require('../helpers/MockRequest')
  19. const MockResponse = require('../helpers/MockResponse')
  20. describe('CompileController', function () {
  21. beforeEach(function () {
  22. this.user_id = 'wat'
  23. this.user = {
  24. _id: this.user_id,
  25. email: 'user@example.com',
  26. features: {
  27. compileGroup: 'premium',
  28. compileTimeout: 100,
  29. },
  30. }
  31. this.CompileManager = { compile: sinon.stub() }
  32. this.ClsiManager = {}
  33. this.UserGetter = { getUser: sinon.stub() }
  34. this.RateLimiter = { addCount: sinon.stub() }
  35. this.settings = {
  36. apis: {
  37. clsi: {
  38. url: 'clsi.example.com',
  39. },
  40. clsi_priority: {
  41. url: 'clsi-priority.example.com',
  42. },
  43. },
  44. defaultFeatures: {
  45. compileGroup: 'standard',
  46. compileTimeout: 60,
  47. },
  48. }
  49. this.jar = { cookie: 'stuff' }
  50. this.ClsiCookieManager = {
  51. getCookieJar: sinon.stub().callsArgWith(1, null, this.jar),
  52. }
  53. this.SessionManager = {
  54. getLoggedInUser: sinon.stub().callsArgWith(1, null, this.user),
  55. getLoggedInUserId: sinon.stub().returns(this.user_id),
  56. getSessionUser: sinon.stub().returns(this.user),
  57. isUserLoggedIn: sinon.stub().returns(true),
  58. }
  59. this.CompileController = SandboxedModule.require(modulePath, {
  60. requires: {
  61. '@overleaf/settings': this.settings,
  62. request: (this.request = sinon.stub()),
  63. '../Project/ProjectGetter': (this.ProjectGetter = {}),
  64. '@overleaf/metrics': (this.Metrics = { inc: sinon.stub() }),
  65. './CompileManager': this.CompileManager,
  66. '../User/UserGetter': this.UserGetter,
  67. './ClsiManager': this.ClsiManager,
  68. '../Authentication/SessionManager': this.SessionManager,
  69. '../../infrastructure/RateLimiter': this.RateLimiter,
  70. './ClsiCookieManager': () => this.ClsiCookieManager,
  71. },
  72. })
  73. this.project_id = 'project-id'
  74. this.next = sinon.stub()
  75. this.req = new MockRequest()
  76. return (this.res = new MockResponse())
  77. })
  78. describe('compile', function () {
  79. beforeEach(function () {
  80. this.req.params = { Project_id: this.project_id }
  81. this.req.session = {}
  82. return (this.CompileManager.compile = sinon
  83. .stub()
  84. .callsArgWith(
  85. 3,
  86. null,
  87. (this.status = 'success'),
  88. (this.outputFiles = ['mock-output-files'])
  89. ))
  90. })
  91. describe('when not an auto compile', function () {
  92. beforeEach(function () {
  93. return this.CompileController.compile(this.req, this.res, this.next)
  94. })
  95. it('should look up the user id', function () {
  96. return this.SessionManager.getLoggedInUserId
  97. .calledWith(this.req.session)
  98. .should.equal(true)
  99. })
  100. it('should do the compile without the auto compile flag', function () {
  101. return this.CompileManager.compile
  102. .calledWith(this.project_id, this.user_id, {
  103. isAutoCompile: false,
  104. enablePdfCaching: false,
  105. })
  106. .should.equal(true)
  107. })
  108. it('should set the content-type of the response to application/json', function () {
  109. this.res.type.should.equal('application/json')
  110. })
  111. it('should send a successful response reporting the status and files', function () {
  112. this.res.statusCode.should.equal(200)
  113. this.res.body.should.equal(
  114. JSON.stringify({
  115. status: this.status,
  116. outputFiles: this.outputFiles,
  117. })
  118. )
  119. })
  120. })
  121. describe('when an auto compile', function () {
  122. beforeEach(function () {
  123. this.req.query = { auto_compile: 'true' }
  124. return this.CompileController.compile(this.req, this.res, this.next)
  125. })
  126. it('should do the compile with the auto compile flag', function () {
  127. return this.CompileManager.compile
  128. .calledWith(this.project_id, this.user_id, {
  129. isAutoCompile: true,
  130. enablePdfCaching: false,
  131. })
  132. .should.equal(true)
  133. })
  134. })
  135. describe('with the draft attribute', function () {
  136. beforeEach(function () {
  137. this.req.body = { draft: true }
  138. return this.CompileController.compile(this.req, this.res, this.next)
  139. })
  140. it('should do the compile without the draft compile flag', function () {
  141. return this.CompileManager.compile
  142. .calledWith(this.project_id, this.user_id, {
  143. isAutoCompile: false,
  144. enablePdfCaching: false,
  145. draft: true,
  146. })
  147. .should.equal(true)
  148. })
  149. })
  150. })
  151. describe('compileSubmission', function () {
  152. beforeEach(function () {
  153. this.submission_id = 'sub-1234'
  154. this.req.params = { submission_id: this.submission_id }
  155. this.req.body = {}
  156. return (this.ClsiManager.sendExternalRequest = sinon
  157. .stub()
  158. .callsArgWith(
  159. 3,
  160. null,
  161. (this.status = 'success'),
  162. (this.outputFiles = ['mock-output-files']),
  163. (this.clsiServerId = 'mock-server-id'),
  164. (this.validationProblems = null)
  165. ))
  166. })
  167. it('should set the content-type of the response to application/json', function () {
  168. this.CompileController.compileSubmission(this.req, this.res, this.next)
  169. return this.res.contentType
  170. .calledWith('application/json')
  171. .should.equal(true)
  172. })
  173. it('should send a successful response reporting the status and files', function () {
  174. this.CompileController.compileSubmission(this.req, this.res, this.next)
  175. this.res.statusCode.should.equal(200)
  176. return this.res.body.should.equal(
  177. JSON.stringify({
  178. status: this.status,
  179. outputFiles: this.outputFiles,
  180. clsiServerId: 'mock-server-id',
  181. validationProblems: null,
  182. })
  183. )
  184. })
  185. describe('with compileGroup and timeout', function () {
  186. beforeEach(function () {
  187. this.req.body = {
  188. compileGroup: 'special',
  189. timeout: 600,
  190. }
  191. return this.CompileController.compileSubmission(
  192. this.req,
  193. this.res,
  194. this.next
  195. )
  196. })
  197. it('should use the supplied values', function () {
  198. return this.ClsiManager.sendExternalRequest
  199. .calledWith(
  200. this.submission_id,
  201. { compileGroup: 'special', timeout: 600 },
  202. { compileGroup: 'special', timeout: 600 }
  203. )
  204. .should.equal(true)
  205. })
  206. })
  207. describe('with other supported options but not compileGroup and timeout', function () {
  208. beforeEach(function () {
  209. this.req.body = {
  210. rootResourcePath: 'main.tex',
  211. compiler: 'lualatex',
  212. draft: true,
  213. check: 'validate',
  214. }
  215. return this.CompileController.compileSubmission(
  216. this.req,
  217. this.res,
  218. this.next
  219. )
  220. })
  221. it('should use the other options but default values for compileGroup and timeout', function () {
  222. return this.ClsiManager.sendExternalRequest
  223. .calledWith(
  224. this.submission_id,
  225. {
  226. rootResourcePath: 'main.tex',
  227. compiler: 'lualatex',
  228. draft: true,
  229. check: 'validate',
  230. },
  231. {
  232. rootResourcePath: 'main.tex',
  233. compiler: 'lualatex',
  234. draft: true,
  235. check: 'validate',
  236. compileGroup: 'standard',
  237. timeout: 60,
  238. }
  239. )
  240. .should.equal(true)
  241. })
  242. })
  243. })
  244. describe('downloadPdf', function () {
  245. beforeEach(function () {
  246. this.req.params = { Project_id: this.project_id }
  247. this.req.query = { pdfng: true }
  248. this.project = { name: 'test namè' }
  249. return (this.ProjectGetter.getProject = sinon
  250. .stub()
  251. .callsArgWith(2, null, this.project))
  252. })
  253. describe('when downloading for embedding', function () {
  254. beforeEach(function () {
  255. this.CompileController.proxyToClsi = sinon.stub()
  256. this.RateLimiter.addCount.callsArgWith(1, null, true)
  257. return this.CompileController.downloadPdf(this.req, this.res, this.next)
  258. })
  259. it('should look up the project', function () {
  260. return this.ProjectGetter.getProject
  261. .calledWith(this.project_id, { name: 1 })
  262. .should.equal(true)
  263. })
  264. it('should set the content-type of the response to application/pdf', function () {
  265. return this.res.contentType
  266. .calledWith('application/pdf')
  267. .should.equal(true)
  268. })
  269. it('should set the content-disposition header with a safe version of the project name', function () {
  270. return this.res.setContentDisposition
  271. .calledWith('', { filename: 'test_nam_.pdf' })
  272. .should.equal(true)
  273. })
  274. it('should increment the pdf-downloads metric', function () {
  275. return this.Metrics.inc.calledWith('pdf-downloads').should.equal(true)
  276. })
  277. it('should proxy the PDF from the CLSI', function () {
  278. return this.CompileController.proxyToClsi
  279. .calledWith(
  280. this.project_id,
  281. `/project/${this.project_id}/user/${this.user_id}/output/output.pdf`,
  282. this.req,
  283. this.res,
  284. this.next
  285. )
  286. .should.equal(true)
  287. })
  288. })
  289. describe('when the a build-id is provided', function () {
  290. beforeEach(function () {
  291. this.req.params.build_id = this.buildId = '1234-5678'
  292. this.CompileController.proxyToClsi = sinon.stub()
  293. this.RateLimiter.addCount.callsArgWith(1, null, true)
  294. return this.CompileController.downloadPdf(this.req, this.res, this.next)
  295. })
  296. it('should proxy the PDF from the CLSI, with a build-id', function () {
  297. return this.CompileController.proxyToClsi
  298. .calledWith(
  299. this.project_id,
  300. `/project/${this.project_id}/user/${this.user_id}/build/${this.buildId}/output/output.pdf`,
  301. this.req,
  302. this.res,
  303. this.next
  304. )
  305. .should.equal(true)
  306. })
  307. })
  308. describe('when the pdf is not going to be used in pdfjs viewer', function () {
  309. it('should check the rate limiter when pdfng is not set', function (done) {
  310. this.req.query = {}
  311. this.RateLimiter.addCount.callsArgWith(1, null, true)
  312. this.CompileController.proxyToClsi = (project_id, url) => {
  313. this.RateLimiter.addCount.args[0][0].throttle.should.equal(1000)
  314. return done()
  315. }
  316. return this.CompileController.downloadPdf(this.req, this.res)
  317. })
  318. it('should check the rate limiter when pdfng is false', function (done) {
  319. this.req.query = { pdfng: false }
  320. this.RateLimiter.addCount.callsArgWith(1, null, true)
  321. this.CompileController.proxyToClsi = (project_id, url) => {
  322. this.RateLimiter.addCount.args[0][0].throttle.should.equal(1000)
  323. return done()
  324. }
  325. return this.CompileController.downloadPdf(this.req, this.res)
  326. })
  327. })
  328. })
  329. describe('getFileFromClsiWithoutUser', function () {
  330. beforeEach(function () {
  331. this.submission_id = 'sub-1234'
  332. this.build_id = 123456
  333. this.file = 'project.pdf'
  334. this.req.params = {
  335. submission_id: this.submission_id,
  336. build_id: this.build_id,
  337. file: this.file,
  338. }
  339. this.req.body = {}
  340. this.expected_url = `/project/${this.submission_id}/build/${this.build_id}/output/${this.file}`
  341. return (this.CompileController.proxyToClsiWithLimits = sinon.stub())
  342. })
  343. describe('without limits specified', function () {
  344. beforeEach(function () {
  345. return this.CompileController.getFileFromClsiWithoutUser(
  346. this.req,
  347. this.res,
  348. this.next
  349. )
  350. })
  351. it('should proxy to CLSI with correct URL and default limits', function () {
  352. return this.CompileController.proxyToClsiWithLimits
  353. .calledWith(this.submission_id, this.expected_url, {
  354. compileGroup: 'standard',
  355. })
  356. .should.equal(true)
  357. })
  358. })
  359. describe('with limits specified', function () {
  360. beforeEach(function () {
  361. this.req.body = { compileTimeout: 600, compileGroup: 'special' }
  362. return this.CompileController.getFileFromClsiWithoutUser(
  363. this.req,
  364. this.res,
  365. this.next
  366. )
  367. })
  368. it('should proxy to CLSI with correct URL and specified limits', function () {
  369. return this.CompileController.proxyToClsiWithLimits
  370. .calledWith(this.submission_id, this.expected_url, {
  371. compileGroup: 'special',
  372. })
  373. .should.equal(true)
  374. })
  375. })
  376. })
  377. describe('proxySyncCode', function () {
  378. let file, line, column, imageName
  379. beforeEach(function (done) {
  380. this.req.params = { Project_id: this.project_id }
  381. file = 'main.tex'
  382. line = String(Date.now())
  383. column = String(Date.now() + 1)
  384. this.req.query = { file, line, column }
  385. imageName = 'foo/bar:tag-0'
  386. this.ProjectGetter.getProject = sinon.stub().yields(null, { imageName })
  387. this.next.callsFake(done)
  388. this.res.callback = done
  389. this.CompileController.proxyToClsi = sinon.stub().callsFake(() => done())
  390. this.CompileController.proxySyncCode(this.req, this.res, this.next)
  391. })
  392. it('should proxy the request with an imageName', function () {
  393. expect(this.CompileController.proxyToClsi).to.have.been.calledWith(
  394. this.project_id,
  395. {
  396. url: `/project/${this.project_id}/user/${this.user_id}/sync/code`,
  397. qs: { file, line, column, imageName },
  398. },
  399. this.req,
  400. this.res,
  401. this.next
  402. )
  403. })
  404. })
  405. describe('proxySyncPdf', function () {
  406. let page, h, v, imageName
  407. beforeEach(function (done) {
  408. this.req.params = { Project_id: this.project_id }
  409. page = String(Date.now())
  410. h = String(Math.random())
  411. v = String(Math.random())
  412. this.req.query = { page, h, v }
  413. imageName = 'foo/bar:tag-1'
  414. this.ProjectGetter.getProject = sinon.stub().yields(null, { imageName })
  415. this.next.callsFake(done)
  416. this.res.callback = done
  417. this.CompileController.proxyToClsi = sinon.stub().callsFake(() => done())
  418. this.CompileController.proxySyncPdf(this.req, this.res, this.next)
  419. })
  420. it('should proxy the request with an imageName', function () {
  421. expect(this.CompileController.proxyToClsi).to.have.been.calledWith(
  422. this.project_id,
  423. {
  424. url: `/project/${this.project_id}/user/${this.user_id}/sync/pdf`,
  425. qs: { page, h, v, imageName },
  426. },
  427. this.req,
  428. this.res,
  429. this.next
  430. )
  431. })
  432. })
  433. describe('proxyToClsi', function () {
  434. beforeEach(function () {
  435. this.request.returns(
  436. (this.proxy = {
  437. pipe: sinon.stub(),
  438. on: sinon.stub(),
  439. })
  440. )
  441. this.upstream = {
  442. statusCode: 204,
  443. headers: { mock: 'header' },
  444. }
  445. this.req.method = 'mock-method'
  446. return (this.req.headers = {
  447. Mock: 'Headers',
  448. Range: '123-456',
  449. 'If-Range': 'abcdef',
  450. 'If-Modified-Since': 'Mon, 15 Dec 2014 15:23:56 GMT',
  451. })
  452. })
  453. describe('old pdf viewer', function () {
  454. describe('user with standard priority', function () {
  455. beforeEach(function () {
  456. this.CompileManager.getProjectCompileLimits = sinon
  457. .stub()
  458. .callsArgWith(1, null, { compileGroup: 'standard' })
  459. return this.CompileController.proxyToClsi(
  460. this.project_id,
  461. (this.url = '/test'),
  462. this.req,
  463. this.res,
  464. this.next
  465. )
  466. })
  467. it('should open a request to the CLSI', function () {
  468. return this.request
  469. .calledWith({
  470. jar: this.jar,
  471. method: this.req.method,
  472. url: `${this.settings.apis.clsi.url}${this.url}`,
  473. timeout: 60 * 1000,
  474. })
  475. .should.equal(true)
  476. })
  477. it('should pass the request on to the client', function () {
  478. return this.proxy.pipe.calledWith(this.res).should.equal(true)
  479. })
  480. it('should bind an error handle to the request proxy', function () {
  481. return this.proxy.on.calledWith('error').should.equal(true)
  482. })
  483. })
  484. describe('user with priority compile', function () {
  485. beforeEach(function () {
  486. this.CompileManager.getProjectCompileLimits = sinon
  487. .stub()
  488. .callsArgWith(1, null, { compileGroup: 'priority' })
  489. return this.CompileController.proxyToClsi(
  490. this.project_id,
  491. (this.url = '/test'),
  492. this.req,
  493. this.res,
  494. this.next
  495. )
  496. })
  497. })
  498. describe('user with standard priority via query string', function () {
  499. beforeEach(function () {
  500. this.req.query = { compileGroup: 'standard' }
  501. return this.CompileController.proxyToClsi(
  502. this.project_id,
  503. (this.url = '/test'),
  504. this.req,
  505. this.res,
  506. this.next
  507. )
  508. })
  509. it('should open a request to the CLSI', function () {
  510. return this.request
  511. .calledWith({
  512. jar: this.jar,
  513. method: this.req.method,
  514. url: `${this.settings.apis.clsi.url}${this.url}`,
  515. timeout: 60 * 1000,
  516. })
  517. .should.equal(true)
  518. })
  519. it('should pass the request on to the client', function () {
  520. return this.proxy.pipe.calledWith(this.res).should.equal(true)
  521. })
  522. it('should bind an error handle to the request proxy', function () {
  523. return this.proxy.on.calledWith('error').should.equal(true)
  524. })
  525. })
  526. describe('user with non-existent priority via query string', function () {
  527. beforeEach(function () {
  528. this.req.query = { compileGroup: 'foobar' }
  529. return this.CompileController.proxyToClsi(
  530. this.project_id,
  531. (this.url = '/test'),
  532. this.req,
  533. this.res,
  534. this.next
  535. )
  536. })
  537. it('should proxy to the standard url', function () {
  538. return this.request
  539. .calledWith({
  540. jar: this.jar,
  541. method: this.req.method,
  542. url: `${this.settings.apis.clsi.url}${this.url}`,
  543. timeout: 60 * 1000,
  544. })
  545. .should.equal(true)
  546. })
  547. })
  548. describe('user with build parameter via query string', function () {
  549. beforeEach(function () {
  550. this.CompileManager.getProjectCompileLimits = sinon
  551. .stub()
  552. .callsArgWith(1, null, { compileGroup: 'standard' })
  553. this.req.query = { build: 1234 }
  554. return this.CompileController.proxyToClsi(
  555. this.project_id,
  556. (this.url = '/test'),
  557. this.req,
  558. this.res,
  559. this.next
  560. )
  561. })
  562. it('should proxy to the standard url without the build parameter', function () {
  563. return this.request
  564. .calledWith({
  565. jar: this.jar,
  566. method: this.req.method,
  567. url: `${this.settings.apis.clsi.url}${this.url}`,
  568. timeout: 60 * 1000,
  569. })
  570. .should.equal(true)
  571. })
  572. })
  573. })
  574. describe('new pdf viewer', function () {
  575. beforeEach(function () {
  576. return (this.req.query = { pdfng: true })
  577. })
  578. describe('user with standard priority', function () {
  579. beforeEach(function () {
  580. this.CompileManager.getProjectCompileLimits = sinon
  581. .stub()
  582. .callsArgWith(1, null, { compileGroup: 'standard' })
  583. return this.CompileController.proxyToClsi(
  584. this.project_id,
  585. (this.url = '/test'),
  586. this.req,
  587. this.res,
  588. this.next
  589. )
  590. })
  591. it('should open a request to the CLSI', function () {
  592. return this.request
  593. .calledWith({
  594. jar: this.jar,
  595. method: this.req.method,
  596. url: `${this.settings.apis.clsi.url}${this.url}`,
  597. timeout: 60 * 1000,
  598. headers: {
  599. Range: '123-456',
  600. 'If-Range': 'abcdef',
  601. 'If-Modified-Since': 'Mon, 15 Dec 2014 15:23:56 GMT',
  602. },
  603. })
  604. .should.equal(true)
  605. })
  606. it('should pass the request on to the client', function () {
  607. return this.proxy.pipe.calledWith(this.res).should.equal(true)
  608. })
  609. it('should bind an error handle to the request proxy', function () {
  610. return this.proxy.on.calledWith('error').should.equal(true)
  611. })
  612. })
  613. describe('user with build parameter via query string', function () {
  614. beforeEach(function () {
  615. this.CompileManager.getProjectCompileLimits = sinon
  616. .stub()
  617. .callsArgWith(1, null, { compileGroup: 'standard' })
  618. this.req.query = { build: 1234, pdfng: true }
  619. return this.CompileController.proxyToClsi(
  620. this.project_id,
  621. (this.url = '/test'),
  622. this.req,
  623. this.res,
  624. this.next
  625. )
  626. })
  627. it('should proxy to the standard url with the build parameter', function () {
  628. return this.request
  629. .calledWith({
  630. jar: this.jar,
  631. method: this.req.method,
  632. qs: { build: 1234 },
  633. url: `${this.settings.apis.clsi.url}${this.url}`,
  634. timeout: 60 * 1000,
  635. headers: {
  636. Range: '123-456',
  637. 'If-Range': 'abcdef',
  638. 'If-Modified-Since': 'Mon, 15 Dec 2014 15:23:56 GMT',
  639. },
  640. })
  641. .should.equal(true)
  642. })
  643. })
  644. })
  645. })
  646. describe('deleteAuxFiles', function () {
  647. beforeEach(function () {
  648. this.CompileManager.deleteAuxFiles = sinon.stub().yields()
  649. this.req.params = { Project_id: this.project_id }
  650. this.req.query = { clsiserverid: 'node-1' }
  651. this.res.sendStatus = sinon.stub()
  652. return this.CompileController.deleteAuxFiles(
  653. this.req,
  654. this.res,
  655. this.next
  656. )
  657. })
  658. it('should proxy to the CLSI', function () {
  659. return this.CompileManager.deleteAuxFiles
  660. .calledWith(this.project_id, this.user_id, 'node-1')
  661. .should.equal(true)
  662. })
  663. it('should return a 200', function () {
  664. return this.res.sendStatus.calledWith(200).should.equal(true)
  665. })
  666. })
  667. describe('compileAndDownloadPdf', function () {
  668. beforeEach(function () {
  669. this.req = {
  670. params: {
  671. project_id: this.project_id,
  672. },
  673. }
  674. this.CompileManager.compile.callsArgWith(3)
  675. this.CompileController.proxyToClsi = sinon.stub()
  676. return (this.res = { send: () => {} })
  677. })
  678. it('should call compile in the compile manager', function (done) {
  679. this.CompileController.compileAndDownloadPdf(this.req, this.res)
  680. this.CompileManager.compile.calledWith(this.project_id).should.equal(true)
  681. return done()
  682. })
  683. it('should proxy the res to the clsi with correct url', function (done) {
  684. this.CompileController.compileAndDownloadPdf(this.req, this.res)
  685. sinon.assert.calledWith(
  686. this.CompileController.proxyToClsi,
  687. this.project_id,
  688. `/project/${this.project_id}/output/output.pdf`,
  689. this.req,
  690. this.res
  691. )
  692. this.CompileController.proxyToClsi
  693. .calledWith(
  694. this.project_id,
  695. `/project/${this.project_id}/output/output.pdf`,
  696. this.req,
  697. this.res
  698. )
  699. .should.equal(true)
  700. return done()
  701. })
  702. })
  703. describe('wordCount', function () {
  704. beforeEach(function () {
  705. this.CompileManager.wordCount = sinon
  706. .stub()
  707. .yields(null, { content: 'body' })
  708. this.req.params = { Project_id: this.project_id }
  709. this.req.query = { clsiserverid: 'node-42' }
  710. this.res.send = sinon.stub()
  711. this.res.contentType = sinon.stub()
  712. return this.CompileController.wordCount(this.req, this.res, this.next)
  713. })
  714. it('should proxy to the CLSI', function () {
  715. return this.CompileManager.wordCount
  716. .calledWith(this.project_id, this.user_id, false, 'node-42')
  717. .should.equal(true)
  718. })
  719. it('should return a 200 and body', function () {
  720. return this.res.send.calledWith({ content: 'body' }).should.equal(true)
  721. })
  722. })
  723. })