Skip to content

Commit b0ec181

Browse files
authored
Merge pull request #20240 from mozilla/fxa-12563
feat(auth-server): migrate email unit tests from Mocha to co-located jest specs
2 parents 3fdec04 + 21dfd04 commit b0ec181

5 files changed

Lines changed: 1510 additions & 0 deletions

File tree

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
import sinon from 'sinon';
6+
import { Container } from 'typedi';
7+
import { AppConfig } from './types';
8+
import { AccountEventsManager } from './account-events';
9+
10+
const sandbox = sinon.createSandbox();
11+
12+
const mockEmailTasks = {
13+
scheduleFirstEmail: sandbox.stub(),
14+
scheduleSecondEmail: sandbox.stub(),
15+
scheduleFinalEmail: sandbox.stub(),
16+
};
17+
const notificationHandlerStub = sandbox.stub();
18+
19+
jest.mock('@fxa/shared/cloud-tasks', () => {
20+
const actual = jest.requireActual('@fxa/shared/cloud-tasks');
21+
return {
22+
...actual,
23+
InactiveAccountEmailTasksFactory: () => mockEmailTasks,
24+
};
25+
});
26+
27+
jest.mock('./inactive-accounts', () => {
28+
const actual = jest.requireActual('./inactive-accounts');
29+
return {
30+
...actual,
31+
InactiveAccountsManager: class InactiveAccountsManager {
32+
async handleNotificationTask(...args: unknown[]) {
33+
notificationHandlerStub.call(this, ...args);
34+
}
35+
},
36+
};
37+
});
38+
39+
const { EmailCloudTaskManager } = require('./email-cloud-tasks');
40+
const { EmailTypes } = require('@fxa/shared/cloud-tasks');
41+
42+
describe('EmailCloudTaskManager', () => {
43+
const mockConfig = {
44+
authFirestore: {},
45+
securityHistory: {},
46+
cloudTasks: {
47+
useLocalEmulator: true,
48+
},
49+
};
50+
const aDayInMs = 24 * 60 * 60 * 1000;
51+
let deliveryTime: number;
52+
let mockStatsd: { increment: sinon.SinonStub };
53+
let emailCloudTaskManager: InstanceType<typeof EmailCloudTaskManager>;
54+
55+
beforeEach(() => {
56+
sandbox.stub(Date, 'now').returns(1736500000000);
57+
deliveryTime = Date.now() + 60 * aDayInMs;
58+
59+
Container.set(AppConfig, mockConfig);
60+
const accountEventsManager = new AccountEventsManager();
61+
Container.set(AccountEventsManager, accountEventsManager);
62+
mockStatsd = { increment: sandbox.stub() };
63+
emailCloudTaskManager = new EmailCloudTaskManager({
64+
config: mockConfig,
65+
statsd: mockStatsd,
66+
});
67+
});
68+
69+
afterEach(() => {
70+
(Date.now as sinon.SinonStub).restore();
71+
sandbox.reset();
72+
Container.reset();
73+
});
74+
75+
const mockTaskPayload = {
76+
emailType: EmailTypes.INACTIVE_DELETE_FIRST_NOTIFICATION,
77+
uid: '5adfe2a2a4c34dd6b77a16efcafedc44',
78+
};
79+
const mockSecondTaskPayload = {
80+
emailType: EmailTypes.INACTIVE_DELETE_SECOND_NOTIFICATION,
81+
uid: mockTaskPayload.uid,
82+
};
83+
const mockFinalTaskPayload = {
84+
emailType: EmailTypes.INACTIVE_DELETE_FINAL_NOTIFICATION,
85+
uid: mockTaskPayload.uid,
86+
};
87+
88+
describe('reschedule', () => {
89+
it('should reschedule a task', async () => {
90+
await emailCloudTaskManager.handleInactiveAccountNotification({
91+
payload: mockTaskPayload,
92+
raw: {
93+
req: {
94+
headers: {
95+
'fxa-cloud-task-delivery-time': deliveryTime.toString(),
96+
'x-cloudtasks-taskname': `${mockTaskPayload.uid}-inactive-notification`,
97+
},
98+
},
99+
},
100+
});
101+
sinon.assert.calledOnceWithExactly(mockEmailTasks.scheduleFirstEmail, {
102+
payload: mockTaskPayload,
103+
emailOptions: {
104+
deliveryTime,
105+
},
106+
taskOptions: {
107+
taskId: `${mockTaskPayload.uid}-inactive-notification-reschedule-1`,
108+
},
109+
});
110+
sinon.assert.calledOnceWithExactly(
111+
mockStatsd.increment,
112+
'cloud-tasks.send-email.rescheduled',
113+
{ email_type: EmailTypes.INACTIVE_DELETE_FIRST_NOTIFICATION }
114+
);
115+
});
116+
117+
it('should increment the reschedule task id', async () => {
118+
await emailCloudTaskManager.handleInactiveAccountNotification({
119+
payload: mockTaskPayload,
120+
raw: {
121+
req: {
122+
headers: {
123+
'fxa-cloud-task-delivery-time': deliveryTime.toString(),
124+
'x-cloudtasks-taskname': `${mockTaskPayload.uid}-inactive-notification-reschedule-1`,
125+
},
126+
},
127+
},
128+
});
129+
sinon.assert.calledOnceWithExactly(mockEmailTasks.scheduleFirstEmail, {
130+
payload: mockTaskPayload,
131+
emailOptions: {
132+
deliveryTime,
133+
},
134+
taskOptions: {
135+
taskId: `${mockTaskPayload.uid}-inactive-notification-reschedule-2`,
136+
},
137+
});
138+
});
139+
});
140+
141+
describe('inactive account notifications', () => {
142+
it('should handle the first notification', async () => {
143+
await emailCloudTaskManager.handleInactiveAccountNotification({
144+
payload: mockTaskPayload,
145+
raw: {
146+
req: {
147+
headers: {
148+
'fxa-cloud-task-delivery-time': Date.now(),
149+
},
150+
},
151+
},
152+
});
153+
sinon.assert.calledOnceWithExactly(
154+
notificationHandlerStub,
155+
mockTaskPayload
156+
);
157+
});
158+
159+
it('should handle the second notification', async () => {
160+
await emailCloudTaskManager.handleInactiveAccountNotification({
161+
payload: mockSecondTaskPayload,
162+
raw: {
163+
req: {
164+
headers: {
165+
'fxa-cloud-task-delivery-time': Date.now(),
166+
},
167+
},
168+
},
169+
});
170+
sinon.assert.calledOnceWithExactly(
171+
notificationHandlerStub,
172+
mockSecondTaskPayload
173+
);
174+
});
175+
176+
it('should handle the final notification', async () => {
177+
await emailCloudTaskManager.handleInactiveAccountNotification({
178+
payload: mockFinalTaskPayload,
179+
raw: {
180+
req: {
181+
headers: {
182+
'fxa-cloud-task-delivery-time': Date.now(),
183+
},
184+
},
185+
},
186+
});
187+
sinon.assert.calledOnceWithExactly(
188+
notificationHandlerStub,
189+
mockFinalTaskPayload
190+
);
191+
});
192+
});
193+
});

0 commit comments

Comments
 (0)