HookTester.js 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. require("babel-polyfill");
  7. describe("HookTester", () => {
  8. it("should run", () => {});
  9. });
  10. process.on("unhandledRejection", err => console.error(err.stack));
  11. class HookTester {
  12. constructor(hookCreator, sync) {
  13. this.hookCreator = hookCreator;
  14. this.sync = sync;
  15. }
  16. async run(syncOnly) {
  17. const result = {
  18. sync: {},
  19. async: {},
  20. intercept: {}
  21. };
  22. if(syncOnly) {
  23. await this.runSync(result.sync, "call");
  24. } else {
  25. await this.runAsync(result.async, "callAsync");
  26. await this.runAsync(result.async, "promise");
  27. await this.runIntercept(result.intercept, "callAsync");
  28. await this.runIntercept(result.intercept, "promise");
  29. }
  30. await this.runSync(result.sync, "callAsync");
  31. await this.runSync(result.sync, "promise");
  32. return result;
  33. }
  34. async runForLoop(syncOnly) {
  35. const result = {
  36. sync: {},
  37. async: {}
  38. };
  39. if(syncOnly) {
  40. await this.runForLoopSync(result.sync, "call");
  41. } else {
  42. await this.runForLoopAsync(result.async, "callAsync");
  43. await this.runForLoopAsync(result.async, "promise");
  44. }
  45. await this.runForLoopSync(result.sync, "callAsync");
  46. await this.runForLoopSync(result.sync, "promise");
  47. return result;
  48. }
  49. async runForLoopAsync(result, method) {
  50. {
  51. const hook = this.createHook([], `${method}SinglePromise`);
  52. hook.tapPromise("promise", () => {
  53. result[`${method}SinglePromiseCalled`] = (result[`${method}SinglePromiseCalled`] || 0) + 1;
  54. if(result[`${method}SinglePromiseCalled`] < 42)
  55. return Promise.resolve().then(() => true);
  56. return Promise.resolve().then(() => {});
  57. });
  58. result[`${method}SinglePromise`] = await this.gainResult(cb => hook[method](cb));
  59. }
  60. {
  61. const hook = this.createHook([], `${method}MultiplePromise`);
  62. hook.tapPromise("promise1", () => {
  63. result[`${method}MultiplePromiseCalled1`] = (result[`${method}MultiplePromiseCalled1`] || 0) + 1;
  64. if(result[`${method}MultiplePromiseCalled1`] < 42)
  65. return Promise.resolve().then(() => true);
  66. return Promise.resolve().then(() => {});
  67. });
  68. hook.tapPromise("promise2", () => {
  69. result[`${method}MultiplePromiseCalled2`] = (result[`${method}MultiplePromiseCalled2`] || 0) + 1;
  70. if(result[`${method}MultiplePromiseCalled2`] < 42)
  71. return Promise.resolve().then(() => true);
  72. return Promise.resolve().then(() => {});
  73. });
  74. result[`${method}MultiplePromise`] = await this.gainResult(cb => hook[method](cb));
  75. }
  76. {
  77. const hook = this.createHook([], `${method}SingleAsync`);
  78. hook.tapAsync("async", (callback) => {
  79. result[`${method}SingleAsyncCalled`] = (result[`${method}SingleAsyncCalled`] || 0) + 1;
  80. if(result[`${method}SingleAsyncCalled`] < 42)
  81. return Promise.resolve().then(() => callback(null, true));
  82. return Promise.resolve().then(() => callback());
  83. });
  84. result[`${method}SingleAsync`] = await this.gainResult(cb => hook[method](cb));
  85. }
  86. {
  87. const hook = this.createHook([], `${method}MultipleAsync`);
  88. hook.tapAsync("async1", (callback) => {
  89. result[`${method}MultipleAsyncCalled1`] = (result[`${method}MultipleAsyncCalled1`] || 0) + 1;
  90. if(result[`${method}MultipleAsyncCalled1`] < 42)
  91. return Promise.resolve().then(() => callback(null, true));
  92. return Promise.resolve().then(() => callback());
  93. });
  94. hook.tapAsync("async2", (callback) => {
  95. result[`${method}MultipleAsyncCalled2`] = (result[`${method}MultipleAsyncCalled2`] || 0) + 1;
  96. if(result[`${method}MultipleAsyncCalled2`] < 42)
  97. return Promise.resolve().then(() => callback(null, true));
  98. return Promise.resolve().then(() => callback());
  99. });
  100. result[`${method}MultipleAsync`] = await this.gainResult(cb => hook[method](cb));
  101. }
  102. {
  103. const hook = this.createHook([], `${method}Mixed`);
  104. hook.tapAsync("async1", (callback) => {
  105. result[`${method}MixedCalled1`] = (result[`${method}MixedCalled1`] || 0) + 1;
  106. if(result[`${method}MixedCalled1`] < 42)
  107. return Promise.resolve().then(() => callback(null, true));
  108. return Promise.resolve().then(() => callback());
  109. });
  110. hook.tap("sync2", () => {
  111. result[`${method}MixedCalled2`] = (result[`${method}MixedCalled2`] || 0) + 1;
  112. if(result[`${method}MixedCalled2`] < 42)
  113. return true;
  114. });
  115. hook.tapPromise("promise3", () => {
  116. result[`${method}MixedCalled3`] = (result[`${method}MixedCalled3`] || 0) + 1;
  117. if(result[`${method}MixedCalled3`] < 42)
  118. return Promise.resolve().then(() => true);
  119. return Promise.resolve().then(() => {});
  120. });
  121. result[`${method}Mixed`] = await this.gainResult(cb => hook[method](cb));
  122. }
  123. }
  124. async runForLoopSync(result, method) {
  125. {
  126. const hook = this.createHook([], `${method}None`);
  127. result[`${method}None`] = await this.gainResult(cb => hook[method](cb));
  128. }
  129. {
  130. const hook = this.createHook(["arg"], `${method}NoneWithArg`);
  131. result[`${method}NoneWithArg`] = await this.gainResult(cb => hook[method](42, cb));
  132. }
  133. {
  134. const hook = this.createHook([], `${method}SingleSync`);
  135. hook.tap("sync", () => {
  136. result[`${method}SingleSyncCalled`] = (result[`${method}SingleSyncCalled`] || 0) + 1;
  137. if(result[`${method}SingleSyncCalled`] < 42)
  138. return true;
  139. });
  140. result[`${method}SingleSync`] = await this.gainResult(cb => hook[method](cb));
  141. }
  142. {
  143. const hook = this.createHook([], `${method}MultipleSync`);
  144. hook.tap("sync1", () => {
  145. result[`${method}MultipleSyncCalled1`] = (result[`${method}MultipleSyncCalled1`] || 0) + 1;
  146. if(result[`${method}MultipleSyncCalled1`] < 42)
  147. return true;
  148. });
  149. hook.tap("sync2", () => {
  150. result[`${method}MultipleSyncCalled2`] = (result[`${method}MultipleSyncCalled2`] || 0) + 1;
  151. if(result[`${method}MultipleSyncCalled2`] < 42)
  152. return true;
  153. });
  154. result[`${method}MultipleSync`] = await this.gainResult(cb => hook[method](cb));
  155. }
  156. {
  157. const hook = this.createHook([], `${method}InterceptedSync`);
  158. hook.tap("sync1", () => {
  159. result[`${method}InterceptedSyncCalled1`] = (result[`${method}InterceptedSyncCalled1`] || 0) + 1;
  160. if(result[`${method}InterceptedSyncCalled1`] < 42)
  161. return true;
  162. });
  163. hook.tap("sync2", () => {
  164. result[`${method}InterceptedSyncCalled2`] = (result[`${method}InterceptedSyncCalled2`] || 0) + 1;
  165. if(result[`${method}InterceptedSyncCalled2`] < 42)
  166. return true;
  167. });
  168. hook.intercept({
  169. call: (a) => result[`${method}InterceptedSyncCalledCall`] = (result[`${method}InterceptedSyncCalledCall`] || 0) + 1,
  170. loop: (a) => result[`${method}InterceptedSyncCalledLoop`] = (result[`${method}InterceptedSyncCalledLoop`] || 0) + 1,
  171. tap: (tap) => {
  172. result[`${method}InterceptedSyncCalledTap`] = (result[`${method}InterceptedSyncCalledTap`] || 0) + 1
  173. },
  174. })
  175. result[`${method}InterceptedSync`] = await this.gainResult(cb => hook[method](cb));
  176. }
  177. }
  178. async runSync(result, method) {
  179. {
  180. const hook = this.createHook([], `${method}None`);
  181. result[`${method}None`] = await this.gainResult(cb => hook[method](cb));
  182. }
  183. {
  184. const hook = this.createHook(["arg"], `${method}NoneWithArg`);
  185. result[`${method}NoneWithArg`] = await this.gainResult(cb => hook[method](42, cb));
  186. }
  187. {
  188. const hook = this.createHook([], `${method}SingleSync`);
  189. hook.tap("sync", () => {
  190. result[`${method}SingleSyncCalled`] = true;
  191. return 42;
  192. });
  193. result[`${method}SingleSync`] = await this.gainResult(cb => hook[method](cb));
  194. }
  195. {
  196. const hook = this.createHook(["myArg"], `${method}SingleSyncWithArg`);
  197. hook.tap("sync", (nr) => {
  198. result[`${method}SingleSyncWithArgCalled`] = nr;
  199. return nr;
  200. });
  201. result[`${method}SingleSyncWithArg`] = await this.gainResult(cb => hook[method](42, cb));
  202. }
  203. {
  204. const hook = this.createHook([], `${method}MultipleSync`);
  205. hook.tap("sync1", () => {
  206. result[`${method}MultipleSyncCalled1`] = true;
  207. return 42;
  208. });
  209. hook.tap("sync2", () => {
  210. result[`${method}MultipleSyncCalled2`] = true;
  211. return 43;
  212. });
  213. result[`${method}MultipleSync`] = await this.gainResult(cb => hook[method](cb));
  214. }
  215. {
  216. const hook = this.createHook(["a"], `${method}MultipleSyncWithArg`);
  217. hook.tap("sync1", (a) => {
  218. result[`${method}MultipleSyncWithArgCalled1`] = a;
  219. return 42 + a;
  220. });
  221. hook.tap("sync2", (a) => {
  222. result[`${method}MultipleSyncWithArgCalled2`] = a;
  223. return 43 + a;
  224. });
  225. result[`${method}MultipleSyncWithArg`] = await this.gainResult(cb => hook[method](42, cb));
  226. }
  227. {
  228. const hook = this.createHook(["a"], `${method}MultipleSyncWithArgNoReturn`);
  229. hook.tap("sync1", (a) => {
  230. result[`${method}MultipleSyncWithArgNoReturnCalled1`] = a;
  231. });
  232. hook.tap("sync2", (a) => {
  233. result[`${method}MultipleSyncWithArgNoReturnCalled2`] = a;
  234. });
  235. result[`${method}MultipleSyncWithArgNoReturn`] = await this.gainResult(cb => hook[method](42, cb));
  236. }
  237. {
  238. const hook = this.createHook(["a"], `${method}MultipleSyncWithArgFirstReturn`);
  239. hook.tap("sync1", (a) => {
  240. result[`${method}MultipleSyncWithArgFirstReturnCalled1`] = a;
  241. return 42 + a;
  242. });
  243. hook.tap("sync2", (a) => {
  244. result[`${method}MultipleSyncWithArgFirstReturnCalled2`] = a;
  245. });
  246. result[`${method}MultipleSyncWithArgFirstReturn`] = await this.gainResult(cb => hook[method](42, cb));
  247. }
  248. {
  249. const hook = this.createHook(["a"], `${method}MultipleSyncWithArgLastReturn`);
  250. hook.tap("sync1", (a) => {
  251. result[`${method}MultipleSyncWithArgLastReturnCalled1`] = a;
  252. });
  253. hook.tap("sync2", (a) => {
  254. result[`${method}MultipleSyncWithArgLastReturnCalled2`] = a;
  255. return 43 + a;
  256. });
  257. result[`${method}MultipleSyncWithArgLastReturn`] = await this.gainResult(cb => hook[method](42, cb));
  258. }
  259. {
  260. const hook = this.createHook(["a", "b", "c"], `${method}MultipleSyncWithArgs`);
  261. hook.tap("sync1", (a, b, c) => {
  262. result[`${method}MultipleSyncWithArgsCalled1`] = [a, b, c];
  263. return a + b + c;
  264. });
  265. hook.tap("sync2", (a, b, c) => {
  266. result[`${method}MultipleSyncWithArgsCalled2`] = [a, b, c];
  267. return a + b + c + 1;
  268. });
  269. result[`${method}MultipleSyncWithArgs`] = await this.gainResult(cb => hook[method](42, 43, 44, cb));
  270. }
  271. {
  272. const hook = this.createHook([], `${method}MultipleSyncError`);
  273. hook.tap("sync1", () => {
  274. result[`${method}MultipleSyncErrorCalled1`] = true;
  275. });
  276. hook.tap("sync2", () => {
  277. result[`${method}MultipleSyncErrorCalled2`] = true;
  278. throw new Error("Error in sync2")
  279. });
  280. hook.tap("sync3", () => {
  281. result[`${method}MultipleSyncErrorCalled3`] = true;
  282. });
  283. result[`${method}MultipleSyncError`] = await this.gainResult(cb => hook[method](cb));
  284. }
  285. {
  286. const hook = this.createHook(["a", "b", "c"], `${method}Intercepted`);
  287. hook.intercept({
  288. call: (a, b, c) => {
  289. result[`${method}InterceptedCall1`] = [a, b, c];
  290. },
  291. tap: (tap) => {
  292. result[`${method}InterceptedTap1`] = Object.assign({}, tap, { fn: tap.fn.length });
  293. }
  294. });
  295. hook.intercept({
  296. call: (a, b, c) => {
  297. result[`${method}InterceptedCall2`] = [a, b, c];
  298. },
  299. tap: (tap) => {
  300. if(!result[`${method}InterceptedTap2`])
  301. result[`${method}InterceptedTap2`] = Object.assign({}, tap, { fn: tap.fn.length });
  302. }
  303. });
  304. hook.tap("sync1", (a, b, c) => a + b + c);
  305. hook.tap("sync2", (a, b) => a + b + 1);
  306. result[`${method}Intercepted`] = await this.gainResult((cb) => hook[method](1, 2, 3, cb));
  307. }
  308. }
  309. async runAsync(result, type) {
  310. {
  311. const hook = this.createHook([], `${type}None`);
  312. result[`${type}None`] = await this.gainResult((cb) => hook[type](cb));
  313. }
  314. {
  315. const hook = this.createHook(["arg"], `${type}NoneWithArg`);
  316. result[`${type}NoneWithArg`] = await this.gainResult((cb) => hook[type](42, cb));
  317. }
  318. {
  319. const hook = this.createHook([], `${type}SingleSync`);
  320. hook.tap("sync", () => {
  321. result[`${type}SingleSyncCalled1`] = true;
  322. return 42;
  323. });
  324. result[`${type}SingleSync`] = await this.gainResult((cb) => hook[type](cb));
  325. }
  326. {
  327. const hook = this.createHook(["x"], `${type}SingleSyncWithArg`);
  328. hook.tap("sync", arg => {
  329. result[`${type}SingleSyncWithArgCalled1`] = arg;
  330. return arg + 1;
  331. });
  332. result[`${type}SingleSyncWithArg`] = await this.gainResult((cb) => hook[type](42, cb));
  333. }
  334. {
  335. const hook = this.createHook(["x"], `${type}SingleSyncWithArgNoReturn`);
  336. hook.tap("sync", arg => {
  337. result[`${type}SingleSyncWithArgNoReturnCalled1`] = arg;
  338. });
  339. result[`${type}SingleSyncWithArgNoReturn`] = await this.gainResult((cb) => hook[type](42, cb));
  340. }
  341. {
  342. const hook = this.createHook([], `${type}MultipleSync`);
  343. hook.tap("sync1", () => {
  344. result[`${type}MultipleSyncCalled1`] = true;
  345. return 42;
  346. });
  347. hook.tap("sync2", () => {
  348. result[`${type}MultipleSyncCalled2`] = true;
  349. return 43;
  350. });
  351. result[`${type}MultipleSync`] = await this.gainResult((cb) => hook[type](cb));
  352. }
  353. {
  354. const hook = this.createHook([], `${type}MultipleSyncLastReturn`);
  355. hook.tap("sync1", () => {
  356. result[`${type}MultipleSyncLastReturnCalled1`] = true;
  357. });
  358. hook.tap("sync2", () => {
  359. result[`${type}MultipleSyncLastReturnCalled2`] = true;
  360. return 43;
  361. });
  362. result[`${type}MultipleSyncLastReturn`] = await this.gainResult((cb) => hook[type](cb));
  363. }
  364. {
  365. const hook = this.createHook([], `${type}MultipleSyncNoReturn`);
  366. hook.tap("sync1", () => {
  367. result[`${type}MultipleSyncNoReturnCalled1`] = true;
  368. });
  369. hook.tap("sync2", () => {
  370. result[`${type}MultipleSyncNoReturnCalled2`] = true;
  371. });
  372. result[`${type}MultipleSyncNoReturn`] = await this.gainResult((cb) => hook[type](cb));
  373. }
  374. {
  375. const hook = this.createHook(["arg"], `${type}MultipleSyncWithArg`);
  376. hook.tap("sync1", arg => {
  377. result[`${type}MultipleSyncWithArgCalled1`] = arg;
  378. return arg + 1;
  379. });
  380. hook.tap("sync2", arg => {
  381. result[`${type}MultipleSyncWithArgCalled2`] = arg;
  382. return arg + 2;
  383. });
  384. result[`${type}MultipleSyncWithArg`] = await this.gainResult((cb) => hook[type](42, cb));
  385. }
  386. {
  387. const hook = this.createHook(["arg"], `${type}MultipleSyncWithArgNoReturn`);
  388. hook.tap("sync1", arg => {
  389. result[`${type}MultipleSyncWithArgNoReturnCalled1`] = arg;
  390. });
  391. hook.tap("sync2", arg => {
  392. result[`${type}MultipleSyncWithArgNoReturnCalled2`] = arg;
  393. });
  394. result[`${type}MultipleSyncWithArgNoReturn`] = await this.gainResult((cb) => hook[type](42, cb));
  395. }
  396. {
  397. const hook = this.createHook(["arg"], `${type}MultipleSyncWithArgLastReturn`);
  398. hook.tap("sync1", arg => {
  399. result[`${type}MultipleSyncWithArgLastReturnCalled1`] = arg;
  400. });
  401. hook.tap("sync2", arg => {
  402. result[`${type}MultipleSyncWithArgLastReturnCalled2`] = arg;
  403. return arg + 2;
  404. });
  405. result[`${type}MultipleSyncWithArgLastReturn`] = await this.gainResult((cb) => hook[type](42, cb));
  406. }
  407. {
  408. const hook = this.createHook(["arg"], `${type}MultipleSyncWithArgFirstReturn`);
  409. hook.tap("sync1", arg => {
  410. result[`${type}MultipleSyncWithArgFirstReturnCalled1`] = arg;
  411. return arg + 1;
  412. });
  413. hook.tap("sync2", arg => {
  414. result[`${type}MultipleSyncWithArgFirstReturnCalled2`] = arg;
  415. });
  416. result[`${type}MultipleSyncWithArgFirstReturn`] = await this.gainResult((cb) => hook[type](42, cb));
  417. }
  418. {
  419. const hook = this.createHook(["x"], `${type}SingleAsyncWithArg`);
  420. hook.tapAsync("async", (arg, callback) => {
  421. result[`${type}SingleAsyncWithArgCalled1`] = arg;
  422. callback(null, arg);
  423. });
  424. result[`${type}SingleAsyncWithArg`] = await this.gainResult((cb) => hook[type](42, cb));
  425. }
  426. {
  427. const hook = this.createHook(["x"], `${type}MultipleAsyncWithArg`);
  428. hook.tapAsync("async1", (arg, callback) => {
  429. result[`${type}MultipleAsyncWithArgCalled1`] = arg;
  430. callback(null, arg + 1);
  431. });
  432. hook.tapAsync("async2", (arg, callback) => {
  433. result[`${type}MultipleAsyncWithArgCalled2`] = arg;
  434. callback(null, arg + 2);
  435. });
  436. result[`${type}MultipleAsyncWithArg`] = await this.gainResult((cb) => hook[type](42, cb));
  437. }
  438. {
  439. const hook = this.createHook(["x"], `${type}MultipleAsyncWithArgNoReturn`);
  440. hook.tapAsync("async1", (arg, callback) => {
  441. result[`${type}MultipleAsyncWithArgNoReturnCalled1`] = arg;
  442. callback();
  443. });
  444. hook.tapAsync("async2", (arg, callback) => {
  445. result[`${type}MultipleAsyncWithArgNoReturnCalled2`] = arg;
  446. callback();
  447. });
  448. result[`${type}MultipleAsyncWithArgNoReturn`] = await this.gainResult((cb) => hook[type](42, cb));
  449. }
  450. {
  451. const hook = this.createHook(["x"], `${type}MultipleAsyncWithArgFirstReturn`);
  452. hook.tapAsync("async1", (arg, callback) => {
  453. result[`${type}MultipleAsyncWithArgFirstReturnCalled1`] = arg;
  454. callback(null, arg + 1);
  455. });
  456. hook.tapAsync("async2", (arg, callback) => {
  457. result[`${type}MultipleAsyncWithArgFirstReturnCalled2`] = arg;
  458. callback();
  459. });
  460. result[`${type}MultipleAsyncWithArgFirstReturn`] = await this.gainResult((cb) => hook[type](42, cb));
  461. }
  462. {
  463. const hook = this.createHook(["x"], `${type}MultipleAsyncWithArgLastReturn`);
  464. hook.tapAsync("async1", (arg, callback) => {
  465. result[`${type}MultipleAsyncWithArgLastReturnCalled1`] = arg;
  466. callback();
  467. });
  468. hook.tapAsync("async2", (arg, callback) => {
  469. result[`${type}MultipleAsyncWithArgLastReturnCalled2`] = arg;
  470. callback(null, arg + 2);
  471. });
  472. result[`${type}MultipleAsyncWithArgLastReturn`] = await this.gainResult((cb) => hook[type](42, cb));
  473. }
  474. {
  475. const hook = this.createHook(["x"], `${type}SinglePromiseWithArg`);
  476. hook.tapPromise("promise", arg => {
  477. result[`${type}SinglePromiseWithArgCalled1`] = arg;
  478. return Promise.resolve(arg + 1);
  479. });
  480. result[`${type}SinglePromiseWithArg`] = await this.gainResult((cb) => hook[type](42, cb));
  481. }
  482. {
  483. const hook = this.createHook(["x"], `${type}MultiplePromiseWithArg`);
  484. hook.tapPromise("promise1", arg => {
  485. result[`${type}MultiplePromiseWithArgCalled1`] = arg;
  486. return Promise.resolve(arg + 1);
  487. });
  488. hook.tapPromise("promise2", arg => {
  489. result[`${type}MultiplePromiseWithArgCalled2`] = arg;
  490. return Promise.resolve(arg + 2);
  491. });
  492. result[`${type}MultiplePromiseWithArg`] = await this.gainResult((cb) => hook[type](42, cb));
  493. }
  494. {
  495. const hook = this.createHook(["x"], `${type}MultiplePromiseWithArgNoReturn`);
  496. hook.tapPromise("promise1", arg => {
  497. result[`${type}MultiplePromiseWithArgNoReturnCalled1`] = arg;
  498. return Promise.resolve();
  499. });
  500. hook.tapPromise("promise2", arg => {
  501. result[`${type}MultiplePromiseWithArgNoReturnCalled2`] = arg;
  502. return Promise.resolve();
  503. });
  504. result[`${type}MultiplePromiseWithArgNoReturn`] = await this.gainResult((cb) => hook[type](42, cb));
  505. }
  506. {
  507. const hook = this.createHook(["x"], `${type}MultiplePromiseWithArgFirstReturn`);
  508. hook.tapPromise("promise1", arg => {
  509. result[`${type}MultiplePromiseWithArgFirstReturnCalled1`] = arg;
  510. return Promise.resolve(arg + 1);
  511. });
  512. hook.tapPromise("promise2", arg => {
  513. result[`${type}MultiplePromiseWithArgFirstReturnCalled2`] = arg;
  514. return Promise.resolve();
  515. });
  516. result[`${type}MultiplePromiseWithArgFirstReturn`] = await this.gainResult((cb) => hook[type](42, cb));
  517. }
  518. {
  519. const hook = this.createHook(["x"], `${type}MultiplePromiseWithArgLastReturn`);
  520. hook.tapPromise("promise1", arg => {
  521. result[`${type}MultiplePromiseWithArgLastReturnCalled1`] = arg;
  522. return Promise.resolve();
  523. });
  524. hook.tapPromise("promise2", arg => {
  525. result[`${type}MultiplePromiseWithArgLastReturnCalled2`] = arg;
  526. return Promise.resolve(arg + 2);
  527. });
  528. result[`${type}MultiplePromiseWithArgLastReturn`] = await this.gainResult((cb) => hook[type](42, cb));
  529. }
  530. {
  531. const hook = this.createHook(["x"], `${type}MultipleMixed1WithArg`);
  532. hook.tapAsync("async", (arg, callback) => {
  533. result[`${type}MultipleMixed1WithArgCalled1`] = arg;
  534. callback(null, arg + 1);
  535. });
  536. hook.tapPromise("promise", arg => {
  537. result[`${type}MultipleMixed1WithArgCalled2`] = arg;
  538. return Promise.resolve(arg + 2);
  539. });
  540. hook.tap("sync", arg => {
  541. result[`${type}MultipleMixed1WithArgCalled3`] = arg;
  542. return arg + 3;
  543. });
  544. result[`${type}MultipleMixed1WithArg`] = await this.gainResult((cb) => hook[type](42, cb));
  545. }
  546. {
  547. const hook = this.createHook(["x"], `${type}MultipleMixed2WithArg`);
  548. hook.tapAsync("async", (arg, callback) => {
  549. result[`${type}MultipleMixed2WithArgCalled1`] = arg;
  550. setTimeout(() => callback(null, arg + 1), 100);
  551. });
  552. hook.tapPromise("promise", arg => {
  553. result[`${type}MultipleMixed2WithArgCalled2`] = arg;
  554. return Promise.resolve(arg + 2);
  555. });
  556. result[`${type}MultipleMixed2WithArg`] = await this.gainResult((cb) => hook[type](42, cb));
  557. }
  558. {
  559. const hook = this.createHook(["x"], `${type}MultipleMixed3WithArg`);
  560. hook.tapAsync("async1", (arg, callback) => {
  561. result[`${type}MultipleMixed3WithArgCalled1`] = arg;
  562. callback(null, arg + 1);
  563. });
  564. hook.tapPromise("promise", arg => {
  565. result[`${type}MultipleMixed3WithArgCalled2`] = arg;
  566. return Promise.resolve(arg + 2);
  567. });
  568. hook.tapAsync("async2", (arg, callback) => {
  569. result[`${type}MultipleMixed3WithArgCalled3`] = arg;
  570. setTimeout(() => callback(null, arg + 3), 100);
  571. });
  572. result[`${type}MultipleMixed3WithArg`] = await this.gainResult((cb) => hook[type](42, cb));
  573. }
  574. {
  575. const hook = this.createHook([], `${type}MultipleSyncError`);
  576. hook.tap("sync1", () => {
  577. result[`${type}MultipleSyncErrorCalled1`] = true;
  578. });
  579. hook.tap("sync2", () => {
  580. throw new Error("Error in sync2")
  581. });
  582. hook.tap("sync3", () => {
  583. result[`${type}MultipleSyncErrorCalled3`] = true;
  584. });
  585. result[`${type}MultipleSyncError`] = await this.gainResult((cb) => hook[type](cb));
  586. }
  587. {
  588. const hook = this.createHook([], `${type}MultipleAsyncError`);
  589. hook.tapAsync("async1", (callback) => {
  590. result[`${type}MultipleAsyncErrorCalled1`] = true;
  591. callback();
  592. });
  593. hook.tapAsync("async2", (callback) => {
  594. callback(new Error("Error in async2"));
  595. });
  596. hook.tapAsync("async3", (callback) => {
  597. result[`${type}MultipleAsyncErrorCalled3`] = true;
  598. callback();
  599. });
  600. result[`${type}MultipleAsyncError`] = await this.gainResult((cb) => hook[type](cb));
  601. }
  602. {
  603. const hook = this.createHook([], `${type}MultipleAsyncLateError`);
  604. hook.tapAsync("async1", (callback) => {
  605. result[`${type}MultipleAsyncLateErrorCalled1`] = true;
  606. callback();
  607. });
  608. hook.tapAsync("async2", (callback) => {
  609. setTimeout(() => callback(new Error("Error in async2")), 100);
  610. });
  611. hook.tapAsync("async3", (callback) => {
  612. result[`${type}MultipleAsyncLateErrorCalled3`] = true;
  613. callback();
  614. });
  615. result[`${type}MultipleAsyncLateError`] = await this.gainResult((cb) => hook[type](cb));
  616. }
  617. {
  618. const hook = this.createHook([], `${type}MultipleAsyncLateErrorEarlyResult1`);
  619. hook.tapAsync("async1", (callback) => {
  620. result[`${type}MultipleAsyncLateErrorEarlyResult1Called1`] = true;
  621. callback();
  622. });
  623. hook.tapAsync("async2", (callback) => {
  624. setTimeout(() => callback(new Error("Error in async2")), 100);
  625. });
  626. hook.tapAsync("async3", (callback) => {
  627. result[`${type}MultipleAsyncLateErrorEarlyResult1Called3`] = true;
  628. callback(null, 7);
  629. });
  630. result[`${type}MultipleAsyncLateErrorEarlyResult1`] = await this.gainResult((cb) => hook[type](cb));
  631. }
  632. {
  633. const hook = this.createHook([], `${type}MultipleAsyncLateErrorEarlyResult2`);
  634. hook.tapAsync("async1", (callback) => {
  635. result[`${type}MultipleAsyncLateErrorEarlyResult2Called1`] = true;
  636. setTimeout(() => callback(null, 42), 200);
  637. });
  638. hook.tapAsync("async2", (callback) => {
  639. setTimeout(() => callback(new Error("Error in async2")), 100);
  640. });
  641. hook.tapAsync("async3", (callback) => {
  642. result[`${type}MultipleAsyncLateErrorEarlyResult2Called3`] = true;
  643. callback(null, 7);
  644. });
  645. result[`${type}MultipleAsyncLateErrorEarlyResult2`] = await this.gainResult((cb) => hook[type](cb));
  646. }
  647. {
  648. const hook = this.createHook([], `${type}MultipleAsyncEarlyError`);
  649. hook.tapAsync("async1", (callback) => {
  650. result[`${type}MultipleAsyncEarlyErrorCalled1`] = true;
  651. setTimeout(() => callback(), 100);
  652. });
  653. hook.tapAsync("async2", (callback) => {
  654. callback(new Error("Error in async2"));
  655. });
  656. hook.tapAsync("async3", (callback) => {
  657. result[`${type}MultipleAsyncEarlyErrorCalled3`] = true;
  658. setTimeout(() => callback(), 100);
  659. });
  660. result[`${type}MultipleAsyncEarlyError`] = await this.gainResult((cb) => hook[type](cb));
  661. }
  662. {
  663. const hook = this.createHook([], `${type}MultiplePromiseError`);
  664. hook.tapPromise("promise1", () => {
  665. result[`${type}MultiplePromiseErrorCalled1`] = true;
  666. return Promise.resolve();
  667. });
  668. hook.tapPromise("promise2", () => {
  669. return Promise.resolve().then(() => { throw new Error("Error in async2"); });
  670. });
  671. hook.tapPromise("promise3", () => {
  672. result[`${type}MultiplePromiseErrorCalled3`] = true;
  673. return Promise.resolve();
  674. });
  675. result[`${type}MultiplePromiseError`] = await this.gainResult((cb) => hook[type](cb));
  676. }
  677. {
  678. const hook = this.createHook([], `${type}MultiplePromiseLateError`);
  679. hook.tapPromise("promise1", () => {
  680. result[`${type}MultiplePromiseLateErrorCalled1`] = true;
  681. return Promise.resolve();
  682. });
  683. hook.tapPromise("promise2", () => {
  684. return new Promise((resolve, reject) => {
  685. setTimeout(() => reject(new Error("Error in async2")), 100);
  686. });
  687. });
  688. hook.tapPromise("promise3", () => {
  689. result[`${type}MultiplePromiseLateErrorCalled3`] = true;
  690. return Promise.resolve();
  691. });
  692. result[`${type}MultiplePromiseLateError`] = await this.gainResult((cb) => hook[type](cb));
  693. }
  694. {
  695. const hook = this.createHook([], `${type}MultiplePromiseEarlyError`);
  696. hook.tapPromise("promise1", () => {
  697. result[`${type}MultiplePromiseEarlyErrorCalled1`] = true;
  698. return new Promise(resolve => setTimeout(() => resolve(), 100));
  699. });
  700. hook.tapPromise("promise2", () => {
  701. return Promise.resolve().then(() => { throw new Error("Error in async2"); });
  702. });
  703. hook.tapPromise("promise3", () => {
  704. result[`${type}MultiplePromiseEarlyErrorCalled3`] = true;
  705. return new Promise(resolve => setTimeout(() => resolve(), 100));
  706. });
  707. result[`${type}MultiplePromiseEarlyError`] = await this.gainResult((cb) => hook[type](cb));
  708. }
  709. {
  710. const hook = this.createHook(["x"], `${type}MultipleMixedError1WithArg`);
  711. hook.tapAsync("async", (arg, callback) => {
  712. result[`${type}MultipleMixedError1WithArgCalled1`] = arg;
  713. callback(null, arg);
  714. });
  715. hook.tapPromise("promise", arg => {
  716. result[`${type}MultipleMixedError1WithArgCalled2`] = arg;
  717. return Promise.resolve(arg + 1);
  718. });
  719. hook.tap("sync", arg => {
  720. result[`${type}MultipleMixedError1WithArgCalled3`] = arg;
  721. throw new Error("Error in sync");
  722. });
  723. result[`${type}MultipleMixedError1WithArg`] = await this.gainResult((cb) => hook[type](42, cb));
  724. }
  725. {
  726. const hook = this.createHook(["x"], `${type}MultipleMixedError2WithArg`);
  727. hook.tapAsync("async", (arg, callback) => {
  728. result[`${type}MultipleMixedError2WithArgCalled1`] = arg;
  729. callback(null, arg);
  730. });
  731. hook.tapPromise("promise", arg => {
  732. result[`${type}MultipleMixedError2WithArgCalled2`] = arg;
  733. return Promise.resolve().then(() => { throw new Error("Error in promise"); });
  734. });
  735. hook.tap("sync", arg => {
  736. result[`${type}MultipleMixedError2WithArgCalled3`] = arg;
  737. return arg + 2;
  738. });
  739. result[`${type}MultipleMixedError2WithArg`] = await this.gainResult((cb) => hook[type](42, cb));
  740. }
  741. {
  742. const hook = this.createHook(["x"], `${type}MultipleMixedError3WithArg`);
  743. hook.tapAsync("async", (arg, callback) => {
  744. result[`${type}MultipleMixedError3WithArgCalled1`] = arg;
  745. callback(new Error("Error in async"));
  746. });
  747. hook.tapPromise("promise", arg => {
  748. result[`${type}MultipleMixedError3WithArgCalled2`] = arg;
  749. return Promise.resolve(arg + 1);
  750. });
  751. hook.tap("sync", arg => {
  752. result[`${type}MultipleMixedError3WithArgCalled3`] = arg;
  753. return arg + 2;
  754. });
  755. result[`${type}MultipleMixedError3WithArg`] = await this.gainResult((cb) => hook[type](42, cb));
  756. }
  757. {
  758. const hook = this.createHook([], `${type}MultipleMixedLateError`);
  759. hook.tapAsync("async", (callback) => {
  760. result[`${type}MultipleMixedLateErrorCalled1`] = true;
  761. setTimeout(() => callback(new Error("Error in async")), 100);
  762. });
  763. hook.tapPromise("promise", () => {
  764. result[`${type}MultipleMixedLateErrorCalled2`] = true;
  765. return Promise.resolve(42);
  766. });
  767. hook.tap("sync", () => {
  768. result[`${type}MultipleMixedLateErrorCalled3`] = true;
  769. return 43;
  770. });
  771. result[`${type}MultipleMixedLateError`] = await this.gainResult((cb) => hook[type](cb));
  772. }
  773. }
  774. async runIntercept(result, type) {
  775. {
  776. const hook = this.createHook(["a", "b", "c"], `${type}Intercepted`);
  777. hook.intercept({
  778. call: (a, b, c) => {
  779. result[`${type}InterceptedCall1`] = [a, b, c];
  780. },
  781. tap: (tap) => {
  782. result[`${type}InterceptedTap1`] = Object.assign({}, tap, { fn: tap.fn.length });
  783. }
  784. });
  785. hook.intercept({
  786. call: (a, b, c) => {
  787. result[`${type}InterceptedCall2`] = [a, b, c];
  788. },
  789. tap: (tap) => {
  790. if(!result[`${type}InterceptedTap2`])
  791. result[`${type}InterceptedTap2`] = Object.assign({}, tap, { fn: tap.fn.length });
  792. }
  793. });
  794. hook.tap("sync", (a, b, c) => a + b + c);
  795. hook.tapPromise("promise", (a, b) => Promise.resolve(a + b + 1));
  796. result[`${type}Intercepted`] = await this.gainResult((cb) => hook[type](1, 2, 3, cb));
  797. }
  798. {
  799. const hook = this.createHook(["a", "b", "c"], `${type}ContextIntercepted`);
  800. hook.intercept({
  801. call: (context, a, b, c) => {
  802. context.number = 42;
  803. result[`${type}ContextInterceptedCall1`] = [context, a, b, c];
  804. },
  805. loop: (context, a, b, c) => {
  806. context.number2 = 88;
  807. result[`${type}ContextInterceptedLoop1`] = [context, a, b, c];
  808. },
  809. tap: (context, tap) => {
  810. result[`${type}ContextInterceptedTap1`] = context;
  811. },
  812. context: true
  813. });
  814. hook.intercept({
  815. call: (a, b, c) => {
  816. result[`${type}ContextInterceptedCall2`] = [a, b, c];
  817. }
  818. });
  819. hook.tap({
  820. name: "sync",
  821. context: true
  822. }, (context, a, b, c) => context.number + a + b + c);
  823. result[`${type}ContextIntercepted`] = await this.gainResult((cb) => hook[type](1, 2, 3, cb));
  824. }
  825. {
  826. const hook = this.createHook(["a", "b", "c"], `${type}UnusedContextIntercepted`);
  827. hook.intercept({
  828. call: (context, a, b, c) => {
  829. result[`${type}UnusedContextInterceptedCall1`] = [context, a, b, c];
  830. },
  831. tap: (context, tap) => {
  832. result[`${type}UnusedContextInterceptedTap1`] = context;
  833. },
  834. context: true
  835. });
  836. hook.intercept({
  837. call: (a, b, c) => {
  838. result[`${type}UnusedContextInterceptedCall2`] = [a, b, c];
  839. }
  840. });
  841. hook.tap("sync", (a, b, c) => a + b + c);
  842. result[`${type}UnusedContextIntercepted`] = await this.gainResult((cb) => hook[type](1, 2, 3, cb));
  843. }
  844. }
  845. gainResult(fn) {
  846. return Promise.race([new Promise(resolve => {
  847. try {
  848. const ret = fn((err, result) => {
  849. if(err) {
  850. resolve({
  851. type: "async",
  852. error: err.message
  853. });
  854. } else {
  855. resolve({
  856. type: "async",
  857. value: result
  858. });
  859. }
  860. });
  861. if(ret instanceof Promise) {
  862. resolve(ret.then(res => ({
  863. type: "promise",
  864. value: res
  865. }), err => ({
  866. type: "promise",
  867. error: err.message
  868. })));
  869. } else if(ret !== undefined) {
  870. resolve({
  871. type: "return",
  872. value: ret
  873. })
  874. }
  875. } catch(e) {
  876. resolve({
  877. error: e.message
  878. });
  879. }
  880. }), new Promise(resolve => {
  881. setTimeout(() => resolve({
  882. type: "no result"
  883. }), 1000);
  884. })]);
  885. }
  886. createHook(args, name) {
  887. try {
  888. return this.hookCreator(args, name);
  889. } catch(err) {
  890. return {
  891. tap: () => {},
  892. tapPromise: () => {},
  893. tapAsync: () => {},
  894. intercept: () => {},
  895. call: () => { throw err; },
  896. callAsync: () => { throw err; },
  897. promise: () => { throw err; },
  898. }
  899. }
  900. }
  901. }
  902. module.exports = HookTester;