hooks.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. 'use strict';
  2. require('../lib/chalk').set();
  3. require('../lib/worker/options').set({});
  4. const test = require('tap').test;
  5. const Runner = require('../lib/runner');
  6. const promiseEnd = (runner, next) => {
  7. return new Promise(resolve => {
  8. resolve(runner.once('finish'));
  9. next(runner);
  10. }).then(() => runner);
  11. };
  12. test('before', t => {
  13. t.plan(1);
  14. const arr = [];
  15. return promiseEnd(new Runner(), runner => {
  16. runner.chain.before(() => {
  17. arr.push('a');
  18. });
  19. runner.chain('test', a => {
  20. a.pass();
  21. arr.push('b');
  22. });
  23. }).then(() => {
  24. t.strictDeepEqual(arr, ['a', 'b']);
  25. });
  26. });
  27. test('after', t => {
  28. t.plan(2);
  29. const arr = [];
  30. return promiseEnd(new Runner(), runner => {
  31. runner.on('stateChange', evt => {
  32. if (evt.type === 'test-passed') {
  33. t.pass();
  34. }
  35. });
  36. runner.chain.after(() => {
  37. arr.push('b');
  38. });
  39. runner.chain('test', a => {
  40. a.pass();
  41. arr.push('a');
  42. });
  43. }).then(() => {
  44. t.strictDeepEqual(arr, ['a', 'b']);
  45. });
  46. });
  47. test('after not run if test failed', t => {
  48. t.plan(2);
  49. const arr = [];
  50. return promiseEnd(new Runner(), runner => {
  51. runner.on('stateChange', evt => {
  52. if (evt.type === 'test-failed') {
  53. t.pass();
  54. }
  55. });
  56. runner.chain.after(() => {
  57. arr.push('a');
  58. });
  59. runner.chain('test', () => {
  60. throw new Error('something went wrong');
  61. });
  62. }).then(() => {
  63. t.strictDeepEqual(arr, []);
  64. });
  65. });
  66. test('after.always run even if test failed', t => {
  67. t.plan(2);
  68. const arr = [];
  69. return promiseEnd(new Runner(), runner => {
  70. runner.on('stateChange', evt => {
  71. if (evt.type === 'test-failed') {
  72. t.pass();
  73. }
  74. });
  75. runner.chain.after.always(() => {
  76. arr.push('a');
  77. });
  78. runner.chain('test', () => {
  79. throw new Error('something went wrong');
  80. });
  81. }).then(() => {
  82. t.strictDeepEqual(arr, ['a']);
  83. });
  84. });
  85. test('after.always run even if before failed', t => {
  86. t.plan(1);
  87. const arr = [];
  88. return promiseEnd(new Runner(), runner => {
  89. runner.chain.before(() => {
  90. throw new Error('something went wrong');
  91. });
  92. runner.chain('test', a => a.pass());
  93. runner.chain.after.always(() => {
  94. arr.push('a');
  95. });
  96. }).then(() => {
  97. t.strictDeepEqual(arr, ['a']);
  98. });
  99. });
  100. test('stop if before hooks failed', t => {
  101. t.plan(1);
  102. const arr = [];
  103. return promiseEnd(new Runner(), runner => {
  104. runner.chain.before(() => {
  105. arr.push('a');
  106. });
  107. runner.chain.before(() => {
  108. throw new Error('something went wrong');
  109. });
  110. runner.chain('test', a => {
  111. a.pass();
  112. arr.push('b');
  113. a.end();
  114. });
  115. }).then(() => {
  116. t.strictDeepEqual(arr, ['a']);
  117. });
  118. });
  119. test('before each with concurrent tests', t => {
  120. t.plan(1);
  121. const arr = [[], []];
  122. return promiseEnd(new Runner(), runner => {
  123. let i = 0;
  124. let k = 0;
  125. runner.chain.beforeEach(() => {
  126. arr[i++].push('a');
  127. });
  128. runner.chain.beforeEach(() => {
  129. arr[k++].push('b');
  130. });
  131. runner.chain('c', a => {
  132. a.pass();
  133. arr[0].push('c');
  134. });
  135. runner.chain('d', a => {
  136. a.pass();
  137. arr[1].push('d');
  138. });
  139. }).then(() => {
  140. t.strictDeepEqual(arr, [['a', 'b', 'c'], ['a', 'b', 'd']]);
  141. });
  142. });
  143. test('before each with serial tests', t => {
  144. t.plan(1);
  145. const arr = [];
  146. return promiseEnd(new Runner(), runner => {
  147. runner.chain.beforeEach(() => {
  148. arr.push('a');
  149. });
  150. runner.chain.beforeEach(() => {
  151. arr.push('b');
  152. });
  153. runner.chain.serial('c', a => {
  154. a.pass();
  155. arr.push('c');
  156. });
  157. runner.chain.serial('d', a => {
  158. a.pass();
  159. arr.push('d');
  160. });
  161. }).then(() => {
  162. t.strictDeepEqual(arr, ['a', 'b', 'c', 'a', 'b', 'd']);
  163. });
  164. });
  165. test('fail if beforeEach hook fails', t => {
  166. t.plan(2);
  167. const arr = [];
  168. return promiseEnd(new Runner(), runner => {
  169. runner.on('stateChange', evt => {
  170. if (evt.type === 'hook-failed') {
  171. t.pass();
  172. }
  173. });
  174. runner.chain.beforeEach(a => {
  175. arr.push('a');
  176. a.fail();
  177. });
  178. runner.chain('test', a => {
  179. arr.push('b');
  180. a.pass();
  181. });
  182. }).then(() => {
  183. t.strictDeepEqual(arr, ['a']);
  184. });
  185. });
  186. test('after each with concurrent tests', t => {
  187. t.plan(1);
  188. const arr = [[], []];
  189. return promiseEnd(new Runner(), runner => {
  190. let i = 0;
  191. let k = 0;
  192. runner.chain.afterEach(() => {
  193. arr[i++].push('a');
  194. });
  195. runner.chain.afterEach(() => {
  196. arr[k++].push('b');
  197. });
  198. runner.chain('c', a => {
  199. a.pass();
  200. arr[0].push('c');
  201. });
  202. runner.chain('d', a => {
  203. a.pass();
  204. arr[1].push('d');
  205. });
  206. }).then(() => {
  207. t.strictDeepEqual(arr, [['c', 'a', 'b'], ['d', 'a', 'b']]);
  208. });
  209. });
  210. test('after each with serial tests', t => {
  211. t.plan(1);
  212. const arr = [];
  213. return promiseEnd(new Runner(), runner => {
  214. runner.chain.afterEach(() => {
  215. arr.push('a');
  216. });
  217. runner.chain.afterEach(() => {
  218. arr.push('b');
  219. });
  220. runner.chain.serial('c', a => {
  221. a.pass();
  222. arr.push('c');
  223. });
  224. runner.chain.serial('d', a => {
  225. a.pass();
  226. arr.push('d');
  227. });
  228. }).then(() => {
  229. t.strictDeepEqual(arr, ['c', 'a', 'b', 'd', 'a', 'b']);
  230. });
  231. });
  232. test('afterEach not run if concurrent tests failed', t => {
  233. t.plan(1);
  234. const arr = [];
  235. return promiseEnd(new Runner(), runner => {
  236. runner.chain.afterEach(() => {
  237. arr.push('a');
  238. });
  239. runner.chain('test', () => {
  240. throw new Error('something went wrong');
  241. });
  242. }).then(() => {
  243. t.strictDeepEqual(arr, []);
  244. });
  245. });
  246. test('afterEach not run if serial tests failed', t => {
  247. t.plan(1);
  248. const arr = [];
  249. return promiseEnd(new Runner(), runner => {
  250. runner.chain.afterEach(() => {
  251. arr.push('a');
  252. });
  253. runner.chain.serial('test', () => {
  254. throw new Error('something went wrong');
  255. });
  256. }).then(() => {
  257. t.strictDeepEqual(arr, []);
  258. });
  259. });
  260. test('afterEach.always run even if concurrent tests failed', t => {
  261. t.plan(1);
  262. const arr = [];
  263. return promiseEnd(new Runner(), runner => {
  264. runner.chain.afterEach.always(() => {
  265. arr.push('a');
  266. });
  267. runner.chain('test', () => {
  268. throw new Error('something went wrong');
  269. });
  270. }).then(() => {
  271. t.strictDeepEqual(arr, ['a']);
  272. });
  273. });
  274. test('afterEach.always run even if serial tests failed', t => {
  275. t.plan(1);
  276. const arr = [];
  277. return promiseEnd(new Runner(), runner => {
  278. runner.chain.afterEach.always(() => {
  279. arr.push('a');
  280. });
  281. runner.chain.serial('test', () => {
  282. throw new Error('something went wrong');
  283. });
  284. }).then(() => {
  285. t.strictDeepEqual(arr, ['a']);
  286. });
  287. });
  288. test('afterEach.always run even if beforeEach failed', t => {
  289. t.plan(1);
  290. const arr = [];
  291. return promiseEnd(new Runner(), runner => {
  292. runner.chain.beforeEach(() => {
  293. throw new Error('something went wrong');
  294. });
  295. runner.chain('test', a => {
  296. a.pass();
  297. arr.push('a');
  298. });
  299. runner.chain.afterEach.always(() => {
  300. arr.push('b');
  301. });
  302. }).then(() => {
  303. t.strictDeepEqual(arr, ['b']);
  304. });
  305. });
  306. test('ensure hooks run only around tests', t => {
  307. t.plan(1);
  308. const arr = [];
  309. return promiseEnd(new Runner(), runner => {
  310. runner.chain.beforeEach(() => {
  311. arr.push('beforeEach');
  312. });
  313. runner.chain.before(() => {
  314. arr.push('before');
  315. });
  316. runner.chain.afterEach(() => {
  317. arr.push('afterEach');
  318. });
  319. runner.chain.after(() => {
  320. arr.push('after');
  321. });
  322. runner.chain('test', a => {
  323. a.pass();
  324. arr.push('test');
  325. });
  326. }).then(() => {
  327. t.strictDeepEqual(arr, ['before', 'beforeEach', 'test', 'afterEach', 'after']);
  328. });
  329. });
  330. test('shared context', t => {
  331. return promiseEnd(new Runner(), runner => {
  332. runner.on('stateChange', evt => {
  333. if (evt.type === 'hook-failed' || evt.type === 'test-failed') {
  334. t.fail();
  335. }
  336. });
  337. runner.chain.before(a => {
  338. a.deepEqual(a.context, {});
  339. a.context.arr = ['a'];
  340. a.context.prop = 'before';
  341. });
  342. runner.chain.after(a => {
  343. a.deepEqual(a.context.arr, ['a', 'b', 'c', 'd']);
  344. a.is(a.context.prop, 'before');
  345. });
  346. runner.chain.beforeEach(a => {
  347. a.deepEqual(a.context.arr, ['a']);
  348. a.context.arr.push('b');
  349. a.is(a.context.prop, 'before');
  350. a.context.prop = 'beforeEach';
  351. });
  352. runner.chain('test', a => {
  353. a.pass();
  354. a.deepEqual(a.context.arr, ['a', 'b']);
  355. a.context.arr.push('c');
  356. a.is(a.context.prop, 'beforeEach');
  357. a.context.prop = 'test';
  358. });
  359. runner.chain.afterEach(a => {
  360. a.deepEqual(a.context.arr, ['a', 'b', 'c']);
  361. a.context.arr.push('d');
  362. a.is(a.context.prop, 'test');
  363. a.context.prop = 'afterEach';
  364. });
  365. });
  366. });
  367. test('shared context of any type', t => {
  368. return promiseEnd(new Runner(), runner => {
  369. runner.on('stateChange', evt => {
  370. if (evt.type === 'hook-failed' || evt.type === 'test-failed') {
  371. t.fail();
  372. }
  373. });
  374. runner.chain.beforeEach(a => {
  375. a.context = 'foo';
  376. });
  377. runner.chain('test', a => {
  378. a.pass();
  379. a.is(a.context, 'foo');
  380. });
  381. });
  382. });