a zip code crypto-currency system good for red ONLY

test.api.js 43KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173
  1. /* global after:true, afterEach:true, before:true, beforeEach:true, describe:true, expect:true, it:true, Promise:true */
  2. var DRIVERS = [
  3. localforage.INDEXEDDB,
  4. localforage.LOCALSTORAGE,
  5. localforage.WEBSQL
  6. ];
  7. var driverApiMethods = [
  8. 'getItem',
  9. 'setItem',
  10. 'clear',
  11. 'length',
  12. 'removeItem',
  13. 'key',
  14. 'keys'
  15. ];
  16. describe('localForage API', function() {
  17. // https://github.com/mozilla/localForage#working-on-localforage
  18. it('has Promises available', function() {
  19. expect(Promise).to.be.a('function');
  20. });
  21. });
  22. describe('localForage', function() {
  23. var appropriateDriver =
  24. (localforage.supports(localforage.INDEXEDDB) &&
  25. localforage.INDEXEDDB) ||
  26. (localforage.supports(localforage.WEBSQL) &&
  27. localforage.WEBSQL) ||
  28. (localforage.supports(localforage.LOCALSTORAGE) &&
  29. localforage.LOCALSTORAGE);
  30. it('automatically selects the most appropriate driver (' +
  31. appropriateDriver + ')', function(done) {
  32. this.timeout(10000);
  33. localforage.ready().then(function() {
  34. expect(localforage.driver()).to.be(appropriateDriver);
  35. done();
  36. }, function(error) {
  37. expect(error).to.be.an(Error);
  38. expect(error.message).to
  39. .be('No available storage method found.');
  40. expect(localforage.driver()).to.be(null);
  41. done();
  42. });
  43. });
  44. it('errors when a requested driver is not found [callback]', function(done) {
  45. localforage.getDriver('UnknownDriver', null, function(error) {
  46. expect(error).to.be.an(Error);
  47. expect(error.message).to
  48. .be('Driver not found.');
  49. done();
  50. });
  51. });
  52. it('errors when a requested driver is not found [promise]', function(done) {
  53. localforage.getDriver('UnknownDriver').then(null, function(error) {
  54. expect(error).to.be.an(Error);
  55. expect(error.message).to
  56. .be('Driver not found.');
  57. done();
  58. });
  59. });
  60. it('retrieves the serializer [callback]', function(done) {
  61. localforage.getSerializer(function(serializer) {
  62. expect(serializer).to.be.an('object');
  63. done();
  64. });
  65. });
  66. it('retrieves the serializer [promise]', function(done) {
  67. var serializerPromise = localforage.getSerializer();
  68. expect(serializerPromise).to.be.an('object');
  69. expect(serializerPromise.then).to.be.a('function');
  70. serializerPromise.then(function(serializer) {
  71. expect(serializer).to.be.an('object');
  72. done();
  73. });
  74. });
  75. it('does not support object parameter to setDriver', function(done) {
  76. var driverPreferedOrder = {
  77. '0': localforage.INDEXEDDB,
  78. '1': localforage.WEBSQL,
  79. '2': localforage.LOCALSTORAGE,
  80. length: 3
  81. };
  82. localforage.setDriver(driverPreferedOrder).then(null, function(error) {
  83. expect(error).to.be.an(Error);
  84. expect(error.message).to
  85. .be('No available storage method found.');
  86. done();
  87. });
  88. });
  89. it('skips drivers that fail to initilize', function(done) {
  90. var failingStorageDriver = (function() {
  91. function driverDummyMethod() {
  92. return Promise.reject(new Error('Driver Method Failed.'));
  93. }
  94. return {
  95. _driver: 'failingStorageDriver',
  96. _initStorage: function _initStorage() {
  97. return Promise.reject(new Error('Driver Failed to Initialize.'));
  98. },
  99. iterate: driverDummyMethod,
  100. getItem: driverDummyMethod,
  101. setItem: driverDummyMethod,
  102. removeItem: driverDummyMethod,
  103. clear: driverDummyMethod,
  104. length: driverDummyMethod,
  105. key: driverDummyMethod,
  106. keys: driverDummyMethod
  107. };
  108. })();
  109. var driverPreferedOrder = [
  110. failingStorageDriver._driver,
  111. localforage.INDEXEDDB,
  112. localforage.WEBSQL,
  113. localforage.LOCALSTORAGE
  114. ];
  115. localforage.defineDriver(failingStorageDriver).then(function() {
  116. return localforage.setDriver(driverPreferedOrder);
  117. }).then(function() {
  118. return localforage.ready();
  119. }).then(function() {
  120. expect(localforage.driver()).to.be(appropriateDriver);
  121. done();
  122. });
  123. });
  124. });
  125. DRIVERS.forEach(function(driverName) {
  126. if ((!localforage.supports(localforage.INDEXEDDB) &&
  127. driverName === localforage.INDEXEDDB) ||
  128. (!localforage.supports(localforage.LOCALSTORAGE) &&
  129. driverName === localforage.LOCALSTORAGE) ||
  130. (!localforage.supports(localforage.WEBSQL) &&
  131. driverName === localforage.WEBSQL)) {
  132. // Browser doesn't support this storage library, so we exit the API
  133. // tests.
  134. return;
  135. }
  136. describe(driverName + ' driver', function() {
  137. 'use strict';
  138. this.timeout(30000);
  139. before(function(done) {
  140. localforage.setDriver(driverName).then(done);
  141. });
  142. beforeEach(function(done) {
  143. localStorage.clear();
  144. localforage.ready().then(function() {
  145. localforage.clear(done);
  146. });
  147. });
  148. it('has a localStorage API', function() {
  149. expect(localforage.getItem).to.be.a('function');
  150. expect(localforage.setItem).to.be.a('function');
  151. expect(localforage.clear).to.be.a('function');
  152. expect(localforage.length).to.be.a('function');
  153. expect(localforage.removeItem).to.be.a('function');
  154. expect(localforage.key).to.be.a('function');
  155. });
  156. it('has the localForage API', function() {
  157. expect(localforage._initStorage).to.be.a('function');
  158. expect(localforage.config).to.be.a('function');
  159. expect(localforage.defineDriver).to.be.a('function');
  160. expect(localforage.driver).to.be.a('function');
  161. expect(localforage.supports).to.be.a('function');
  162. expect(localforage.iterate).to.be.a('function');
  163. expect(localforage.getItem).to.be.a('function');
  164. expect(localforage.setItem).to.be.a('function');
  165. expect(localforage.clear).to.be.a('function');
  166. expect(localforage.length).to.be.a('function');
  167. expect(localforage.removeItem).to.be.a('function');
  168. expect(localforage.key).to.be.a('function');
  169. expect(localforage.getDriver).to.be.a('function');
  170. expect(localforage.setDriver).to.be.a('function');
  171. expect(localforage.ready).to.be.a('function');
  172. expect(localforage.createInstance).to.be.a('function');
  173. expect(localforage.getSerializer).to.be.a('function');
  174. });
  175. // Make sure we don't support bogus drivers.
  176. it('supports ' + driverName + ' database driver', function() {
  177. expect(localforage.supports(driverName) === true);
  178. expect(localforage.supports('I am not a driver') === false);
  179. });
  180. it('sets the right database driver', function() {
  181. expect(localforage.driver() === driverName);
  182. });
  183. it('has an empty length by default', function(done) {
  184. localforage.length(function(err, length) {
  185. expect(length).to.be(0);
  186. done();
  187. });
  188. });
  189. if (driverName === localforage.INDEXEDDB) {
  190. describe('Blob support', function() {
  191. var transaction;
  192. var called;
  193. var db;
  194. var blob = new Blob([''], {type: 'image/png'});
  195. before(function() {
  196. db = localforage._dbInfo.db;
  197. transaction = db.transaction;
  198. db.transaction = function() {
  199. called += 1;
  200. return transaction.apply(db, arguments);
  201. };
  202. });
  203. beforeEach(function() {
  204. called = 0;
  205. });
  206. it('not check for non Blob', function(done) {
  207. localforage.setItem('key', {}).then(function() {
  208. expect(called).to.be(1);
  209. done();
  210. }, function(error) {
  211. done(error || 'error');
  212. });
  213. });
  214. it('check for Blob', function(done) {
  215. localforage.setItem('key', blob).then(function() {
  216. expect(called).to.be.above(1);
  217. done();
  218. }, function(error) {
  219. done(error || 'error');
  220. });
  221. });
  222. it('check for Blob once', function(done) {
  223. localforage.setItem('key', blob).then(function() {
  224. expect(called).to.be(1);
  225. done();
  226. }, function(error) {
  227. done(error || 'error');
  228. });
  229. });
  230. after(function() {
  231. localforage._dbInfo.db.transaction = transaction;
  232. });
  233. });
  234. }
  235. it('should iterate [callback]', function(done) {
  236. localforage.setItem('officeX', 'InitechX', function(err, setValue) {
  237. expect(setValue).to.be('InitechX');
  238. localforage.getItem('officeX', function(err, value) {
  239. expect(value).to.be(setValue);
  240. localforage.setItem('officeY', 'InitechY',
  241. function(err, setValue) {
  242. expect(setValue).to.be('InitechY');
  243. localforage.getItem('officeY', function(err, value) {
  244. expect(value).to.be(setValue);
  245. var accumulator = {};
  246. var iterationNumbers = [];
  247. localforage.iterate(function(value, key, iterationNumber) {
  248. accumulator[key] = value;
  249. iterationNumbers.push(iterationNumber);
  250. }, function() {
  251. try {
  252. expect(accumulator.officeX).to.be('InitechX');
  253. expect(accumulator.officeY).to.be('InitechY');
  254. expect(iterationNumbers).to.eql([1, 2]);
  255. done();
  256. } catch (e) {
  257. done(e);
  258. }
  259. });
  260. });
  261. });
  262. });
  263. });
  264. });
  265. it('should iterate [promise]', function(done) {
  266. var accumulator = {};
  267. var iterationNumbers = [];
  268. return localforage.setItem('officeX',
  269. 'InitechX').then(function(setValue) {
  270. expect(setValue).to.be('InitechX');
  271. return localforage.getItem('officeX');
  272. }).then(function(value) {
  273. expect(value).to.be('InitechX');
  274. return localforage.setItem('officeY', 'InitechY');
  275. }).then(function(setValue) {
  276. expect(setValue).to.be('InitechY');
  277. return localforage.getItem('officeY');
  278. }).then(function(value) {
  279. expect(value).to.be('InitechY');
  280. return localforage.iterate(function(value, key,
  281. iterationNumber) {
  282. accumulator[key] = value;
  283. iterationNumbers.push(iterationNumber);
  284. });
  285. }).then(function() {
  286. expect(accumulator.officeX).to.be('InitechX');
  287. expect(accumulator.officeY).to.be('InitechY');
  288. expect(iterationNumbers).to.eql([1, 2]);
  289. done();
  290. });
  291. });
  292. it('should break iteration with defined return value [callback]',
  293. function(done) {
  294. var breakCondition = 'Some value!';
  295. localforage.setItem('officeX', 'InitechX', function(err, setValue) {
  296. expect(setValue).to.be('InitechX');
  297. localforage.getItem('officeX', function(err, value) {
  298. expect(value).to.be(setValue);
  299. localforage.setItem('officeY', 'InitechY',
  300. function(err, setValue) {
  301. expect(setValue).to.be('InitechY');
  302. localforage.getItem('officeY', function(err, value) {
  303. expect(value).to.be(setValue);
  304. // Loop is broken within first iteration.
  305. localforage.iterate(function() {
  306. // Returning defined value will break the cycle.
  307. return breakCondition;
  308. }, function(err, loopResult) {
  309. // The value that broken the cycle is returned
  310. // as a result.
  311. expect(loopResult).to.be(breakCondition);
  312. done();
  313. });
  314. });
  315. });
  316. });
  317. });
  318. });
  319. it('should break iteration with defined return value [promise]',
  320. function(done) {
  321. var breakCondition = 'Some value!';
  322. localforage.setItem('officeX', 'InitechX').then(function(setValue) {
  323. expect(setValue).to.be('InitechX');
  324. return localforage.getItem('officeX');
  325. }).then(function(value) {
  326. expect(value).to.be('InitechX');
  327. return localforage.setItem('officeY', 'InitechY');
  328. }).then(function(setValue) {
  329. expect(setValue).to.be('InitechY');
  330. return localforage.getItem('officeY');
  331. }).then(function(value) {
  332. expect(value).to.be('InitechY');
  333. return localforage.iterate(function() {
  334. return breakCondition;
  335. });
  336. }).then(function(result) {
  337. expect(result).to.be(breakCondition);
  338. done();
  339. });
  340. });
  341. it('should iterate() through only its own keys/values', function(done) {
  342. localStorage.setItem('local', 'forage');
  343. localforage.setItem('office', 'Initech').then(function() {
  344. return localforage.setItem('name', 'Bob');
  345. }).then(function() {
  346. // Loop through all key/value pairs; {local: 'forage'} set
  347. // manually should not be returned.
  348. var numberOfItems = 0;
  349. var iterationNumberConcat = '';
  350. localStorage.setItem('locals', 'forages');
  351. localforage.iterate(function(value, key, iterationNumber) {
  352. expect(key).to.not.be('local');
  353. expect(value).to.not.be('forage');
  354. numberOfItems++;
  355. iterationNumberConcat += iterationNumber;
  356. }, function(err) {
  357. if (!err) {
  358. // While there are 4 items in localStorage,
  359. // only 2 items were set using localForage.
  360. expect(numberOfItems).to.be(2);
  361. // Only 2 items were set using localForage,
  362. // so we should get '12' and not '1234'
  363. expect(iterationNumberConcat).to.be('12');
  364. done();
  365. }
  366. });
  367. });
  368. });
  369. // Test for https://github.com/mozilla/localForage/issues/175
  370. it('nested getItem inside clear works [callback]', function(done) {
  371. localforage.setItem('hello', 'Hello World !', function() {
  372. localforage.clear(function() {
  373. localforage.getItem('hello', function(secondValue) {
  374. expect(secondValue).to.be(null);
  375. done();
  376. });
  377. });
  378. });
  379. });
  380. it('nested getItem inside clear works [promise]', function(done) {
  381. localforage.setItem('hello', 'Hello World !').then(function() {
  382. return localforage.clear();
  383. }).then(function() {
  384. return localforage.getItem('hello');
  385. }).then(function(secondValue) {
  386. expect(secondValue).to.be(null);
  387. done();
  388. });
  389. });
  390. // Because localStorage doesn't support saving the `undefined` type, we
  391. // always return `null` so that localForage is consistent across
  392. // browsers.
  393. // https://github.com/mozilla/localForage/pull/42
  394. it('returns null for undefined key [callback]', function(done) {
  395. localforage.getItem('key', function(err, value) {
  396. expect(value).to.be(null);
  397. done();
  398. });
  399. });
  400. it('returns null for undefined key [promise]', function(done) {
  401. localforage.getItem('key').then(function(value) {
  402. expect(value).to.be(null);
  403. done();
  404. });
  405. });
  406. it('saves an item [callback]', function(done) {
  407. localforage.setItem('office', 'Initech', function(err, setValue) {
  408. expect(setValue).to.be('Initech');
  409. localforage.getItem('office', function(err, value) {
  410. expect(value).to.be(setValue);
  411. done();
  412. });
  413. });
  414. });
  415. it('saves an item [promise]', function(done) {
  416. localforage.setItem('office', 'Initech').then(function(setValue) {
  417. expect(setValue).to.be('Initech');
  418. return localforage.getItem('office');
  419. }).then(function(value) {
  420. expect(value).to.be('Initech');
  421. done();
  422. });
  423. });
  424. it('saves an item over an existing key [callback]', function(done) {
  425. localforage.setItem('4th floor', 'Mozilla',
  426. function(err, setValue) {
  427. expect(setValue).to.be('Mozilla');
  428. localforage.setItem('4th floor', 'Quora',
  429. function(err, newValue) {
  430. expect(newValue).to.not.be(setValue);
  431. expect(newValue).to.be('Quora');
  432. localforage.getItem('4th floor', function(err, value) {
  433. expect(value).to.not.be(setValue);
  434. expect(value).to.be(newValue);
  435. done();
  436. });
  437. });
  438. });
  439. });
  440. it('saves an item over an existing key [promise]', function(done) {
  441. localforage.setItem('4e', 'Mozilla').then(function(setValue) {
  442. expect(setValue).to.be('Mozilla');
  443. return localforage.setItem('4e', 'Quora');
  444. }).then(function(newValue) {
  445. expect(newValue).to.not.be('Mozilla');
  446. expect(newValue).to.be('Quora');
  447. return localforage.getItem('4e');
  448. }).then(function(value) {
  449. expect(value).to.not.be('Mozilla');
  450. expect(value).to.be('Quora');
  451. done();
  452. });
  453. });
  454. it('returns null when saving undefined [callback]', function(done) {
  455. localforage.setItem('undef', undefined, function(err, setValue) {
  456. expect(setValue).to.be(null);
  457. done();
  458. });
  459. });
  460. it('returns null when saving undefined [promise]', function(done) {
  461. localforage.setItem('undef', undefined).then(function(setValue) {
  462. expect(setValue).to.be(null);
  463. done();
  464. });
  465. });
  466. it('returns null for a non-existant key [callback]', function(done) {
  467. localforage.getItem('undef', function(err, value) {
  468. expect(value).to.be(null);
  469. done();
  470. });
  471. });
  472. it('returns null for a non-existant key [promise]', function(done) {
  473. localforage.getItem('undef').then(function(value) {
  474. expect(value).to.be(null);
  475. done();
  476. });
  477. });
  478. // github.com/mozilla/localforage/pull/24#discussion-diff-9389662R158
  479. // localStorage's method API (`localStorage.getItem('foo')`) returns
  480. // `null` for undefined keys, even though its getter/setter API
  481. // (`localStorage.foo`) returns `undefined` for the same key. Gaia's
  482. // asyncStorage API, which is based on localStorage and upon which
  483. // localforage is based, ALSO returns `null`. BLARG! So for now, we
  484. // just return null, because there's no way to know from localStorage
  485. // if the key is ACTUALLY `null` or undefined but returning `null`.
  486. // And returning `undefined` here would break compatibility with
  487. // localStorage fallback. Maybe in the future we won't care...
  488. it('returns null from an undefined key [callback]', function(done) {
  489. localforage.key(0, function(err, key) {
  490. expect(key).to.be(null);
  491. done();
  492. });
  493. });
  494. it('returns null from an undefined key [promise]', function(done) {
  495. localforage.key(0).then(function(key) {
  496. expect(key).to.be(null);
  497. done();
  498. });
  499. });
  500. it('returns key name [callback]', function(done) {
  501. localforage.setItem('office', 'Initech').then(function() {
  502. localforage.key(0, function(err, key) {
  503. expect(key).to.be('office');
  504. done();
  505. });
  506. });
  507. });
  508. it('returns key name [promise]', function(done) {
  509. localforage.setItem('office', 'Initech').then(function() {
  510. return localforage.key(0);
  511. }).then(function(key) {
  512. expect(key).to.be('office');
  513. done();
  514. });
  515. });
  516. it('removes an item [callback]', function(done) {
  517. localforage.setItem('office', 'Initech', function() {
  518. localforage.setItem('otherOffice', 'Initrode', function() {
  519. localforage.removeItem('office', function() {
  520. localforage.getItem('office',
  521. function(err, emptyValue) {
  522. expect(emptyValue).to.be(null);
  523. localforage.getItem('otherOffice',
  524. function(err, value) {
  525. expect(value).to.be('Initrode');
  526. done();
  527. });
  528. });
  529. });
  530. });
  531. });
  532. });
  533. it('removes an item [promise]', function(done) {
  534. localforage.setItem('office', 'Initech').then(function() {
  535. return localforage.setItem('otherOffice', 'Initrode');
  536. }).then(function() {
  537. return localforage.removeItem('office');
  538. }).then(function() {
  539. return localforage.getItem('office');
  540. }).then(function(emptyValue) {
  541. expect(emptyValue).to.be(null);
  542. return localforage.getItem('otherOffice');
  543. }).then(function(value) {
  544. expect(value).to.be('Initrode');
  545. done();
  546. });
  547. });
  548. it('removes all items [callback]', function(done) {
  549. localforage.setItem('office', 'Initech', function() {
  550. localforage.setItem('otherOffice', 'Initrode', function() {
  551. localforage.length(function(err, length) {
  552. expect(length).to.be(2);
  553. localforage.clear(function() {
  554. localforage.getItem('office', function(err, value) {
  555. expect(value).to.be(null);
  556. localforage.length(function(err, length) {
  557. expect(length).to.be(0);
  558. done();
  559. });
  560. });
  561. });
  562. });
  563. });
  564. });
  565. });
  566. it('removes all items [promise]', function(done) {
  567. localforage.setItem('office', 'Initech').then(function() {
  568. return localforage.setItem('otherOffice', 'Initrode');
  569. }).then(function() {
  570. return localforage.length();
  571. }).then(function(length) {
  572. expect(length).to.be(2);
  573. return localforage.clear();
  574. }).then(function() {
  575. return localforage.getItem('office');
  576. }).then(function(value) {
  577. expect(value).to.be(null);
  578. return localforage.length();
  579. }).then(function(length) {
  580. expect(length).to.be(0);
  581. done();
  582. });
  583. });
  584. if (driverName === localforage.LOCALSTORAGE) {
  585. it('removes only own items upon clear', function(done) {
  586. localStorage.setItem('local', 'forage');
  587. localforage.setItem('office', 'Initech').then(function() {
  588. return localforage.clear();
  589. }).then(function() {
  590. expect(localStorage.getItem('local')).to.be('forage');
  591. localStorage.clear();
  592. done();
  593. });
  594. });
  595. it('returns only its own keys from keys()', function(done) {
  596. localStorage.setItem('local', 'forage');
  597. localforage.setItem('office', 'Initech').then(function() {
  598. return localforage.keys();
  599. }).then(function(keys) {
  600. expect(keys).to.eql(['office']);
  601. localStorage.clear();
  602. done();
  603. });
  604. });
  605. it('counts only its own items with length()', function(done) {
  606. localStorage.setItem('local', 'forage');
  607. localStorage.setItem('another', 'value');
  608. localforage.setItem('office', 'Initech').then(function() {
  609. return localforage.length();
  610. }).then(function(length) {
  611. expect(length).to.be(1);
  612. localStorage.clear();
  613. done();
  614. });
  615. });
  616. }
  617. it('has a length after saving an item [callback]', function(done) {
  618. localforage.length(function(err, length) {
  619. expect(length).to.be(0);
  620. localforage.setItem('rapper', 'Black Thought', function() {
  621. localforage.length(function(err, length) {
  622. expect(length).to.be(1);
  623. done();
  624. });
  625. });
  626. });
  627. });
  628. it('has a length after saving an item [promise]', function(done) {
  629. localforage.length().then(function(length) {
  630. expect(length).to.be(0);
  631. return localforage.setItem('lame rapper', 'Vanilla Ice');
  632. }).then(function() {
  633. return localforage.length();
  634. }).then(function(length) {
  635. expect(length).to.be(1);
  636. done();
  637. });
  638. });
  639. // Deal with non-string keys, see issue #250
  640. // https://github.com/mozilla/localForage/issues/250
  641. it('casts an undefined key to a String', function(done) {
  642. localforage.setItem(undefined, 'goodness!').then(function(value) {
  643. expect(value).to.be('goodness!');
  644. return localforage.getItem(undefined);
  645. }).then(function(value) {
  646. expect(value).to.be('goodness!');
  647. return localforage.removeItem(undefined);
  648. }).then(function() {
  649. return localforage.length();
  650. }).then(function(length) {
  651. expect(length).to.be(0);
  652. done();
  653. });
  654. });
  655. it('casts a null key to a String', function(done) {
  656. localforage.setItem(null, 'goodness!').then(function(value) {
  657. expect(value).to.be('goodness!');
  658. return localforage.getItem(null);
  659. }).then(function(value) {
  660. expect(value).to.be('goodness!');
  661. return localforage.removeItem(null);
  662. }).then(function() {
  663. return localforage.length();
  664. }).then(function(length) {
  665. expect(length).to.be(0);
  666. done();
  667. });
  668. });
  669. it('casts a float key to a String', function(done) {
  670. localforage.setItem(537.35737, 'goodness!').then(function(value) {
  671. expect(value).to.be('goodness!');
  672. return localforage.getItem(537.35737);
  673. }).then(function(value) {
  674. expect(value).to.be('goodness!');
  675. return localforage.removeItem(537.35737);
  676. }).then(function() {
  677. return localforage.length();
  678. }).then(function(length) {
  679. expect(length).to.be(0);
  680. done();
  681. });
  682. });
  683. it('is retrieved by getDriver [callback]', function(done) {
  684. localforage.getDriver(driverName, function(driver) {
  685. expect(typeof driver).to.be('object');
  686. driverApiMethods.concat('_initStorage').forEach(function(methodName) {
  687. expect(typeof driver[methodName]).to.be('function');
  688. });
  689. expect(driver._driver).to.be(driverName);
  690. done();
  691. });
  692. });
  693. it('is retrieved by getDriver [promise]', function(done) {
  694. localforage.getDriver(driverName).then(function(driver) {
  695. expect(typeof driver).to.be('object');
  696. driverApiMethods.concat('_initStorage').forEach(function(methodName) {
  697. expect(typeof driver[methodName]).to.be('function');
  698. });
  699. expect(driver._driver).to.be(driverName);
  700. done();
  701. });
  702. });
  703. if (driverName === localforage.WEBSQL ||
  704. driverName === localforage.LOCALSTORAGE) {
  705. it('exposes the serializer on the dbInfo object', function(done) {
  706. localforage.ready().then(function() {
  707. expect(localforage._dbInfo.serializer).to.be.an('object');
  708. done();
  709. });
  710. });
  711. }
  712. });
  713. function prepareStorage(storageName) {
  714. // Delete IndexedDB storages (start from scratch)
  715. // Refers to issue #492 - https://github.com/mozilla/localForage/issues/492
  716. if (driverName === localforage.INDEXEDDB) {
  717. return new Promise(function(resolve) {
  718. var indexedDB = (indexedDB || window.indexedDB ||
  719. window.webkitIndexedDB ||
  720. window.mozIndexedDB || window.OIndexedDB ||
  721. window.msIndexedDB);
  722. indexedDB.deleteDatabase(storageName).onsuccess = resolve;
  723. });
  724. }
  725. // Otherwise, do nothing
  726. return Promise.resolve();
  727. }
  728. describe(driverName + ' driver multiple instances', function() {
  729. 'use strict';
  730. this.timeout(30000);
  731. var localforage2 = null;
  732. var localforage3 = null;
  733. before(function(done) {
  734. prepareStorage('storage2').then(function() {
  735. localforage2 = localforage.createInstance({
  736. name: 'storage2',
  737. // We need a small value here
  738. // otherwise local PhantomJS test
  739. // will fail with SECURITY_ERR.
  740. // TravisCI seem to work fine though.
  741. size: 1024,
  742. storeName: 'storagename2'
  743. });
  744. // Same name, but different storeName since this has been
  745. // malfunctioning before w/ IndexedDB.
  746. localforage3 = localforage.createInstance({
  747. name: 'storage2',
  748. // We need a small value here
  749. // otherwise local PhantomJS test
  750. // will fail with SECURITY_ERR.
  751. // TravisCI seem to work fine though.
  752. size: 1024,
  753. storeName: 'storagename3'
  754. });
  755. Promise.all([
  756. localforage.setDriver(driverName),
  757. localforage2.setDriver(driverName),
  758. localforage3.setDriver(driverName)
  759. ]).then(function() {
  760. done();
  761. });
  762. });
  763. });
  764. beforeEach(function(done) {
  765. Promise.all([
  766. localforage.clear(),
  767. localforage2.clear(),
  768. localforage3.clear()
  769. ]).then(function() {
  770. done();
  771. });
  772. });
  773. it('is not be able to access values of other instances', function(done) {
  774. Promise.all([
  775. localforage.setItem('key1', 'value1a'),
  776. localforage2.setItem('key2', 'value2a'),
  777. localforage3.setItem('key3', 'value3a')
  778. ]).then(function() {
  779. return Promise.all([
  780. localforage.getItem('key2').then(function(value) {
  781. expect(value).to.be(null);
  782. }),
  783. localforage2.getItem('key1').then(function(value) {
  784. expect(value).to.be(null);
  785. }),
  786. localforage2.getItem('key3').then(function(value) {
  787. expect(value).to.be(null);
  788. }),
  789. localforage3.getItem('key2').then(function(value) {
  790. expect(value).to.be(null);
  791. })
  792. ]);
  793. }).then(function() {
  794. done();
  795. }, function(errors) {
  796. done(new Error(errors));
  797. });
  798. });
  799. it('retrieves the proper value when using the same key with other instances', function(done) {
  800. Promise.all([
  801. localforage.setItem('key', 'value1'),
  802. localforage2.setItem('key', 'value2'),
  803. localforage3.setItem('key', 'value3')
  804. ]).then(function() {
  805. return Promise.all([
  806. localforage.getItem('key').then(function(value) {
  807. expect(value).to.be('value1');
  808. }),
  809. localforage2.getItem('key').then(function(value) {
  810. expect(value).to.be('value2');
  811. }),
  812. localforage3.getItem('key').then(function(value) {
  813. expect(value).to.be('value3');
  814. })
  815. ]);
  816. }).then(function() {
  817. done();
  818. }, function(errors) {
  819. done(new Error(errors));
  820. });
  821. });
  822. });
  823. // Refers to issue #492 - https://github.com/mozilla/localForage/issues/492
  824. describe(driverName + ' driver multiple instances (concurrent on same database)', function() {
  825. 'use strict';
  826. this.timeout(30000);
  827. it('chains operation on multiple stores', function(done) {
  828. prepareStorage('storage3').then(function() {
  829. var localforage1 = localforage.createInstance({
  830. name: 'storage3',
  831. storeName: 'store1',
  832. size: 1024
  833. });
  834. var localforage2 = localforage.createInstance({
  835. name: 'storage3',
  836. storeName: 'store2',
  837. size: 1024
  838. });
  839. var localforage3 = localforage.createInstance({
  840. name: 'storage3',
  841. storeName: 'store3',
  842. size: 1024
  843. });
  844. var promise1 = localforage1.setItem('key', 'value1').then(function() {
  845. return localforage1.getItem('key');
  846. }).then(function(value) {
  847. expect(value).to.be('value1');
  848. });
  849. var promise2 = localforage2.setItem('key', 'value2').then(function() {
  850. return localforage2.getItem('key');
  851. }).then(function(value) {
  852. expect(value).to.be('value2');
  853. });
  854. var promise3 = localforage3.setItem('key', 'value3').then(function() {
  855. return localforage3.getItem('key');
  856. }).then(function(value) {
  857. expect(value).to.be('value3');
  858. });
  859. Promise.all([
  860. promise1,
  861. promise2,
  862. promise3
  863. ]).then(function() {
  864. done();
  865. }).catch(function(errors) {
  866. done(new Error(errors));
  867. });
  868. });
  869. });
  870. });
  871. describe(driverName + ' driver', function() {
  872. 'use strict';
  873. var driverPreferedOrder;
  874. before(function() {
  875. // add some unsupported drivers before
  876. // and after the target driver
  877. driverPreferedOrder = ['I am a not supported driver'];
  878. if (!localforage.supports(localforage.WEBSQL)) {
  879. driverPreferedOrder.push(localforage.WEBSQL);
  880. }
  881. if (!localforage.supports(localforage.INDEXEDDB)) {
  882. driverPreferedOrder.push(localforage.INDEXEDDB);
  883. }
  884. if (!localforage.supports(localforage.LOCALSTORAGE)) {
  885. driverPreferedOrder.push(localforage.localStorage);
  886. }
  887. driverPreferedOrder.push(driverName);
  888. driverPreferedOrder.push('I am another not supported driver');
  889. });
  890. it('is used according to setDriver preference order', function(done) {
  891. localforage.setDriver(driverPreferedOrder).then(function() {
  892. expect(localforage.driver()).to.be(driverName);
  893. done();
  894. });
  895. });
  896. });
  897. describe(driverName + ' driver when the callback throws an Error', function() {
  898. 'use strict';
  899. var testObj = {
  900. throwFunc: function() {
  901. testObj.throwFuncCalls++;
  902. throw new Error('Thrown test error');
  903. },
  904. throwFuncCalls: 0
  905. };
  906. beforeEach(function(done) {
  907. testObj.throwFuncCalls = 0;
  908. done();
  909. });
  910. it('resolves the promise of getItem()', function(done) {
  911. localforage.getItem('key', testObj.throwFunc).then(function() {
  912. expect(testObj.throwFuncCalls).to.be(1);
  913. done();
  914. });
  915. });
  916. it('resolves the promise of setItem()', function(done) {
  917. localforage.setItem('key', 'test', testObj.throwFunc).then(function() {
  918. expect(testObj.throwFuncCalls).to.be(1);
  919. done();
  920. });
  921. });
  922. it('resolves the promise of clear()', function(done) {
  923. localforage.clear(testObj.throwFunc).then(function() {
  924. expect(testObj.throwFuncCalls).to.be(1);
  925. done();
  926. });
  927. });
  928. it('resolves the promise of length()', function(done) {
  929. localforage.length(testObj.throwFunc).then(function() {
  930. expect(testObj.throwFuncCalls).to.be(1);
  931. done();
  932. });
  933. });
  934. it('resolves the promise of removeItem()', function(done) {
  935. localforage.removeItem('key', testObj.throwFunc).then(function() {
  936. expect(testObj.throwFuncCalls).to.be(1);
  937. done();
  938. });
  939. });
  940. it('resolves the promise of key()', function(done) {
  941. localforage.key('key', testObj.throwFunc).then(function() {
  942. expect(testObj.throwFuncCalls).to.be(1);
  943. done();
  944. });
  945. });
  946. it('resolves the promise of keys()', function(done) {
  947. localforage.keys(testObj.throwFunc).then(function() {
  948. expect(testObj.throwFuncCalls).to.be(1);
  949. done();
  950. });
  951. });
  952. });
  953. describe(driverName + ' driver when ready() gets rejected', function() {
  954. 'use strict';
  955. this.timeout(30000);
  956. var _oldReady;
  957. beforeEach(function(done) {
  958. _oldReady = localforage.ready;
  959. localforage.ready = function() {
  960. return Promise.reject();
  961. };
  962. done();
  963. });
  964. afterEach(function(done) {
  965. localforage.ready = _oldReady;
  966. _oldReady = null;
  967. done();
  968. });
  969. driverApiMethods.forEach(function(methodName) {
  970. it('rejects ' + methodName + '() promise', function(done) {
  971. localforage[methodName]().then(null, function(/*err*/) {
  972. done();
  973. });
  974. });
  975. });
  976. });
  977. });
  978. DRIVERS.forEach(function(driverName) {
  979. describe(driverName + ' driver instance', function() {
  980. it('creates a new instance and sets the driver', function(done) {
  981. var localforage2 = localforage.createInstance({
  982. name: 'storage2',
  983. driver: driverName,
  984. // We need a small value here
  985. // otherwise local PhantomJS test
  986. // will fail with SECURITY_ERR.
  987. // TravisCI seem to work fine though.
  988. size: 1024,
  989. storeName: 'storagename2'
  990. });
  991. // since config actually uses setDriver which is async,
  992. // and since driver() and supports() are not defered (are sync),
  993. // we have to wait till an async method returns
  994. localforage2.length().then(function() {
  995. expect(localforage2.driver()).to.be(driverName);
  996. done();
  997. }, function() {
  998. expect(localforage2.driver()).to.be(null);
  999. done();
  1000. });
  1001. });
  1002. });
  1003. });