filedownloader_test.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. // Copyright 2011 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. goog.provide('goog.net.FileDownloaderTest');
  15. goog.setTestOnly('goog.net.FileDownloaderTest');
  16. goog.require('goog.fs.Error');
  17. goog.require('goog.net.ErrorCode');
  18. goog.require('goog.net.FileDownloader');
  19. goog.require('goog.net.XhrIo');
  20. goog.require('goog.testing.PropertyReplacer');
  21. goog.require('goog.testing.TestCase');
  22. goog.require('goog.testing.fs');
  23. goog.require('goog.testing.fs.FileSystem');
  24. goog.require('goog.testing.jsunit');
  25. goog.require('goog.testing.net.XhrIoPool');
  26. var xhrIoPool, xhr, fs, dir, downloader;
  27. function setUpPage() {
  28. goog.testing.fs.install(new goog.testing.PropertyReplacer());
  29. goog.testing.TestCase.getActiveTestCase().promiseTimeout = 10000; // 10s
  30. }
  31. function setUp() {
  32. xhrIoPool = new goog.testing.net.XhrIoPool();
  33. xhr = xhrIoPool.getXhr();
  34. fs = new goog.testing.fs.FileSystem();
  35. dir = fs.getRoot();
  36. downloader = new goog.net.FileDownloader(dir, xhrIoPool);
  37. }
  38. function tearDown() {
  39. goog.dispose(downloader);
  40. }
  41. function testDownload() {
  42. var promise = downloader.download('/foo/bar').then(function(blob) {
  43. var fileEntry = dir.getFileSync('`3fa/``2Ffoo`2Fbar/`bar');
  44. assertEquals('data', blob.toString());
  45. assertEquals('data', fileEntry.fileSync().toString());
  46. });
  47. xhr.simulateResponse(200, 'data');
  48. assertEquals('/foo/bar', xhr.getLastUri());
  49. assertEquals(goog.net.XhrIo.ResponseType.ARRAY_BUFFER, xhr.getResponseType());
  50. return promise;
  51. }
  52. function testGetDownloadedBlob() {
  53. var promise =
  54. downloader.download('/foo/bar')
  55. .then(function() { return downloader.getDownloadedBlob('/foo/bar'); })
  56. .then(function(blob) { assertEquals('data', blob.toString()); });
  57. xhr.simulateResponse(200, 'data');
  58. return promise;
  59. }
  60. function testGetLocalUrl() {
  61. var promise =
  62. downloader.download('/foo/bar')
  63. .then(function() { return downloader.getLocalUrl('/foo/bar'); })
  64. .then(function(url) { assertMatches(/\/`bar$/, url); });
  65. xhr.simulateResponse(200, 'data');
  66. return promise;
  67. }
  68. function testLocalUrlWithContentDisposition() {
  69. var promise =
  70. downloader.download('/foo/bar')
  71. .then(function() { return downloader.getLocalUrl('/foo/bar'); })
  72. .then(function(url) { assertMatches(/\/`qux`22bap$/, url); });
  73. xhr.simulateResponse(
  74. 200, 'data', {'Content-Disposition': 'attachment; filename="qux\\"bap"'});
  75. return promise;
  76. }
  77. function testIsDownloaded() {
  78. var promise =
  79. downloader.download('/foo/bar')
  80. .then(function() { return downloader.isDownloaded('/foo/bar'); })
  81. .then(assertTrue)
  82. .then(function(isDownloaded) {
  83. return downloader.isDownloaded('/foo/baz');
  84. })
  85. .then(assertFalse);
  86. xhr.simulateResponse(200, 'data');
  87. return promise;
  88. }
  89. function testRemove() {
  90. var promise =
  91. downloader.download('/foo/bar')
  92. .then(function() { return downloader.remove('/foo/bar'); })
  93. .then(function() { return downloader.isDownloaded('/foo/bar'); })
  94. .then(assertFalse)
  95. .then(function() { return downloader.getDownloadedBlob('/foo/bar'); })
  96. .then(
  97. function() {
  98. fail('Should not be able to download a missing blob.');
  99. },
  100. function(err) {
  101. assertEquals(goog.fs.Error.ErrorCode.NOT_FOUND, err.code);
  102. var download = downloader.download('/foo/bar');
  103. xhr.simulateResponse(200, 'more data');
  104. return download;
  105. })
  106. .then(function() { return downloader.isDownloaded('/foo/bar'); })
  107. .then(assertTrue)
  108. .then(function() { return downloader.getDownloadedBlob('/foo/bar'); })
  109. .then(function(blob) { assertEquals('more data', blob.toString()); });
  110. xhr.simulateResponse(200, 'data');
  111. return promise;
  112. }
  113. function testSetBlob() {
  114. return downloader.setBlob('/foo/bar', goog.testing.fs.getBlob('data'))
  115. .then(function() { return downloader.isDownloaded('/foo/bar'); })
  116. .then(assertTrue)
  117. .then(function() { return downloader.getDownloadedBlob('/foo/bar'); })
  118. .then(function(blob) { assertEquals('data', blob.toString()); });
  119. }
  120. function testSetBlobWithName() {
  121. return downloader.setBlob('/foo/bar', goog.testing.fs.getBlob('data'), 'qux')
  122. .then(function() { return downloader.getLocalUrl('/foo/bar'); })
  123. .then(function(url) { assertMatches(/\/`qux$/, url); });
  124. }
  125. function testDownloadDuringDownload() {
  126. var download1 = downloader.download('/foo/bar');
  127. var download2 = downloader.download('/foo/bar');
  128. var promise =
  129. download1.then(function() { return download2; })
  130. .then(function() { return downloader.getDownloadedBlob('/foo/bar'); })
  131. .then(function(blob) { assertEquals('data', blob.toString()); });
  132. // There should only need to be one response for both downloads, since the
  133. // second should return the same deferred as the first.
  134. xhr.simulateResponse(200, 'data');
  135. return promise;
  136. }
  137. function testGetDownloadedBlobDuringDownload() {
  138. var hasDownloaded = false;
  139. downloader.download('/foo/bar').then(function() { hasDownloaded = true; });
  140. var promise =
  141. downloader.waitForDownload('/foo/bar')
  142. .then(function() { return downloader.getDownloadedBlob('/foo/bar'); })
  143. .then(function(blob) {
  144. assertTrue(hasDownloaded);
  145. assertEquals('data', blob.toString());
  146. });
  147. xhr.simulateResponse(200, 'data');
  148. return promise;
  149. }
  150. function testIsDownloadedDuringDownload() {
  151. var hasDownloaded = false;
  152. downloader.download('/foo/bar').then(function() { hasDownloaded = true; });
  153. var promise = downloader.waitForDownload('/foo/bar')
  154. .then(function() {
  155. return downloader.isDownloaded('/foo/bar');
  156. })
  157. .then(function() {
  158. assertTrue(hasDownloaded);
  159. });
  160. xhr.simulateResponse(200, 'data');
  161. return promise;
  162. }
  163. function testRemoveDuringDownload() {
  164. var hasDownloaded = false;
  165. downloader.download('/foo/bar').then(function() { hasDownloaded = true; });
  166. var promise =
  167. downloader.waitForDownload('/foo/bar')
  168. .then(function() { return downloader.remove('/foo/bar'); })
  169. .then(function() { assertTrue(hasDownloaded); })
  170. .then(function() { return downloader.isDownloaded('/foo/bar'); })
  171. .then(assertFalse);
  172. xhr.simulateResponse(200, 'data');
  173. return promise;
  174. }
  175. function testSetBlobDuringDownload() {
  176. var download = downloader.download('/foo/bar');
  177. var promise =
  178. downloader.waitForDownload('/foo/bar')
  179. .then(function() {
  180. return downloader.setBlob(
  181. '/foo/bar', goog.testing.fs.getBlob('blob data'));
  182. })
  183. .then(
  184. function() {
  185. fail('Should not be able to set blob during a download.');
  186. },
  187. function(err) {
  188. assertEquals(
  189. goog.fs.Error.ErrorCode.INVALID_MODIFICATION,
  190. err.fileError.code);
  191. return download;
  192. })
  193. .then(function() { return downloader.getDownloadedBlob('/foo/bar'); })
  194. .then(function(b) { assertEquals('xhr data', b.toString()); });
  195. xhr.simulateResponse(200, 'xhr data');
  196. return promise;
  197. }
  198. function testDownloadCanceledBeforeXhr() {
  199. var download = downloader.download('/foo/bar');
  200. var promise =
  201. download
  202. .then(
  203. function() { fail('Download should have been canceled.'); },
  204. function() {
  205. assertEquals('/foo/bar', xhr.getLastUri());
  206. assertEquals(goog.net.ErrorCode.ABORT, xhr.getLastErrorCode());
  207. assertFalse(xhr.isActive());
  208. return downloader.isDownloaded('/foo/bar');
  209. })
  210. .then(assertFalse);
  211. download.cancel();
  212. return promise;
  213. }
  214. function testDownloadCanceledAfterXhr() {
  215. var download = downloader.download('/foo/bar');
  216. xhr.simulateResponse(200, 'data');
  217. download.cancel();
  218. return download
  219. .then(
  220. function() { fail('Should not succeed after cancellation.'); },
  221. function() {
  222. assertEquals('/foo/bar', xhr.getLastUri());
  223. assertEquals(goog.net.ErrorCode.NO_ERROR, xhr.getLastErrorCode());
  224. assertFalse(xhr.isActive());
  225. return downloader.isDownloaded('/foo/bar');
  226. })
  227. .then(assertFalse);
  228. }
  229. function testFailedXhr() {
  230. var promise =
  231. downloader.download('/foo/bar')
  232. .then(
  233. function() { fail('Download should not have succeeded.'); },
  234. function(err) {
  235. assertEquals('/foo/bar', err.url);
  236. assertEquals(404, err.xhrStatus);
  237. assertEquals(goog.net.ErrorCode.HTTP_ERROR, err.xhrErrorCode);
  238. assertUndefined(err.fileError);
  239. return downloader.isDownloaded('/foo/bar');
  240. })
  241. .then(assertFalse);
  242. xhr.simulateResponse(404);
  243. return promise;
  244. }
  245. function testFailedDownloadSave() {
  246. var promise =
  247. downloader.download('/foo/bar')
  248. .then(function() {
  249. var download = downloader.download('/foo/bar');
  250. xhr.simulateResponse(200, 'data');
  251. return download;
  252. })
  253. .then(
  254. function() {
  255. fail('Should not be able to modify an active download.');
  256. },
  257. function(err) {
  258. assertEquals('/foo/bar', err.url);
  259. assertUndefined(err.xhrStatus);
  260. assertUndefined(err.xhrErrorCode);
  261. assertEquals(
  262. goog.fs.Error.ErrorCode.INVALID_MODIFICATION,
  263. err.fileError.code);
  264. });
  265. xhr.simulateResponse(200, 'data');
  266. return promise;
  267. }
  268. function testFailedGetDownloadedBlob() {
  269. return downloader.getDownloadedBlob('/foo/bar')
  270. .then(
  271. function() { fail('Should not be able to get a missing blob.'); },
  272. function(err) {
  273. assertEquals(goog.fs.Error.ErrorCode.NOT_FOUND, err.code);
  274. });
  275. }
  276. function testFailedRemove() {
  277. return downloader.remove('/foo/bar')
  278. .then(
  279. function() { fail('Should not be able to remove a missing file.'); },
  280. function(err) {
  281. assertEquals(goog.fs.Error.ErrorCode.NOT_FOUND, err.code);
  282. });
  283. }
  284. function testIsDownloading() {
  285. assertFalse(downloader.isDownloading('/foo/bar'));
  286. var promise = downloader.download('/foo/bar').then(function() {
  287. assertFalse(downloader.isDownloading('/foo/bar'));
  288. });
  289. assertTrue(downloader.isDownloading('/foo/bar'));
  290. xhr.simulateResponse(200, 'data');
  291. return promise;
  292. }
  293. function testIsDownloadingWhenCancelled() {
  294. assertFalse(downloader.isDownloading('/foo/bar'));
  295. var deferred = downloader.download('/foo/bar').addErrback(function() {
  296. assertFalse(downloader.isDownloading('/foo/bar'));
  297. });
  298. assertTrue(downloader.isDownloading('/foo/bar'));
  299. deferred.cancel();
  300. }
  301. function assertMatches(expected, actual) {
  302. assert(
  303. 'Expected "' + actual + '" to match ' + expected, expected.test(actual));
  304. }