fs_test.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  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.fsTest');
  15. goog.setTestOnly('goog.fsTest');
  16. goog.require('goog.Promise');
  17. goog.require('goog.array');
  18. goog.require('goog.dom');
  19. goog.require('goog.dom.TagName');
  20. goog.require('goog.events');
  21. goog.require('goog.fs');
  22. goog.require('goog.fs.DirectoryEntry');
  23. goog.require('goog.fs.Error');
  24. goog.require('goog.fs.FileReader');
  25. goog.require('goog.fs.FileSaver');
  26. goog.require('goog.string');
  27. goog.require('goog.testing.PropertyReplacer');
  28. goog.require('goog.testing.jsunit');
  29. var TEST_DIR = 'goog-fs-test-dir';
  30. var fsExists = goog.isDef(goog.global.requestFileSystem) ||
  31. goog.isDef(goog.global.webkitRequestFileSystem);
  32. var deferredFs = fsExists ? goog.fs.getTemporary() : null;
  33. var stubs = new goog.testing.PropertyReplacer();
  34. function setUpPage() {
  35. if (!fsExists) {
  36. return;
  37. }
  38. return loadTestDir().then(null, function(err) {
  39. var msg;
  40. if (err.code == goog.fs.Error.ErrorCode.QUOTA_EXCEEDED) {
  41. msg = err.message + '. If you\'re using Chrome, you probably need to ' +
  42. 'pass --unlimited-quota-for-files on the command line.';
  43. } else if (
  44. err.code == goog.fs.Error.ErrorCode.SECURITY &&
  45. window.location.href.match(/^file:/)) {
  46. msg = err.message + '. file:// URLs can\'t access the filesystem API.';
  47. } else {
  48. msg = err.message;
  49. }
  50. var body = goog.dom.getDocument().body;
  51. goog.dom.insertSiblingBefore(
  52. goog.dom.createDom(goog.dom.TagName.H1, {}, msg), body.childNodes[0]);
  53. });
  54. }
  55. function tearDown() {
  56. if (!fsExists) {
  57. return;
  58. }
  59. return loadTestDir().then(function(dir) { return dir.removeRecursively(); });
  60. }
  61. function testUnavailableTemporaryFilesystem() {
  62. stubs.set(goog.global, 'requestFileSystem', null);
  63. stubs.set(goog.global, 'webkitRequestFileSystem', null);
  64. return goog.fs.getTemporary(1024).then(
  65. fail, function(e) { assertEquals('File API unsupported', e.message); });
  66. }
  67. function testUnavailablePersistentFilesystem() {
  68. stubs.set(goog.global, 'requestFileSystem', null);
  69. stubs.set(goog.global, 'webkitRequestFileSystem', null);
  70. return goog.fs.getPersistent(2048).then(
  71. fail, function(e) { assertEquals('File API unsupported', e.message); });
  72. }
  73. function testIsFile() {
  74. if (!fsExists) {
  75. return;
  76. }
  77. return loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE)
  78. .then(function(fileEntry) {
  79. assertFalse(fileEntry.isDirectory());
  80. assertTrue(fileEntry.isFile());
  81. });
  82. }
  83. function testIsDirectory() {
  84. if (!fsExists) {
  85. return;
  86. }
  87. return loadDirectory('test', goog.fs.DirectoryEntry.Behavior.CREATE)
  88. .then(function(fileEntry) {
  89. assertTrue(fileEntry.isDirectory());
  90. assertFalse(fileEntry.isFile());
  91. });
  92. }
  93. function testReadFileUtf16() {
  94. if (!fsExists) {
  95. return;
  96. }
  97. var str = 'test content';
  98. var buf = new ArrayBuffer(str.length * 2);
  99. var arr = new Uint16Array(buf);
  100. for (var i = 0; i < str.length; i++) {
  101. arr[i] = str.charCodeAt(i);
  102. }
  103. return loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE)
  104. .then(goog.partial(writeToFile, arr.buffer))
  105. .then(goog.partial(checkFileContentWithEncoding, str, 'UTF-16'));
  106. }
  107. function testReadFileUtf8() {
  108. if (!fsExists) {
  109. return;
  110. }
  111. var str = 'test content';
  112. var buf = new ArrayBuffer(str.length);
  113. var arr = new Uint8Array(buf);
  114. for (var i = 0; i < str.length; i++) {
  115. arr[i] = str.charCodeAt(i) & 0xff;
  116. }
  117. return loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE)
  118. .then(goog.partial(writeToFile, arr.buffer))
  119. .then(goog.partial(checkFileContentWithEncoding, str, 'UTF-8'));
  120. }
  121. function testReadFileAsArrayBuffer() {
  122. if (!fsExists) {
  123. return;
  124. }
  125. var str = 'test content';
  126. var buf = new ArrayBuffer(str.length);
  127. var arr = new Uint8Array(buf);
  128. for (var i = 0; i < str.length; i++) {
  129. arr[i] = str.charCodeAt(i) & 0xff;
  130. }
  131. return loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE)
  132. .then(goog.partial(writeToFile, arr.buffer))
  133. .then(
  134. goog.partial(
  135. checkFileContentAs, arr.buffer, 'ArrayBuffer', undefined));
  136. }
  137. function testReadFileAsBinaryString() {
  138. if (!fsExists) {
  139. return;
  140. }
  141. var str = 'test content';
  142. var buf = new ArrayBuffer(str.length);
  143. var arr = new Uint8Array(buf);
  144. for (var i = 0; i < str.length; i++) {
  145. arr[i] = str.charCodeAt(i);
  146. }
  147. return loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE)
  148. .then(goog.partial(writeToFile, arr.buffer))
  149. .then(goog.partial(checkFileContentAs, str, 'BinaryString', undefined));
  150. }
  151. function testWriteFile() {
  152. if (!fsExists) {
  153. return;
  154. }
  155. return loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE)
  156. .then(goog.partial(writeToFile, 'test content'))
  157. .then(goog.partial(checkFileContent, 'test content'));
  158. }
  159. function testRemoveFile() {
  160. if (!fsExists) {
  161. return;
  162. }
  163. return loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE)
  164. .then(goog.partial(writeToFile, 'test content'))
  165. .then(function(file) { return file.remove(); })
  166. .then(goog.partial(checkFileRemoved, 'test'));
  167. }
  168. function testMoveFile() {
  169. if (!fsExists) {
  170. return;
  171. }
  172. var deferredSubdir =
  173. loadDirectory('subdir', goog.fs.DirectoryEntry.Behavior.CREATE);
  174. var deferredWrittenFile =
  175. loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE)
  176. .then(goog.partial(writeToFile, 'test content'));
  177. return goog.Promise.all([deferredSubdir, deferredWrittenFile])
  178. .then(splitArgs(function(dir, file) { return file.moveTo(dir); }))
  179. .then(goog.partial(checkFileContent, 'test content'))
  180. .then(goog.partial(checkFileRemoved, 'test'));
  181. }
  182. function testCopyFile() {
  183. if (!fsExists) {
  184. return;
  185. }
  186. var deferredFile = loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE);
  187. var deferredSubdir =
  188. loadDirectory('subdir', goog.fs.DirectoryEntry.Behavior.CREATE);
  189. var deferredWrittenFile =
  190. deferredFile.then(goog.partial(writeToFile, 'test content'));
  191. return goog.Promise.all([deferredSubdir, deferredWrittenFile])
  192. .then(splitArgs(function(dir, file) { return file.copyTo(dir); }))
  193. .then(goog.partial(checkFileContent, 'test content'))
  194. .then(function() { return deferredFile; })
  195. .then(goog.partial(checkFileContent, 'test content'));
  196. }
  197. function testAbortWrite() {
  198. // TODO(nicksantos): This test is broken in newer versions of chrome.
  199. // We don't know why yet.
  200. if (true) return;
  201. if (!fsExists) {
  202. return;
  203. }
  204. var deferredFile = loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE);
  205. return deferredFile.then(goog.partial(startWrite, 'test content'))
  206. .then(function(writer) {
  207. return new goog.Promise(function(resolve) {
  208. goog.events.listenOnce(
  209. writer, goog.fs.FileSaver.EventType.ABORT, resolve);
  210. writer.abort();
  211. });
  212. })
  213. .then(function() { return loadFile('test'); })
  214. .then(goog.partial(checkFileContent, ''));
  215. }
  216. function testSeek() {
  217. if (!fsExists) {
  218. return;
  219. }
  220. var deferredFile = loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE);
  221. return deferredFile.then(goog.partial(writeToFile, 'test content'))
  222. .then(function(file) { return file.createWriter(); })
  223. .then(goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.INIT))
  224. .then(function(writer) {
  225. writer.seek(5);
  226. writer.write(goog.fs.getBlob('stuff and things'));
  227. return writer;
  228. })
  229. .then(goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.WRITING))
  230. .then(goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE))
  231. .then(function() { return deferredFile; })
  232. .then(goog.partial(checkFileContent, 'test stuff and things'));
  233. }
  234. function testTruncate() {
  235. if (!fsExists) {
  236. return;
  237. }
  238. var deferredFile = loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE);
  239. return deferredFile.then(goog.partial(writeToFile, 'test content'))
  240. .then(function(file) { return file.createWriter(); })
  241. .then(goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.INIT))
  242. .then(function(writer) {
  243. writer.truncate(4);
  244. return writer;
  245. })
  246. .then(goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.WRITING))
  247. .then(goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE))
  248. .then(function() { return deferredFile; })
  249. .then(goog.partial(checkFileContent, 'test'));
  250. }
  251. function testGetLastModified() {
  252. if (!fsExists) {
  253. return;
  254. }
  255. var now = goog.now();
  256. return loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE)
  257. .then(function(entry) { return entry.getLastModified(); })
  258. .then(function(date) {
  259. assertRoughlyEquals(
  260. 'Expected the last modified date to be within ' +
  261. 'a few milliseconds of the test start time.',
  262. now, date.getTime(), 2000);
  263. });
  264. }
  265. function testCreatePath() {
  266. if (!fsExists) {
  267. return;
  268. }
  269. return loadTestDir()
  270. .then(function(testDir) { return testDir.createPath('foo'); })
  271. .then(function(fooDir) {
  272. assertEquals('/goog-fs-test-dir/foo', fooDir.getFullPath());
  273. return fooDir.createPath('bar/baz/bat');
  274. })
  275. .then(function(batDir) {
  276. assertEquals('/goog-fs-test-dir/foo/bar/baz/bat', batDir.getFullPath());
  277. });
  278. }
  279. function testCreateAbsolutePath() {
  280. if (!fsExists) {
  281. return;
  282. }
  283. return loadTestDir()
  284. .then(function(testDir) {
  285. return testDir.createPath('/' + TEST_DIR + '/fee/fi/fo/fum');
  286. })
  287. .then(function(absDir) {
  288. assertEquals('/goog-fs-test-dir/fee/fi/fo/fum', absDir.getFullPath());
  289. });
  290. }
  291. function testCreateRelativePath() {
  292. if (!fsExists) {
  293. return;
  294. }
  295. return loadTestDir()
  296. .then(function(dir) { return dir.createPath('../' + TEST_DIR + '/dir'); })
  297. .then(function(relDir) {
  298. assertEquals('/goog-fs-test-dir/dir', relDir.getFullPath());
  299. return relDir.createPath('.');
  300. })
  301. .then(function(sameDir) {
  302. assertEquals('/goog-fs-test-dir/dir', sameDir.getFullPath());
  303. return sameDir.createPath('./././.');
  304. })
  305. .then(function(reallySameDir) {
  306. assertEquals('/goog-fs-test-dir/dir', reallySameDir.getFullPath());
  307. return reallySameDir.createPath('./new/../..//dir/./new////.');
  308. })
  309. .then(function(newDir) {
  310. assertEquals('/goog-fs-test-dir/dir/new', newDir.getFullPath());
  311. });
  312. }
  313. function testCreateBadPath() {
  314. if (!fsExists) {
  315. return;
  316. }
  317. return loadTestDir()
  318. .then(function() { return loadTestDir(); })
  319. .then(function(dir) {
  320. // There is only one layer of parent directory from the test dir.
  321. return dir.createPath('../../../../' + TEST_DIR + '/baz/bat');
  322. })
  323. .then(function(batDir) {
  324. assertEquals(
  325. 'The parent directory of the root directory should ' +
  326. 'point back to the root directory.',
  327. '/goog-fs-test-dir/baz/bat', batDir.getFullPath());
  328. })
  329. .
  330. then(function() { return loadTestDir(); })
  331. .then(function(dir) {
  332. // An empty path should return the same as the input directory.
  333. return dir.createPath('');
  334. })
  335. .then(function(testDir) {
  336. assertEquals('/goog-fs-test-dir', testDir.getFullPath());
  337. });
  338. }
  339. function testGetAbsolutePaths() {
  340. if (!fsExists) {
  341. return;
  342. }
  343. return loadFile('foo', goog.fs.DirectoryEntry.Behavior.CREATE)
  344. .then(function() { return loadTestDir(); })
  345. .then(function(testDir) { return testDir.getDirectory('/'); })
  346. .then(function(root) {
  347. assertEquals('/', root.getFullPath());
  348. return root.getDirectory('/' + TEST_DIR);
  349. })
  350. .then(function(testDir) {
  351. assertEquals('/goog-fs-test-dir', testDir.getFullPath());
  352. return testDir.getDirectory('//' + TEST_DIR + '////');
  353. })
  354. .then(function(testDir) {
  355. assertEquals('/goog-fs-test-dir', testDir.getFullPath());
  356. return testDir.getDirectory('////');
  357. })
  358. .then(function(testDir) { assertEquals('/', testDir.getFullPath()); });
  359. }
  360. function testListEmptyDirectory() {
  361. if (!fsExists) {
  362. return;
  363. }
  364. return loadTestDir()
  365. .then(function(dir) { return dir.listDirectory(); })
  366. .then(function(entries) { assertArrayEquals([], entries); });
  367. }
  368. function testListDirectory() {
  369. if (!fsExists) {
  370. return;
  371. }
  372. return loadDirectory('testDir', goog.fs.DirectoryEntry.Behavior.CREATE)
  373. .then(function() {
  374. return loadFile('testFile', goog.fs.DirectoryEntry.Behavior.CREATE);
  375. })
  376. .then(function() { return loadTestDir(); })
  377. .then(function(testDir) { return testDir.listDirectory(); })
  378. .then(function(entries) {
  379. // Verify the contents of the directory listing.
  380. assertEquals(2, entries.length);
  381. var dir = goog.array.find(
  382. entries, function(entry) { return entry.getName() == 'testDir'; });
  383. assertNotNull(dir);
  384. assertTrue(dir.isDirectory());
  385. var file = goog.array.find(
  386. entries, function(entry) { return entry.getName() == 'testFile'; });
  387. assertNotNull(file);
  388. assertTrue(file.isFile());
  389. });
  390. }
  391. function testListBigDirectory() {
  392. // TODO(nicksantos): This test is broken in newer versions of chrome.
  393. // We don't know why yet.
  394. if (true) return;
  395. if (!fsExists) {
  396. return;
  397. }
  398. function getFileName(i) {
  399. return 'file' + goog.string.padNumber(i, String(count).length);
  400. }
  401. // NOTE: This was intended to verify that the results from repeated
  402. // DirectoryReader.readEntries() callbacks are appropriately concatenated.
  403. // In current versions of Chrome (March 2011), all results are returned in the
  404. // first callback regardless of directory size. The count can be increased in
  405. // the future to test batched result lists once they are implemented.
  406. var count = 100;
  407. var expectedNames = [];
  408. var def = goog.Promise.resolve();
  409. for (var i = 0; i < count; i++) {
  410. var name = getFileName(i);
  411. expectedNames.push(name);
  412. def.then(function() {
  413. return loadFile(name, goog.fs.DirectoryEntry.Behavior.CREATE);
  414. });
  415. }
  416. return def.then(function() { return loadTestDir(); })
  417. .then(function(testDir) { return testDir.listDirectory(); })
  418. .then(function(entries) {
  419. assertEquals(count, entries.length);
  420. assertSameElements(
  421. expectedNames, goog.array.map(entries, function(entry) {
  422. return entry.getName();
  423. }));
  424. assertTrue(goog.array.every(entries, function(entry) {
  425. return entry.isFile();
  426. }));
  427. });
  428. }
  429. function testSliceBlob() {
  430. // A mock blob object whose slice returns the parameters it was called with.
  431. var blob = {
  432. 'size': 10,
  433. 'slice': function(start, end) {
  434. return [start, end];
  435. }
  436. };
  437. // Simulate Firefox 13 that implements the new slice.
  438. var tmpStubs = new goog.testing.PropertyReplacer();
  439. tmpStubs.set(goog.userAgent, 'GECKO', true);
  440. tmpStubs.set(goog.userAgent, 'WEBKIT', false);
  441. tmpStubs.set(goog.userAgent, 'IE', false);
  442. tmpStubs.set(goog.userAgent, 'VERSION', '13.0');
  443. tmpStubs.set(goog.userAgent, 'isVersionOrHigherCache_', {});
  444. // Expect slice to be called with no change to parameters
  445. assertArrayEquals([2, 10], goog.fs.sliceBlob(blob, 2));
  446. assertArrayEquals([-2, 10], goog.fs.sliceBlob(blob, -2));
  447. assertArrayEquals([3, 6], goog.fs.sliceBlob(blob, 3, 6));
  448. assertArrayEquals([3, -6], goog.fs.sliceBlob(blob, 3, -6));
  449. // Simulate IE 10 that implements the new slice.
  450. var tmpStubs = new goog.testing.PropertyReplacer();
  451. tmpStubs.set(goog.userAgent, 'GECKO', false);
  452. tmpStubs.set(goog.userAgent, 'WEBKIT', false);
  453. tmpStubs.set(goog.userAgent, 'IE', true);
  454. tmpStubs.set(goog.userAgent, 'VERSION', '10.0');
  455. tmpStubs.set(goog.userAgent, 'isVersionOrHigherCache_', {});
  456. // Expect slice to be called with no change to parameters
  457. assertArrayEquals([2, 10], goog.fs.sliceBlob(blob, 2));
  458. assertArrayEquals([-2, 10], goog.fs.sliceBlob(blob, -2));
  459. assertArrayEquals([3, 6], goog.fs.sliceBlob(blob, 3, 6));
  460. assertArrayEquals([3, -6], goog.fs.sliceBlob(blob, 3, -6));
  461. // Simulate Firefox 4 that implements the old slice.
  462. tmpStubs.set(goog.userAgent, 'GECKO', true);
  463. tmpStubs.set(goog.userAgent, 'WEBKIT', false);
  464. tmpStubs.set(goog.userAgent, 'IE', false);
  465. tmpStubs.set(goog.userAgent, 'VERSION', '2.0');
  466. tmpStubs.set(goog.userAgent, 'isVersionOrHigherCache_', {});
  467. // Expect slice to be called with transformed parameters.
  468. assertArrayEquals([2, 8], goog.fs.sliceBlob(blob, 2));
  469. assertArrayEquals([8, 2], goog.fs.sliceBlob(blob, -2));
  470. assertArrayEquals([3, 3], goog.fs.sliceBlob(blob, 3, 6));
  471. assertArrayEquals([3, 1], goog.fs.sliceBlob(blob, 3, -6));
  472. // Simulate Firefox 5 that implements mozSlice (new spec).
  473. delete blob.slice;
  474. blob.mozSlice = function(start, end) { return ['moz', start, end]; };
  475. tmpStubs.set(goog.userAgent, 'GECKO', true);
  476. tmpStubs.set(goog.userAgent, 'WEBKIT', false);
  477. tmpStubs.set(goog.userAgent, 'IE', false);
  478. tmpStubs.set(goog.userAgent, 'VERSION', '5.0');
  479. tmpStubs.set(goog.userAgent, 'isVersionOrHigherCache_', {});
  480. // Expect mozSlice to be called with no change to parameters.
  481. assertArrayEquals(['moz', 2, 10], goog.fs.sliceBlob(blob, 2));
  482. assertArrayEquals(['moz', -2, 10], goog.fs.sliceBlob(blob, -2));
  483. assertArrayEquals(['moz', 3, 6], goog.fs.sliceBlob(blob, 3, 6));
  484. assertArrayEquals(['moz', 3, -6], goog.fs.sliceBlob(blob, 3, -6));
  485. // Simulate Chrome 20 that implements webkitSlice (new spec).
  486. delete blob.mozSlice;
  487. blob.webkitSlice = function(start, end) { return ['webkit', start, end]; };
  488. tmpStubs.set(goog.userAgent, 'GECKO', false);
  489. tmpStubs.set(goog.userAgent, 'WEBKIT', true);
  490. tmpStubs.set(goog.userAgent, 'IE', false);
  491. tmpStubs.set(goog.userAgent, 'VERSION', '536.10');
  492. tmpStubs.set(goog.userAgent, 'isVersionOrHigherCache_', {});
  493. // Expect webkitSlice to be called with no change to parameters.
  494. assertArrayEquals(['webkit', 2, 10], goog.fs.sliceBlob(blob, 2));
  495. assertArrayEquals(['webkit', -2, 10], goog.fs.sliceBlob(blob, -2));
  496. assertArrayEquals(['webkit', 3, 6], goog.fs.sliceBlob(blob, 3, 6));
  497. assertArrayEquals(['webkit', 3, -6], goog.fs.sliceBlob(blob, 3, -6));
  498. tmpStubs.reset();
  499. }
  500. function testGetBlobThrowsError() {
  501. stubs.remove(goog.global, 'BlobBuilder');
  502. stubs.remove(goog.global, 'WebKitBlobBuilder');
  503. stubs.remove(goog.global, 'Blob');
  504. try {
  505. goog.fs.getBlob();
  506. fail();
  507. } catch (e) {
  508. assertEquals(
  509. 'This browser doesn\'t seem to support creating Blobs', e.message);
  510. }
  511. stubs.reset();
  512. }
  513. function testGetBlobWithProperties() {
  514. // Skip test if browser doesn't support Blob API.
  515. if (typeof(goog.global.Blob) != 'function') {
  516. return;
  517. }
  518. var blob = goog.fs.getBlobWithProperties(['test'], 'text/test', 'native');
  519. assertEquals('text/test', blob.type);
  520. }
  521. function testGetBlobWithPropertiesThrowsError() {
  522. stubs.remove(goog.global, 'BlobBuilder');
  523. stubs.remove(goog.global, 'WebKitBlobBuilder');
  524. stubs.remove(goog.global, 'Blob');
  525. try {
  526. goog.fs.getBlobWithProperties();
  527. fail();
  528. } catch (e) {
  529. assertEquals(
  530. 'This browser doesn\'t seem to support creating Blobs', e.message);
  531. }
  532. stubs.reset();
  533. }
  534. function testGetBlobWithPropertiesUsingBlobBuilder() {
  535. function BlobBuilder() {
  536. this.parts = [];
  537. this.append = function(value, endings) {
  538. this.parts.push({value: value, endings: endings});
  539. };
  540. this.getBlob = function(type) { return {type: type, builder: this}; };
  541. }
  542. stubs.set(goog.global, 'BlobBuilder', BlobBuilder);
  543. var blob = goog.fs.getBlobWithProperties(['test'], 'text/test', 'native');
  544. assertEquals('text/test', blob.type);
  545. assertEquals('test', blob.builder.parts[0].value);
  546. assertEquals('native', blob.builder.parts[0].endings);
  547. stubs.reset();
  548. }
  549. function loadTestDir() {
  550. return deferredFs.then(function(fs) {
  551. return fs.getRoot().getDirectory(
  552. TEST_DIR, goog.fs.DirectoryEntry.Behavior.CREATE);
  553. });
  554. }
  555. function loadFile(filename, behavior) {
  556. return loadTestDir().then(function(dir) {
  557. return dir.getFile(filename, behavior);
  558. });
  559. }
  560. function loadDirectory(filename, behavior) {
  561. return loadTestDir().then(function(dir) {
  562. return dir.getDirectory(filename, behavior);
  563. });
  564. }
  565. function startWrite(content, file) {
  566. return file.createWriter()
  567. .then(goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.INIT))
  568. .then(function(writer) {
  569. writer.write(goog.fs.getBlob(content));
  570. return writer;
  571. })
  572. .then(
  573. goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.WRITING));
  574. }
  575. function waitForEvent(type, target) {
  576. var done;
  577. var promise = new goog.Promise(function(_done) { done = _done; });
  578. goog.events.listenOnce(target, type, done);
  579. return promise;
  580. }
  581. function writeToFile(content, file) {
  582. return startWrite(content, file)
  583. .then(goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE))
  584. .then(function() { return file; });
  585. }
  586. function checkFileContent(content, file) {
  587. return checkFileContentAs(content, 'Text', undefined, file);
  588. }
  589. function checkFileContentWithEncoding(content, encoding, file) {
  590. return checkFileContentAs(content, 'Text', encoding, file);
  591. }
  592. function checkFileContentAs(content, filetype, encoding, file) {
  593. return file.file()
  594. .then(function(blob) {
  595. return goog.fs.FileReader['readAs' + filetype](blob, encoding);
  596. })
  597. .then(goog.partial(checkEquals, content));
  598. }
  599. function checkEquals(a, b) {
  600. if (a instanceof ArrayBuffer && b instanceof ArrayBuffer) {
  601. assertEquals(a.byteLength, b.byteLength);
  602. var viewA = new DataView(a);
  603. var viewB = new DataView(b);
  604. for (var i = 0; i < a.byteLength; i++) {
  605. assertEquals(viewA.getUint8(i), viewB.getUint8(i));
  606. }
  607. } else {
  608. assertEquals(a, b);
  609. }
  610. }
  611. function checkFileRemoved(filename) {
  612. return loadFile(filename).then(
  613. goog.partial(fail, 'expected file to be removed'), function(err) {
  614. assertEquals(err.code, goog.fs.Error.ErrorCode.NOT_FOUND);
  615. });
  616. }
  617. function checkReadyState(expectedState, writer) {
  618. assertEquals(expectedState, writer.getReadyState());
  619. return writer;
  620. }
  621. function splitArgs(fn) {
  622. return function(args) { return fn(args[0], args[1]); };
  623. }