ClsiManagerTests.coffee 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. sinon = require('sinon')
  2. chai = require('chai')
  3. should = chai.should()
  4. expect = chai.expect
  5. modulePath = "../../../../app/js/Features/Compile/ClsiManager.js"
  6. SandboxedModule = require('sandboxed-module')
  7. describe "ClsiManager", ->
  8. beforeEach ->
  9. @ClsiManager = SandboxedModule.require modulePath, requires:
  10. "settings-sharelatex": @settings =
  11. apis:
  12. filestore:
  13. url: "filestore.example.com"
  14. secret: "secret"
  15. clsi:
  16. url: "http://clsi.example.com"
  17. "../../models/Project": Project: @Project = {}
  18. "../Project/ProjectEntityHandler": @ProjectEntityHandler = {}
  19. "logger-sharelatex": @logger = { log: sinon.stub(), error: sinon.stub() }
  20. "request": @request = {}
  21. @project_id = "project-id"
  22. @callback = sinon.stub()
  23. describe "sendRequest", ->
  24. beforeEach ->
  25. @ClsiManager._buildRequest = sinon.stub().callsArgWith(1, null, @request = "mock-request")
  26. describe "with a successful compile", ->
  27. beforeEach ->
  28. @ClsiManager._postToClsi = sinon.stub().callsArgWith(2, null, {
  29. compile:
  30. status: @status = "success"
  31. outputFiles: [{
  32. url: "#{@settings.apis.clsi.url}/project/#{@project_id}/output/output.pdf"
  33. type: "pdf"
  34. },{
  35. url: "#{@settings.apis.clsi.url}/project/#{@project_id}/output/output.log"
  36. type: "log"
  37. }]
  38. })
  39. @ClsiManager.sendRequest @project_id, @callback
  40. it "should build the request", ->
  41. @ClsiManager._buildRequest
  42. .calledWith(@project_id)
  43. .should.equal true
  44. it "should send the request to the CLSI", ->
  45. @ClsiManager._postToClsi
  46. .calledWith(@project_id, @request)
  47. .should.equal true
  48. it "should call the callback with the status and output files", ->
  49. outputFiles = [{
  50. path: "output.pdf"
  51. type: "pdf"
  52. },{
  53. path: "output.log"
  54. type: "log"
  55. }]
  56. @callback.calledWith(null, @status, outputFiles).should.equal true
  57. describe "with a failed compile", ->
  58. beforeEach ->
  59. @ClsiManager._postToClsi = sinon.stub().callsArgWith(2, null, {
  60. compile:
  61. status: @status = "failure"
  62. })
  63. @ClsiManager.sendRequest @project_id, @callback
  64. it "should call the callback with a failure statue", ->
  65. @callback.calledWith(null, @status).should.equal true
  66. describe "_buildRequest", ->
  67. beforeEach ->
  68. @project =
  69. _id: @project_id
  70. compiler: @compiler = "latex"
  71. rootDoc_id: "mock-doc-id-1"
  72. @docs = {
  73. "/main.tex": @doc_1 = {
  74. name: "main.tex"
  75. _id: "mock-doc-id-1"
  76. lines: ["Hello", "world"]
  77. },
  78. "/chapters/chapter1.tex": @doc_2 = {
  79. name: "chapter1.tex"
  80. _id: "mock-doc-id-2"
  81. lines: [
  82. "Chapter 1"
  83. ]
  84. }
  85. }
  86. @files = {
  87. "/images/image.png": @file_1 = {
  88. name: "image.png"
  89. _id: "mock-file-id-1"
  90. created: new Date()
  91. }
  92. }
  93. @Project.findById = sinon.stub().callsArgWith(2, null, @project)
  94. @ProjectEntityHandler.getAllDocs = sinon.stub().callsArgWith(1, null, @docs)
  95. @ProjectEntityHandler.getAllFiles = sinon.stub().callsArgWith(1, null, @files)
  96. describe "with a valid project", ->
  97. beforeEach (done) ->
  98. @ClsiManager._buildRequest @project_id, (error, request) =>
  99. @request = request
  100. done()
  101. it "should get the project with the required fields", ->
  102. @Project.findById
  103. .calledWith(@project_id, {compiler:1, rootDoc_id: 1})
  104. .should.equal true
  105. it "should get all the docs", ->
  106. @ProjectEntityHandler.getAllDocs
  107. .calledWith(@project_id)
  108. .should.equal true
  109. it "should get all the files", ->
  110. @ProjectEntityHandler.getAllFiles
  111. .calledWith(@project_id)
  112. .should.equal true
  113. it "should build up the CLSI request", ->
  114. expect(@request).to.deep.equal(
  115. compile:
  116. options:
  117. compiler: @compiler
  118. rootResourcePath: "main.tex"
  119. resources: [{
  120. path: "main.tex"
  121. content: @doc_1.lines.join("\n")
  122. }, {
  123. path: "chapters/chapter1.tex"
  124. content: @doc_2.lines.join("\n")
  125. }, {
  126. path: "images/image.png"
  127. url: "#{@settings.apis.filestore.url}/project/#{@project_id}/file/#{@file_1._id}"
  128. modified: @file_1.created.getTime()
  129. }]
  130. )
  131. describe "when the project has an invalid compiler", ->
  132. beforeEach (done) ->
  133. @project.compiler = "context"
  134. @ClsiManager._buildRequest @project, (error, request) =>
  135. @request = request
  136. done()
  137. it "should set the compiler to pdflatex", ->
  138. @request.compile.options.compiler.should.equal "pdflatex"
  139. describe "when there is no valid root document", ->
  140. beforeEach (done) ->
  141. @project.rootDoc_id = "not-valid"
  142. @ClsiManager._buildRequest @project, (@error, @request) =>
  143. done()
  144. it "should return an error", ->
  145. expect(@error).to.exist
  146. describe '_postToClsi', ->
  147. beforeEach ->
  148. @req = { mock: "req" }
  149. describe "successfully", ->
  150. beforeEach ->
  151. @request.post = sinon.stub().callsArgWith(1, null, {statusCode: 204}, @body = { mock: "foo" })
  152. @ClsiManager._postToClsi @project_id, @req, @callback
  153. it 'should send the request to the CLSI', ->
  154. url = "#{@settings.apis.clsi.url}/project/#{@project_id}/compile"
  155. @request.post.calledWith({
  156. url: url
  157. json: @req
  158. jar: false
  159. }).should.equal true
  160. it "should call the callback with the body and no error", ->
  161. @callback.calledWith(null, @body).should.equal true
  162. describe "when the CLSI returns an error", ->
  163. beforeEach ->
  164. @request.post = sinon.stub().callsArgWith(1, null, {statusCode: 500}, @body = { mock: "foo" })
  165. @ClsiManager._postToClsi @project_id, @req, @callback
  166. it "should call the callback with the body and the error", ->
  167. @callback.calledWith(new Error("CLSI returned non-success code: 500"), @body).should.equal true