diff --git a/lib/notify.js b/lib/notify.js index 5f6894394..8ad49ff61 100644 --- a/lib/notify.js +++ b/lib/notify.js @@ -8,7 +8,9 @@ const logger = require('./logger'); const handleNotify = function(metadata, notifyEntry) { let regex; if (metadata.name && notifyEntry.packagePattern) { - regex = new RegExp(notifyEntry.packagePattern, notifyEntry.packagePatternFlags || ''); + // FUTURE: comment out due https://github.com/verdaccio/verdaccio/pull/108#issuecomment-312421052 + // regex = new RegExp(notifyEntry.packagePattern, notifyEntry.packagePatternFlags || ''); + regex = new RegExp(notifyEntry.packagePattern); if (!regex.test(metadata.name)) { return; } @@ -44,26 +46,32 @@ const handleNotify = function(metadata, notifyEntry) { options.url = notifyEntry.endpoint; } - request(options, function(err, response, body) { - if (err) { - logger.logger.error({err: err}, ' notify error: @{err.message}' ); - } else { - logger.logger.info({content: content}, 'A notification has been shipped: @{content}'); - if (body) { - logger.logger.debug({body: body}, ' body: @{body}' ); + return new Promise(( resolve, reject) => { + request(options, function(err, response, body) { + if (err || response.statusCode >= 400) { + const errorMessage = _.isNil(err) ? response.statusMessage : err; + logger.logger.error({err: errorMessage}, ' notify error: @{err.message}' ); + reject(errorMessage); + } else { + logger.logger.info({content: content}, 'A notification has been shipped: @{content}'); + if (body) { + logger.logger.debug({body: body}, ' body: @{body}' ); + } + resolve(_.isNil(body) === false ? body : null); } - } + }); }); }; const notify = function(metadata, config) { if (config.notify) { if (config.notify.content) { - handleNotify(metadata, config.notify); + return handleNotify(metadata, config.notify); } else { + // multiple notifications endpoints PR #108 for (const key in config.notify) { if (config.notify.hasOwnProperty(key)) { - handleNotify(metadata, config.notify[key]); + return handleNotify(metadata, config.notify[key]); } } } diff --git a/test/functional/index.js b/test/functional/index.js index ea64ee2d7..460b1ad06 100644 --- a/test/functional/index.js +++ b/test/functional/index.js @@ -66,6 +66,7 @@ describe('Func', function() { require('./plugins')(); // requires packages published to server1/server2 require('./gh131')(); + require('./notify')(); after(function(done) { const check = (server) => { diff --git a/test/functional/lib/startup.js b/test/functional/lib/startup.js index 4b9ccca2b..e01991756 100644 --- a/test/functional/lib/startup.js +++ b/test/functional/lib/startup.js @@ -2,6 +2,7 @@ const _ = require('lodash'); const fork = require('child_process').fork; +const bodyParser = require('body-parser'); const express = require('express'); const rimRaf = require('rimraf'); const Server = require('./server'); @@ -10,7 +11,12 @@ const forks = process.forks = []; process.server = new Server('http://localhost:55551/'); process.server2 = new Server('http://localhost:55552/'); process.server3 = new Server('http://localhost:55553/'); -process.express = express(); +const app = express(); +app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ + extended: true +})); +process.express = app; process.express.listen(55550); module.exports.start = function(dir, conf) { diff --git a/test/functional/notify.js b/test/functional/notify.js new file mode 100644 index 000000000..d36816905 --- /dev/null +++ b/test/functional/notify.js @@ -0,0 +1,116 @@ +'use strict'; + +const assert = require('assert'); +const _ = require('lodash'); +const notify = require('../../lib/notify').notify; + +module.exports = function() { + const express = process.express; + + const config = { + notify: { + method: 'POST', + headers: [{ + 'Content-Type': 'application/json' + }], + endpoint: "http://localhost:55550/api/notify", + content: '{"color":"green","message":"New package published: * {{ name }}*","notify":true,"message_format":"text"}' + } + }; + + describe('notifications', function () { + + before(function () { + express.post('/api/notify', function (req, res) { + res.send(req.body); + }); + express.post('/api/notify/bad', function (req, res) { + res.status(400); + res.send('bad response'); + }); + }); + + it('notification should be send', function (done) { + const metadata = { + name: "pkg-test" + }; + + notify(metadata, config).then(function (body) { + const jsonBody = JSON.parse(body); + assert.ok(`New package published: * ${metadata.name}*` === jsonBody.message, + 'Body notify message should be equal'); + done(); + }, function (err) { + assert.fail(err); + done(); + }); + }); + + it('notification should be send single header', function (done) { + const metadata = { + name: "pkg-test" + }; + + const configMultipleHeader = _.cloneDeep(config); + configMultipleHeader.notify.headers = { + 'Content-Type': 'application/json' + }; + + notify(metadata, configMultipleHeader).then(function (body) { + const jsonBody = JSON.parse(body); + assert.ok(`New package published: * ${metadata.name}*` === jsonBody.message, + 'Body notify message should be equal'); + done(); + }, function (err) { + assert.fail(err); + done(); + }); + }); + + it('notification should be send multiple notifications endpoints', function (done) { + const metadata = { + name: "pkg-test" + }; + // let notificationsCounter = 0; + + const multipleNotificationsEndpoint = { + notify: [] + }; + + for (let i = 0; i < 10; i++) { + const notificationSettings = _.cloneDeep(config.notify); + // basically we allow al notifications + notificationSettings.packagePattern = /^pkg-test$/; + // notificationSettings.packagePatternFlags = 'i'; + multipleNotificationsEndpoint.notify.push(notificationSettings); + } + + notify(metadata, multipleNotificationsEndpoint).then(function (body) { + const jsonBody = JSON.parse(body); + assert.ok(`New package published: * ${metadata.name}*` === jsonBody.message, + 'Body notify message should be equal'); + done(); + }, function (err) { + assert.fail(err); + done(); + }); + }); + + it('notification should fails', function (done) { + const metadata = { + name: "pkg-test" + }; + const configFail = _.cloneDeep(config); + configFail.notify.endpoint = "http://localhost:55550/api/notify/bad"; + + notify(metadata, configFail).then(function () { + assert.equal(false, 'This service should fails with status code 400'); + done(); + }, function (err) { + assert.ok('Bad Request' === err, 'The error message should be "Bad Request'); + done(); + }); + }); + + }); +};