upload.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. if (typeof require == "function") {
  2. require("../lib/mock-ajax.js")
  3. }
  4. describe("tus", function() {
  5. describe("#Upload", function() {
  6. beforeEach(function() {
  7. jasmine.Ajax.install()
  8. localStorage.clear()
  9. })
  10. afterEach(function() {
  11. jasmine.Ajax.uninstall()
  12. })
  13. it("should throw if no error handler is available", function() {
  14. var upload = new tus.Upload(null)
  15. expect(upload.start).toThrow()
  16. })
  17. it("should upload a file", function(done) {
  18. var file = new FakeBlob("hello world".split(""))
  19. var options = {
  20. endpoint: "/uploads",
  21. headers: {
  22. Custom: "blargh"
  23. },
  24. metadata: {
  25. foo: "hello",
  26. bar: "world",
  27. nonlatin: "słońce"
  28. },
  29. withCredentials: true,
  30. onProgress: function() {},
  31. fingerprint: function() {}
  32. }
  33. spyOn(options, "fingerprint").and.returnValue("fingerprinted")
  34. spyOn(options, "onProgress")
  35. var upload = new tus.Upload(file, options)
  36. upload.start()
  37. expect(options.fingerprint).toHaveBeenCalledWith(file)
  38. var req = jasmine.Ajax.requests.mostRecent()
  39. expect(req.url).toBe("/uploads")
  40. expect(req.method).toBe("POST")
  41. expect(req.withCredentials).toBe(true)
  42. expect(req.requestHeaders.Custom).toBe("blargh")
  43. expect(req.requestHeaders["Tus-Resumable"]).toBe("1.0.0")
  44. expect(req.requestHeaders["Upload-Length"]).toBe(file.size)
  45. if("btoa" in window) {
  46. expect(req.requestHeaders["Upload-Metadata"]).toBe("foo aGVsbG8=,bar d29ybGQ=,nonlatin c8WCb8WEY2U=")
  47. }
  48. req.respondWith({
  49. status: 201,
  50. responseHeaders: {
  51. Location: "/uploads/blargh"
  52. }
  53. })
  54. expect(upload.url).toBe("/uploads/blargh")
  55. expect(localStorage.getItem("fingerprinted")).toBe("/uploads/blargh")
  56. req = jasmine.Ajax.requests.mostRecent()
  57. expect(req.url).toBe("/uploads/blargh")
  58. expect(req.method).toBe("PATCH")
  59. expect(req.withCredentials).toBe(true)
  60. expect(req.requestHeaders.Custom).toBe("blargh")
  61. expect(req.requestHeaders["Tus-Resumable"]).toBe("1.0.0")
  62. expect(req.requestHeaders["Upload-Offset"]).toBe(0)
  63. expect(req.contentType()).toBe("application/offset+octet-stream")
  64. expect(req.params.size).toBe(file.size)
  65. req.respondWith({
  66. status: 204,
  67. responseHeaders: {
  68. "Upload-Offset": file.size
  69. }
  70. })
  71. expect(options.onProgress).toHaveBeenCalledWith(11, 11)
  72. done()
  73. })
  74. it("should resume an upload", function(done) {
  75. localStorage.setItem("fingerprinted", "/uploads/resuming")
  76. var file = new FakeBlob("hello world".split(""))
  77. var options = {
  78. endpoint: "/uploads",
  79. onProgress: function() {},
  80. fingerprint: function() {}
  81. }
  82. spyOn(options, "fingerprint").and.returnValue("fingerprinted")
  83. spyOn(options, "onProgress")
  84. var upload = new tus.Upload(file, options)
  85. upload.start()
  86. expect(options.fingerprint).toHaveBeenCalledWith(file)
  87. var req = jasmine.Ajax.requests.mostRecent()
  88. expect(req.url).toBe("/uploads/resuming")
  89. expect(req.method).toBe("HEAD")
  90. expect(req.requestHeaders["Tus-Resumable"]).toBe("1.0.0")
  91. req.respondWith({
  92. status: 204,
  93. responseHeaders: {
  94. "Upload-Length": 11,
  95. "Upload-Offset": 3
  96. }
  97. })
  98. expect(upload.url).toBe("/uploads/resuming")
  99. req = jasmine.Ajax.requests.mostRecent()
  100. expect(req.url).toBe("/uploads/resuming")
  101. expect(req.method).toBe("PATCH")
  102. expect(req.requestHeaders["Tus-Resumable"]).toBe("1.0.0")
  103. expect(req.requestHeaders["Upload-Offset"]).toBe(3)
  104. expect(req.contentType()).toBe("application/offset+octet-stream")
  105. expect(req.params.size).toBe(file.size - 3)
  106. req.respondWith({
  107. status: 204,
  108. responseHeaders: {
  109. "Upload-Offset": file.size
  110. }
  111. })
  112. expect(options.onProgress).toHaveBeenCalledWith(11, 11)
  113. done()
  114. })
  115. it("should create an upload if resuming fails", function() {
  116. localStorage.setItem("fingerprinted", "/uploads/resuming")
  117. var file = new FakeBlob("hello world".split(""))
  118. var options = {
  119. endpoint: "/uploads",
  120. fingerprint: function() {}
  121. }
  122. spyOn(options, "fingerprint").and.returnValue("fingerprinted")
  123. var upload = new tus.Upload(file, options)
  124. upload.start()
  125. expect(options.fingerprint).toHaveBeenCalledWith(file)
  126. var req = jasmine.Ajax.requests.mostRecent()
  127. expect(req.url).toBe("/uploads/resuming")
  128. expect(req.method).toBe("HEAD")
  129. expect(req.requestHeaders["Tus-Resumable"]).toBe("1.0.0")
  130. req.respondWith({
  131. status: 404
  132. })
  133. expect(upload.url).toBe(null)
  134. req = jasmine.Ajax.requests.mostRecent()
  135. expect(req.url).toBe("/uploads")
  136. expect(req.method).toBe("POST")
  137. expect(req.requestHeaders["Tus-Resumable"]).toBe("1.0.0")
  138. expect(req.requestHeaders["Upload-Length"]).toBe(11)
  139. })
  140. it("should upload a file in chunks", function(done) {
  141. var file = new FakeBlob("hello world".split(""))
  142. var options = {
  143. endpoint: "/uploads",
  144. chunkSize: 7,
  145. onProgress: function() {},
  146. onChunkComplete: function() {},
  147. fingerprint: function() {}
  148. }
  149. spyOn(options, "fingerprint").and.returnValue("fingerprinted")
  150. spyOn(options, "onProgress")
  151. spyOn(options, "onChunkComplete")
  152. var upload = new tus.Upload(file, options)
  153. upload.start()
  154. expect(options.fingerprint).toHaveBeenCalledWith(file)
  155. var req = jasmine.Ajax.requests.mostRecent()
  156. expect(req.url).toBe("/uploads")
  157. expect(req.method).toBe("POST")
  158. expect(req.requestHeaders["Tus-Resumable"]).toBe("1.0.0")
  159. expect(req.requestHeaders["Upload-Length"]).toBe(file.size)
  160. req.respondWith({
  161. status: 201,
  162. responseHeaders: {
  163. Location: "/uploads/blargh"
  164. }
  165. })
  166. expect(upload.url).toBe("/uploads/blargh")
  167. expect(localStorage.getItem("fingerprinted")).toBe("/uploads/blargh")
  168. req = jasmine.Ajax.requests.mostRecent()
  169. expect(req.url).toBe("/uploads/blargh")
  170. expect(req.method).toBe("PATCH")
  171. expect(req.requestHeaders["Tus-Resumable"]).toBe("1.0.0")
  172. expect(req.requestHeaders["Upload-Offset"]).toBe(0)
  173. expect(req.contentType()).toBe("application/offset+octet-stream")
  174. expect(req.params.size).toBe(7)
  175. req.respondWith({
  176. status: 204,
  177. responseHeaders: {
  178. "Upload-Offset": 7
  179. }
  180. })
  181. req = jasmine.Ajax.requests.mostRecent()
  182. expect(req.url).toBe("/uploads/blargh")
  183. expect(req.method).toBe("PATCH")
  184. expect(req.requestHeaders["Tus-Resumable"]).toBe("1.0.0")
  185. expect(req.requestHeaders["Upload-Offset"]).toBe(7)
  186. expect(req.contentType()).toBe("application/offset+octet-stream")
  187. expect(req.params.size).toBe(4)
  188. req.respondWith({
  189. status: 204,
  190. responseHeaders: {
  191. "Upload-Offset": file.size
  192. }
  193. })
  194. expect(options.onProgress).toHaveBeenCalledWith(11, 11)
  195. expect(options.onChunkComplete).toHaveBeenCalledWith(7, 7, 11)
  196. expect(options.onChunkComplete).toHaveBeenCalledWith(4, 11, 11)
  197. done()
  198. })
  199. it("should add the original request to errors", function() {
  200. var file = new FakeBlob("hello world".split(""))
  201. var err
  202. var options = {
  203. endpoint: "/uploads",
  204. onError: function(e) {
  205. err = e
  206. },
  207. }
  208. var upload = new tus.Upload(file, options)
  209. upload.start()
  210. var req = jasmine.Ajax.requests.mostRecent()
  211. expect(req.url).toBe("/uploads")
  212. expect(req.method).toBe("POST")
  213. req.respondWith({
  214. status: 500,
  215. responseHeaders: {
  216. Custom: "blargh"
  217. }
  218. })
  219. expect(upload.url).toBe(null)
  220. expect(err.message).toBe("tus: unexpected response while creating upload")
  221. expect(err.originalRequest).toBe(req)
  222. expect(err.originalRequest.getResponseHeader("Custom")).toBe("blargh")
  223. })
  224. })
  225. })