RequestParserTests.coffee 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. SandboxedModule = require('sandboxed-module')
  2. sinon = require('sinon')
  3. require('chai').should()
  4. expect = require('chai').expect
  5. modulePath = require('path').join __dirname, '../../../app/js/RequestParser'
  6. tk = require("timekeeper")
  7. describe "RequestParser", ->
  8. beforeEach ->
  9. tk.freeze()
  10. @callback = sinon.stub()
  11. @validResource =
  12. path: "main.tex"
  13. date: "12:00 01/02/03"
  14. content: "Hello world"
  15. @validRequest =
  16. compile:
  17. token: "token-123"
  18. options:
  19. imageName: "basicImageName/here:2017-1"
  20. compiler: "pdflatex"
  21. timeout: 42
  22. resources: []
  23. @RequestParser = SandboxedModule.require modulePath, requires:
  24. "settings-sharelatex": @settings = {}
  25. afterEach ->
  26. tk.reset()
  27. describe "without a top level object", ->
  28. beforeEach ->
  29. @RequestParser.parse [], @callback
  30. it "should return an error", ->
  31. @callback.calledWith("top level object should have a compile attribute")
  32. .should.equal true
  33. describe "without a compile attribute", ->
  34. beforeEach ->
  35. @RequestParser.parse {}, @callback
  36. it "should return an error", ->
  37. @callback.calledWith("top level object should have a compile attribute")
  38. .should.equal true
  39. describe "without a valid compiler", ->
  40. beforeEach ->
  41. @validRequest.compile.options.compiler = "not-a-compiler"
  42. @RequestParser.parse @validRequest, @callback
  43. it "should return an error", ->
  44. @callback.calledWith("compiler attribute should be one of: pdflatex, latex, xelatex, lualatex")
  45. .should.equal true
  46. describe "without a compiler specified", ->
  47. beforeEach ->
  48. delete @validRequest.compile.options.compiler
  49. @RequestParser.parse @validRequest, (error, @data) =>
  50. it "should set the compiler to pdflatex by default", ->
  51. @data.compiler.should.equal "pdflatex"
  52. describe "with imageName set", ->
  53. beforeEach ->
  54. @RequestParser.parse @validRequest, (error, @data) =>
  55. it "should set the imageName", ->
  56. @data.imageName.should.equal "basicImageName/here:2017-1"
  57. describe "with flags set", ->
  58. beforeEach ->
  59. @validRequest.compile.options.flags = ["-file-line-error"]
  60. @RequestParser.parse @validRequest, (error, @data) =>
  61. it "should set the flags attribute", ->
  62. expect(@data.flags).to.deep.equal ["-file-line-error"]
  63. describe "with flags not specified", ->
  64. beforeEach ->
  65. @RequestParser.parse @validRequest, (error, @data) =>
  66. it "it should have an empty flags list", ->
  67. expect(@data.flags).to.deep.equal []
  68. describe "without a timeout specified", ->
  69. beforeEach ->
  70. delete @validRequest.compile.options.timeout
  71. @RequestParser.parse @validRequest, (error, @data) =>
  72. it "should set the timeout to MAX_TIMEOUT", ->
  73. @data.timeout.should.equal @RequestParser.MAX_TIMEOUT * 1000
  74. describe "with a timeout larger than the maximum", ->
  75. beforeEach ->
  76. @validRequest.compile.options.timeout = @RequestParser.MAX_TIMEOUT + 1
  77. @RequestParser.parse @validRequest, (error, @data) =>
  78. it "should set the timeout to MAX_TIMEOUT", ->
  79. @data.timeout.should.equal @RequestParser.MAX_TIMEOUT * 1000
  80. describe "with a timeout", ->
  81. beforeEach ->
  82. @RequestParser.parse @validRequest, (error, @data) =>
  83. it "should set the timeout (in milliseconds)", ->
  84. @data.timeout.should.equal @validRequest.compile.options.timeout * 1000
  85. describe "with a resource without a path", ->
  86. beforeEach ->
  87. delete @validResource.path
  88. @validRequest.compile.resources.push @validResource
  89. @RequestParser.parse @validRequest, @callback
  90. it "should return an error", ->
  91. @callback.calledWith("all resources should have a path attribute")
  92. .should.equal true
  93. describe "with a resource with a path", ->
  94. beforeEach ->
  95. @validResource.path = @path = "test.tex"
  96. @validRequest.compile.resources.push @validResource
  97. @RequestParser.parse @validRequest, @callback
  98. @data = @callback.args[0][1]
  99. it "should return the path in the parsed response", ->
  100. @data.resources[0].path.should.equal @path
  101. describe "with a resource with a malformed modified date", ->
  102. beforeEach ->
  103. @validResource.modified = "not-a-date"
  104. @validRequest.compile.resources.push @validResource
  105. @RequestParser.parse @validRequest, @callback
  106. it "should return an error", ->
  107. @callback
  108. .calledWith(
  109. "resource modified date could not be understood: "+
  110. @validResource.modified
  111. )
  112. .should.equal true
  113. describe "with a resource with a valid date", ->
  114. beforeEach ->
  115. @date = "12:00 01/02/03"
  116. @validResource.modified = @date
  117. @validRequest.compile.resources.push @validResource
  118. @RequestParser.parse @validRequest, @callback
  119. @data = @callback.args[0][1]
  120. it "should return the date as a Javascript Date object", ->
  121. (@data.resources[0].modified instanceof Date).should.equal true
  122. @data.resources[0].modified.getTime().should.equal Date.parse(@date)
  123. describe "with a resource without either a content or URL attribute", ->
  124. beforeEach ->
  125. delete @validResource.url
  126. delete @validResource.content
  127. @validRequest.compile.resources.push @validResource
  128. @RequestParser.parse @validRequest, @callback
  129. it "should return an error", ->
  130. @callback.calledWith("all resources should have either a url or content attribute")
  131. .should.equal true
  132. describe "with a resource where the content is not a string", ->
  133. beforeEach ->
  134. @validResource.content = []
  135. @validRequest.compile.resources.push @validResource
  136. @RequestParser.parse (@validRequest), @callback
  137. it "should return an error", ->
  138. @callback.calledWith("content attribute should be a string")
  139. .should.equal true
  140. describe "with a resource where the url is not a string", ->
  141. beforeEach ->
  142. @validResource.url = []
  143. @validRequest.compile.resources.push @validResource
  144. @RequestParser.parse (@validRequest), @callback
  145. it "should return an error", ->
  146. @callback.calledWith("url attribute should be a string")
  147. .should.equal true
  148. describe "with a resource with a url", ->
  149. beforeEach ->
  150. @validResource.url = @url = "www.example.com"
  151. @validRequest.compile.resources.push @validResource
  152. @RequestParser.parse (@validRequest), @callback
  153. @data = @callback.args[0][1]
  154. it "should return the url in the parsed response", ->
  155. @data.resources[0].url.should.equal @url
  156. describe "with a resource with a content attribute", ->
  157. beforeEach ->
  158. @validResource.content = @content = "Hello world"
  159. @validRequest.compile.resources.push @validResource
  160. @RequestParser.parse (@validRequest), @callback
  161. @data = @callback.args[0][1]
  162. it "should return the content in the parsed response", ->
  163. @data.resources[0].content.should.equal @content
  164. describe "without a root resource path", ->
  165. beforeEach ->
  166. delete @validRequest.compile.rootResourcePath
  167. @RequestParser.parse (@validRequest), @callback
  168. @data = @callback.args[0][1]
  169. it "should set the root resource path to 'main.tex' by default", ->
  170. @data.rootResourcePath.should.equal "main.tex"
  171. describe "with a root resource path", ->
  172. beforeEach ->
  173. @validRequest.compile.rootResourcePath = @path = "test.tex"
  174. @RequestParser.parse (@validRequest), @callback
  175. @data = @callback.args[0][1]
  176. it "should return the root resource path in the parsed response", ->
  177. @data.rootResourcePath.should.equal @path
  178. describe "with a root resource path that is not a string", ->
  179. beforeEach ->
  180. @validRequest.compile.rootResourcePath = []
  181. @RequestParser.parse (@validRequest), @callback
  182. it "should return an error", ->
  183. @callback.calledWith("rootResourcePath attribute should be a string")
  184. .should.equal true
  185. describe "with a root resource path that needs escaping", ->
  186. beforeEach ->
  187. @badPath = "`rm -rf foo`.tex"
  188. @goodPath = "rm -rf foo.tex"
  189. @validRequest.compile.rootResourcePath = @badPath
  190. @validRequest.compile.resources.push {
  191. path: @badPath
  192. date: "12:00 01/02/03"
  193. content: "Hello world"
  194. }
  195. @RequestParser.parse @validRequest, @callback
  196. @data = @callback.args[0][1]
  197. it "should return the escaped resource", ->
  198. @data.rootResourcePath.should.equal @goodPath
  199. it "should also escape the resource path", ->
  200. @data.resources[0].path.should.equal @goodPath
  201. describe "with a root resource path that has a relative path", ->
  202. beforeEach ->
  203. @validRequest.compile.rootResourcePath = "foo/../../bar.tex"
  204. @RequestParser.parse @validRequest, @callback
  205. @data = @callback.args[0][1]
  206. it "should return an error", ->
  207. @callback.calledWith("relative path in root resource")
  208. .should.equal true
  209. describe "with a root resource path that has unescaped + relative path", ->
  210. beforeEach ->
  211. @validRequest.compile.rootResourcePath = "foo/#../bar.tex"
  212. @RequestParser.parse @validRequest, @callback
  213. @data = @callback.args[0][1]
  214. it "should return an error", ->
  215. @callback.calledWith("relative path in root resource")
  216. .should.equal true
  217. describe "with an unknown syncType", ->
  218. beforeEach ->
  219. @validRequest.compile.options.syncType = "unexpected"
  220. @RequestParser.parse @validRequest, @callback
  221. @data = @callback.args[0][1]
  222. it "should return an error", ->
  223. @callback.calledWith("syncType attribute should be one of: full, incremental")
  224. .should.equal true