exec.test.js 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. /**
  2. * Module dependencies
  3. */
  4. var assert = require('assert');
  5. var Machine = require('../');
  6. // ███████╗██╗ ██╗███████╗ ██████╗ ██╗██╗
  7. // ██╔════╝╚██╗██╔╝██╔════╝██╔════╝██╔╝╚██╗
  8. // █████╗ ╚███╔╝ █████╗ ██║ ██║ ██║
  9. // ██╔══╝ ██╔██╗ ██╔══╝ ██║ ██║ ██║
  10. // ██╗███████╗██╔╝ ██╗███████╗╚██████╗╚██╗██╔╝
  11. // ╚═╝╚══════╝╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝╚═╝
  12. //
  13. describe('Machine.prototype.exec()', function (){
  14. // ██╗ ██╗██╗████████╗██╗ ██╗ █████╗ ██╗ ██╗
  15. // ██║ ██║██║╚══██╔══╝██║ ██║ ██╔══██╗██║ ██║
  16. // ██║ █╗ ██║██║ ██║ ███████║ ███████║██║ ██║
  17. // ██║███╗██║██║ ██║ ██╔══██║ ██╔══██║██║ ██║
  18. // ╚███╔███╔╝██║ ██║ ██║ ██║ ██║ ██║███████╗███████╗
  19. // ╚══╝╚══╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝
  20. //
  21. // ██████╗ ███████╗ ██████╗ ██╗ ██╗██╗██████╗ ███████╗██████╗
  22. // ██╔══██╗██╔════╝██╔═══██╗██║ ██║██║██╔══██╗██╔════╝██╔══██╗
  23. // ██████╔╝█████╗ ██║ ██║██║ ██║██║██████╔╝█████╗ ██║ ██║
  24. // ██╔══██╗██╔══╝ ██║▄▄ ██║██║ ██║██║██╔══██╗██╔══╝ ██║ ██║
  25. // ██║ ██║███████╗╚██████╔╝╚██████╔╝██║██║ ██║███████╗██████╔╝
  26. // ╚═╝ ╚═╝╚══════╝ ╚══▀▀═╝ ╚═════╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═════╝
  27. //
  28. // █████╗ ██████╗ ██████╗ ██╗███╗ ██╗███████╗
  29. // ██╔══██╗██╔══██╗██╔════╝ ██║████╗ ██║██╔════╝
  30. // ███████║██████╔╝██║ ███╗██║██╔██╗ ██║███████╗
  31. // ██╔══██║██╔══██╗██║ ██║██║██║╚██╗██║╚════██║
  32. // ██║ ██║██║ ██║╚██████╔╝██║██║ ╚████║███████║
  33. // ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═╝╚═╝ ╚═══╝╚══════╝
  34. //
  35. // ██████╗ ██████╗ ██████╗ ██╗ ██╗██╗██████╗ ███████╗██████╗
  36. // ██╔══██╗██╔══██╗██╔═══██╗██║ ██║██║██╔══██╗██╔════╝██╔══██╗
  37. // ██████╔╝██████╔╝██║ ██║██║ ██║██║██║ ██║█████╗ ██║ ██║
  38. // ██╔═══╝ ██╔══██╗██║ ██║╚██╗ ██╔╝██║██║ ██║██╔══╝ ██║ ██║
  39. // ██║ ██║ ██║╚██████╔╝ ╚████╔╝ ██║██████╔╝███████╗██████╔╝
  40. // ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═══╝ ╚═╝╚═════╝ ╚══════╝╚═════╝
  41. //
  42. describe('when all required argins are provided', function () {
  43. var NM_DEF_FIXTURE = {
  44. inputs: {
  45. foo: { example: 'wat', required: true }
  46. },
  47. fn: function (inputs, exits){
  48. throw new Error('Surprise! This one always fails.');
  49. }
  50. };
  51. describe('calling naked .exec()', function () {
  52. it('should not hang forever, go into an infinite loop, or crash the process -- instead, throw a predictable error', function (){
  53. var m = Machine.build(NM_DEF_FIXTURE);
  54. try {
  55. m({ foo: 'bar' }).exec();
  56. } catch (e) {
  57. // (Note: In past versions, this was indicated by a code of 'E_NO_ERROR_CALLBACK_CONFIGURED'.)
  58. if (e.name === 'UsageError') {
  59. return;
  60. }
  61. else { throw e; }
  62. }//</catch>
  63. });
  64. });//</describe :: calling naked .exec()>
  65. describe('calling .exec(cb)', function () {
  66. it('should trigger the callback with the appropriate error', function (done){
  67. var m = Machine.build(NM_DEF_FIXTURE);
  68. // Save a reference to the original machine instance for comparison below.
  69. var _origMachineInstance = m({ foo: 'bar' });
  70. try {
  71. _origMachineInstance.exec(function (err) {
  72. if (err) {
  73. // if (err.exit !== 'error') { return done(new Error('The error should have had a `exit` property set to `error`-- but instead, got `'+err.exit+'`. Here\'s the whole stack:\n '+err.stack)); }
  74. // ^^ Not actually guaranteed-- and not officially part of the spec. TODO: investigate this for next major version.
  75. if (!err.stack.match('Surprise! This one always fails.')) { return done(new Error('Got the wrong error! Here\'s the whole stack:\n '+err.stack)); }
  76. return done();
  77. }
  78. else { return done(new Error('There should have been an error provided to this callback!')); }
  79. });
  80. } catch (e) { return done(e); }
  81. });
  82. });//</describe :: calling .exec(cb)>
  83. describe('calling .exec(perExitCallbacks)', function () {
  84. describe('with an `error` callback provided', function () {
  85. it('should not hang forever, go into an infinite loop, or crash the process -- instead, throw a predictable UsageError', function (done){
  86. var m = Machine.build(NM_DEF_FIXTURE);
  87. // Save a reference to the original machine instance for comparison below.
  88. var _origMachineInstance = m({ foo: 'bar' });
  89. try {
  90. _origMachineInstance.exec({
  91. error: function (err) {
  92. return done(new Error('Should never have made it here'));
  93. },
  94. success: function (){
  95. return done(new Error('Should never have made it here'));
  96. }
  97. });
  98. } catch (e) {
  99. if (e.name === 'UsageError') { return done(); }
  100. return done(e);
  101. }
  102. return done(new Error('Should have thrown a UsageError'));
  103. });
  104. });//</describe :: with an `error` callback provided>
  105. describe('WITHOUT providing an `error` callback', function () {
  106. it('should not hang forever, go into an infinite loop, or crash the process -- instead, throw a predictable UsageError', function (done){
  107. var m = Machine.build(NM_DEF_FIXTURE);
  108. try {
  109. m({ foo: 'bar' }).exec({
  110. success: function (){
  111. return done(new Error('Should never have called this callback!'));
  112. }
  113. });
  114. } catch (e) {
  115. if (e.name === 'UsageError') { return done(); }
  116. return done(e);
  117. }
  118. return done(new Error('Should have thrown a UsageError'));
  119. });
  120. });//</describe :: WITHOUT providing an `error` callback>
  121. });//</describe :: calling .exec(perExitCallbacks)>
  122. describe('calling .switch(perExitCallbacks)', function () {
  123. describe('with an `error` callback provided', function () {
  124. it('should trigger the `error` callback', function (done){
  125. var m = Machine.build(NM_DEF_FIXTURE);
  126. // Save a reference to the original machine instance for comparison below.
  127. var _origMachineInstance = m({ foo: 'bar' });
  128. try {
  129. _origMachineInstance.switch({
  130. error: function (err) {
  131. if (err) {
  132. // if (err.exit !== 'error') { return done(new Error('The error should have had a `exit` property set to `error`. Here\'s the whole stack:\n '+err.stack)); }
  133. // ^^ Not actually guaranteed-- and not officially part of the spec. TODO: investigate this for next major version.
  134. if (!err.stack.match('Surprise! This one always fails.')) { return done(new Error('Got the wrong error! Here\'s the whole stack:\n '+err.stack)); }
  135. return done();
  136. }
  137. else { return done(new Error('There should have been an error provided to this callback!')); }
  138. },
  139. success: function (){
  140. return done(new Error('Should have called the `error` callback-- not this one!'));
  141. }
  142. });
  143. } catch (e) { return done(e); }
  144. });
  145. });//</describe :: with an `error` callback provided>
  146. describe('WITHOUT providing an `error` callback', function () {
  147. it('should not hang forever, go into an infinite loop, or crash the process -- instead, throw a predictable error', function (done){
  148. var m = Machine.build(NM_DEF_FIXTURE);
  149. try {
  150. m({ foo: 'bar' }).switch({
  151. success: function (){
  152. return done(new Error('Should never have called this callback!'));
  153. }
  154. });
  155. } catch (e) {
  156. // (Note: In past versions, this was indicated by a code of 'E_NO_ERROR_CALLBACK_CONFIGURED'.)
  157. if (e.name === 'UsageError') {
  158. return done();
  159. }
  160. else { return done(e); }
  161. }//</catch>
  162. });
  163. });//</describe :: WITHOUT providing an `error` callback>
  164. });//</describe :: calling .switch(perExitCallbacks)>
  165. });//</describe :: when all required argins are provided>
  166. // ██╗ ██╗██╗████████╗██╗ ██╗
  167. // ██║ ██║██║╚══██╔══╝██║ ██║
  168. // ██║ █╗ ██║██║ ██║ ███████║
  169. // ██║███╗██║██║ ██║ ██╔══██║
  170. // ╚███╔███╔╝██║ ██║ ██║ ██║
  171. // ╚══╝╚══╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
  172. //
  173. // ██████╗ ███████╗ ██████╗ ██╗ ██╗██╗██████╗ ███████╗██████╗
  174. // ██╔══██╗██╔════╝██╔═══██╗██║ ██║██║██╔══██╗██╔════╝██╔══██╗
  175. // ██████╔╝█████╗ ██║ ██║██║ ██║██║██████╔╝█████╗ ██║ ██║
  176. // ██╔══██╗██╔══╝ ██║▄▄ ██║██║ ██║██║██╔══██╗██╔══╝ ██║ ██║
  177. // ██║ ██║███████╗╚██████╔╝╚██████╔╝██║██║ ██║███████╗██████╔╝
  178. // ╚═╝ ╚═╝╚══════╝ ╚══▀▀═╝ ╚═════╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═════╝
  179. //
  180. // █████╗ ██████╗ ██████╗ ██╗███╗ ██╗███████╗
  181. // ██╔══██╗██╔══██╗██╔════╝ ██║████╗ ██║██╔════╝
  182. // ███████║██████╔╝██║ ███╗██║██╔██╗ ██║███████╗
  183. // ██╔══██║██╔══██╗██║ ██║██║██║╚██╗██║╚════██║
  184. // ██║ ██║██║ ██║╚██████╔╝██║██║ ╚████║███████║
  185. // ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═╝╚═╝ ╚═══╝╚══════╝
  186. //
  187. // ██████╗ ███╗ ███╗██╗████████╗████████╗███████╗██████╗
  188. // ██╔═══██╗████╗ ████║██║╚══██╔══╝╚══██╔══╝██╔════╝██╔══██╗
  189. // ██║ ██║██╔████╔██║██║ ██║ ██║ █████╗ ██║ ██║
  190. // ██║ ██║██║╚██╔╝██║██║ ██║ ██║ ██╔══╝ ██║ ██║
  191. // ╚██████╔╝██║ ╚═╝ ██║██║ ██║ ██║ ███████╗██████╔╝
  192. // ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═════╝
  193. //
  194. describe('when argins are omitted for 1 or more required inputs', function () {
  195. var NM_DEF_FIXTURE = {
  196. inputs: {
  197. foo: { example: 'wat', required: true }
  198. },
  199. fn: function (inputs, exits){ return exits.success(); }
  200. };
  201. describe('calling naked .exec()', function () {
  202. it('should not hang forever, go into an infinite loop, or crash the process -- instead, throw a predictable error', function (){
  203. var m = Machine.build(NM_DEF_FIXTURE);
  204. try {
  205. m().exec();
  206. } catch (e) {
  207. // (Note: In past versions, this was indicated by a code of 'E_NO_ERROR_CALLBACK_CONFIGURED'.)
  208. if (e.name === 'UsageError') {
  209. return;
  210. }
  211. else { throw e; }
  212. }//</catch>
  213. });
  214. });//</describe :: calling naked .exec()>
  215. describe('calling .exec(cb)', function () {
  216. it('should trigger the callback with the appropriate error', function (done){
  217. var m = Machine.build(NM_DEF_FIXTURE);
  218. // Save a reference to the original machine instance for comparison below.
  219. var _origMachineInstance = m();
  220. try {
  221. _origMachineInstance.exec(function (err) {
  222. if (err) {
  223. if (err.code === 'E_INVALID_ARGINS') {
  224. if (err.machineInstance !== _origMachineInstance) { return done(new Error('The `E_INVALID_ARGINS` error should have had a `machineInstance` property which is the same reference as the original machine instance-- but instead, got: '+util.inspect(err.machineInstance, {depth: null}))); }
  225. else { return done(); }
  226. }
  227. else { return done(new Error('Error should have had `code: \'E_INVALID_ARGINS\', but instead, got: `'+err.code+'`. Here is the stack:'+err.stack)); }
  228. }
  229. else { return done(new Error('There should have been a validation error provided to this callback!')); }
  230. });
  231. } catch (e) { return done(e); }
  232. });
  233. });//</describe :: calling .exec(cb)>
  234. describe('calling .exec(perExitCallbacks)', function () {
  235. describe('with an `error` callback provided', function () {
  236. it('should trigger the `error` callback', function (done){
  237. var m = Machine.build(NM_DEF_FIXTURE);
  238. // Save a reference to the original machine instance for comparison below.
  239. var _origMachineInstance = m();
  240. try {
  241. _origMachineInstance.exec({
  242. error: function (err) {
  243. if (err) {
  244. if (err.code === 'E_INVALID_ARGINS') {
  245. if (err.machineInstance !== _origMachineInstance) { return done(new Error('The `E_INVALID_ARGINS` error should have had a `machineInstance` property which is the same reference as the original machine instance-- but instead, got: '+util.inspect(err.machineInstance, {depth: null}))); }
  246. else { return done(); }
  247. }
  248. else { return done(new Error('Error should have had `code: \'E_INVALID_ARGINS\', but instead, got: `'+err.code+'`. Here is the stack:'+err.stack)); }
  249. }
  250. else { return done(new Error('There should have been a validation error provided to this callback!')); }
  251. },
  252. success: function (){
  253. return done(new Error('Should have called the `error` callback-- not this one!'));
  254. }
  255. });
  256. } catch (e) { return done(e); }
  257. });
  258. });//</describe :: with an `error` callback provided>
  259. describe('WITHOUT providing an `error` callback', function () {
  260. it('should not hang forever, go into an infinite loop, or crash the process -- instead, throw a predictable error', function (done){
  261. var m = Machine.build(NM_DEF_FIXTURE);
  262. try {
  263. m().exec({
  264. success: function (){
  265. return done(new Error('Should never have called this callback!'));
  266. }
  267. });
  268. } catch (e) {
  269. // (Note: In past versions, this was indicated by a code of 'E_NO_ERROR_CALLBACK_CONFIGURED'.)
  270. if (e.name === 'UsageError') {
  271. return done();
  272. }
  273. else { return done(e); }
  274. }//</catch>
  275. });
  276. });//</describe :: WITHOUT providing an `error` callback>
  277. });//</describe :: calling .exec(perExitCallbacks)>
  278. });//</describe :: when argins are omitted for 1 or more required inputs>
  279. // ██╗ ██╗██╗████████╗██╗ ██╗ ███████╗███╗ ███╗██████╗ ████████╗██╗ ██╗
  280. // ██║ ██║██║╚══██╔══╝██║ ██║ ██╔════╝████╗ ████║██╔══██╗╚══██╔══╝╚██╗ ██╔╝
  281. // ██║ █╗ ██║██║ ██║ ███████║ █████╗ ██╔████╔██║██████╔╝ ██║ ╚████╔╝
  282. // ██║███╗██║██║ ██║ ██╔══██║ ██╔══╝ ██║╚██╔╝██║██╔═══╝ ██║ ╚██╔╝
  283. // ╚███╔███╔╝██║ ██║ ██║ ██║ ███████╗██║ ╚═╝ ██║██║ ██║ ██║
  284. // ╚══╝╚══╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝
  285. //
  286. // ███████╗████████╗██████╗ ██╗███╗ ██╗ ██████╗ ███████╗ ██████╗ ██████╗
  287. // ██╔════╝╚══██╔══╝██╔══██╗██║████╗ ██║██╔════╝ ██╔════╝██╔═══██╗██╔══██╗
  288. // ███████╗ ██║ ██████╔╝██║██╔██╗ ██║██║ ███╗ █████╗ ██║ ██║██████╔╝
  289. // ╚════██║ ██║ ██╔══██╗██║██║╚██╗██║██║ ██║ ██╔══╝ ██║ ██║██╔══██╗
  290. // ███████║ ██║ ██║ ██║██║██║ ╚████║╚██████╔╝ ██║ ╚██████╔╝██║ ██║
  291. // ╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
  292. //
  293. // ██████╗ ███████╗ ██████╗ ██╗ ██╗██╗██████╗ ███████╗██████╗
  294. // ██╔══██╗██╔════╝██╔═══██╗██║ ██║██║██╔══██╗██╔════╝██╔══██╗
  295. // ██████╔╝█████╗ ██║ ██║██║ ██║██║██████╔╝█████╗ ██║ ██║
  296. // ██╔══██╗██╔══╝ ██║▄▄ ██║██║ ██║██║██╔══██╗██╔══╝ ██║ ██║
  297. // ██║ ██║███████╗╚██████╔╝╚██████╔╝██║██║ ██║███████╗██████╔╝
  298. // ╚═╝ ╚═╝╚══════╝ ╚══▀▀═╝ ╚═════╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═════╝
  299. //
  300. // ███████╗████████╗██████╗ ██╗███╗ ██╗ ██████╗ ██╗███╗ ██╗██████╗ ██╗ ██╗████████╗
  301. // ██╔════╝╚══██╔══╝██╔══██╗██║████╗ ██║██╔════╝ ██║████╗ ██║██╔══██╗██║ ██║╚══██╔══╝
  302. // ███████╗ ██║ ██████╔╝██║██╔██╗ ██║██║ ███╗ ██║██╔██╗ ██║██████╔╝██║ ██║ ██║
  303. // ╚════██║ ██║ ██╔══██╗██║██║╚██╗██║██║ ██║ ██║██║╚██╗██║██╔═══╝ ██║ ██║ ██║
  304. // ███████║ ██║ ██║ ██║██║██║ ╚████║╚██████╔╝ ██║██║ ╚████║██║ ╚██████╔╝ ██║
  305. // ╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═════╝ ╚═╝
  306. //
  307. describe('when empty string is provided for a required string input', function () {
  308. var NM_DEF_FIXTURE = {
  309. inputs: {
  310. foo: { example: 'wat', required: true }
  311. },
  312. fn: function (inputs, exits){ return exits.success(); }
  313. };
  314. describe('calling naked .exec()', function () {
  315. it('should not hang forever, go into an infinite loop, or crash the process -- instead, throw a predictable error', function (){
  316. var m = Machine.build(NM_DEF_FIXTURE);
  317. try {
  318. m({foo: ''}).exec();
  319. } catch (e) {
  320. // (Note: In past versions, this was indicated by a code of 'E_NO_ERROR_CALLBACK_CONFIGURED'.)
  321. if (e.name === 'UsageError') {
  322. return;
  323. }
  324. else { throw e; }
  325. }//</catch>
  326. });
  327. });//</describe :: calling naked .exec()>
  328. describe('calling .exec(cb)', function () {
  329. it('should trigger the callback with the appropriate error', function (done){
  330. var m = Machine.build(NM_DEF_FIXTURE);
  331. // Save a reference to the original machine instance for comparison below.
  332. var _origMachineInstance = m({foo: ''});
  333. try {
  334. _origMachineInstance.exec(function (err) {
  335. if (err) {
  336. if (err.code === 'E_INVALID_ARGINS') {
  337. if (err.machineInstance !== _origMachineInstance) { return done(new Error('The `E_INVALID_ARGINS` error should have had a `machineInstance` property which is the same reference as the original machine instance-- but instead, got: '+util.inspect(err.machineInstance, {depth: null}))); }
  338. else { return done(); }
  339. }
  340. else { return done(new Error('Error should have had `code: \'E_INVALID_ARGINS\', but instead, got: `'+err.code+'`. Here is the stack:'+err.stack)); }
  341. }
  342. else { return done(new Error('There should have been a validation error provided to this callback!')); }
  343. });
  344. } catch (e) { return done(e); }
  345. });
  346. });//</describe :: calling .exec(cb)>
  347. describe('calling .exec(perExitCallbacks)', function () {
  348. describe('with an `error` callback provided', function () {
  349. it('should trigger the `error` callback', function (done){
  350. var m = Machine.build(NM_DEF_FIXTURE);
  351. // Save a reference to the original machine instance for comparison below.
  352. var _origMachineInstance = m({foo: ''});
  353. try {
  354. _origMachineInstance.exec({
  355. error: function (err) {
  356. if (err) {
  357. if (err.code === 'E_INVALID_ARGINS') {
  358. if (err.machineInstance !== _origMachineInstance) { return done(new Error('The `E_INVALID_ARGINS` error should have had a `machineInstance` property which is the same reference as the original machine instance-- but instead, got: '+util.inspect(err.machineInstance, {depth: null}))); }
  359. else { return done(); }
  360. }
  361. else { return done(new Error('Error should have had `code: \'E_INVALID_ARGINS\', but instead, got: `'+err.code+'`. Here is the stack:'+err.stack)); }
  362. }
  363. else { return done(new Error('There should have been a validation error provided to this callback!')); }
  364. },
  365. success: function (){
  366. return done(new Error('Should have called the `error` callback-- not this one!'));
  367. }
  368. });
  369. } catch (e) { return done(e); }
  370. });
  371. });//</describe :: with an `error` callback provided>
  372. describe('WITHOUT providing an `error` callback', function () {
  373. it('should not hang forever, go into an infinite loop, or crash the process -- instead, throw a predictable error', function (done){
  374. var m = Machine.build(NM_DEF_FIXTURE);
  375. try {
  376. m({foo: ''}).exec({
  377. success: function (){
  378. return done(new Error('Should never have called this callback!'));
  379. }
  380. });
  381. } catch (e) {
  382. // (Note: In past versions, this was indicated by a code of 'E_NO_ERROR_CALLBACK_CONFIGURED'.)
  383. if (e.name === 'UsageError') {
  384. return done();
  385. }
  386. else { return done(e); }
  387. }//</catch>
  388. });
  389. });//</describe :: WITHOUT providing an `error` callback>
  390. });//</describe :: calling .exec(perExitCallbacks)>
  391. });//</describe :: when argins are omitted for 1 or more required inputs>
  392. // ███╗ ██╗██╗ ██╗██╗ ██╗ ██╗ ██╗ █████╗ ██╗ ██╗ ██╗███████╗███████╗
  393. // ████╗ ██║██║ ██║██║ ██║ ██║ ██║██╔══██╗██║ ██║ ██║██╔════╝██╔════╝
  394. // ██╔██╗ ██║██║ ██║██║ ██║ ██║ ██║███████║██║ ██║ ██║█████╗ ███████╗
  395. // ██║╚██╗██║██║ ██║██║ ██║ ╚██╗ ██╔╝██╔══██║██║ ██║ ██║██╔══╝ ╚════██║
  396. // ██║ ╚████║╚██████╔╝███████╗███████╗ ╚████╔╝ ██║ ██║███████╗╚██████╔╝███████╗███████║
  397. // ╚═╝ ╚═══╝ ╚═════╝ ╚══════╝╚══════╝ ╚═══╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚══════╝╚══════╝
  398. //
  399. // ██╗███╗ ██╗ ██╗███╗ ██╗██████╗ ██╗ ██╗████████╗███████╗
  400. // ██║████╗ ██║ ██║████╗ ██║██╔══██╗██║ ██║╚══██╔══╝██╔════╝
  401. // ██║██╔██╗ ██║ ██║██╔██╗ ██║██████╔╝██║ ██║ ██║ ███████╗
  402. // ██║██║╚██╗██║ ██║██║╚██╗██║██╔═══╝ ██║ ██║ ██║ ╚════██║
  403. // ██║██║ ╚████║ ██║██║ ╚████║██║ ╚██████╔╝ ██║ ███████║
  404. // ╚═╝╚═╝ ╚═══╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═════╝ ╚═╝ ╚══════╝
  405. //
  406. // ██╗ ██╗██╗████████╗██╗ ██╗
  407. // ██║ ██║██║╚══██╔══╝██║ ██║
  408. // ██║ █╗ ██║██║ ██║ ███████║
  409. // ██║███╗██║██║ ██║ ██╔══██║
  410. // ╚███╔███╔╝██║ ██║ ██║ ██║
  411. // ╚══╝╚══╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
  412. //
  413. // █████╗ ██╗ ██╗ ██████╗ ██╗ ██╗███╗ ██╗██╗ ██╗██╗ ██╗
  414. // ██╔══██╗██║ ██║ ██╔═══██╗██║ ██║████╗ ██║██║ ██║██║ ██║
  415. // ███████║██║ ██║ ██║ ██║██║ █╗ ██║██╔██╗ ██║██║ ██║██║ ██║
  416. // ██╔══██║██║ ██║ ██║ ██║██║███╗██║██║╚██╗██║██║ ██║██║ ██║
  417. // ██║ ██║███████╗███████╗╚██████╔╝╚███╔███╔╝██║ ╚████║╚██████╔╝███████╗███████╗
  418. // ╚═╝ ╚═╝╚══════╝╚══════╝ ╚═════╝ ╚══╝╚══╝ ╚═╝ ╚═══╝ ╚═════╝ ╚══════╝╚══════╝
  419. //
  420. describe('with null values in required inputs that have `allowNull: true`', function() {
  421. var NM_DEF_FIXTURE = {
  422. inputs: {
  423. str: { example: 'wat', allowNull: true },
  424. num: { example: 123, allowNull: true },
  425. bool: { example: true, allowNull: true }
  426. },
  427. fn: function (inputs, exits){ return exits.success(); }
  428. };
  429. describe('calling .exec(cb)', function () {
  430. it('should not trigger any errors', function (done){
  431. var m = Machine.build(NM_DEF_FIXTURE);
  432. m({str: null, num: null, bool: null}).exec(done);
  433. });
  434. });//</describe :: calling .exec(cb)>
  435. });
  436. // ███╗ ██╗██╗ ██╗██╗ ██╗ ██╗ ██╗ █████╗ ██╗ ██╗ ██╗███████╗
  437. // ████╗ ██║██║ ██║██║ ██║ ██║ ██║██╔══██╗██║ ██║ ██║██╔════╝
  438. // ██╔██╗ ██║██║ ██║██║ ██║ ██║ ██║███████║██║ ██║ ██║█████╗
  439. // ██║╚██╗██║██║ ██║██║ ██║ ╚██╗ ██╔╝██╔══██║██║ ██║ ██║██╔══╝
  440. // ██║ ╚████║╚██████╔╝███████╗███████╗ ╚████╔╝ ██║ ██║███████╗╚██████╔╝███████╗
  441. // ╚═╝ ╚═══╝ ╚═════╝ ╚══════╝╚══════╝ ╚═══╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚══════╝
  442. //
  443. // ██╗███╗ ██╗ ██████╗ ███████╗ ██████╗ ██╗ ██╗██╗██████╗ ███████╗██████╗
  444. // ██║████╗ ██║ ██╔══██╗██╔════╝██╔═══██╗██║ ██║██║██╔══██╗██╔════╝██╔══██╗
  445. // ██║██╔██╗ ██║ ██████╔╝█████╗ ██║ ██║██║ ██║██║██████╔╝█████╗ ██║ ██║
  446. // ██║██║╚██╗██║ ██╔══██╗██╔══╝ ██║▄▄ ██║██║ ██║██║██╔══██╗██╔══╝ ██║ ██║
  447. // ██║██║ ╚████║ ██║ ██║███████╗╚██████╔╝╚██████╔╝██║██║ ██║███████╗██████╔╝
  448. // ╚═╝╚═╝ ╚═══╝ ╚═╝ ╚═╝╚══════╝ ╚══▀▀═╝ ╚═════╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═════╝
  449. //
  450. // ██╗███████╗ ██████╗ ███╗ ██╗ ██╗███╗ ██╗██████╗ ██╗ ██╗████████╗
  451. // ██║██╔════╝██╔═══██╗████╗ ██║ ██║████╗ ██║██╔══██╗██║ ██║╚══██╔══╝
  452. // ██║███████╗██║ ██║██╔██╗ ██║ ██║██╔██╗ ██║██████╔╝██║ ██║ ██║
  453. // ██ ██║╚════██║██║ ██║██║╚██╗██║ ██║██║╚██╗██║██╔═══╝ ██║ ██║ ██║
  454. // ╚█████╔╝███████║╚██████╔╝██║ ╚████║ ██║██║ ╚████║██║ ╚██████╔╝ ██║
  455. // ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═════╝ ╚═╝
  456. //
  457. describe('with null value in required json input', function() {
  458. var NM_DEF_FIXTURE = {
  459. inputs: {
  460. foo: { example: '*', required: true }
  461. },
  462. fn: function (inputs, exits){ return exits.success(); }
  463. };
  464. describe('calling .exec(cb)', function () {
  465. it('should trigger the callback with the appropriate error', function (done){
  466. var m = Machine.build(NM_DEF_FIXTURE);
  467. // Save a reference to the original machine instance for comparison below.
  468. var _origMachineInstance = m({foo: null});
  469. try {
  470. _origMachineInstance.exec(function (err) {
  471. if (err) {
  472. if (err.code === 'E_INVALID_ARGINS') {
  473. if (err.machineInstance !== _origMachineInstance) { return done(new Error('The `E_INVALID_ARGINS` error should have had a `machineInstance` property which is the same reference as the original machine instance-- but instead, got: '+util.inspect(err.machineInstance, {depth: null}))); }
  474. else { return done(); }
  475. }
  476. else { return done(new Error('Error should have had `code: \'E_INVALID_ARGINS\', but instead, got: `'+err.code+'`. Here is the stack:'+err.stack)); }
  477. }
  478. else { return done(new Error('There should have been a validation error provided to this callback!')); }
  479. });
  480. } catch (e) { return done(e); }
  481. });
  482. });//</describe :: calling .exec(cb)>
  483. });
  484. // ███╗ ██╗██╗ ██╗██╗ ██╗ ██╗ ██╗ █████╗ ██╗ ██╗ ██╗███████╗
  485. // ████╗ ██║██║ ██║██║ ██║ ██║ ██║██╔══██╗██║ ██║ ██║██╔════╝
  486. // ██╔██╗ ██║██║ ██║██║ ██║ ██║ ██║███████║██║ ██║ ██║█████╗
  487. // ██║╚██╗██║██║ ██║██║ ██║ ╚██╗ ██╔╝██╔══██║██║ ██║ ██║██╔══╝
  488. // ██║ ╚████║╚██████╔╝███████╗███████╗ ╚████╔╝ ██║ ██║███████╗╚██████╔╝███████╗
  489. // ╚═╝ ╚═══╝ ╚═════╝ ╚══════╝╚══════╝ ╚═══╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚══════╝
  490. //
  491. // ██╗███╗ ██╗ ██████╗ ███████╗ ██████╗ ██╗ ██╗██╗██████╗ ███████╗██████╗
  492. // ██║████╗ ██║ ██╔══██╗██╔════╝██╔═══██╗██║ ██║██║██╔══██╗██╔════╝██╔══██╗
  493. // ██║██╔██╗ ██║ ██████╔╝█████╗ ██║ ██║██║ ██║██║██████╔╝█████╗ ██║ ██║
  494. // ██║██║╚██╗██║ ██╔══██╗██╔══╝ ██║▄▄ ██║██║ ██║██║██╔══██╗██╔══╝ ██║ ██║
  495. // ██║██║ ╚████║ ██║ ██║███████╗╚██████╔╝╚██████╔╝██║██║ ██║███████╗██████╔╝
  496. // ╚═╝╚═╝ ╚═══╝ ╚═╝ ╚═╝╚══════╝ ╚══▀▀═╝ ╚═════╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═════╝
  497. //
  498. // ██████╗ ███████╗███████╗ ██╗███╗ ██╗██████╗ ██╗ ██╗████████╗
  499. // ██╔══██╗██╔════╝██╔════╝ ██║████╗ ██║██╔══██╗██║ ██║╚══██╔══╝
  500. // ██████╔╝█████╗ █████╗ ██║██╔██╗ ██║██████╔╝██║ ██║ ██║
  501. // ██╔══██╗██╔══╝ ██╔══╝ ██║██║╚██╗██║██╔═══╝ ██║ ██║ ██║
  502. // ██║ ██║███████╗██║ ██║██║ ╚████║██║ ╚██████╔╝ ██║
  503. // ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═════╝ ╚═╝
  504. //
  505. describe('with null value in required ref input', function() {
  506. var NM_DEF_FIXTURE = {
  507. inputs: {
  508. foo: { example: '===', required: true }
  509. },
  510. fn: function (inputs, exits){ return exits.success(); }
  511. };
  512. describe('calling .exec(cb)', function () {
  513. it('should trigger the callback with the appropriate error', function (done){
  514. var m = Machine.build(NM_DEF_FIXTURE);
  515. // Save a reference to the original machine instance for comparison below.
  516. var _origMachineInstance = m({foo: null});
  517. try {
  518. _origMachineInstance.exec(function (err) {
  519. if (err) {
  520. if (err.code === 'E_INVALID_ARGINS') {
  521. if (err.machineInstance !== _origMachineInstance) { return done(new Error('The `E_INVALID_ARGINS` error should have had a `machineInstance` property which is the same reference as the original machine instance-- but instead, got: '+util.inspect(err.machineInstance, {depth: null}))); }
  522. else { return done(); }
  523. }
  524. else { return done(new Error('Error should have had `code: \'E_INVALID_ARGINS\', but instead, got: `'+err.code+'`. Here is the stack:'+err.stack)); }
  525. }
  526. else { return done(new Error('There should have been a validation error provided to this callback!')); }
  527. });
  528. } catch (e) { return done(e); }
  529. });
  530. });//</describe :: calling .exec(cb)>
  531. });
  532. });//</describe :: Machine.prototype.exec()>