file-tests.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. function bin2str(bufView) {
  2. var length = bufView.length;
  3. var result = '';
  4. for (var i = 0; i<length; i+=65535) {
  5. var addition = 65535;
  6. if(i + 65535 > length) {
  7. addition = length - i;
  8. }
  9. try {
  10. // this fails on phantomjs due to old webkit bug; hence the try/catch
  11. result += String.fromCharCode.apply(null, bufView.subarray(i,i+addition));
  12. } catch (e) {
  13. var dataArray = [];
  14. for (var j = i; j < i+addition; j++) {
  15. dataArray.push(bufView[j]);
  16. }
  17. result += String.fromCharCode.apply(null, dataArray);
  18. }
  19. }
  20. return result;
  21. }
  22. //function ab2str(buffer) {
  23. // return bin2str(new Uint8Array(buffer));
  24. //}
  25. function str2ab(str) {
  26. var buf = new ArrayBuffer(str.length);
  27. var bufView = new Uint8Array(buf);
  28. for (var i=0, strLen=str.length; i<strLen; i++) {
  29. bufView[i] = str.charCodeAt(i);
  30. }
  31. return buf;
  32. }
  33. var fileCollection = new FS.Collection('files', {
  34. stores: [
  35. new FS.Store.GridFS('files')
  36. ],
  37. uploader: null
  38. });
  39. // Set up server stuff
  40. if (Meteor.isServer) {
  41. var fs = Npm.require('fs');
  42. var temp = Npm.require('temp');
  43. var path = Npm.require('path');
  44. // Automatically track and cleanup files at exit
  45. temp.track();
  46. // Set up HTTP method URL used by client tests
  47. var conf = {
  48. get: function () {
  49. var buf = new Buffer('Hello World');
  50. this.setContentType('text/plain');
  51. return buf;
  52. },
  53. head: function () {
  54. var buf = new Buffer('Hello World');
  55. this.setContentType('text/plain');
  56. this.addHeader('Content-Length', buf.length);
  57. buf = null;
  58. }
  59. };
  60. HTTP.methods({
  61. 'test': conf,
  62. 'test.txt': conf
  63. });
  64. // Save temp file for testing with
  65. function openTempFile(name, callback) {
  66. return temp.open(name, callback);
  67. }
  68. var openTempFileSync = Meteor.wrapAsync(openTempFile);
  69. var info = openTempFileSync({suffix: '.txt'});
  70. var tempFilePath = info.path;
  71. var tempFileName = path.basename(tempFilePath);
  72. fs.writeSync(info.fd, 'Hello World');
  73. fs.closeSync(info.fd);
  74. fileCollection.allow({
  75. insert: function () {
  76. return true;
  77. },
  78. update: function () {
  79. return true;
  80. },
  81. remove: function () {
  82. return true;
  83. }
  84. });
  85. Meteor.publish("files", function () {
  86. return fileCollection.find();
  87. });
  88. }
  89. if (Meteor.isClient) {
  90. Meteor.subscribe("files");
  91. }
  92. Tinytest.add('cfs-file - test environment', function(test) {
  93. test.isTrue(typeof FS.Collection !== 'undefined', 'test environment not initialized FS.Collection');
  94. test.isTrue(typeof FS.File !== 'undefined', 'test environment not initialized FS.File');
  95. });
  96. Tinytest.add('cfs-file - construction', function(test) {
  97. // Normal object provided will extend the fileObj
  98. var f = new FS.File({foo: "bar"});
  99. test.equal(f.foo, "bar");
  100. // If passed another FS.File instance, we clone it
  101. var f2 = new FS.File(f);
  102. test.equal(f2.foo, "bar");
  103. });
  104. // Types of data and how we support attaching:
  105. //
  106. // Type C/S Constructor attachData w/ callback attachData w/o callback
  107. // ----------------------------------------------------------------------------------------------
  108. // Buffer Server No Yes Yes
  109. // ArrayBuffer Both No Yes Yes
  110. // Binary Both No Yes Yes
  111. // Data URI Both Yes Yes Yes
  112. // URL Both Yes on Server Yes Yes on Server
  113. // Filepath Server Yes Yes Yes
  114. // File Client Yes Yes Yes
  115. // Blob Client Yes Yes Yes
  116. function doAttachDataConstructorTest(data, name, test) {
  117. var f = new FS.File(data);
  118. if (!name) {
  119. test.isUndefined(f.name());
  120. } else {
  121. test.equal(f.name(), name);
  122. }
  123. test.equal(f.type(), "text/plain");
  124. test.equal(f.size(), 11);
  125. }
  126. function doAttachDataSyncTest(data, opts, name, test) {
  127. var f = new FS.File();
  128. f.attachData(data, opts);
  129. if (!name) {
  130. test.isUndefined(f.name());
  131. } else {
  132. test.equal(f.name(), name);
  133. }
  134. test.equal(f.type(), "text/plain");
  135. test.equal(f.size(), 11);
  136. }
  137. function doAttachDataAsyncTest(data, opts, name, test, next) {
  138. var f = new FS.File();
  139. f.attachData(data, opts, function (error) {
  140. test.isFalse(!!error);
  141. if (!name) {
  142. test.isUndefined(f.name());
  143. } else {
  144. test.equal(f.name(), name);
  145. }
  146. test.equal(f.type(), "text/plain");
  147. test.equal(f.size(), 11);
  148. next();
  149. });
  150. }
  151. /*
  152. * BUFFER
  153. */
  154. if (Meteor.isServer) {
  155. Tinytest.add('cfs-file - attachData sync - Buffer', function(test) {
  156. doAttachDataSyncTest(new Buffer('Hello World'), {type: "text/plain"}, null, test);
  157. });
  158. Tinytest.addAsync('cfs-file - attachData async - Buffer', function(test, next) {
  159. doAttachDataAsyncTest(new Buffer('Hello World'), {type: "text/plain"}, null, test, next);
  160. });
  161. }
  162. /*
  163. * ARRAYBUFFER
  164. */
  165. Tinytest.add('cfs-file - attachData sync - ArrayBuffer', function(test) {
  166. doAttachDataSyncTest(str2ab('Hello World'), {type: "text/plain"}, null, test);
  167. });
  168. Tinytest.addAsync('cfs-file - attachData async - ArrayBuffer', function(test, next) {
  169. doAttachDataAsyncTest(str2ab('Hello World'), {type: "text/plain"}, null, test, next);
  170. });
  171. /*
  172. * Binary
  173. */
  174. Tinytest.add('cfs-file - attachData sync - Binary', function(test) {
  175. doAttachDataSyncTest(new Uint8Array(str2ab('Hello World')), {type: "text/plain"}, null, test);
  176. });
  177. Tinytest.addAsync('cfs-file - attachData async - Binary', function(test, next) {
  178. doAttachDataAsyncTest(new Uint8Array(str2ab('Hello World')), {type: "text/plain"}, null, test, next);
  179. });
  180. /*
  181. * Data URI
  182. */
  183. var dataUri = 'data:text/plain;base64,SGVsbG8gV29ybGQ='; //'Hello World'
  184. Tinytest.add('cfs-file - attachData sync - Data URI', function(test) {
  185. doAttachDataSyncTest(dataUri, null, null, test);
  186. });
  187. Tinytest.addAsync('cfs-file - attachData async - Data URI', function(test, next) {
  188. doAttachDataAsyncTest(dataUri, null, null, test, next);
  189. });
  190. Tinytest.add('cfs-file - attachData from constructor - Data URI', function(test) {
  191. doAttachDataConstructorTest(dataUri, null, test);
  192. });
  193. /*
  194. * URL
  195. */
  196. var url = Meteor.absoluteUrl('test');
  197. var url2 = Meteor.absoluteUrl('test.txt');
  198. if (Meteor.isServer) {
  199. Tinytest.add('cfs-file - attachData sync - URL', function(test) {
  200. doAttachDataSyncTest(url, null, null, test);
  201. doAttachDataSyncTest(url2, null, 'test.txt', test);
  202. });
  203. Tinytest.add('cfs-file - attachData from constructor - URL', function(test) {
  204. doAttachDataConstructorTest(url, null, test);
  205. doAttachDataConstructorTest(url2, 'test.txt', test);
  206. });
  207. }
  208. Tinytest.addAsync('cfs-file - attachData async - URL', function(test, next) {
  209. doAttachDataAsyncTest(url, null, null, test, function () {
  210. doAttachDataAsyncTest(url2, null, 'test.txt', test, next);
  211. });
  212. });
  213. /*
  214. * Filepath
  215. */
  216. if (Meteor.isServer) {
  217. Tinytest.add('cfs-file - attachData sync - Filepath', function(test) {
  218. doAttachDataSyncTest(tempFilePath, null, tempFileName, test);
  219. });
  220. Tinytest.addAsync('cfs-file - attachData async - Filepath', function(test, next) {
  221. doAttachDataAsyncTest(tempFilePath, null, tempFileName, test, next);
  222. });
  223. Tinytest.add('cfs-file - attachData from constructor - Filepath', function(test) {
  224. doAttachDataConstructorTest(tempFilePath, tempFileName, test);
  225. });
  226. }
  227. /*
  228. * Blob
  229. */
  230. if (Meteor.isClient) {
  231. var blob = new Blob(['Hello World'], {type : 'text/plain'});
  232. Tinytest.add('cfs-file - attachData sync - Blob', function(test) {
  233. doAttachDataSyncTest(blob, null, null, test);
  234. });
  235. Tinytest.addAsync('cfs-file - attachData async - Blob', function(test, next) {
  236. doAttachDataAsyncTest(blob, null, null, test, next);
  237. });
  238. Tinytest.add('cfs-file - attachData from constructor - Blob', function(test) {
  239. doAttachDataConstructorTest(blob, null, test);
  240. });
  241. }
  242. /*
  243. * Collection Mounting
  244. */
  245. Tinytest.add('cfs-file - isMounted', function(test) {
  246. var f = new FS.File();
  247. test.isFalse(!!f.isMounted());
  248. f.collectionName = "files";
  249. test.isTrue(!!f.isMounted());
  250. });
  251. /*
  252. * name/extension
  253. */
  254. Tinytest.add('cfs-file - name/extension', function(test) {
  255. var f = new FS.File();
  256. // Set names
  257. f.name("foo.pdf");
  258. f.name("bar.txt", {store: "files"});
  259. // Get names
  260. test.equal(f.name(), "foo.pdf");
  261. test.equal(f.name({store: "files"}), "bar.txt");
  262. // Get extensions
  263. test.equal(f.extension(), "pdf");
  264. test.equal(f.extension({store: "files"}), "txt");
  265. // Now change extensions
  266. f.extension("txt");
  267. f.extension("pdf", {store: "files"});
  268. // Get changed extensions
  269. test.equal(f.extension(), "txt");
  270. test.equal(f.extension({store: "files"}), "pdf");
  271. });
  272. /*
  273. * size
  274. */
  275. Tinytest.add('cfs-file - size', function(test) {
  276. var f = new FS.File();
  277. // Set size
  278. f.size(1);
  279. f.size(2, {store: "files"});
  280. // Get size
  281. test.equal(f.size(), 1);
  282. test.equal(f.size({store: "files"}), 2);
  283. });
  284. /*
  285. * type
  286. */
  287. Tinytest.add('cfs-file - type', function(test) {
  288. var f = new FS.File();
  289. // Set type
  290. f.type("image/png");
  291. f.type("image/jpg", {store: "files"});
  292. // Get type
  293. test.equal(f.type(), "image/png");
  294. test.equal(f.type({store: "files"}), "image/jpg");
  295. });
  296. /*
  297. * updatedAt
  298. */
  299. Tinytest.add('cfs-file - updatedAt', function(test) {
  300. var f = new FS.File();
  301. var d1 = new Date("2014-01-01");
  302. var d2 = new Date("2014-02-01");
  303. // Set updatedAt
  304. f.updatedAt(d1);
  305. f.updatedAt(d2, {store: "files"});
  306. // Get updatedAt
  307. test.equal(f.updatedAt().getTime(), d1.getTime());
  308. test.equal(f.updatedAt({store: "files"}).getTime(), d2.getTime());
  309. });
  310. /*
  311. * update, uploadProgress, and isUploaded
  312. */
  313. Tinytest.addAsync('cfs-file - update, uploadProgress, and isUploaded', function(test, next) {
  314. // Progress is based on chunkCount/chunkSum
  315. var f = new FS.File('data:text/plain;base64,SGVsbG8gV29ybGQ=');
  316. fileCollection.insert(f, function () {
  317. f.update({$set: {chunkSum: 2, chunkCount: 1}}, function (error, result) {
  318. test.isFalse(!!error);
  319. test.equal(f.uploadProgress(), 50);
  320. test.isFalse(f.isUploaded());
  321. // But if uploadedAt is set, we should always get 100
  322. f.update({$set: {uploadedAt: new Date}}, function (error, result) {
  323. test.isFalse(!!error);
  324. test.equal(f.uploadProgress(), 100);
  325. test.isTrue(f.isUploaded());
  326. next();
  327. });
  328. });
  329. });
  330. });
  331. /*
  332. * remove
  333. */
  334. Tinytest.addAsync('cfs-file - remove', function(test, next) {
  335. var f = new FS.File('data:text/plain;base64,SGVsbG8gV29ybGQ=');
  336. var newId;
  337. fileCollection.insert(f, function (error, fileObj) {
  338. test.isFalse(!!error);
  339. test.instanceOf(fileObj, FS.File);
  340. newId = fileObj._id;
  341. test.isTrue(!!fileCollection.findOne(newId));
  342. // Wait 5 seconds to remove; otherwise we could
  343. // cause errors with the tempstore or SA trying
  344. // to save.
  345. Meteor.setTimeout(function () {
  346. fileObj.remove(function (error, result) {
  347. test.isFalse(!!error);
  348. test.equal(result, 1);
  349. test.isFalse(!!fileCollection.findOne(newId));
  350. next();
  351. });
  352. }, 5000);
  353. });
  354. });
  355. if (Meteor.isServer) {
  356. /*
  357. * createWriteStream
  358. */
  359. Tinytest.add('cfs-file - createWriteStream', function(test) {
  360. //TODO
  361. test.isTrue(true);
  362. });
  363. /*
  364. * createReadStream
  365. */
  366. Tinytest.add('cfs-file - createReadStream', function(test) {
  367. //TODO
  368. test.isTrue(true);
  369. });
  370. }
  371. //Test API:
  372. //test.isFalse(v, msg)
  373. //test.isTrue(v, msg)
  374. //test.equalactual, expected, message, not
  375. //test.length(obj, len)
  376. //test.include(s, v)
  377. //test.isNaN(v, msg)
  378. //test.isUndefined(v, msg)
  379. //test.isNotNull
  380. //test.isNull
  381. //test.throws(func)
  382. //test.instanceOf(obj, klass)
  383. //test.notEqual(actual, expected, message)
  384. //test.runId()
  385. //test.exception(exception)
  386. //test.expect_fail()
  387. //test.ok(doc)
  388. //test.fail(doc)
  389. //test.equal(a, b, msg)