mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Merge pull request #6335 from damsonn/fix-mailer-specs
Improve test coverage for mailer
This commit is contained in:
commit
15cb71b408
4 changed files with 183 additions and 186 deletions
|
@ -62,19 +62,15 @@ GhostMailer.prototype.getDomain = function () {
|
||||||
// This assumes that api.settings.read('email') was already done on the API level
|
// This assumes that api.settings.read('email') was already done on the API level
|
||||||
GhostMailer.prototype.send = function (message) {
|
GhostMailer.prototype.send = function (message) {
|
||||||
var self = this,
|
var self = this,
|
||||||
to,
|
to;
|
||||||
sendMail;
|
|
||||||
|
|
||||||
message = message || {};
|
// important to clone message as we modify it
|
||||||
|
message = _.clone(message) || {};
|
||||||
to = message.to || false;
|
to = message.to || false;
|
||||||
|
|
||||||
if (!this.transport) {
|
|
||||||
return Promise.reject(new Error(i18n.t('errors.mail.noEmailTransportConfigured.error')));
|
|
||||||
}
|
|
||||||
if (!(message && message.subject && message.html && message.to)) {
|
if (!(message && message.subject && message.html && message.to)) {
|
||||||
return Promise.reject(new Error(i18n.t('errors.mail.incompleteMessageData.error')));
|
return Promise.reject(new Error(i18n.t('errors.mail.incompleteMessageData.error')));
|
||||||
}
|
}
|
||||||
sendMail = Promise.promisify(self.transport.sendMail.bind(self.transport));
|
|
||||||
|
|
||||||
message = _.extend(message, {
|
message = _.extend(message, {
|
||||||
from: self.from(),
|
from: self.from(),
|
||||||
|
@ -84,7 +80,7 @@ GhostMailer.prototype.send = function (message) {
|
||||||
});
|
});
|
||||||
|
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
sendMail(message, function (error, response) {
|
self.transport.sendMail(message, function (error, response) {
|
||||||
if (error) {
|
if (error) {
|
||||||
return reject(new Error(error));
|
return reject(new Error(error));
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,9 +191,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"mail": {
|
"mail": {
|
||||||
"noEmailTransportConfigured": {
|
|
||||||
"error": "Error: No email transport configured."
|
|
||||||
},
|
|
||||||
"incompleteMessageData": {
|
"incompleteMessageData": {
|
||||||
"error": "Error: Incomplete message data."
|
"error": "Error: Incomplete message data."
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,21 +4,13 @@ var testUtils = require('../../utils'),
|
||||||
should = require('should'),
|
should = require('should'),
|
||||||
config = require('../../../server/config'),
|
config = require('../../../server/config'),
|
||||||
mailer = require('../../../server/mail'),
|
mailer = require('../../../server/mail'),
|
||||||
i18n = require('../../../../core/server/i18n'),
|
i18n = require('../../../../core/server/i18n'),
|
||||||
|
|
||||||
// Stuff we are testing
|
// Stuff we are testing
|
||||||
MailAPI = require('../../../server/api/mail'),
|
MailAPI = require('../../../server/api/mail'),
|
||||||
mailDataNoDomain = {
|
|
||||||
mail: [{
|
// test data
|
||||||
message: {
|
mailData = {
|
||||||
to: 'joe@doesntexistexample091283zalgo.com',
|
|
||||||
subject: 'testemail',
|
|
||||||
html: '<p>This</p>'
|
|
||||||
},
|
|
||||||
options: {}
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
mailDataNoServer = {
|
|
||||||
mail: [{
|
mail: [{
|
||||||
message: {
|
message: {
|
||||||
to: 'joe@example.com',
|
to: 'joe@example.com',
|
||||||
|
@ -27,15 +19,6 @@ var testUtils = require('../../utils'),
|
||||||
},
|
},
|
||||||
options: {}
|
options: {}
|
||||||
}]
|
}]
|
||||||
},
|
|
||||||
mailDataIncomplete = {
|
|
||||||
mail: [{
|
|
||||||
message: {
|
|
||||||
subject: 'testemail',
|
|
||||||
html: '<p>This</p>'
|
|
||||||
},
|
|
||||||
options: {}
|
|
||||||
}]
|
|
||||||
};
|
};
|
||||||
i18n.init();
|
i18n.init();
|
||||||
|
|
||||||
|
@ -46,106 +29,34 @@ describe('Mail API', function () {
|
||||||
|
|
||||||
should.exist(MailAPI);
|
should.exist(MailAPI);
|
||||||
|
|
||||||
describe('Nothing configured', function () {
|
it('returns a success', function (done) {
|
||||||
it('return no email configured', function (done) {
|
config.set({mail: {transport: 'stub'}});
|
||||||
MailAPI.send(mailDataNoServer, testUtils.context.internal).then(function (response) {
|
|
||||||
/*jshint unused:false */
|
|
||||||
done();
|
|
||||||
}).catch(function (error) {
|
|
||||||
error.message.should.eql('Error: No email transport configured.');
|
|
||||||
error.errorType.should.eql('EmailError');
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('return no email configured even when sending incomplete data', function (done) {
|
mailer.init().then(function () {
|
||||||
MailAPI.send(mailDataIncomplete, testUtils.context.internal).then(function (response) {
|
mailer.transport.transportType.should.eql('STUB');
|
||||||
/*jshint unused:false */
|
return MailAPI.send(mailData, testUtils.context.internal);
|
||||||
done();
|
}).then(function (response) {
|
||||||
}).catch(function (error) {
|
should.exist(response.mail);
|
||||||
error.message.should.eql('Error: No email transport configured.');
|
should.exist(response.mail[0].message);
|
||||||
error.errorType.should.eql('EmailError');
|
should.exist(response.mail[0].status);
|
||||||
done();
|
|
||||||
}).catch(done);
|
response.mail[0].message.subject.should.eql('testemail');
|
||||||
});
|
done();
|
||||||
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Mail API Direct', function () {
|
it('returns a boo boo', function (done) {
|
||||||
before(function (done) {
|
config.set({mail: {transport: 'stub', options: {error: 'Stub made a boo boo :('}}});
|
||||||
config.set({mail: {}});
|
|
||||||
|
|
||||||
mailer.init().then(function () {
|
mailer.init().then(function () {
|
||||||
done();
|
mailer.transport.transportType.should.eql('STUB');
|
||||||
});
|
return MailAPI.send(mailData, testUtils.context.internal);
|
||||||
});
|
}).then(function () {
|
||||||
|
done(new Error('Stub did not error'));
|
||||||
it('return correct failure message for domain doesn\'t exist', function (done) {
|
}).catch(function (error) {
|
||||||
mailer.transport.transportType.should.eql('DIRECT');
|
error.message.should.startWith('Error: Stub made a boo boo :(');
|
||||||
return MailAPI.send(mailDataNoDomain, testUtils.context.internal).then(function () {
|
error.errorType.should.eql('EmailError');
|
||||||
done(new Error('Error message not shown.'));
|
done();
|
||||||
}, function (error) {
|
}).catch(done);
|
||||||
error.message.should.startWith('Error: Failed to send email');
|
|
||||||
error.errorType.should.eql('EmailError');
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
// This test doesn't work properly - it times out locally
|
|
||||||
it.skip('return correct failure message for no mail server at this address', function (done) {
|
|
||||||
mailer.transport.transportType.should.eql('DIRECT');
|
|
||||||
MailAPI.send(mailDataNoServer, testUtils.context.internal).then(function () {
|
|
||||||
done(new Error('Error message not shown.'));
|
|
||||||
}, function (error) {
|
|
||||||
error.message.should.eql('Error: Failed to send email.');
|
|
||||||
error.errorType.should.eql('EmailError');
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('return correct failure message for incomplete data', function (done) {
|
|
||||||
mailer.transport.transportType.should.eql('DIRECT');
|
|
||||||
|
|
||||||
MailAPI.send(mailDataIncomplete, testUtils.context.internal).then(function () {
|
|
||||||
done(new Error('Error message not shown.'));
|
|
||||||
}, function (error) {
|
|
||||||
error.message.should.eql('Error: Incomplete message data.');
|
|
||||||
error.errorType.should.eql('EmailError');
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe.skip('Stub', function () {
|
|
||||||
it('returns a success', function (done) {
|
|
||||||
config.set({mail: {transport: 'stub'}});
|
|
||||||
|
|
||||||
mailer.init().then(function () {
|
|
||||||
mailer.transport.transportType.should.eql('STUB');
|
|
||||||
return MailAPI.send(mailDataNoServer, testUtils.context.internal);
|
|
||||||
}).then(function (response) {
|
|
||||||
should.exist(response.mail);
|
|
||||||
should.exist(response.mail[0].message);
|
|
||||||
should.exist(response.mail[0].status);
|
|
||||||
response.mail[0].status.should.eql({message: 'Message Queued'});
|
|
||||||
response.mail[0].message.subject.should.eql('testemail');
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns a boo boo', function (done) {
|
|
||||||
config.set({mail: {transport: 'stub', error: 'Stub made a boo boo :('}});
|
|
||||||
|
|
||||||
mailer.init().then(function () {
|
|
||||||
mailer.transport.transportType.should.eql('STUB');
|
|
||||||
return MailAPI.send(mailDataNoServer, testUtils.context.internal);
|
|
||||||
}).then(function (response) {
|
|
||||||
console.log('res', response.mail[0]);
|
|
||||||
done(new Error('Stub did not error'));
|
|
||||||
}, function (error) {
|
|
||||||
error.message.should.startWith('Error: Failed to send email - no mail server found at');
|
|
||||||
error.errorType.should.eql('EmailError');
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/*globals describe, afterEach, it*/
|
/*globals describe, afterEach, beforeEach, it*/
|
||||||
/*jshint expr:true*/
|
/*jshint expr:true*/
|
||||||
var should = require('should'),
|
var should = require('should'),
|
||||||
Promise = require('bluebird'),
|
Promise = require('bluebird'),
|
||||||
|
@ -8,20 +8,35 @@ var should = require('should'),
|
||||||
configUtils = require('../utils/configUtils'),
|
configUtils = require('../utils/configUtils'),
|
||||||
i18n = require('../../server/i18n'),
|
i18n = require('../../server/i18n'),
|
||||||
|
|
||||||
SMTP;
|
// Mock SMTP config
|
||||||
i18n.init();
|
SMTP = {
|
||||||
|
transport: 'SMTP',
|
||||||
// Mock SMTP config
|
options: {
|
||||||
SMTP = {
|
service: 'Gmail',
|
||||||
transport: 'SMTP',
|
auth: {
|
||||||
options: {
|
user: 'nil',
|
||||||
service: 'Gmail',
|
pass: '123'
|
||||||
auth: {
|
}
|
||||||
user: 'nil',
|
|
||||||
pass: '123'
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
|
||||||
|
// test data
|
||||||
|
mailDataNoDomain = {
|
||||||
|
to: 'joe@doesntexistexample091283zalgo.com',
|
||||||
|
subject: 'testemail',
|
||||||
|
html: '<p>This</p>'
|
||||||
|
},
|
||||||
|
mailDataNoServer = {
|
||||||
|
to: 'joe@example.com',
|
||||||
|
subject: 'testemail',
|
||||||
|
html: '<p>This</p>'
|
||||||
|
},
|
||||||
|
mailDataIncomplete = {
|
||||||
|
subject: 'testemail',
|
||||||
|
html: '<p>This</p>'
|
||||||
|
};
|
||||||
|
|
||||||
|
i18n.init();
|
||||||
|
|
||||||
describe('Mail', function () {
|
describe('Mail', function () {
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
|
@ -54,6 +69,34 @@ describe('Mail', function () {
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('sends valid message successfully ', function (done) {
|
||||||
|
configUtils.set({mail: {transport: 'stub'}});
|
||||||
|
|
||||||
|
mailer.init().then(function () {
|
||||||
|
mailer.transport.transportType.should.eql('STUB');
|
||||||
|
return mailer.send(mailDataNoServer);
|
||||||
|
}).then(function (response) {
|
||||||
|
should.exist(response.message);
|
||||||
|
should.exist(response.envelope);
|
||||||
|
response.envelope.to.should.containEql('joe@example.com');
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles failure', function (done) {
|
||||||
|
configUtils.set({mail: {transport: 'stub', options: {error: 'Stub made a boo boo :('}}});
|
||||||
|
|
||||||
|
mailer.init().then(function () {
|
||||||
|
mailer.transport.transportType.should.eql('STUB');
|
||||||
|
return mailer.send(mailDataNoServer);
|
||||||
|
}).then(function () {
|
||||||
|
done(new Error('Stub did not error'));
|
||||||
|
}).catch(function (error) {
|
||||||
|
error.message.should.eql('Error: Stub made a boo boo :(');
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
it('should fail to send messages when given insufficient data', function (done) {
|
it('should fail to send messages when given insufficient data', function (done) {
|
||||||
Promise.settle([
|
Promise.settle([
|
||||||
mailer.send(),
|
mailer.send(),
|
||||||
|
@ -70,60 +113,110 @@ describe('Mail', function () {
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should use from address as configured in config.js', function () {
|
describe('Direct', function () {
|
||||||
configUtils.set({
|
beforeEach(function (done) {
|
||||||
mail: {
|
configUtils.set({mail: {}});
|
||||||
from: '"Blog Title" <static@example.com>'
|
|
||||||
}
|
mailer.init().then(function () {
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('return correct failure message for domain doesn\'t exist', function (done) {
|
||||||
|
mailer.transport.transportType.should.eql('DIRECT');
|
||||||
|
|
||||||
|
mailer.send(mailDataNoDomain).then(function () {
|
||||||
|
done(new Error('Error message not shown.'));
|
||||||
|
}, function (error) {
|
||||||
|
error.message.should.startWith('Error: Failed to send email');
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('return correct failure message for no mail server at this address', function (done) {
|
||||||
|
mailer.transport.transportType.should.eql('DIRECT');
|
||||||
|
|
||||||
|
mailer.send(mailDataNoServer).then(function () {
|
||||||
|
done(new Error('Error message not shown.'));
|
||||||
|
}, function (error) {
|
||||||
|
error.message.should.eql('Error: Failed to send email.');
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('return correct failure message for incomplete data', function (done) {
|
||||||
|
mailer.transport.transportType.should.eql('DIRECT');
|
||||||
|
|
||||||
|
mailer.send(mailDataIncomplete).then(function () {
|
||||||
|
done(new Error('Error message not shown.'));
|
||||||
|
}, function (error) {
|
||||||
|
error.message.should.eql('Error: Incomplete message data.');
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
});
|
});
|
||||||
mailer.from().should.equal('"Blog Title" <static@example.com>');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fall back to [blog.title] <ghost@[blog.url]> as from address', function () {
|
describe('From address', function () {
|
||||||
// Standard domain
|
it('should use the config', function () {
|
||||||
configUtils.set({url: 'http://default.com', mail: {from: null}, theme: {title: 'Test'}});
|
configUtils.set({
|
||||||
mailer.from().should.equal('"Test" <ghost@default.com>');
|
mail: {
|
||||||
|
from: '"Blog Title" <static@example.com>'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mailer.from().should.equal('"Blog Title" <static@example.com>');
|
||||||
|
});
|
||||||
|
|
||||||
// Trailing slash
|
it('should fall back to [blog.title] <ghost@[blog.url]>', function () {
|
||||||
configUtils.set({url: 'http://default.com/', mail: {from: null}, theme: {title: 'Test'}});
|
// Standard domain
|
||||||
mailer.from().should.equal('"Test" <ghost@default.com>');
|
configUtils.set({url: 'http://default.com', mail: {from: null}, theme: {title: 'Test'}});
|
||||||
|
mailer.from().should.equal('"Test" <ghost@default.com>');
|
||||||
|
|
||||||
// Strip Port
|
// Trailing slash
|
||||||
configUtils.set({url: 'http://default.com:2368/', mail: {from: null}, theme: {title: 'Test'}});
|
configUtils.set({url: 'http://default.com/', mail: {from: null}, theme: {title: 'Test'}});
|
||||||
mailer.from().should.equal('"Test" <ghost@default.com>');
|
mailer.from().should.equal('"Test" <ghost@default.com>');
|
||||||
});
|
|
||||||
|
|
||||||
it('should use mail.from if both from and fromaddress are present', function () {
|
// Strip Port
|
||||||
// Standard domain
|
configUtils.set({url: 'http://default.com:2368/', mail: {from: null}, theme: {title: 'Test'}});
|
||||||
configUtils.set({mail: {from: '"bar" <from@default.com>', fromaddress: '"Qux" <fa@default.com>'}});
|
mailer.from().should.equal('"Test" <ghost@default.com>');
|
||||||
mailer.from().should.equal('"bar" <from@default.com>');
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('should attach blog title if from or fromaddress are only email addresses', function () {
|
it('should use mail.from if both from and fromaddress are present', function () {
|
||||||
// from and fromaddress are both set
|
// Standard domain
|
||||||
configUtils.set({mail: {from: 'from@default.com', fromaddress: 'fa@default.com'}, theme: {title: 'Test'}});
|
configUtils.set({mail: {from: '"bar" <from@default.com>', fromaddress: '"Qux" <fa@default.com>'}});
|
||||||
mailer.from().should.equal('"Test" <from@default.com>');
|
mailer.from().should.equal('"bar" <from@default.com>');
|
||||||
|
});
|
||||||
|
|
||||||
// only from set
|
it('should attach blog title if from or fromaddress are only email addresses', function () {
|
||||||
configUtils.set({mail: {from: 'from@default.com', fromaddress: null}, theme: {title: 'Test'}});
|
// from and fromaddress are both set
|
||||||
mailer.from().should.equal('"Test" <from@default.com>');
|
configUtils.set({mail: {from: 'from@default.com', fromaddress: 'fa@default.com'}, theme: {title: 'Test'}});
|
||||||
|
mailer.from().should.equal('"Test" <from@default.com>');
|
||||||
|
|
||||||
// only fromaddress set
|
// only from set
|
||||||
configUtils.set({mail: {from: null, fromaddress: 'fa@default.com'}, theme: {title: 'Test'}});
|
configUtils.set({mail: {from: 'from@default.com', fromaddress: null}, theme: {title: 'Test'}});
|
||||||
mailer.from().should.equal('"Test" <fa@default.com>');
|
mailer.from().should.equal('"Test" <from@default.com>');
|
||||||
});
|
|
||||||
|
|
||||||
it('should ignore theme title if from address is Title <email@address.com> format', function () {
|
// only fromaddress set
|
||||||
// from and fromaddress are both set
|
configUtils.set({mail: {from: null, fromaddress: 'fa@default.com'}, theme: {title: 'Test'}});
|
||||||
configUtils.set({mail: {from: '"R2D2" <from@default.com>', fromaddress: '"C3PO" <fa@default.com>'}, theme: {title: 'Test'}});
|
mailer.from().should.equal('"Test" <fa@default.com>');
|
||||||
mailer.from().should.equal('"R2D2" <from@default.com>');
|
});
|
||||||
|
|
||||||
// only from set
|
it('should ignore theme title if from address is Title <email@address.com> format', function () {
|
||||||
configUtils.set({mail: {from: '"R2D2" <from@default.com>', fromaddress: null}, theme: {title: 'Test'}});
|
// from and fromaddress are both set
|
||||||
mailer.from().should.equal('"R2D2" <from@default.com>');
|
configUtils.set({mail: {from: '"R2D2" <from@default.com>', fromaddress: '"C3PO" <fa@default.com>'}, theme: {title: 'Test'}});
|
||||||
|
mailer.from().should.equal('"R2D2" <from@default.com>');
|
||||||
|
|
||||||
// only fromaddress set
|
// only from set
|
||||||
configUtils.set({mail: {from: null, fromaddress: '"C3PO" <fa@default.com>'}, theme: {title: 'Test'}});
|
configUtils.set({mail: {from: '"R2D2" <from@default.com>', fromaddress: null}, theme: {title: 'Test'}});
|
||||||
mailer.from().should.equal('"C3PO" <fa@default.com>');
|
mailer.from().should.equal('"R2D2" <from@default.com>');
|
||||||
|
|
||||||
|
// only fromaddress set
|
||||||
|
configUtils.set({mail: {from: null, fromaddress: '"C3PO" <fa@default.com>'}, theme: {title: 'Test'}});
|
||||||
|
mailer.from().should.equal('"C3PO" <fa@default.com>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use default title if not theme title is provided', function () {
|
||||||
|
configUtils.set({url: 'http://default.com:2368/', mail: {from: null}, theme: {title: null}});
|
||||||
|
mailer.from().should.equal('"Ghost at default.com" <ghost@default.com>');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue