Skip to content

Commit

Permalink
Tag emails according to type and audience (#2959)
Browse files Browse the repository at this point in the history
* Tag emails according to type and audience.

* Fix fromName in tests.

* Add more options to sendDebugEmail script.

* Add comment.
  • Loading branch information
sanason authored Apr 24, 2024
1 parent ed55ef9 commit 8865505
Show file tree
Hide file tree
Showing 21 changed files with 388 additions and 241 deletions.
10 changes: 5 additions & 5 deletions packages/server/__tests__/api/grants.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ describe('`/api/grants` endpoint', () => {
const assignEndpoint = `333816/assign/agencies`;
context('by a user with admin role', () => {
it('assigns this user\'s own agency to a grant', async () => {
const emailSpy = sandbox.spy(email, 'sendGrantAssignedEmail');
const emailSpy = sandbox.spy(email, 'sendGrantAssignedEmails');
const response = await fetchApi(`/grants/${assignEndpoint}`, agencies.own, {
...fetchOptions.admin,
method: 'put',
Expand All @@ -189,7 +189,7 @@ describe('`/api/grants` endpoint', () => {
expect(emailSpy.called).to.equal(true);
});
it('assigns subagencies of this user\'s own agency to a grant', async () => {
const emailSpy = sandbox.spy(email, 'sendGrantAssignedEmail');
const emailSpy = sandbox.spy(email, 'sendGrantAssignedEmails');
const response = await fetchApi(`/grants/${assignEndpoint}`, agencies.ownSub, {
...fetchOptions.admin,
method: 'put',
Expand All @@ -200,7 +200,7 @@ describe('`/api/grants` endpoint', () => {
expect(emailSpy.called).to.equal(true);
});
it('forbids requests for any agency outside this user\'s hierarchy', async () => {
const emailSpy = sandbox.spy(email, 'sendGrantAssignedEmail');
const emailSpy = sandbox.spy(email, 'sendGrantAssignedEmails');
const response = await fetchApi(`/grants/${assignEndpoint}`, agencies.offLimits, {
...fetchOptions.admin,
method: 'put',
Expand All @@ -212,7 +212,7 @@ describe('`/api/grants` endpoint', () => {
});
context('by a user with staff role', () => {
it('assigns this user\'s own agency to a grant', async () => {
const emailSpy = sandbox.spy(email, 'sendGrantAssignedEmail');
const emailSpy = sandbox.spy(email, 'sendGrantAssignedEmails');
const response = await fetchApi(`/grants/${assignEndpoint}`, agencies.own, {
...fetchOptions.staff,
method: 'put',
Expand All @@ -223,7 +223,7 @@ describe('`/api/grants` endpoint', () => {
expect(emailSpy.called).to.equal(true);
});
it('forbids requests for any agency except this user\'s own agency', async () => {
const emailSpy = sandbox.spy(email, 'sendGrantAssignedEmail');
const emailSpy = sandbox.spy(email, 'sendGrantAssignedEmails');
let response = await fetchApi(`/grants/${assignEndpoint}`, agencies.ownSub, {
...fetchOptions.staff,
method: 'put',
Expand Down
35 changes: 19 additions & 16 deletions packages/server/__tests__/api/users.test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
const { expect } = require('chai');
const sinon = require('sinon');
const moment = require('moment');
const { getSessionCookie, makeTestServer, knex } = require('./utils');
const email = require('../../src/lib/email');
const emailConstants = require('../../src/lib/email/constants');
const emailService = require('../../src/lib/email/service-email');

describe('`/api/users` endpoint', () => {
const agencies = {
Expand Down Expand Up @@ -367,7 +369,8 @@ describe('`/api/users` endpoint', () => {

context('GET /users/:userId/sendDigestEmail (admin send digest email for a specific user)', () => {
beforeEach(async () => {
this.clockFn = (date) => sinon.useFakeTimers(new Date(date));
// Set clock to given date in local time zone
this.clockFn = (date) => sinon.useFakeTimers(moment(date).toDate());
this.clock = this.clockFn('2021-08-06');
});
afterEach(async () => {
Expand All @@ -376,48 +379,48 @@ describe('`/api/users` endpoint', () => {
});
context('by a user with admin role', () => {
it('Sends an email based on this user\'s saved searches', async () => {
const deliverEmailSpy = sinon.fake.returns('foo');
sinon.replace(email, 'deliverEmail', deliverEmailSpy);
const sendEmailSpy = sinon.fake();
sinon.replace(emailService, 'getTransport', sinon.fake.returns({ sendEmail: sendEmailSpy }));
const response = await fetchApi(
`/users/2/sendDigestEmail`,
agencies.own,
{ ...fetchOptions.admin },
);
expect(response.statusText).to.equal('OK');
expect(deliverEmailSpy.calledOnce).to.equal(true);
expect(sendEmailSpy.calledOnce).to.equal(true);
});
it('Sends an email based on this user\'s saved searches date specified', async () => {
const deliverEmailSpy = sinon.fake.returns('foo');
sinon.replace(email, 'deliverEmail', deliverEmailSpy);
const sendEmailSpy = sinon.fake();
sinon.replace(emailService, 'getTransport', sinon.fake.returns({ sendEmail: sendEmailSpy }));
const response = await fetchApi(
`/users/2/sendDigestEmail?date=2021-08-05`,
agencies.own,
{ ...fetchOptions.admin },
);
expect(response.statusText).to.equal('OK');
expect(deliverEmailSpy.calledOnce).to.equal(true);
expect(sendEmailSpy.calledOnce).to.equal(true);
});
it('Sends an email based on this user\'s saved searches at a time without grants', async () => {
const deliverEmailSpy = sinon.fake.returns('foo');
sinon.replace(email, 'deliverEmail', deliverEmailSpy);
const sendEmailSpy = sinon.fake();
sinon.replace(emailService, 'getTransport', sinon.fake.returns({ sendEmail: sendEmailSpy }));
const response = await fetchApi(
`/users/2/sendDigestEmail?date=1985-08-06`,
agencies.own,
{ ...fetchOptions.admin },
);
expect(response.statusText).to.equal('OK');
expect(deliverEmailSpy.calledOnce).to.equal(false);
expect(sendEmailSpy.calledOnce).to.equal(false);
});
it('Sends an email based on this user\'s saved searches without admin rights', async () => {
const deliverEmailSpy = sinon.fake.returns('foo');
sinon.replace(email, 'deliverEmail', deliverEmailSpy);
const sendEmailSpy = sinon.fake();
sinon.replace(emailService, 'getTransport', sinon.fake.returns({ sendEmail: sendEmailSpy }));
const response = await fetchApi(
`/users/2/sendDigestEmail`,
agencies.own,
{ ...fetchOptions.nonUSDRAdmin },
);
expect(response.statusText).to.equal('Forbidden');
expect(deliverEmailSpy.calledOnce).to.equal(false);
expect(sendEmailSpy.calledOnce).to.equal(false);
});
});
context('When the user is not subscribed', () => {
Expand Down Expand Up @@ -454,15 +457,15 @@ describe('`/api/users` endpoint', () => {
);
});
it('updates this user\'s own agency', async () => {
const deliverEmailSpy = sinon.fake.returns('foo');
sinon.replace(email, 'deliverEmail', deliverEmailSpy);
const sendEmailSpy = sinon.fake();
sinon.replace(emailService, 'getTransport', sinon.fake.returns({ sendEmail: sendEmailSpy }));
const response = await fetchApi(
`/users/2/sendDigestEmail`,
agencies.own,
{ ...fetchOptions.admin },
);
expect(response.statusText).to.equal('Bad Request');
expect(deliverEmailSpy.calledOnce).to.equal(false);
expect(sendEmailSpy.calledOnce).to.equal(false);
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('audit report generation', () => {
expect(sendFake.calledOnce).to.equal(true);
expect(sendFake.firstCall.args[0]).to.equal('[email protected]');
expect(sendFake.firstCall.args[1]).to.equal(`${process.env.API_DOMAIN}/api/audit_report/1/99/example.xlsx`);
expect(sendFake.firstCall.args[2]).to.equal('audit');
expect(sendFake.firstCall.args[2]).to.equal(email.ASYNC_REPORT_TYPES.audit);
});
it('generateAndSendEmail generates a report, uploads to s3, and sends an email', async () => {
const sendFake = sandbox.fake.returns('foo');
Expand Down
17 changes: 17 additions & 0 deletions packages/server/__tests__/db/db.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@ describe('db', () => {
'DRY RUN :: Begin migrating legacy agency criteria to saved searches',
'DRY RUN :: Migrating agency criteria for agency 0',
'DRY RUN :: No agency criteria to migrate for agency 1',
'DRY RUN :: No agency criteria to migrate for agency 2',
'DRY RUN :: Migrating agency criteria for agency 4',
'DRY RUN :: Migrating agency criteria for users 1,2 belonging to agency 0',
'DRY RUN :: No agency criteria to migrate for users 3 belonging to agency 1',
'DRY RUN :: No agency criteria to migrate for users 4 belonging to agency 2',
'DRY RUN :: No users to migrate for agency 4',
'DRY RUN :: Would have inserted approximately 2 saved searches. Note: there may be duplicates.',
'DRY RUN :: Done migrating legacy agency criteria to saved searches',
Expand All @@ -64,9 +66,11 @@ describe('db', () => {
'Begin migrating legacy agency criteria to saved searches',
'Migrating agency criteria for agency 0',
'No agency criteria to migrate for agency 1',
'No agency criteria to migrate for agency 2',
'Migrating agency criteria for agency 4',
'Migrating agency criteria for users 1,2 belonging to agency 0',
'No agency criteria to migrate for users 3 belonging to agency 1',
'No agency criteria to migrate for users 4 belonging to agency 2',
'No users to migrate for agency 4',
'Inserted 2 saved searches',
'Done migrating legacy agency criteria to saved searches',
Expand Down Expand Up @@ -109,9 +113,11 @@ describe('db', () => {
'Begin migrating legacy agency criteria to saved searches',
'Migrating agency criteria for agency 0',
'No agency criteria to migrate for agency 1',
'No agency criteria to migrate for agency 2',
'Migrating agency criteria for agency 4',
'Migrating agency criteria for users 1,2 belonging to agency 0',
'No agency criteria to migrate for users 3 belonging to agency 1',
'No agency criteria to migrate for users 4 belonging to agency 2',
'No users to migrate for agency 4',
'Inserted 1 saved searches', // This would have been 2 if not for the duplication mechanism.
'Done migrating legacy agency criteria to saved searches',
Expand Down Expand Up @@ -797,6 +803,17 @@ describe('db', () => {
});
});

context('getUserIdForEmail', () => {
it('returns id when user exists', async () => {
const result = await db.getUserIdForEmail(fixtures.users.adminUser.email);
expect(result).to.equal(fixtures.users.adminUser.id);
});
it('returns null when user does not exist', async () => {
const result = await db.getUserIdForEmail('[email protected]');
expect(result).to.be.null;
});
});

context('getNewGrantsForAgency', () => {
beforeEach(() => {
this.clockFn = (date) => sinon.useFakeTimers(new Date(date));
Expand Down
22 changes: 21 additions & 1 deletion packages/server/__tests__/db/seeds/fixtures.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ const tenants = {
id: 0,
display_name: 'SBA',
},
FS: {
USDR: {
id: 1,
display_name: 'USDR',
},
FS: {
id: 2,
display_name: 'FS',
},
};
Expand All @@ -34,6 +38,14 @@ const agencies = {
parent: 0,
tenant_id: tenants.SBA.id,
},
usdr: {
id: 2,
abbreviation: 'USDR',
code: 'USDR',
name: 'United States Digital Response',
parent: null,
tenant_id: tenants.USDR.id,
},
fleetServices: {
id: 4,
abbreviation: 'FSD',
Expand Down Expand Up @@ -69,6 +81,14 @@ const users = {
id: 3,
tenant_id: agencies.subAccountancy.tenant_id,
},
usdrUser: {
email: '[email protected]',
name: 'USDR user',
agency_id: agencies.usdr.id,
role_id: roles.staffRole.id,
id: 4,
tenant_id: agencies.usdr.tenant_id,
},
};

const keywords = {
Expand Down
Loading

0 comments on commit 8865505

Please sign in to comment.