assert = require("chai").assert sinon = require('sinon') chai = require('chai') should = chai.should() expect = chai.expect modulePath = "../../../../app/js/Features/FileStore/FileStoreController.js" SandboxedModule = require('sandboxed-module') describe "FileStoreController", -> beforeEach -> @FileStoreHandler = getFileStream: sinon.stub() @ProjectLocator = findElement: sinon.stub() @controller = SandboxedModule.require modulePath, requires: "settings-sharelatex": @settings "logger-sharelatex" : @logger = {log:sinon.stub(), err:sinon.stub()} "../Project/ProjectLocator": @ProjectLocator "./FileStoreHandler": @FileStoreHandler @stream = {} @project_id = "2k3j1lk3j21lk3j" @file_id = "12321kklj1lk3jk12" @req = params: Project_id: @project_id File_id: @file_id query: "query string here" get: (key) -> undefined @res = setHeader: sinon.stub() setContentDisposition: sinon.stub() @file = name: "myfile.png" describe "getFile", -> beforeEach -> @FileStoreHandler.getFileStream.callsArgWith(3, null, @stream) @ProjectLocator.findElement.callsArgWith(1, null, @file) it "should call the file store handler with the project_id file_id and any query string", (done)-> @stream.pipe = (des)=> @FileStoreHandler.getFileStream.calledWith(@req.params.Project_id, @req.params.File_id, @req.query).should.equal true done() @controller.getFile @req, @res it "should pipe to res", (done)-> @stream.pipe = (des)=> des.should.equal @res done() @controller.getFile @req, @res it "should get the file from the db", (done)-> @stream.pipe = (des)=> opts = project_id: @project_id element_id: @file_id type: "file" @ProjectLocator.findElement.calledWith(opts).should.equal true done() @controller.getFile @req, @res it "should set the Content-Disposition header", (done)-> @stream.pipe = (des)=> @res.setContentDisposition.calledWith( "attachment", {filename: @file.name} ).should.equal true done() @controller.getFile @req, @res # Test behaviour around handling html files ['.html', '.htm', '.xhtml'].forEach (extension) -> describe "with a '#{extension}' file extension", -> beforeEach -> @file.name = "bad#{extension}" @req.get = (key) => if key == 'User-Agent' return 'A generic browser' describe "from a non-ios browser", -> it "should not set Content-Type", (done) -> @stream.pipe = (des) => @res.setHeader.calledWith("Content-Type", "text/plain").should.equal false done() @controller.getFile @req, @res describe "from an iPhone", -> beforeEach -> @req.get = (key) => if key == 'User-Agent' return "An iPhone browser" it "should set Content-Type to 'text/plain'", (done) -> @stream.pipe = (des) => @res.setHeader.calledWith("Content-Type", "text/plain").should.equal true done() @controller.getFile @req, @res describe "from an iPad", -> beforeEach -> @req.get = (key) => if key == 'User-Agent' return "An iPad browser" it "should set Content-Type to 'text/plain'", (done) -> @stream.pipe = (des) => @res.setHeader.calledWith("Content-Type", "text/plain").should.equal true done() @controller.getFile @req, @res # None of these should trigger the iOS/html logic ['x.html-is-rad', 'html.pdf', '.html-is-good-for-hidden-files', 'somefile'].forEach (filename) -> describe "with filename as '#{filename}'", -> beforeEach -> @user_agent = 'A generic browser' @file.name = filename @req.get = (key) => if key == 'User-Agent' @user_agent ['iPhone', 'iPad', 'Firefox', 'Chrome'].forEach (browser) -> describe "downloaded from #{browser}", -> beforeEach -> @user_agent = "Some #{browser} thing" it 'Should not set the Content-type', (done) -> @stream.pipe = (des) => @res.setHeader.calledWith("Content-Type", "text/plain").should.equal false done() @controller.getFile @req, @res