ProjectDownloadsControllerTests.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /* eslint-disable
  2. max-len,
  3. no-return-assign,
  4. no-unused-vars,
  5. */
  6. // TODO: This file was created by bulk-decaffeinate.
  7. // Fix any style issues and re-enable lint.
  8. /*
  9. * decaffeinate suggestions:
  10. * DS102: Remove unnecessary code created because of implicit returns
  11. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  12. */
  13. const sinon = require('sinon')
  14. const { expect } = require('chai')
  15. const modulePath =
  16. '../../../../app/src/Features/Downloads/ProjectDownloadsController.js'
  17. const SandboxedModule = require('sandboxed-module')
  18. const MockRequest = require('../helpers/MockRequest')
  19. const MockResponse = require('../helpers/MockResponse')
  20. describe('ProjectDownloadsController', function () {
  21. beforeEach(function () {
  22. this.project_id = 'project-id-123'
  23. this.req = new MockRequest()
  24. this.res = new MockResponse()
  25. this.next = sinon.stub()
  26. this.DocumentUpdaterHandler = sinon.stub()
  27. return (this.ProjectDownloadsController = SandboxedModule.require(
  28. modulePath,
  29. {
  30. requires: {
  31. './ProjectZipStreamManager': (this.ProjectZipStreamManager = {}),
  32. '../Project/ProjectGetter': (this.ProjectGetter = {}),
  33. '@overleaf/metrics': (this.metrics = {}),
  34. '../DocumentUpdater/DocumentUpdaterHandler':
  35. this.DocumentUpdaterHandler,
  36. },
  37. }
  38. ))
  39. })
  40. describe('downloadProject', function () {
  41. beforeEach(function () {
  42. this.stream = { pipe: sinon.stub() }
  43. this.ProjectZipStreamManager.createZipStreamForProject = sinon
  44. .stub()
  45. .callsArgWith(1, null, this.stream)
  46. this.req.params = { Project_id: this.project_id }
  47. this.project_name = 'project name with accênts'
  48. this.ProjectGetter.getProject = sinon
  49. .stub()
  50. .callsArgWith(2, null, { name: this.project_name })
  51. this.DocumentUpdaterHandler.flushProjectToMongo = sinon
  52. .stub()
  53. .callsArgWith(1)
  54. this.metrics.inc = sinon.stub()
  55. return this.ProjectDownloadsController.downloadProject(
  56. this.req,
  57. this.res,
  58. this.next
  59. )
  60. })
  61. it('should create a zip from the project', function () {
  62. return this.ProjectZipStreamManager.createZipStreamForProject
  63. .calledWith(this.project_id)
  64. .should.equal(true)
  65. })
  66. it('should stream the zip to the request', function () {
  67. return this.stream.pipe.calledWith(this.res).should.equal(true)
  68. })
  69. it('should set the correct content type on the request', function () {
  70. return this.res.contentType
  71. .calledWith('application/zip')
  72. .should.equal(true)
  73. })
  74. it('should flush the project to mongo', function () {
  75. return this.DocumentUpdaterHandler.flushProjectToMongo
  76. .calledWith(this.project_id)
  77. .should.equal(true)
  78. })
  79. it("should look up the project's name", function () {
  80. return this.ProjectGetter.getProject
  81. .calledWith(this.project_id, { name: true })
  82. .should.equal(true)
  83. })
  84. it('should name the downloaded file after the project', function () {
  85. this.res.headers.should.deep.equal({
  86. 'Content-Disposition': `attachment; filename="${this.project_name}.zip"`,
  87. 'Content-Type': 'application/zip',
  88. 'X-Content-Type-Options': 'nosniff',
  89. })
  90. })
  91. it('should record the action via Metrics', function () {
  92. return this.metrics.inc.calledWith('zip-downloads').should.equal(true)
  93. })
  94. })
  95. describe('downloadMultipleProjects', function () {
  96. beforeEach(function () {
  97. this.stream = { pipe: sinon.stub() }
  98. this.ProjectZipStreamManager.createZipStreamForMultipleProjects = sinon
  99. .stub()
  100. .callsArgWith(1, null, this.stream)
  101. this.project_ids = ['project-1', 'project-2']
  102. this.req.query = { project_ids: this.project_ids.join(',') }
  103. this.DocumentUpdaterHandler.flushMultipleProjectsToMongo = sinon
  104. .stub()
  105. .callsArgWith(1)
  106. this.metrics.inc = sinon.stub()
  107. return this.ProjectDownloadsController.downloadMultipleProjects(
  108. this.req,
  109. this.res,
  110. this.next
  111. )
  112. })
  113. it('should create a zip from the project', function () {
  114. return this.ProjectZipStreamManager.createZipStreamForMultipleProjects
  115. .calledWith(this.project_ids)
  116. .should.equal(true)
  117. })
  118. it('should stream the zip to the request', function () {
  119. return this.stream.pipe.calledWith(this.res).should.equal(true)
  120. })
  121. it('should set the correct content type on the request', function () {
  122. return this.res.contentType
  123. .calledWith('application/zip')
  124. .should.equal(true)
  125. })
  126. it('should flush the projects to mongo', function () {
  127. return this.DocumentUpdaterHandler.flushMultipleProjectsToMongo
  128. .calledWith(this.project_ids)
  129. .should.equal(true)
  130. })
  131. it('should name the downloaded file after the project', function () {
  132. this.res.headers.should.deep.equal({
  133. 'Content-Disposition':
  134. 'attachment; filename="Overleaf Projects (2 items).zip"',
  135. 'Content-Type': 'application/zip',
  136. 'X-Content-Type-Options': 'nosniff',
  137. })
  138. })
  139. it('should record the action via Metrics', function () {
  140. return this.metrics.inc
  141. .calledWith('zip-downloads-multiple')
  142. .should.equal(true)
  143. })
  144. })
  145. })