FileControllerTests.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /* eslint-disable
  2. no-return-assign,
  3. no-unused-vars,
  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 {
  13. assert
  14. } = require("chai");
  15. const sinon = require('sinon');
  16. const chai = require('chai');
  17. const should = chai.should();
  18. const {
  19. expect
  20. } = chai;
  21. const modulePath = "../../../app/js/FileController.js";
  22. const SandboxedModule = require('sandboxed-module');
  23. describe("FileController", function() {
  24. beforeEach(function() {
  25. this.PersistorManager = {
  26. sendStream: sinon.stub(),
  27. copyFile: sinon.stub(),
  28. deleteFile:sinon.stub()
  29. };
  30. this.settings = {
  31. s3: {
  32. buckets: {
  33. user_files:"user_files"
  34. }
  35. }
  36. };
  37. this.FileHandler = {
  38. getFile: sinon.stub(),
  39. getFileSize: sinon.stub(),
  40. deleteFile: sinon.stub(),
  41. insertFile: sinon.stub(),
  42. getDirectorySize: sinon.stub()
  43. };
  44. this.LocalFileWriter = {};
  45. this.controller = SandboxedModule.require(modulePath, { requires: {
  46. "./LocalFileWriter":this.LocalFileWriter,
  47. "./FileHandler": this.FileHandler,
  48. "./PersistorManager":this.PersistorManager,
  49. "./Errors": (this.Errors =
  50. {NotFoundError: sinon.stub()}),
  51. "settings-sharelatex": this.settings,
  52. "metrics-sharelatex": {
  53. inc() {}
  54. },
  55. "logger-sharelatex": {
  56. log() {},
  57. err() {}
  58. }
  59. }
  60. }
  61. );
  62. this.project_id = "project_id";
  63. this.file_id = "file_id";
  64. this.bucket = "user_files";
  65. this.key = `${this.project_id}/${this.file_id}`;
  66. this.req = {
  67. key:this.key,
  68. bucket:this.bucket,
  69. query:{},
  70. params: {
  71. project_id:this.project_id,
  72. file_id:this.file_id
  73. },
  74. headers: {}
  75. };
  76. this.res = {
  77. set: sinon.stub().returnsThis(),
  78. status: sinon.stub().returnsThis()
  79. };
  80. return this.fileStream = {};});
  81. describe("getFile", function() {
  82. it("should pipe the stream", function(done){
  83. this.FileHandler.getFile.callsArgWith(3, null, this.fileStream);
  84. this.fileStream.pipe = res=> {
  85. res.should.equal(this.res);
  86. return done();
  87. };
  88. return this.controller.getFile(this.req, this.res);
  89. });
  90. it("should send a 200 if the cacheWarm param is true", function(done){
  91. this.req.query.cacheWarm = true;
  92. this.FileHandler.getFile.callsArgWith(3, null, this.fileStream);
  93. this.res.send = statusCode=> {
  94. statusCode.should.equal(200);
  95. return done();
  96. };
  97. return this.controller.getFile(this.req, this.res);
  98. });
  99. it("should send a 500 if there is a problem", function(done){
  100. this.FileHandler.getFile.callsArgWith(3, "error");
  101. this.res.send = code=> {
  102. code.should.equal(500);
  103. return done();
  104. };
  105. return this.controller.getFile(this.req, this.res);
  106. });
  107. return describe("with a 'Range' header set", function() {
  108. beforeEach(function() {
  109. return this.req.headers.range = 'bytes=0-8';
  110. });
  111. return it("should pass 'start' and 'end' options to FileHandler", function(done) {
  112. this.FileHandler.getFile.callsArgWith(3, null, this.fileStream);
  113. this.fileStream.pipe = res=> {
  114. expect(this.FileHandler.getFile.lastCall.args[2].start).to.equal(0);
  115. expect(this.FileHandler.getFile.lastCall.args[2].end).to.equal(8);
  116. return done();
  117. };
  118. return this.controller.getFile(this.req, this.res);
  119. });
  120. });
  121. });
  122. describe("getFileHead", function() {
  123. it("should return the file size in a Content-Length header", function(done) {
  124. const expectedFileSize = 84921;
  125. this.FileHandler.getFileSize.yields(
  126. new Error("FileHandler.getFileSize: unexpected arguments")
  127. );
  128. this.FileHandler.getFileSize.withArgs(this.bucket, this.key).yields(null, expectedFileSize);
  129. this.res.end = () => {
  130. expect(this.res.status.lastCall.args[0]).to.equal(200);
  131. expect(this.res.set.calledWith("Content-Length", expectedFileSize)).to.equal(true);
  132. return done();
  133. };
  134. return this.controller.getFileHead(this.req, this.res);
  135. });
  136. it("should return a 404 is the file is not found", function(done) {
  137. this.FileHandler.getFileSize.yields(new this.Errors.NotFoundError());
  138. this.res.end = () => {
  139. expect(this.res.status.lastCall.args[0]).to.equal(404);
  140. return done();
  141. };
  142. return this.controller.getFileHead(this.req, this.res);
  143. });
  144. return it("should return a 500 on internal errors", function(done) {
  145. this.FileHandler.getFileSize.yields(new Error());
  146. this.res.end = () => {
  147. expect(this.res.status.lastCall.args[0]).to.equal(500);
  148. return done();
  149. };
  150. return this.controller.getFileHead(this.req, this.res);
  151. });
  152. });
  153. describe("insertFile", () => it("should send bucket name key and res to PersistorManager", function(done){
  154. this.FileHandler.insertFile.callsArgWith(3);
  155. this.res.send = () => {
  156. this.FileHandler.insertFile.calledWith(this.bucket, this.key, this.req).should.equal(true);
  157. return done();
  158. };
  159. return this.controller.insertFile(this.req, this.res);
  160. }));
  161. describe("copyFile", function() {
  162. beforeEach(function() {
  163. this.oldFile_id = "old_file_id";
  164. this.oldProject_id = "old_project_id";
  165. return this.req.body = {
  166. source: {
  167. project_id: this.oldProject_id,
  168. file_id: this.oldFile_id
  169. }
  170. };
  171. });
  172. it("should send bucket name and both keys to PersistorManager", function(done){
  173. this.PersistorManager.copyFile.callsArgWith(3);
  174. this.res.send = code=> {
  175. code.should.equal(200);
  176. this.PersistorManager.copyFile.calledWith(this.bucket, `${this.oldProject_id}/${this.oldFile_id}`, this.key).should.equal(true);
  177. return done();
  178. };
  179. return this.controller.copyFile(this.req, this.res);
  180. });
  181. it("should send a 404 if the original file was not found", function(done) {
  182. this.PersistorManager.copyFile.callsArgWith(3, new this.Errors.NotFoundError());
  183. this.res.send = code=> {
  184. code.should.equal(404);
  185. return done();
  186. };
  187. return this.controller.copyFile(this.req, this.res);
  188. });
  189. return it("should send a 500 if there was an error", function(done){
  190. this.PersistorManager.copyFile.callsArgWith(3, "error");
  191. this.res.send = code=> {
  192. code.should.equal(500);
  193. return done();
  194. };
  195. return this.controller.copyFile(this.req, this.res);
  196. });
  197. });
  198. describe("delete file", function() {
  199. it("should tell the file handler", function(done){
  200. this.FileHandler.deleteFile.callsArgWith(2);
  201. this.res.send = code=> {
  202. code.should.equal(204);
  203. this.FileHandler.deleteFile.calledWith(this.bucket, this.key).should.equal(true);
  204. return done();
  205. };
  206. return this.controller.deleteFile(this.req, this.res);
  207. });
  208. return it("should send a 500 if there was an error", function(done){
  209. this.FileHandler.deleteFile.callsArgWith(2, "error");
  210. this.res.send = function(code){
  211. code.should.equal(500);
  212. return done();
  213. };
  214. return this.controller.deleteFile(this.req, this.res);
  215. });
  216. });
  217. describe("_get_range", function() {
  218. it("should parse a valid Range header", function(done) {
  219. const result = this.controller._get_range('bytes=0-200');
  220. expect(result).to.not.equal(null);
  221. expect(result.start).to.equal(0);
  222. expect(result.end).to.equal(200);
  223. return done();
  224. });
  225. it("should return null for an invalid Range header", function(done) {
  226. const result = this.controller._get_range('wat');
  227. expect(result).to.equal(null);
  228. return done();
  229. });
  230. return it("should return null for any type other than 'bytes'", function(done) {
  231. const result = this.controller._get_range('carrots=0-200');
  232. expect(result).to.equal(null);
  233. return done();
  234. });
  235. });
  236. return describe("directorySize", function() {
  237. it("should return total directory size bytes", function(done) {
  238. this.FileHandler.getDirectorySize.callsArgWith(2, null, 1024);
  239. return this.controller.directorySize(this.req, { json:result=> {
  240. expect(result['total bytes']).to.equal(1024);
  241. return done();
  242. }
  243. }
  244. );
  245. });
  246. return it("should send a 500 if there was an error", function(done){
  247. this.FileHandler.getDirectorySize.callsArgWith(2, "error");
  248. this.res.send = function(code){
  249. code.should.equal(500);
  250. return done();
  251. };
  252. return this.controller.directorySize(this.req, this.res);
  253. });
  254. });
  255. });