promise.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. var bcrypt = require('../bcrypt');
  2. var promises = require('../promises');
  3. var fail = function(assert, error) {
  4. assert.ok(false, error);
  5. assert.done();
  6. };
  7. // only run these tests if Promise is available
  8. if (typeof Promise !== 'undefined') {
  9. module.exports = {
  10. test_salt_returns_promise_on_no_args: function(assert) {
  11. // make sure test passes with non-native implementations such as bluebird
  12. // http://stackoverflow.com/questions/27746304/how-do-i-tell-if-an-object-is-a-promise
  13. assert.strictEqual(typeof bcrypt.genSalt().then, 'function', "Should return a promise");
  14. assert.done();
  15. },
  16. test_salt_returns_promise_on_null_callback: function(assert) {
  17. assert.strictEqual(typeof bcrypt.genSalt(13, null, null).then,'function', "Should return a promise");
  18. assert.done();
  19. },
  20. test_salt_length: function(assert) {
  21. assert.expect(2);
  22. bcrypt.genSalt(10).then(function(salt) {
  23. assert.ok(salt,'salt must be defined');
  24. assert.strictEqual(29, salt.length, "Salt isn't the correct length.");
  25. assert.done();
  26. });
  27. },
  28. test_salt_rounds_is_string_number: function(assert) {
  29. assert.expect(1);
  30. bcrypt.genSalt('10').then(function() {
  31. fail(assert, "should not be resolved");
  32. }).catch(function(err) {
  33. assert.ok((err instanceof Error), "Should be an Error. genSalt requires round to be of type number.");
  34. }).then(function() {
  35. assert.done();
  36. });
  37. },
  38. test_salt_rounds_is_string_non_number: function(assert) {
  39. assert.expect(1);
  40. bcrypt.genSalt('b').then(function() {
  41. fail(assert, "should not be resolved");
  42. }).catch(function(err) {
  43. assert.ok((err instanceof Error), "Should be an Error. genSalt requires round to be of type number.");
  44. }).then(function() {
  45. assert.done();
  46. });
  47. },
  48. test_hash_returns_promise_on_null_callback: function(assert) {
  49. assert.strictEqual(typeof bcrypt.hash('password', 10, null).then,'function', "Should return a promise");
  50. assert.done();
  51. },
  52. test_hash: function(assert) {
  53. assert.expect(1);
  54. bcrypt.genSalt(10).then(function(salt) {
  55. return bcrypt.hash('password', salt);
  56. }).then(function(res) {
  57. assert.ok(res, "Res should be defined.");
  58. assert.done();
  59. });
  60. },
  61. test_hash_rounds: function(assert) {
  62. assert.expect(1);
  63. bcrypt.hash('bacon', 8).then(function(hash) {
  64. assert.strictEqual(bcrypt.getRounds(hash), 8, "Number of rounds should be that specified in the function call.");
  65. assert.done();
  66. });
  67. },
  68. test_hash_empty_strings: function(assert) {
  69. assert.expect(2);
  70. Promise.all([
  71. bcrypt.genSalt(10).then(function(salt) {
  72. return bcrypt.hash('', salt);
  73. }).then(function(res) {
  74. assert.ok(res, "Res should be defined even with an empty pw.");
  75. }),
  76. bcrypt.hash('', '').then(function() {
  77. fail(assert, "should not be resolved")
  78. }).catch(function(err) {
  79. assert.ok(err);
  80. }),
  81. ]).then(function() {
  82. assert.done();
  83. });
  84. },
  85. test_hash_no_params: function(assert) {
  86. assert.expect(1);
  87. bcrypt.hash().then(function() {
  88. fail(assert, "should not be resolved");
  89. }).catch(function(err) {
  90. assert.ok(err, "Should be an error. No params.");
  91. }).then(function() {
  92. assert.done();
  93. });
  94. },
  95. test_hash_one_param: function(assert) {
  96. assert.expect(1);
  97. bcrypt.hash('password').then(function() {
  98. fail(assert, "should not be resolved");
  99. }).catch(function(err) {
  100. assert.ok(err, "Should be an error. No salt.");
  101. }).then(function() {
  102. assert.done();
  103. });
  104. },
  105. test_hash_salt_validity: function(assert) {
  106. assert.expect(3);
  107. Promise.all(
  108. [
  109. bcrypt.hash('password', '$2a$10$somesaltyvaluertsetrse').then(function(enc) {
  110. assert.ok(enc, "should be resolved with a value");
  111. }),
  112. bcrypt.hash('password', 'some$value').then(function() {
  113. fail(assert, "should not resolve");
  114. }).catch(function(err) {
  115. assert.notEqual(err, undefined);
  116. assert.strictEqual(err.message, "Invalid salt. Salt must be in the form of: $Vers$log2(NumRounds)$saltvalue");
  117. })
  118. ]).then(function() {
  119. assert.done();
  120. });
  121. },
  122. test_verify_salt: function(assert) {
  123. assert.expect(2);
  124. bcrypt.genSalt(10).then(function(salt) {
  125. var split_salt = salt.split('$');
  126. assert.strictEqual(split_salt[1], '2b');
  127. assert.strictEqual(split_salt[2], '10');
  128. assert.done();
  129. });
  130. },
  131. test_verify_salt_min_rounds: function(assert) {
  132. assert.expect(2);
  133. bcrypt.genSalt(1).then(function(salt) {
  134. var split_salt = salt.split('$');
  135. assert.strictEqual(split_salt[1], '2b');
  136. assert.strictEqual(split_salt[2], '04');
  137. assert.done();
  138. });
  139. },
  140. test_verify_salt_max_rounds: function(assert) {
  141. assert.expect(2);
  142. bcrypt.genSalt(100).then(function(salt) {
  143. var split_salt = salt.split('$');
  144. assert.strictEqual(split_salt[1], '2b');
  145. assert.strictEqual(split_salt[2], '31');
  146. assert.done();
  147. });
  148. },
  149. test_hash_compare_returns_promise_on_null_callback: function(assert) {
  150. assert.strictEqual(typeof bcrypt.compare('password', 'something', null).then, 'function', "Should return a promise");
  151. assert.done();
  152. },
  153. test_hash_compare: function(assert) {
  154. assert.expect(3);
  155. bcrypt.genSalt(10).then(function(salt) {
  156. assert.strictEqual(29, salt.length, "Salt isn't the correct length.");
  157. return bcrypt.hash("test", salt);
  158. }).then(function(hash) {
  159. return Promise.all(
  160. [
  161. bcrypt.compare("test", hash).then(function(res) {
  162. assert.strictEqual(res, true, "These hashes should be equal.");
  163. }),
  164. bcrypt.compare("blah", hash).then(function(res) {
  165. assert.strictEqual(res, false, "These hashes should not be equal.");
  166. })
  167. ]).then(function() {
  168. assert.done();
  169. });
  170. });
  171. },
  172. test_hash_compare_empty_strings: function(assert) {
  173. assert.expect(2);
  174. var hash = bcrypt.hashSync("test", bcrypt.genSaltSync(10));
  175. bcrypt.compare("", hash).then(function(res) {
  176. assert.strictEqual(res, false, "These hashes should not be equal.");
  177. return bcrypt.compare("", "");
  178. }).then(function(res) {
  179. assert.strictEqual(res, false, "These hashes should not be equal.");
  180. assert.done();
  181. });
  182. },
  183. test_hash_compare_invalid_strings: function(assert) {
  184. var fullString = 'envy1362987212538';
  185. var hash = '$2a$10$XOPbrlUPQdwdJUpSrIF6X.LbE14qsMmKGhM1A8W9iqaG3vv1BD7WC';
  186. var wut = ':';
  187. Promise.all([
  188. bcrypt.compare(fullString, hash).then(function(res) {
  189. assert.ok(res);
  190. }),
  191. bcrypt.compare(fullString, wut).then(function(res) {
  192. assert.ok(!res);
  193. })
  194. ]).then(function() {
  195. assert.done();
  196. });
  197. },
  198. test_hash_compare_no_params: function(assert) {
  199. assert.expect(1);
  200. bcrypt.compare().then(function() {
  201. fail(assert, 'Should not resolve');
  202. }).catch(function(err) {
  203. assert.strictEqual(err.message, 'data and hash arguments required', 'Promise should be rejected when no parameters are supplied');
  204. }).then(function() {
  205. assert.done();
  206. });
  207. },
  208. test_hash_compare_one_param: function(assert) {
  209. assert.expect(1);
  210. bcrypt.compare('password').then(function() {
  211. fail(assert, 'Should not resolve');
  212. }).catch(function(err) {
  213. assert.strictEqual(err.message, 'data and hash arguments required', 'Promise should be rejected when no parameters are supplied');
  214. }).then(function() {
  215. assert.done();
  216. });
  217. },
  218. test_change_promise_impl_reject: function(assert) {
  219. promises.use({
  220. reject: function() {
  221. return 'mock';
  222. }
  223. });
  224. assert.equal(promises.reject(), 'mock');
  225. // need to reset the promise implementation because of require cache
  226. promises.use(global.Promise);
  227. assert.done();
  228. },
  229. test_change_promise_impl_promise: function(assert) {
  230. promises.use({
  231. reject: function(err) {
  232. assert.equal(err.message, 'fn must be a function');
  233. return 'mock';
  234. }
  235. });
  236. assert.equal(promises.promise('', '', ''), 'mock');
  237. // need to reset the promise implementation because of require cache
  238. promises.use(global.Promise);
  239. assert.done();
  240. }
  241. };
  242. }