behavior.test.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /**
  2. * Module dependencies
  3. */
  4. var util = require('util');
  5. var assert = require('assert');
  6. var _ = require('@sailshq/lodash');
  7. var parley = require('../');
  8. /**
  9. * behavior.test.js
  10. *
  11. * Tests verifying parley's behavior with both callback and promise usage.
  12. */
  13. describe('behavior.test.js', function() {
  14. // ███████╗██╗ ██╗███████╗ ██████╗ ██╗██╗
  15. // ██╔════╝╚██╗██╔╝██╔════╝██╔════╝██╔╝╚██╗
  16. // █████╗ ╚███╔╝ █████╗ ██║ ██║ ██║
  17. // ██╔══╝ ██╔██╗ ██╔══╝ ██║ ██║ ██║
  18. // ██╗███████╗██╔╝ ██╗███████╗╚██████╗╚██╗██╔╝
  19. // ╚═╝╚══════╝╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝╚═╝
  20. //
  21. describe('.exec()', function() {
  22. describe('with proper usage', function() {
  23. var deferred; before(function(){ deferred = parley(function(done){ setTimeout(function (){ return done(undefined, 'hello!'); }, 12); }); });
  24. it('should work', function(done){
  25. deferred.exec(function(err) {
  26. if (err) { return done(err); }
  27. return done();
  28. });
  29. });
  30. });
  31. describe('when called more than once', function() {
  32. var deferred; before(function(){ deferred = parley(function(done){ setTimeout(function (){ return done(undefined, 'hello!'); }, 12); }); });
  33. it('should ignore subsequent calls', function(done){
  34. this.slow(300);
  35. // As a hack, override console.warn().
  36. // (this is mainly to improve the experience of looking at test results,
  37. // but it also has the benefit of adding another check.)
  38. var origConsoleWarn = global.console.warn;
  39. var counter = 0;
  40. global.console.warn = function(){
  41. counter++;
  42. };
  43. deferred.exec(function (){
  44. setTimeout(function (){
  45. global.console.warn = origConsoleWarn;
  46. try {
  47. assert.equal(counter, 3);
  48. } catch(e) { return done(e); }
  49. return done();
  50. }, 125);
  51. });
  52. // The following .exec() calls will be ignored.
  53. // (Note that 3 extra warnings will be logged, though.)
  54. deferred.exec(function (){
  55. return done(new Error('Should never make it here'));
  56. });
  57. deferred.exec(function (){
  58. return done(new Error('Should never make it here'));
  59. });
  60. deferred.exec(function (){
  61. return done(new Error('Should never make it here'));
  62. });
  63. });
  64. });
  65. describe('with invalid callback', function() {
  66. var deferred; before(function(){ deferred = parley(function(done){ setTimeout(function (){ return done(undefined, 'hello!'); }, 12); }); });
  67. it('should throw', function(){
  68. try { deferred.exec(123); }
  69. catch (e) { return; }
  70. throw new Error('Should have thrown an Error');
  71. });
  72. });
  73. describe('with no arguments', function() {
  74. var deferred; before(function(){ deferred = parley(function(done){ setTimeout(function (){ return done(undefined, 'hello!'); }, 12); }); });
  75. it('should throw', function(){
  76. try { deferred.exec(); }
  77. catch (e) { return; }
  78. throw new Error('Should have thrown an Error');
  79. });
  80. });
  81. describe('with two arguments and a callback that throws an uncaught exception', function() {
  82. var deferred; before(function(){ deferred = parley(function(done){ setTimeout(function (){ return done(undefined, 'hello!'); }, 12); }); });
  83. it('should run uncaught exception handler', function(done){
  84. this.slow(300);
  85. deferred.exec(function (){
  86. throw new Error('This is uncaught! Watch out!');
  87. }, function(uncaughtError) {
  88. try {
  89. assert.equal(uncaughtError.message, 'This is uncaught! Watch out!');
  90. } catch (e) { return done(e); }
  91. return done();
  92. });
  93. });
  94. });
  95. });//</.exec()>
  96. // ████████╗██╗ ██╗███████╗███╗ ██╗ ██╗██╗
  97. // ╚══██╔══╝██║ ██║██╔════╝████╗ ██║██╔╝╚██╗
  98. // ██║ ███████║█████╗ ██╔██╗ ██║██║ ██║
  99. // ██║ ██╔══██║██╔══╝ ██║╚██╗██║██║ ██║
  100. // ██╗██║ ██║ ██║███████╗██║ ╚████║╚██╗██╔╝
  101. // ╚═╝╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═╝╚═╝
  102. //
  103. describe('.then()', function() {
  104. describe('with proper usage', function() {
  105. var deferred; before(function(){ deferred = parley(function(done){ setTimeout(function (){ return done(undefined, 'hello!'); }, 12); }); });
  106. it('should work', function(done){
  107. deferred.then(function(result) {
  108. return done();
  109. }).catch(function(err){ return done(err); });
  110. });
  111. });
  112. describe('when called more than once', function() {
  113. var deferred; before(function(){ deferred = parley(function(done){ setTimeout(function (){ return done(undefined, 'hello!'); }, 12); }); });
  114. it('should do the normal promise chaining thing', function(done){
  115. this.slow(300);
  116. deferred.then(function (){
  117. // do nothing
  118. }).catch(function(err){ return done(err); });
  119. // The following .then() calls will all run in order.
  120. deferred.then(function (){
  121. // do nothing
  122. }).catch(function(err){ return done(err); });
  123. deferred.then(function (){
  124. // do nothing
  125. }).catch(function(err){ return done(err); });
  126. deferred.then(function (){
  127. return done();
  128. }).catch(function(err){ return done(err); });
  129. });
  130. });
  131. });//</.then()>
  132. // ██╗ ██╗ ██╗ ██████╗██╗ ██╗███████╗████████╗ ██████╗ ███╗ ███╗
  133. // ██║ ██║ ██╔╝ ██╔════╝██║ ██║██╔════╝╚══██╔══╝██╔═══██╗████╗ ████║
  134. // ██║ █╗ ██║ ██╔╝ ██║ ██║ ██║███████╗ ██║ ██║ ██║██╔████╔██║
  135. // ██║███╗██║ ██╔╝ ██║ ██║ ██║╚════██║ ██║ ██║ ██║██║╚██╔╝██║
  136. // ╚███╔███╔╝██╔╝ ╚██████╗╚██████╔╝███████║ ██║ ╚██████╔╝██║ ╚═╝ ██║
  137. // ╚══╝╚══╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
  138. //
  139. // ███╗ ███╗███████╗████████╗██╗ ██╗ ██████╗ ██████╗ ███████╗
  140. // ████╗ ████║██╔════╝╚══██╔══╝██║ ██║██╔═══██╗██╔══██╗██╔════╝
  141. // ██╔████╔██║█████╗ ██║ ███████║██║ ██║██║ ██║███████╗
  142. // ██║╚██╔╝██║██╔══╝ ██║ ██╔══██║██║ ██║██║ ██║╚════██║
  143. // ██║ ╚═╝ ██║███████╗ ██║ ██║ ██║╚██████╔╝██████╔╝███████║
  144. // ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝
  145. //
  146. describe('building and/or executing a deferred that uses one or more custom methods', function(){
  147. // ┌┐┌┌─┐┬─┐┌┬┐┌─┐┬ ┌─┐┌─┐┌─┐┌─┐
  148. // ││││ │├┬┘│││├─┤│ │ ├─┤└─┐├┤
  149. // ┘└┘└─┘┴└─┴ ┴┴ ┴┴─┘ └─┘┴ ┴└─┘└─┘
  150. describe('where everything is valid and normal', function(){
  151. it('should work', function(){
  152. var deferred = parley(function(done){
  153. setTimeout(function (){ return done(undefined, 'hello!'); }, 12);
  154. }, undefined, {
  155. foo: function (){ return deferred; }
  156. });
  157. });//</it>
  158. });//</ describe (valid & normal) >
  159. // ┌─┐┬ ┬┌─┐┌┬┐┌─┐┌┬┐ ┌┬┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ ┌┐┌┌─┐┌┬┐┌─┐
  160. // │ │ │└─┐ │ │ ││││ │││├┤ │ ├─┤│ │ ││ │││├─┤│││├┤
  161. // └─┘└─┘└─┘ ┴ └─┘┴ ┴ ┴ ┴└─┘ ┴ ┴ ┴└─┘─┴┘ ┘└┘┴ ┴┴ ┴└─┘
  162. // ╔═╗╔═╗╔╗╔╔═╗╦ ╦╔═╗╔╦╗╔═╗ ┬ ┬┬┌┬┐┬ ┬ ╦═╗╔═╗╔═╗╔═╗╦═╗╦ ╦╔═╗╔╦╗ ╔═╗╦═╗╔═╗╔═╗╔═╗╦═╗╔╦╗╦ ╦
  163. // ║ ║ ║║║║╠╣ ║ ║║ ║ ╚═╗ ││││ │ ├─┤ ╠╦╝║╣ ╚═╗║╣ ╠╦╝╚╗╔╝║╣ ║║ ╠═╝╠╦╝║ ║╠═╝║╣ ╠╦╝ ║ ╚╦╝
  164. // ╚═╝╚═╝╝╚╝╚ ╩═╝╩╚═╝ ╩ ╚═╝ └┴┘┴ ┴ ┴ ┴ ╩╚═╚═╝╚═╝╚═╝╩╚═ ╚╝ ╚═╝═╩╝ ╩ ╩╚═╚═╝╩ ╚═╝╩╚═ ╩ ╩
  165. describe('but where one or more custom methods have names which conflict with a reserved property', function(){
  166. describe('given `exec`', function(){
  167. it('should throw', function(){
  168. try {
  169. var deferred = parley(function(done){ throw new Error('Should never make it here.'); }, undefined, {
  170. foo: function (){ return deferred; },
  171. exec: function (){ return deferred; }
  172. });
  173. } catch (e) { return; }
  174. throw new Error('Should have thrown an Error');
  175. });//</it>
  176. });//</ describe >
  177. describe('given `toPromise`', function(){
  178. it('should throw', function(){
  179. try {
  180. var deferred = parley(function(done){ throw new Error('Should never make it here.'); }, undefined, {
  181. foo: function (){ return deferred; },
  182. toPromise: function (){ return deferred; }
  183. });
  184. } catch (e) { return; }
  185. throw new Error('Should have thrown an Error');
  186. });//</it>
  187. });//</ describe >
  188. describe('given `_hasBegunExecuting`', function(){
  189. it('should throw', function(){
  190. try {
  191. var deferred = parley(function(done){ throw new Error('Should never make it here.'); }, undefined, {
  192. foo: function (){ return deferred; },
  193. _hasBegunExecuting: function (){ return deferred; }
  194. });
  195. } catch (e) { return; }
  196. throw new Error('Should have thrown an Error');
  197. });//</it>
  198. });//</ describe >
  199. describe('given `constructor`', function(){
  200. it('should throw', function(){
  201. try {
  202. var deferred = parley(function(done){ throw new Error('Should never make it here.'); }, undefined, {
  203. foo: function (){ return deferred; },
  204. constructor: function (){ return deferred; }
  205. });
  206. } catch (e) { return; }
  207. throw new Error('Should have thrown an Error');
  208. });//</it>
  209. });//</ describe >
  210. describe('given `inspect`', function(){
  211. it('should throw', function(){
  212. try {
  213. var deferred = parley(function(done){ throw new Error('Should never make it here.'); }, undefined, {
  214. foo: function (){ return deferred; },
  215. inspect: function (){ return deferred; }
  216. });
  217. } catch (e) { return; }
  218. throw new Error('Should have thrown an Error');
  219. });//</it>
  220. });//</ describe >
  221. });//</ describe (custom method name conflicts w/ reserved property) >
  222. });//</ custom methods >
  223. });
  224. // // A few additional, ad hoc tests:
  225. // // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  226. // // Success condition:
  227. // // ====================
  228. // // .toPromise()
  229. // π = require('./')({ codeName: 'asdf', handleExec: function foo(done){ console.log('working...'); setTimeout(function (){ console.log('finishing...'); return done(undefined, 'hello!'); }, 1000); } }); promise = π.toPromise(); promise.then(function(result){ console.log('done!', result); }).catch(function(err){ console.error('ERROR',err); });
  230. // // .then() shortcut
  231. // π = require('./')({ codeName: 'asdf', handleExec: function foo(done){ console.log('working...'); setTimeout(function (){ console.log('finishing...'); return done(undefined, 'hello!'); }, 1000); } }); π.then(function(result){ console.log('done!', result); }).catch(function(err){ console.error('ERROR',err); });
  232. // // .exec()
  233. // π = require('./')({ codeName: 'asdf', handleExec: function foo(done){ console.log('working...'); setTimeout(function (){ console.log('finishing...'); return done(undefined, 'hello!'); }, 1000); } }); π.exec(function(err, result){ if (err){ console.error('ERROR',err, result); return; } console.log('done!', err, result); });
  234. // // Error condition:
  235. // // ====================
  236. // // .toPromise()
  237. // π = require('./')({ codeName: 'asdf', handleExec: function foo(done){ console.log('working...'); setTimeout(function (){ console.log('finishing...'); return done(new Error('uh oh'), 'should never get this!'); }, 1000); } }); promise = π.toPromise(); promise.then(function(result){ console.log('done!', result); }).catch(function(err){ console.error('ERROR',err); });
  238. // // .then() shortcut
  239. // π = require('./')({ codeName: 'asdf', handleExec: function foo(done){ console.log('working...'); setTimeout(function (){ console.log('finishing...'); return done(new Error('uh oh'), 'should never get this!'); }, 1000); } }); π.then(function(result){ console.log('done!', result); }).catch(function(err){ console.error('ERROR',err); });
  240. // // .catch() shortcut
  241. // π = require('./')({ codeName: 'asdf', handleExec: function foo(done){ console.log('working...'); setTimeout(function (){ console.log('finishing...'); return done(new Error('uh oh'), 'should never get this!'); }, 1000); } }); π.catch(function(err){ console.error('ERROR',err); });
  242. // // .exec()
  243. // π = require('./')({ codeName: 'asdf', handleExec: function foo(done){ console.log('working...'); setTimeout(function (){ console.log('finishing...'); return done(new Error('uh oh'), 'should never get this!'); }, 1000); } }); π.exec(function(err, result){ if (err){ console.error('ERROR',err, result); return; } console.log('done!', err, result); });
  244. // // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -