RequestParserTests.coffee 8.5 KB

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