/* eslint-disable global-require */ import got from 'got'; import nconf from 'nconf'; import requireAgain from 'require-again'; import { TAVERN_ID } from '../../../../website/server/models/group'; import { defer } from '../../../helpers/api-unit.helper'; function getUser () { return { _id: 'random _id', auth: { local: { username: 'username', email: 'email@email', }, google: { emails: [{ value: 'email@google', }], }, apple: { emails: [{ value: 'email@apple', }], }, }, profile: { name: 'profile name', }, preferences: { emailNotifications: { unsubscribeFromAll: false, }, }, }; } describe('emails', () => { const pathToEmailLib = '../../../../website/server/libs/email'; describe('getUserInfo', () => { it('returns an empty object if no field request', () => { const attachEmail = requireAgain(pathToEmailLib); const { getUserInfo } = attachEmail; expect(getUserInfo({}, [])).to.be.empty; }); it('returns correct user data', () => { const attachEmail = requireAgain(pathToEmailLib); const { getUserInfo } = attachEmail; const user = getUser(); const data = getUserInfo(user, ['name', 'email', '_id', 'canSend']); expect(data).to.have.property('name', user.auth.local.username); expect(data).to.have.property('email', user.auth.local.email); expect(data).to.have.property('_id', user._id); expect(data).to.have.property('canSend', true); }); it('returns correct user data [google users]', () => { const attachEmail = requireAgain(pathToEmailLib); const { getUserInfo } = attachEmail; const user = getUser(); delete user.profile.name; delete user.auth.local.email; delete user.auth.apple.emails; const data = getUserInfo(user, ['name', 'email', '_id', 'canSend']); expect(data).to.have.property('name', user.auth.local.username); expect(data).to.have.property('email', user.auth.google.emails[0].value); expect(data).to.have.property('_id', user._id); expect(data).to.have.property('canSend', true); }); it('returns correct user data [apple users]', () => { const attachEmail = requireAgain(pathToEmailLib); const { getUserInfo } = attachEmail; const user = getUser(); delete user.profile.name; delete user.auth.local.email; delete user.auth.google.emails; const data = getUserInfo(user, ['name', 'email', '_id', 'canSend']); expect(data).to.have.property('name', user.auth.local.username); expect(data).to.have.property('email', user.auth.apple.emails[0].value); expect(data).to.have.property('_id', user._id); expect(data).to.have.property('canSend', true); }); it('has fallbacks for missing data', () => { const attachEmail = requireAgain(pathToEmailLib); const { getUserInfo } = attachEmail; const user = getUser(); delete user.auth.local.email; delete user.auth.google; delete user.auth.apple; const data = getUserInfo(user, ['name', 'email', '_id', 'canSend']); expect(data).to.have.property('name', user.auth.local.username); expect(data).not.to.have.property('email'); expect(data).to.have.property('_id', user._id); expect(data).to.have.property('canSend', true); }); }); describe('getGroupUrl', () => { it('returns correct url if group is the tavern', () => { const { getGroupUrl } = require(pathToEmailLib); // eslint-disable-line import/no-dynamic-require, max-len expect(getGroupUrl({ _id: TAVERN_ID, type: 'guild' })).to.eql('/groups/tavern'); }); it('returns correct url if group is a guild', () => { const { getGroupUrl } = require(pathToEmailLib); // eslint-disable-line import/no-dynamic-require, max-len expect(getGroupUrl({ _id: 'random _id', type: 'guild' })).to.eql('/groups/guild/random _id'); }); it('returns correct url if group is a party', () => { const { getGroupUrl } = require(pathToEmailLib); // eslint-disable-line import/no-dynamic-require, max-len expect(getGroupUrl({ _id: 'random _id', type: 'party' })).to.eql('party'); }); }); describe('sendTxn', () => { let sendTxn = null; beforeEach(() => { sandbox.stub(got, 'post').returns(defer().promise); const nconfGetStub = sandbox.stub(nconf, 'get'); nconfGetStub.withArgs('IS_PROD').returns(true); nconfGetStub.withArgs('BASE_URL').returns('BASE_URL'); const attachEmail = requireAgain(pathToEmailLib); sendTxn = attachEmail.sendTxn; }); afterEach(() => { sandbox.restore(); }); it('can send a txn email to one recipient', () => { const emailType = 'an email type'; const mailingInfo = { name: 'my name', email: 'my@email', }; sendTxn(mailingInfo, emailType); expect(got.post).to.be.called; expect(got.post).to.be.calledWith('http://example.com/job', sinon.match({ json: { data: { emailType: sinon.match.same(emailType), to: sinon.match(value => Array.isArray(value) && value[0].name === mailingInfo.name, 'matches mailing info array'), }, }, })); }); it('does not send email if address is missing', () => { const emailType = 'an email type'; const mailingInfo = { name: 'my name', // email: 'my@email', }; sendTxn(mailingInfo, emailType); expect(got.post).not.to.be.called; }); it('throws error when mail target is only a string', async () => { const emailType = 'an email type'; const mailingInfo = 'my email'; await expect(sendTxn(mailingInfo, emailType)).to.be.rejectedWith('Argument Error mailingInfoArray: does not contain email or _id'); }); it('throws error when mail target has no _id or email', async () => { const emailType = 'an email type'; const mailingInfo = { }; await expect(sendTxn(mailingInfo, emailType)).to.be.rejectedWith('Argument Error mailingInfoArray: does not contain email or _id'); }); it('throws error when variables not an array', async () => { const emailType = 'an email type'; const mailingInfo = { name: 'my name', email: 'my@email', }; const variables = {}; await expect(sendTxn(mailingInfo, emailType, variables)).to.be.rejectedWith('Argument Error variables: is not an array'); }); it('throws error when variables array not contain name/content', async () => { const emailType = 'an email type'; const mailingInfo = { name: 'my name', email: 'my@email', }; const variables = [ { }, ]; await expect(sendTxn(mailingInfo, emailType, variables)).to.be.rejectedWith('Argument Error variables: does not contain name or content'); }); it('throws no error when variables array contain name but no content', () => { const emailType = 'an email type'; const mailingInfo = { name: 'my name', email: 'my@email', }; const variables = [ { name: 'MY_VAR', }, ]; expect(sendTxn(mailingInfo, emailType, variables)).to.not.throw; }); it('uses getUserInfo in case of user data', () => { const emailType = 'an email type'; const mailingInfo = getUser(); sendTxn(mailingInfo, emailType); expect(got.post).to.be.called; expect(got.post).to.be.calledWith('http://example.com/job', sinon.match({ json: { data: { emailType: sinon.match.same(emailType), to: sinon.match(val => val[0]._id === mailingInfo._id), }, }, })); }); it('sends email with some default variables', () => { const emailType = 'an email type'; const mailingInfo = { name: 'my name', email: 'my@email', }; const variables = []; sendTxn(mailingInfo, emailType, variables); expect(got.post).to.be.called; expect(got.post).to.be.calledWith('http://example.com/job', sinon.match({ json: { data: { variables: sinon.match(value => value[0].name === 'BASE_URL', 'matches variables'), personalVariables: sinon.match(value => value[0].rcpt === mailingInfo.email && value[0].vars[0].name === 'RECIPIENT_NAME' && value[0].vars[1].name === 'RECIPIENT_UNSUB_URL', 'matches personal variables'), }, }, })); }); }); });