methods.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. 'use strict';
  2. var contra = typeof contra !== 'undefined' ? contra : require('..');
  3. var a = typeof assert !== 'undefined' ? assert : require('assert');
  4. a.falsy = function (value, message) { a.equal(false, !!value, message); };
  5. describe('waterfall()', function () {
  6. it('should run tasks in a waterfall', function (done) {
  7. var cb = false, cc = false;
  8. function b (next) {
  9. cb = true;
  10. a.falsy(cc);
  11. next(null, 'a');
  12. }
  13. function c (d, next) {
  14. cc = true;
  15. a.ok(cb);
  16. a.equal(d, 'a');
  17. next(null, 'b');
  18. }
  19. function d (err, result) {
  20. a.falsy(err);
  21. a.ok(cb);
  22. a.ok(cc);
  23. a.equal(result, 'b');
  24. done();
  25. }
  26. contra.waterfall([b,c],d);
  27. });
  28. });
  29. describe('series()', function () {
  30. it('should run tasks in a series as array', function (done) {
  31. var cb = false, cc = false;
  32. function b (next) {
  33. cb = true;
  34. a.falsy(cc);
  35. next(null, 'a');
  36. }
  37. function c (next) {
  38. cc = true;
  39. a.ok(cb);
  40. next(null, 'b');
  41. }
  42. function d (err, results) {
  43. a.falsy(err);
  44. a.ok(cb);
  45. a.ok(cc);
  46. a.equal(Object.keys(results).length, 2);
  47. a.equal(results[0], 'a');
  48. a.equal(results[1], 'b');
  49. done();
  50. }
  51. contra.series([b,c],d);
  52. });
  53. it('should run tasks in a series as object', function (done) {
  54. var cb = false, cc = false;
  55. function b (next) {
  56. cb = true;
  57. a.falsy(cc);
  58. next(null, 'a');
  59. }
  60. function c (next) {
  61. cc = true;
  62. a.ok(cb);
  63. next(null, 'b');
  64. }
  65. function d (err, results) {
  66. a.falsy(err);
  67. a.ok(cb);
  68. a.ok(cc);
  69. a.equal(Object.keys(results).length, 2);
  70. a.equal(results.e, 'a');
  71. a.equal(results.f, 'b');
  72. done();
  73. }
  74. contra.series({ e: b, f: c }, d);
  75. });
  76. it('should short-circuit on error', function (done) {
  77. var cb = false, cc = false;
  78. function b (next) {
  79. cb = true;
  80. a.falsy(cc);
  81. next('d', 'a');
  82. }
  83. function c (next) {
  84. cc = true;
  85. a.ok(cb);
  86. next(null, 'b');
  87. }
  88. function d (err, results) {
  89. a.ok(err);
  90. a.equal(err, 'd');
  91. a.ok(cb);
  92. a.falsy(cc);
  93. a.falsy(results);
  94. done();
  95. }
  96. contra.series([b,c],d);
  97. });
  98. });
  99. describe('concurrent()', function () {
  100. it('should run tasks concurrently as array', function (done) {
  101. var cb = false, cc = false;
  102. function b (next) {
  103. cb = true;
  104. a.falsy(cc);
  105. next(null, 'a');
  106. }
  107. function c (next) {
  108. cc = true;
  109. a.ok(cb);
  110. next(null, 'b');
  111. }
  112. function d (err, results) {
  113. a.falsy(err);
  114. a.ok(cb);
  115. a.ok(cc);
  116. a.equal(Object.keys(results).length, 2);
  117. a.equal(results[0], 'a');
  118. a.equal(results[1], 'b');
  119. done();
  120. }
  121. contra.concurrent([b,c],d);
  122. });
  123. it('should run tasks concurrently as object', function (done) {
  124. var cb = false, cc = false;
  125. function b (next) {
  126. cb = true;
  127. a.falsy(cc);
  128. next(null, 'a');
  129. }
  130. function c (next) {
  131. cc = true;
  132. a.ok(cb);
  133. next(null, 'b');
  134. }
  135. function d (err, results) {
  136. a.falsy(err);
  137. a.ok(cb);
  138. a.ok(cc);
  139. a.equal(Object.keys(results).length, 2);
  140. a.equal(results.a, 'a');
  141. a.equal(results.d, 'b');
  142. done();
  143. }
  144. contra.concurrent({ a: b, d: c }, d);
  145. });
  146. it('should short-circuit on error', function (done) {
  147. function b (next) {
  148. next('b', 'a');
  149. }
  150. function c (next) {
  151. next(null, 'b');
  152. }
  153. function d (err, results) {
  154. a.ok(err);
  155. a.equal(err, 'b');
  156. a.falsy(results);
  157. done();
  158. }
  159. contra.concurrent([b,c],d);
  160. });
  161. });
  162. describe('curry()', function () {
  163. it('should work with no extra arguments', function () {
  164. var fn = function (b,c,d) {
  165. a.equal(b, 1);
  166. a.equal(c, 3);
  167. a.equal(d, 'c');
  168. };
  169. var applied = contra.curry(fn, 1, 3, 'c');
  170. applied();
  171. });
  172. it('should include extra arguments as well', function () {
  173. var fn = function (b,c,d,e,f) {
  174. a.equal(b, 1);
  175. a.equal(c, 3);
  176. a.equal(d, 'c');
  177. a.equal(e, 'd');
  178. a.equal(f, 'e');
  179. };
  180. var applied = contra.curry(fn, 1, 3, 'c');
  181. applied('d', 'e');
  182. });
  183. it('should play well with contra.series', function (done) {
  184. var cb = false, cc = false;
  185. function b (n, next) {
  186. a.equal(n, 1);
  187. cb = true;
  188. a.falsy(cc);
  189. next(null, 'd');
  190. }
  191. function c (p, next) {
  192. a.deepEqual(p, ['a']);
  193. cc = true;
  194. a.ok(cb);
  195. next(null, 'b');
  196. }
  197. function d (err, results) {
  198. a.falsy(err);
  199. a.ok(cb);
  200. a.ok(cc);
  201. a.equal(Object.keys(results).length, 2);
  202. a.equal(results[0], 'd');
  203. a.equal(results[1], 'b');
  204. done();
  205. }
  206. contra.series([
  207. contra.curry(b, 1),
  208. contra.curry(c, ['a']),
  209. ], d);
  210. });
  211. });
  212. describe('each()', function () {
  213. it('should loop array concurrently', function (done) {
  214. var n = 0;
  215. function t (i, done) {
  216. n++;
  217. done();
  218. }
  219. function d (err, results) {
  220. a.equal(n, 2);
  221. a.falsy(err);
  222. a.falsy(results);
  223. done();
  224. }
  225. contra.each(['b','c'],t,d);
  226. });
  227. it('should loop object concurrently', function (done) {
  228. var n = 0;
  229. function t (i, done) {
  230. n++;
  231. done();
  232. }
  233. function d (err, results) {
  234. a.equal(n, 2);
  235. a.falsy(err);
  236. a.falsy(results);
  237. done();
  238. }
  239. contra.each({ a: 'b', b: 'c' }, t, d);
  240. });
  241. it('should short-circuit on error', function (done) {
  242. function t (i, done) {
  243. done(i);
  244. }
  245. function d (err, results) {
  246. a.ok(err);
  247. a.falsy(results);
  248. done();
  249. }
  250. contra.each(['b','c','e'],t,d);
  251. });
  252. it('should pass array keys to iterator', function(done){
  253. var items = ['a', 'c', 'e'];
  254. var keys = [];
  255. function iterator(item, key, done) {
  256. setTimeout(function() {
  257. keys.push(key);
  258. done();
  259. }, Math.random());
  260. }
  261. function d(err) {
  262. a.falsy(err);
  263. a.deepEqual(Object.keys(items), keys);
  264. done();
  265. }
  266. contra.each(items, iterator, d);
  267. });
  268. it('should pass object keys to iterator', function(done){
  269. var items = {a: 'b', c: 'd', e: 'f'};
  270. var keys = [];
  271. function iterator(item, key, done) {
  272. setTimeout(function() {
  273. keys.push(key);
  274. done();
  275. }, Math.random());
  276. }
  277. function d(err) {
  278. a.falsy(err);
  279. a.deepEqual(Object.keys(items), keys);
  280. done();
  281. }
  282. contra.each(items, iterator, d);
  283. });
  284. });
  285. describe('each.series()', function () {
  286. it('should loop array in a series', function (done) {
  287. var n = 0;
  288. function t (i, done) {
  289. n++;
  290. done();
  291. }
  292. function d (err, results) {
  293. a.equal(n, 2);
  294. a.falsy(err);
  295. a.falsy(results);
  296. done();
  297. }
  298. contra.each.series(['b','c'],t,d);
  299. });
  300. it('should loop object in a series', function (done) {
  301. var n = 0;
  302. function t (i, done) {
  303. n++;
  304. done();
  305. }
  306. function d (err, results) {
  307. a.equal(n, 2);
  308. a.falsy(err);
  309. a.falsy(results);
  310. done();
  311. }
  312. contra.each.series({ a: 'b', b: 'c' }, t, d);
  313. });
  314. it('should short-circuit on error', function (done) {
  315. var n = 0;
  316. function t (i, done) {
  317. n++;
  318. done(i);
  319. }
  320. function d (err, results) {
  321. a.equal(n, 1);
  322. a.ok(err);
  323. a.falsy(results);
  324. done();
  325. }
  326. contra.each.series(['b','c'],t,d);
  327. });
  328. });
  329. describe('map()', function () {
  330. it('should map array concurrently', function (done) {
  331. var n = 4;
  332. function t (i, done) {
  333. done(null, n++);
  334. }
  335. function d (err, results) {
  336. a.falsy(err);
  337. a.equal(Object.keys(results).length, 2);
  338. a.deepEqual(results, [4, 5]);
  339. done();
  340. }
  341. contra.map(['b','c'],t,d);
  342. });
  343. it('should map object concurrently', function (done) {
  344. var n = 4;
  345. function t (i, done) {
  346. done(null, n++);
  347. }
  348. function d (err, results) {
  349. a.falsy(err);
  350. a.equal(Object.keys(results).length, 2);
  351. a.deepEqual(results, { a: 4, b: 5 });
  352. done();
  353. }
  354. contra.map({ a: 'b', b: 'c' }, t, d);
  355. });
  356. it('should short-circuit on error', function (done) {
  357. function t (i, done) {
  358. done(i);
  359. }
  360. function d (err, results) {
  361. a.ok(err);
  362. a.falsy(results);
  363. done();
  364. }
  365. contra.map(['b','c','e'],t,d);
  366. });
  367. it('should pass array keys to iterator', function(done){
  368. var items = [
  369. 'a',
  370. { m: 2 },
  371. 'c',
  372. 'foo',
  373. [2],
  374. [3, 6, 7]
  375. ];
  376. var keys = [];
  377. function iterator(item, key, done) {
  378. setTimeout(function() {
  379. keys.push(key);
  380. done();
  381. }, Math.random());
  382. }
  383. function d(err) {
  384. a.falsy(err);
  385. a.deepEqual(Object.keys(items), keys);
  386. done();
  387. }
  388. contra.map(items, iterator, d);
  389. });
  390. it('should pass object keys to iterator', function(done){
  391. var items = {
  392. a: 'a',
  393. b: { m: 2 },
  394. c: 'c',
  395. d: 'foo',
  396. e: [2],
  397. z: [3, 6, 7]
  398. };
  399. var keys = [];
  400. function iterator(item, key, done) {
  401. setTimeout(function() {
  402. keys.push(key);
  403. done();
  404. }, Math.random());
  405. }
  406. function d(err) {
  407. a.falsy(err);
  408. a.deepEqual(Object.keys(items), keys);
  409. done();
  410. }
  411. contra.map(items, iterator, d);
  412. });
  413. });
  414. describe('map.series()', function () {
  415. it('should map array in a series', function (done) {
  416. var n = 4;
  417. function t (i, done) {
  418. done(null, n++);
  419. }
  420. function d (err, results) {
  421. a.falsy(err);
  422. a.equal(Object.keys(results).length, 2);
  423. a.deepEqual(results, [4, 5]);
  424. done();
  425. }
  426. contra.map.series(['b','c'],t,d);
  427. });
  428. it('should map object in a series', function (done) {
  429. var n = 4;
  430. function t (i, done) {
  431. done(null, n++);
  432. }
  433. function d (err, results) {
  434. a.falsy(err);
  435. a.equal(Object.keys(results).length, 2);
  436. a.deepEqual(results, { a: 4, b: 5 });
  437. done();
  438. }
  439. contra.map.series({ a: 'b', b: 'c' }, t, d);
  440. });
  441. it('should fail on error', function (done) {
  442. function t (i, done) {
  443. done(i);
  444. }
  445. function d (err, results) {
  446. a.ok(err);
  447. a.falsy(results);
  448. done();
  449. }
  450. contra.map.series(['b','c'],t,d);
  451. });
  452. it('should short-circuit on error', function (done) {
  453. var n = 0;
  454. function t (i, done) {
  455. n++;
  456. done(i);
  457. }
  458. function d (err, results) {
  459. a.equal(n, 1);
  460. a.ok(err);
  461. a.falsy(results);
  462. done();
  463. }
  464. contra.map.series(['b','c'],t,d);
  465. });
  466. });
  467. describe('filter()', function () {
  468. it('should filter array concurrently', function (done) {
  469. function t (i, done) {
  470. done(null, typeof i === 'string');
  471. }
  472. function d (err, results) {
  473. a.falsy(err);
  474. a.equal(results.length, 2);
  475. a.deepEqual(results, ['b', 'c']);
  476. done();
  477. }
  478. contra.filter([1,2,'b',3,'c',5],t,d);
  479. });
  480. it('should filter object concurrently', function (done) {
  481. function t (i, done) {
  482. done(null, typeof i === 'string');
  483. }
  484. function d (err, results) {
  485. a.falsy(err);
  486. a.equal(Object.keys(results).length, 2);
  487. a.deepEqual(results, { a: 'b', b: 'c' });
  488. done();
  489. }
  490. contra.filter({ n: 3, a: 'b', b: 'c', c: 4, d: 5, e: 6 }, t, d);
  491. });
  492. it('should short-circuit on error', function (done) {
  493. function t (i, done) {
  494. done(i);
  495. }
  496. function d (err, results) {
  497. a.ok(err);
  498. a.falsy(results);
  499. done();
  500. }
  501. contra.filter(['b','c','e'],t,d);
  502. });
  503. it('should pass array keys to iterator', function(done){
  504. var items = ['a', 'c', 'e'];
  505. var keys = [];
  506. function iterator(item, key, done) {
  507. setTimeout(function() {
  508. keys.push(key);
  509. done();
  510. }, Math.random());
  511. }
  512. function d(err) {
  513. a.falsy(err);
  514. a.deepEqual(Object.keys(items), keys);
  515. done();
  516. }
  517. contra.filter(items, iterator, d);
  518. });
  519. it('should pass object keys to iterator', function(done){
  520. var items = {a: 'b', c: 'd', e: 'f'};
  521. var keys = [];
  522. function iterator(item, key, done) {
  523. setTimeout(function() {
  524. keys.push(key);
  525. done();
  526. }, Math.random());
  527. }
  528. function d(err) {
  529. a.falsy(err);
  530. a.deepEqual(Object.keys(items), keys);
  531. done();
  532. }
  533. contra.filter(items, iterator, d);
  534. });
  535. });
  536. describe('filter.series()', function () {
  537. it('should filter array in a series', function (done) {
  538. function t (i, done) {
  539. done(null, typeof i === 'string');
  540. }
  541. function d (err, results) {
  542. a.falsy(err);
  543. a.equal(results.length, 2);
  544. a.deepEqual(results, ['b', 'c']);
  545. done();
  546. }
  547. contra.filter.series([1,2,'b',3,'c',5],t,d);
  548. });
  549. it('should filter object in a series', function (done) {
  550. function t (i, done) {
  551. done(null, typeof i === 'string');
  552. }
  553. function d (err, results) {
  554. a.falsy(err);
  555. a.equal(Object.keys(results).length, 2);
  556. a.deepEqual(results, { a: 'b', b: 'c' });
  557. done();
  558. }
  559. contra.filter.series({ n: 3, a: 'b', b: 'c', c: 4, d: 5, e: 6 }, t, d);
  560. });
  561. });
  562. describe('queue()', function () {
  563. it('should queue things', function (done) {
  564. var ww;
  565. function w (job, done) {
  566. ww = true;
  567. a.equal(job, 'a');
  568. done();
  569. }
  570. function d (err) {
  571. a.falsy(err);
  572. a.ok(ww);
  573. done();
  574. }
  575. var q = contra.queue(w);
  576. q.push('a', d);
  577. });
  578. it('should pause and resume the queue', function (done) {
  579. var ww;
  580. function w (job, cb) {
  581. ww = true;
  582. a.equal(job, 'a');
  583. cb();
  584. }
  585. function d (err) {
  586. a.falsy(err);
  587. a.ok(ww);
  588. done();
  589. }
  590. var q = contra.queue(w);
  591. q.pause();
  592. q.push('a', d);
  593. a.equal(q.pending.length, 1);
  594. q.resume();
  595. });
  596. it('should forward errors', function (done) {
  597. var ww;
  598. function w (job, done) {
  599. ww = true;
  600. a.equal(job, 'a');
  601. done('e');
  602. }
  603. function d (err) {
  604. a.equal(err, 'e');
  605. a.ok(ww);
  606. done();
  607. }
  608. var q = contra.queue(w);
  609. q.push('a', d);
  610. });
  611. it('should emit drain', function (done) {
  612. var ww;
  613. function w () {
  614. a.fail(null, null, 'invoked worker');
  615. }
  616. function d () {
  617. a.fail(null, null, 'invoked job completion');
  618. }
  619. function drained () {
  620. a.falsy(ww);
  621. done();
  622. }
  623. var q = contra.queue(w);
  624. q.on('drain', drained);
  625. q.push([], d);
  626. });
  627. });
  628. describe('emitter()', function () {
  629. it('should just work', function (done) {
  630. var thing = { foo: 'bar' };
  631. contra.emitter(thing);
  632. a.ok(thing.emit);
  633. a.ok(thing.on);
  634. a.ok(thing.once);
  635. a.ok(thing.off);
  636. thing.on('something', function (b, c) {
  637. a.equal(b, 'a');
  638. a.equal(c, 2);
  639. done();
  640. });
  641. thing.emit('something', 'a', 2);
  642. });
  643. it('should just work without arguments', function (done) {
  644. var thing = contra.emitter();
  645. a.ok(thing.emit);
  646. a.ok(thing.on);
  647. a.ok(thing.once);
  648. a.ok(thing.off);
  649. thing.on('something', function (b, c) {
  650. a.equal(b, 'a');
  651. a.equal(c, 2);
  652. done();
  653. });
  654. thing.emit('something', 'a', 2);
  655. });
  656. it('should run once() listeners once', function (done) {
  657. var thing = { foo: 'bar' };
  658. var c = 0;
  659. contra.emitter(thing);
  660. function me () {
  661. c++;
  662. a.ok(c < 2);
  663. done();
  664. }
  665. thing.once('something', me);
  666. thing.on('something', function () {
  667. a.equal(c, 1);
  668. });
  669. thing.emit('something');
  670. thing.emit('something');
  671. });
  672. it('shouldn\'t blow up on careless off() calls', function () {
  673. var thing = { foo: 'bar' };
  674. contra.emitter(thing);
  675. // the thing event type doesn't even exist.
  676. thing.off('something', function () {});
  677. });
  678. it('should turn off on() listeners', function (done) {
  679. var thing = { foo: 'bar' };
  680. contra.emitter(thing);
  681. function me () {
  682. a.fail(null, null, 'invoked on() listener');
  683. }
  684. thing.on('something', me);
  685. thing.off('something', me);
  686. thing.on('something', done);
  687. thing.emit('something');
  688. });
  689. it('should turn off once() listeners', function (done) {
  690. var thing = { foo: 'bar' };
  691. contra.emitter(thing);
  692. function me () {
  693. a.fail(null, null, 'invoked once() listener');
  694. }
  695. thing.once('something', me);
  696. thing.off('something', me);
  697. thing.on('something', done);
  698. thing.emit('something');
  699. });
  700. it('should blow up on error if no listeners', function (done) {
  701. var thing = { foo: 'bar' };
  702. contra.emitter(thing);
  703. a.throws(thing.emit.bind(thing, 'error'));
  704. done();
  705. });
  706. it('should work just fine with at least one error listener', function (done) {
  707. var thing = { foo: 'bar' };
  708. contra.emitter(thing);
  709. thing.on('error', function () {
  710. done();
  711. });
  712. a.doesNotThrow(thing.emit.bind(thing, 'error'));
  713. });
  714. });