main.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. /*global describe, it*/
  2. "use strict";
  3. var gulp = require('gulp'),
  4. should = require('should'),
  5. through = require('through2'),
  6. plumber = require('gulp-plumber'),
  7. PluginError = require('plugin-error'),
  8. Vinyl = require('vinyl'),
  9. join = require('path').join,
  10. fs = require('fs'),
  11. notify = require('../');
  12. var mockGenerator = function (tester) {
  13. tester = tester || function () { };
  14. return function (opts, callback) {
  15. tester(opts);
  16. callback();
  17. };
  18. };
  19. var originalLogger = notify.logger();
  20. describe('gulp output stream', function() {
  21. beforeEach(function () {
  22. notify.logLevel(0);
  23. notify.logger(originalLogger);
  24. });
  25. describe('notify()', function() {
  26. it('should return a stream', function(done) {
  27. var stream = notify({
  28. notifier: mockGenerator()
  29. });
  30. should.exist(stream);
  31. should.exist(stream.on);
  32. should.exist(stream.pipe);
  33. done();
  34. });
  35. it('should allow setting of own reporter', function(done) {
  36. var notifier = notify.withReporter(mockGenerator);
  37. var stream = notifier();
  38. should.exist(stream);
  39. should.exist(stream.on);
  40. should.exist(stream.pipe);
  41. done();
  42. });
  43. it('should set message, title and have default icon of Gulp logo', function(done) {
  44. var testString = "this is a test";
  45. var expectedIcon = join(__dirname, '..', 'assets', 'gulp.png');
  46. var expectedFile = new Vinyl({
  47. path: "test/fixtures/1.txt",
  48. cwd: "test/",
  49. base: "test/fixtures/",
  50. contents: fs.createReadStream("test/fixtures/1.txt")
  51. });
  52. var mockedNotify = notify.withReporter(mockGenerator(function (opts) {
  53. opts.should.have.property('title');
  54. opts.should.have.property('message');
  55. opts.should.have.property('icon');
  56. String(opts.icon).should.equal(expectedIcon);
  57. String(opts.message).should.equal(testString);
  58. done();
  59. }.bind(this)));
  60. var outstream = mockedNotify({
  61. message: testString
  62. });
  63. outstream.write(expectedFile);
  64. });
  65. it('should be able to override default icon', function(done) {
  66. var testString = "this is a test";
  67. var expectedIcon = "testIcon";
  68. var expectedFile = new Vinyl({
  69. path: "test/fixtures/1.txt",
  70. cwd: "test/",
  71. base: "test/fixtures/",
  72. contents: fs.createReadStream("test/fixtures/1.txt")
  73. });
  74. var mockedNotify = notify.withReporter(mockGenerator(function (opts) {
  75. opts.should.have.property('title');
  76. opts.should.have.property('message');
  77. opts.should.have.property('icon');
  78. String(opts.icon).should.equal(expectedIcon);
  79. String(opts.message).should.equal(testString);
  80. done();
  81. }.bind(this)));
  82. var outstream = mockedNotify({
  83. message: testString,
  84. icon: expectedIcon
  85. });
  86. outstream.write(expectedFile);
  87. });
  88. it('should call notifier with extra options untouched', function(done) {
  89. var testString = "this is a test";
  90. var testIcon = "face-cool";
  91. var mockedNotify = notify.withReporter(mockGenerator(function (opts) {
  92. should.exist(opts);
  93. should.exist(opts.icon);
  94. should.exist(opts.message);
  95. String(opts.icon).should.equal(testIcon);
  96. String(opts.message).should.equal(testString);
  97. }));
  98. var instream = gulp.src(join(__dirname, "./fixtures/*.txt")),
  99. outstream = mockedNotify({
  100. message: testString,
  101. icon: testIcon
  102. });
  103. outstream.on('data', function(file) {
  104. should.exist(file);
  105. should.exist(file.path);
  106. should.exist(file.contents);
  107. });
  108. outstream.on('end', function() {
  109. done();
  110. });
  111. instream.pipe(outstream);
  112. });
  113. it('should emit error when sub-module returns error and emitError is true', function(done) {
  114. var mockedNotify = notify.withReporter(function (options, callback) {
  115. callback(new Error(testString));
  116. });
  117. var testString = "testString",
  118. instream = gulp.src(join(__dirname, "./fixtures/*.txt")),
  119. outstream = mockedNotify({
  120. message: testString,
  121. emitError: true
  122. });
  123. outstream.on('error', function (error) {
  124. should.exist(error);
  125. should.exist(error.message);
  126. String(error.message).should.equal(testString);
  127. done();
  128. });
  129. instream.pipe(outstream);
  130. });
  131. it('should pass on files', function(done) {
  132. var mockedNotify = notify.withReporter(mockGenerator());
  133. var
  134. testSuffix = "tester",
  135. srcFile = join(__dirname, "./fixtures/*"),
  136. instream = gulp.src(srcFile),
  137. outstream = mockedNotify();
  138. var numFilesBefore = 0,
  139. numFilesAfter = 0;
  140. instream
  141. .pipe(through.obj(function (file, enc, cb) {
  142. numFilesBefore++;
  143. this.push(file);
  144. cb();
  145. }, function (cb) {
  146. numFilesBefore.should.equal(3);
  147. cb();
  148. }))
  149. .pipe(outstream)
  150. .pipe(through.obj(function (file, enc, cb) {
  151. numFilesAfter++;
  152. this.push(file);
  153. cb();
  154. }, function (callback) {
  155. numFilesAfter.should.equal(3);
  156. done();
  157. }));
  158. });
  159. it('should pass on files even on error in notifier (with use of plumber)', function(done) {
  160. var
  161. testString = "tester",
  162. srcFile = join(__dirname, "./fixtures/*"),
  163. instream = gulp.src(srcFile),
  164. outstream = notify({
  165. notifier: function (options, callback) {
  166. callback(new Error(testString));
  167. }
  168. });
  169. var numFilesBefore = 0,
  170. numFilesAfter = 0;
  171. instream
  172. .pipe(plumber())
  173. .pipe(through.obj(function (file, enc, cb) {
  174. numFilesBefore++;
  175. this.push(file);
  176. cb();
  177. }, function (cb) {
  178. numFilesBefore.should.equal(3);
  179. cb();
  180. }))
  181. .pipe(outstream)
  182. .on('error', function (error) {
  183. error.message.should.equal(testString);
  184. })
  185. .pipe(through.obj(function (file, enc, cb) {
  186. numFilesAfter++;
  187. this.push(file);
  188. cb();
  189. }, function (callback) {
  190. numFilesAfter.should.equal(3);
  191. done();
  192. }));
  193. });
  194. it('should emit error when sub-module throws exception/error and emitError flag is true', function(done) {
  195. var testString = "some exception",
  196. instream = gulp.src(join(__dirname, "./fixtures/*.txt")),
  197. outstream = notify({
  198. message: testString,
  199. notifier: function (options, callback) {
  200. throw new Error(testString);
  201. },
  202. emitError: true
  203. });
  204. outstream.on('error', function (error) {
  205. should.exist(error);
  206. should.exist(error.message);
  207. String(error.message).should.equal(testString);
  208. done();
  209. });
  210. instream.pipe(outstream);
  211. });
  212. it('should not emit error when sub-module throws exception/error if emitError flag is false (default)', function(done) {
  213. notify.logLevel(1);
  214. notify.logger(function () {
  215. should.exist(true);
  216. done();
  217. });
  218. var testString = "some exception",
  219. expectedFile = new Vinyl({
  220. path: "test/fixtures/1.txt",
  221. cwd: "test/",
  222. base: "test/fixtures/",
  223. contents: fs.createReadStream("test/fixtures/1.txt")
  224. }),
  225. outstream = notify({
  226. message: testString,
  227. notifier: function (options, callback) {
  228. throw new Error(testString);
  229. }
  230. });
  231. outstream.on('error', function (error) {
  232. should.not.exist(error);
  233. should.not.exist(error.message);
  234. String(error.message).should.not.equal(testString);
  235. done();
  236. });
  237. outstream.on('end', function () {
  238. done();
  239. });
  240. outstream.write(expectedFile);
  241. outstream.write(null);
  242. outstream.end();
  243. });
  244. it('should default to notifying file path and default title', function(done) {
  245. var srcFile = join(__dirname, "./fixtures/1.txt");
  246. var instream = gulp.src(srcFile),
  247. outstream = notify({
  248. notifier: mockGenerator(function (opts) {
  249. should.exist(opts);
  250. should.exist(opts.title);
  251. should.exist(opts.message);
  252. String(opts.message).should.equal(srcFile);
  253. String(opts.title).should.equal("Gulp notification");
  254. })
  255. });
  256. outstream.on('data', function(file) {
  257. should.exist(file);
  258. should.exist(file.path);
  259. should.exist(file.contents);
  260. });
  261. outstream.on('end', function() {
  262. done();
  263. });
  264. instream.pipe(outstream);
  265. });
  266. it('should take function with file as argument, as message or title', function(done) {
  267. var
  268. testSuffix = "tester",
  269. srcFile = join(__dirname, "./fixtures/1.txt"),
  270. instream = gulp.src(srcFile),
  271. outstream = notify({
  272. notifier: mockGenerator(function (opts) {
  273. should.exist(opts);
  274. should.exist(opts.title);
  275. should.exist(opts.message);
  276. String(opts.message).should.equal(srcFile + testSuffix);
  277. String(opts.title).should.equal(srcFile + testSuffix);
  278. }),
  279. message: function (file) {
  280. String(file.path).should.equal(srcFile);
  281. return file.path + testSuffix;
  282. },
  283. title: function (file) {
  284. String(file.path).should.equal(srcFile);
  285. return file.path + testSuffix;
  286. }
  287. });
  288. outstream.on('data', function(file) {
  289. should.exist(file);
  290. should.exist(file.path);
  291. should.exist(file.contents);
  292. });
  293. outstream.on('end', function() {
  294. done();
  295. });
  296. instream.pipe(outstream);
  297. });
  298. it('should notify on all files per default', function(done) {
  299. var
  300. testSuffix = "tester",
  301. srcFile = join(__dirname, "./fixtures/*"),
  302. instream = gulp.src(srcFile),
  303. numFunctionCalls = 0,
  304. outstream = notify({
  305. notifier: mockGenerator(function (opts) {
  306. should.exist(opts);
  307. should.exist(opts.title);
  308. should.exist(opts.message);
  309. numFunctionCalls++;
  310. })
  311. });
  312. outstream.on('data', function(file) {
  313. should.exist(file);
  314. should.exist(file.path);
  315. should.exist(file.contents);
  316. });
  317. outstream.on('end', function() {
  318. numFunctionCalls.should.equal(3);
  319. done();
  320. });
  321. instream.pipe(outstream)
  322. });
  323. it('should handle streamed files', function (done) {
  324. var expectedFile = new Vinyl({
  325. path: "test/fixtures/1.txt",
  326. cwd: "test/",
  327. base: "test/fixtures/",
  328. contents: fs.createReadStream("test/fixtures/1.txt")
  329. });
  330. var testString = "testString";
  331. var outstream = notify({
  332. message: testString,
  333. notifier: mockGenerator(function (opts) {
  334. should.exist(opts);
  335. should.exist(opts.title);
  336. should.exist(opts.message);
  337. String(opts.message).should.equal(testString);
  338. })
  339. });
  340. outstream.on('error', function (err) {
  341. should.not.exist(err);
  342. });
  343. outstream.on('data', function(file) {
  344. should.exist(file);
  345. should.exist(file.isStream());
  346. should.exist(file.path);
  347. should.exist(file.contents);
  348. done();
  349. });
  350. outstream.write(expectedFile);
  351. });
  352. it('should support lodash template for titles and messages', function (done) {
  353. var expectedFile = new Vinyl({
  354. path: "test/fixtures/1.txt",
  355. cwd: "test/",
  356. base: "test/fixtures/",
  357. contents: fs.createReadStream("test/fixtures/1.txt")
  358. });
  359. var testString = "Template: <%= file.relative %>";
  360. var expectedString = "Template: 1.txt";
  361. var outstream = notify({
  362. message: testString,
  363. title: testString,
  364. notifier: mockGenerator(function (opts) {
  365. should.exist(opts);
  366. should.exist(opts.title);
  367. should.exist(opts.message);
  368. String(opts.message).should.equal(expectedString);
  369. String(opts.title).should.equal(expectedString);
  370. })
  371. });
  372. outstream.on('error', function (err) {
  373. should.not.exist(err);
  374. });
  375. outstream.on('data', function(file) {
  376. should.exist(file);
  377. should.exist(file.path);
  378. should.exist(file.contents);
  379. done();
  380. });
  381. outstream.write(expectedFile);
  382. });
  383. });
  384. describe('notify.onLast', function() {
  385. it('should only notify on the last file, if onLast flag is activated', function(done) {
  386. var
  387. testSuffix = "tester",
  388. srcFile = join(__dirname, "./fixtures/*"),
  389. instream = gulp.src(srcFile),
  390. numFunctionCalls = 0,
  391. outstream = notify({
  392. onLast: true,
  393. notifier: mockGenerator(function (opts) {
  394. should.exist(opts);
  395. should.exist(opts.title);
  396. should.exist(opts.message);
  397. numFunctionCalls++;
  398. })
  399. });
  400. outstream.on('data', function(file) {
  401. should.exist(file);
  402. should.exist(file.path);
  403. should.exist(file.contents);
  404. });
  405. outstream.on('end', function() {
  406. numFunctionCalls.should.equal(1);
  407. done();
  408. });
  409. instream.pipe(outstream);
  410. });
  411. it('should stream all files even if onLast is activated', function(done) {
  412. var
  413. testSuffix = "tester",
  414. srcFile = join(__dirname, "./fixtures/*"),
  415. instream = gulp.src(srcFile),
  416. outstream = notify({
  417. onLast: true,
  418. notifier: mockGenerator()
  419. });
  420. var numFilesBefore = 0,
  421. numFilesAfter = 0;
  422. instream
  423. .pipe(through.obj(function (file, enc, cb) {
  424. numFilesBefore++;
  425. this.push(file);
  426. cb();
  427. }, function (cb) {
  428. numFilesBefore.should.equal(3);
  429. cb();
  430. }))
  431. .pipe(outstream)
  432. .pipe(through.obj(function (file, enc, cb) {
  433. numFilesAfter++;
  434. this.push(file);
  435. cb();
  436. }, function (callback) {
  437. numFilesAfter.should.equal(3);
  438. done();
  439. }));
  440. });
  441. it('should support lodash template for titles and messages when onLast', function (done) {
  442. var
  443. testSuffix = "tester",
  444. srcFile = join(__dirname, "./fixtures/*"),
  445. instream = gulp.src(srcFile),
  446. numFunctionCalls = 0,
  447. outstream = notify({
  448. onLast: true,
  449. message: 'Template: <%= file.relative %>',
  450. notifier: mockGenerator(function (opts) {
  451. should.exist(opts);
  452. should.exist(opts.title);
  453. should.exist(opts.message);
  454. opts.message.should.startWith('Template:')
  455. opts.message.should.endWith('.txt')
  456. numFunctionCalls++;
  457. })
  458. });
  459. outstream.on('data', function(file) {
  460. should.exist(file);
  461. should.exist(file.path);
  462. should.exist(file.contents);
  463. });
  464. outstream.on('end', function() {
  465. numFunctionCalls.should.equal(1);
  466. done();
  467. });
  468. instream.pipe(outstream);
  469. });
  470. });
  471. describe('notify.logger()', function() {
  472. it('should allow setting of logLevel', function(done) {
  473. var notifier = notify.withReporter(mockGenerator);
  474. should.exist(notify.logLevel);
  475. should.exist(notify.logger);
  476. done();
  477. });
  478. it('should log error on log level 1', function(done) {
  479. var srcFile = join(__dirname, "./fixtures/1.txt");
  480. notify.logLevel(1);
  481. notify.logger(function (options) {
  482. should.exist(true);
  483. done();
  484. });
  485. var notifier = notify.withReporter(mockGenerator);
  486. gulp.src(srcFile)
  487. .pipe(through.obj(function (file, enc, cb) {
  488. this.emit("error", new PluginError("testPlugin", "foo"));
  489. cb();
  490. }))
  491. .on("error", notifier.onError())
  492. });
  493. it('should not log on log level 0', function(done) {
  494. var srcFile = join(__dirname, "./fixtures/1.txt");
  495. var hasBeenCalled = false;
  496. notify.logLevel(0);
  497. notify.logger(function () {
  498. hasBeenCalled = true;
  499. should.not.exist(arguments);
  500. });
  501. var notifier = notify.withReporter(mockGenerator(function () {
  502. should(hasBeenCalled).equal(false);
  503. done();
  504. }));
  505. gulp.src(srcFile)
  506. .pipe(through.obj(function (file, enc, cb) {
  507. this.emit("error", new PluginError("testPlugin", "foo"));
  508. cb();
  509. }))
  510. .on("error", notifier.onError())
  511. });
  512. });
  513. describe('notify.onError()', function() {
  514. it('should have defined onError function on object', function (done) {
  515. should.exist(notify.onError);
  516. done();
  517. });
  518. it('should have onError event withReporter', function(done) {
  519. var notifier = notify.withReporter(mockGenerator);
  520. should.exist(notifier.onError);
  521. done();
  522. });
  523. it('should call end on stream', function (done) {
  524. var onError = notify.onError({
  525. notifier: mockGenerator(function (opts) { })
  526. });
  527. var stream = through.obj(function (file, enc, cb) {
  528. this.emit('error', 'error');
  529. cb();
  530. });
  531. stream.on('error', onError).on('end', done);
  532. stream.write({});
  533. });
  534. it('should be limited by notifying on error if th onError-option is passed', function (done) {
  535. var
  536. testMessage = "tester",
  537. srcFile = join(__dirname, "./fixtures/*"),
  538. onError = notify.onError({
  539. notifier: mockGenerator(function (opts) {
  540. should.exist(opts);
  541. should.exist(opts.title);
  542. should.exist(opts.message);
  543. String(opts.message).should.equal(testMessage);
  544. String(opts.title).should.equal("Error running Gulp");
  545. done();
  546. })
  547. });
  548. gulp.src(srcFile)
  549. .pipe(through.obj(function (file, enc, cb) {
  550. this.emit("error", new PluginError("testPlugin", testMessage));
  551. cb();
  552. }))
  553. .on("error", onError)
  554. });
  555. it('should have onError options on withReporter sugar', function (done) {
  556. var
  557. testMessage = "tester",
  558. srcFile = join(__dirname, "./fixtures/*");
  559. var custom = notify.withReporter(mockGenerator(function (opts) {
  560. should.exist(opts);
  561. should.exist(opts.title);
  562. should.exist(opts.message);
  563. String(opts.message).should.equal(testMessage);
  564. String(opts.title).should.equal("Error running Gulp");
  565. done();
  566. }));
  567. gulp.src(srcFile)
  568. .pipe(through.obj(function (file, enc, cb) {
  569. this.emit("error", new PluginError("testPlugin", testMessage));
  570. cb();
  571. }))
  572. .on("error", custom.onError())
  573. });
  574. it('should have default Gulp-error logo onError', function (done) {
  575. var expectedIcon = join(__dirname, '..', 'assets', 'gulp-error.png');
  576. var
  577. testMessage = "tester",
  578. srcFile = join(__dirname, "./fixtures/*");
  579. var custom = notify.withReporter(mockGenerator(function (opts) {
  580. should.exist(opts);
  581. should.exist(opts.title);
  582. should.exist(opts.message);
  583. should.exist(opts.icon);
  584. String(opts.message).should.equal(testMessage);
  585. String(opts.icon).should.equal(expectedIcon);
  586. String(opts.title).should.equal("Error running Gulp");
  587. done();
  588. }));
  589. gulp.src(srcFile)
  590. .pipe(through.obj(function (file, enc, cb) {
  591. this.emit("error", new PluginError("testPlugin", testMessage));
  592. cb();
  593. }))
  594. .on("error", custom.onError())
  595. });
  596. it('should be able to override default icon onError', function (done) {
  597. var expectedIcon = "testIcon";
  598. var testMessage = "tester";
  599. var custom = notify.withReporter(mockGenerator(function (opts) {
  600. should.exist(opts);
  601. should.exist(opts.title);
  602. should.exist(opts.message);
  603. should.exist(opts.icon);
  604. String(opts.message).should.equal(testMessage);
  605. String(opts.icon).should.equal(expectedIcon);
  606. String(opts.title).should.equal("Error running Gulp");
  607. done();
  608. }));
  609. custom.onError({
  610. icon: expectedIcon,
  611. })(new PluginError("testPlugin", testMessage));
  612. });
  613. it('should have Frog sound per default onError', function (done) {
  614. var expectedIcon = "testIcon";
  615. var testMessage = "tester";
  616. var custom = notify.withReporter(mockGenerator(function (opts) {
  617. should.exist(opts);
  618. should.exist(opts.sound);
  619. String(opts.sound).should.equal('Frog');
  620. done();
  621. }));
  622. custom.onError({
  623. icon: expectedIcon,
  624. })(new PluginError("testPlugin", testMessage));
  625. });
  626. it('should support lodash template for titles and messages on onError', function (done) {
  627. var testString = "Template: <%= error.message %>";
  628. var expectedString = "Template: test";
  629. var srcFile = join(__dirname, "./fixtures/*");
  630. var onError = notify.onError({
  631. message: testString,
  632. title: testString,
  633. notifier: mockGenerator(function (opts) {
  634. should.exist(opts);
  635. should.exist(opts.title);
  636. should.exist(opts.message);
  637. String(opts.message).should.equal(expectedString);
  638. String(opts.title).should.equal(expectedString);
  639. done();
  640. })
  641. });
  642. gulp.src(srcFile)
  643. .pipe(through.obj(function (file, enc, cb) {
  644. this.emit("error", new PluginError("testPlugin", "test"));
  645. cb();
  646. }))
  647. .on('error', onError);
  648. });
  649. });
  650. });