FileHandlerTests.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. const sinon = require('sinon')
  2. const chai = require('chai')
  3. const { expect } = chai
  4. const modulePath = '../../../app/js/FileHandler.js'
  5. const SandboxedModule = require('sandboxed-module')
  6. describe('FileHandler', function() {
  7. let PersistorManager,
  8. LocalFileWriter,
  9. FileConverter,
  10. KeyBuilder,
  11. ImageOptimiser,
  12. FileHandler,
  13. fs
  14. const settings = {
  15. s3: {
  16. buckets: {
  17. user_files: 'user_files'
  18. }
  19. }
  20. }
  21. const bucket = 'my_bucket'
  22. const key = 'key/here'
  23. const convertedFolderKey = 'convertedFolder'
  24. const sourceStream = 'sourceStream'
  25. const convertedKey = 'convertedKey'
  26. const readStream = {
  27. stream: 'readStream',
  28. on: sinon.stub()
  29. }
  30. beforeEach(function() {
  31. PersistorManager = {
  32. getFileStream: sinon.stub().yields(null, sourceStream),
  33. checkIfFileExists: sinon.stub().yields(),
  34. deleteFile: sinon.stub().yields(),
  35. deleteDirectory: sinon.stub().yields(),
  36. sendStream: sinon.stub().yields(),
  37. insertFile: sinon.stub().yields(),
  38. sendFile: sinon.stub().yields(),
  39. directorySize: sinon.stub().yields()
  40. }
  41. LocalFileWriter = {
  42. writeStream: sinon.stub().yields(),
  43. deleteFile: sinon.stub().yields()
  44. }
  45. FileConverter = {
  46. convert: sinon.stub().yields(),
  47. thumbnail: sinon.stub().yields(),
  48. preview: sinon.stub().yields()
  49. }
  50. KeyBuilder = {
  51. addCachingToKey: sinon.stub().returns(convertedKey),
  52. getConvertedFolderKey: sinon.stub().returns(convertedFolderKey)
  53. }
  54. ImageOptimiser = { compressPng: sinon.stub().yields() }
  55. fs = {
  56. createReadStream: sinon.stub().returns(readStream)
  57. }
  58. FileHandler = SandboxedModule.require(modulePath, {
  59. requires: {
  60. 'settings-sharelatex': settings,
  61. './PersistorManager': PersistorManager,
  62. './LocalFileWriter': LocalFileWriter,
  63. './FileConverter': FileConverter,
  64. './KeyBuilder': KeyBuilder,
  65. './ImageOptimiser': ImageOptimiser,
  66. fs: fs,
  67. 'logger-sharelatex': {
  68. log() {},
  69. err() {}
  70. }
  71. },
  72. globals: { console }
  73. })
  74. })
  75. describe('insertFile', function() {
  76. const stream = 'stream'
  77. it('should send file to the filestore', function(done) {
  78. FileHandler.insertFile(bucket, key, stream, err => {
  79. expect(err).not.to.exist
  80. expect(PersistorManager.sendStream).to.have.been.calledWith(
  81. bucket,
  82. key,
  83. stream
  84. )
  85. done()
  86. })
  87. })
  88. it('should delete the convertedKey folder', function(done) {
  89. FileHandler.insertFile(bucket, key, stream, err => {
  90. expect(err).not.to.exist
  91. expect(PersistorManager.deleteDirectory).to.have.been.calledWith(
  92. bucket,
  93. convertedFolderKey
  94. )
  95. done()
  96. })
  97. })
  98. })
  99. describe('deleteFile', function() {
  100. it('should tell the filestore manager to delete the file', function(done) {
  101. FileHandler.deleteFile(bucket, key, err => {
  102. expect(err).not.to.exist
  103. expect(PersistorManager.deleteFile).to.have.been.calledWith(bucket, key)
  104. done()
  105. })
  106. })
  107. it('should tell the filestore manager to delete the cached folder', function(done) {
  108. FileHandler.deleteFile(bucket, key, err => {
  109. expect(err).not.to.exist
  110. expect(PersistorManager.deleteDirectory).to.have.been.calledWith(
  111. bucket,
  112. convertedFolderKey
  113. )
  114. done()
  115. })
  116. })
  117. })
  118. describe('getFile', function() {
  119. it('should return the source stream no format or style are defined', function(done) {
  120. FileHandler.getFile(bucket, key, null, (err, stream) => {
  121. expect(err).not.to.exist
  122. expect(stream).to.equal(sourceStream)
  123. done()
  124. })
  125. })
  126. it('should pass options through to PersistorManager', function(done) {
  127. const options = { start: 0, end: 8 }
  128. FileHandler.getFile(bucket, key, options, err => {
  129. expect(err).not.to.exist
  130. expect(PersistorManager.getFileStream).to.have.been.calledWith(
  131. bucket,
  132. key,
  133. options
  134. )
  135. done()
  136. })
  137. })
  138. describe('when a format is defined', function() {
  139. let result
  140. describe('when the file is not cached', function() {
  141. beforeEach(function(done) {
  142. FileHandler.getFile(bucket, key, { format: 'png' }, (err, stream) => {
  143. result = { err, stream }
  144. done()
  145. })
  146. })
  147. it('should convert the file', function() {
  148. expect(FileConverter.convert).to.have.been.called
  149. expect(ImageOptimiser.compressPng).to.have.been.called
  150. })
  151. it('should return the the converted stream', function() {
  152. expect(result.err).not.to.exist
  153. expect(result.stream).to.equal(readStream)
  154. expect(PersistorManager.getFileStream).to.have.been.calledWith(
  155. bucket,
  156. key
  157. )
  158. })
  159. })
  160. describe('when the file is cached', function() {
  161. beforeEach(function(done) {
  162. PersistorManager.checkIfFileExists = sinon.stub().yields(null, true)
  163. FileHandler.getFile(bucket, key, { format: 'png' }, (err, stream) => {
  164. result = { err, stream }
  165. done()
  166. })
  167. })
  168. it('should not convert the file', function() {
  169. expect(FileConverter.convert).not.to.have.been.called
  170. expect(ImageOptimiser.compressPng).not.to.have.been.called
  171. })
  172. it('should return the cached stream', function() {
  173. expect(result.err).not.to.exist
  174. expect(result.stream).to.equal(sourceStream)
  175. expect(PersistorManager.getFileStream).to.have.been.calledWith(
  176. bucket,
  177. convertedKey
  178. )
  179. })
  180. })
  181. })
  182. describe('when a style is defined', function() {
  183. it('generates a thumbnail when requested', function(done) {
  184. FileHandler.getFile(bucket, key, { style: 'thumbnail' }, err => {
  185. expect(err).not.to.exist
  186. expect(FileConverter.thumbnail).to.have.been.called
  187. expect(FileConverter.preview).not.to.have.been.called
  188. done()
  189. })
  190. })
  191. it('generates a preview when requested', function(done) {
  192. FileHandler.getFile(bucket, key, { style: 'preview' }, err => {
  193. expect(err).not.to.exist
  194. expect(FileConverter.thumbnail).not.to.have.been.called
  195. expect(FileConverter.preview).to.have.been.called
  196. done()
  197. })
  198. })
  199. })
  200. })
  201. describe('getDirectorySize', function() {
  202. it('should call the filestore manager to get directory size', function(done) {
  203. FileHandler.getDirectorySize(bucket, key, err => {
  204. expect(err).not.to.exist
  205. expect(PersistorManager.directorySize).to.have.been.calledWith(
  206. bucket,
  207. key
  208. )
  209. done()
  210. })
  211. })
  212. })
  213. })