Skip to content

Commit 470bc93

Browse files
committed
refactor notifier tests
1 parent 4c26214 commit 470bc93

File tree

1 file changed

+98
-139
lines changed

1 file changed

+98
-139
lines changed

workers/notifier/tests/worker.test.ts

Lines changed: 98 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,14 @@ const rule = {
1717
telegram: {
1818
isEnabled: true,
1919
endpoint: 'tgEndpoint',
20-
minPeriod: 0.5,
2120
},
2221
slack: {
2322
isEnabled: true,
2423
endpoint: 'slackEndpoint',
25-
minPeriod: 0.5,
2624
},
2725
email: {
2826
isEnabled: false,
2927
endpoint: 'emailEndpoint',
30-
minPeriod: 0.5,
3128
},
3229
},
3330
} as any;
@@ -200,200 +197,162 @@ describe('NotifierWorker', () => {
200197
});
201198

202199
describe('handling', () => {
203-
it('should correctly handle first message', async () => {
200+
it('should not send task to sender workers if event is not new and repetitions today not equal to threshold', async () => {
204201
const worker = new NotifierWorker();
205-
202+
206203
await worker.start();
207204

208-
worker.sendToSenderWorker = jest.fn();
205+
const message = { ...messageMock };
206+
const event = { ...message.event };
207+
event.isNew = false;
209208

210-
worker.buffer.push = jest.fn();
211-
worker.buffer.setTimer = jest.fn();
209+
worker.redis.getEventRepetitionsFromDigest = jest.fn(async (_projectId, _groupHash) => {
210+
return Promise<1>;
211+
});
212212

213-
const message = { ...messageMock };
214-
const channels = ['telegram', 'slack'];
215-
const channelKeyPart = [message.projectId, rule._id];
216-
const events = [ {
217-
key: message.event.groupHash,
218-
count: 1,
219-
} ];
213+
worker.redis.getProjectNotificationThreshold = jest.fn(async (_projectId) => {
214+
return Promise<10>;
215+
});
220216

221-
await worker.handle(message);
217+
worker.sendToSenderWorker = jest.fn();
218+
219+
worker.handle(message);
222220

223-
expect(worker.buffer.setTimer).toBeCalledTimes(2);
224-
expect(worker.buffer.push).not.toBeCalled();
225-
226-
channels.forEach((channel, i) => {
227-
expect(worker.buffer.setTimer).toHaveBeenNthCalledWith(
228-
i + 1,
229-
[...channelKeyPart, channel],
230-
rule.channels[channel].minPeriod * 1000,
231-
worker.sendEvents
232-
);
233-
expect(worker.sendToSenderWorker).toHaveBeenNthCalledWith(
234-
i + 1,
235-
[...channelKeyPart, channels[i]],
236-
events
237-
);
221+
/**
222+
* Check that we haven't sent any tasks to sender worker
223+
* because event repetitions today are less than threshold
224+
*/
225+
expect(worker.sendToSenderWorker).not.toBeCalled();
226+
227+
worker.redis.getEventRepetitionsFromDigest = jest.fn(async (_projectId, _groupHash) => {
228+
return Promise<100>;
238229
});
239230

231+
worker.handle(message);
232+
233+
/**
234+
* Check that we haven't sent any tasks to sender worker
235+
* because event repetitions today are more than threshold
236+
*/
237+
expect(worker.sendToSenderWorker).not.toBeCalled();
238+
240239
await worker.finish();
241240
});
242241

243-
it('should correctly handle messages after first one', async () => {
242+
it('should send task to sender workers if event is new', async () => {
244243
const worker = new NotifierWorker();
245244

246245
await worker.start();
247246

247+
const message = { ...messageMock };
248+
const event = { ...message.event };
249+
250+
event.isNew = true;
251+
248252
worker.sendToSenderWorker = jest.fn();
249253

250-
jest.useFakeTimers();
254+
worker.handle(message);
251255

252-
const realGetTimer = worker.buffer.getTimer;
253-
const realSetTimer = worker.buffer.setTimer;
256+
expect(worker.sendToSenderWorker).toBeCalled();
254257

255-
worker.buffer.getTimer = jest.fn((...args) => realGetTimer.apply(worker.buffer, args));
256-
worker.buffer.setTimer = jest.fn((...args) => realSetTimer.apply(worker.buffer, args));
257-
worker.buffer.push = jest.fn();
258+
await worker.finish();
259+
});
258260

259-
const message = { ...messageMock };
260-
const channels = ['telegram', 'slack'];
261-
const channelKeyPart = [message.projectId, rule._id];
261+
it('should send task to sender workers if event repetitions today equal to threshold', async () => {
262+
const worker = new NotifierWorker();
262263

263-
await worker.handle(message);
264-
await worker.handle(message);
264+
await worker.start();
265+
266+
const message = { ...messageMock };
267+
const event = { ...message.event };
268+
event.isNew = false;
265269

266-
expect(worker.buffer.getTimer).toBeCalledTimes(4);
267-
expect(worker.buffer.push).toBeCalledTimes(2);
268-
expect(worker.sendToSenderWorker).toBeCalledTimes(2);
270+
worker.redis.getEventRepetitionsFromDigest = jest.fn(async (_projectId, _groupHash) => {
271+
return Promise<10>;
272+
});
269273

270-
channels.forEach((channel, i) => {
271-
expect(worker.buffer.push).toHaveBeenNthCalledWith(
272-
i + 1,
273-
[...channelKeyPart, channel, messageMock.event.groupHash]
274-
);
274+
worker.redis.getProjectNotificationThreshold = jest.fn(async (_projectId) => {
275+
return Promise<10>;
275276
});
276277

277-
jest.useRealTimers();
278+
worker.sendToSenderWorker = jest.fn();
279+
280+
worker.handle(message);
281+
282+
expect(worker.sendToSenderWorker).toBeCalled();
278283

279284
await worker.finish();
280285
});
281286

282-
it('should send events after timeout', async () => {
287+
it('should not call events database for threshold calculation if threshold set in redis', async () => {
283288
const worker = new NotifierWorker();
284289

285290
await worker.start();
286291

287-
worker.sendToSenderWorker = jest.fn();
288-
289-
const realSendEvents = worker.sendEvents;
290-
291-
worker.sendEvents = jest.fn((...args) => realSendEvents.apply(worker, args));
292+
/**
293+
* Mock of the function that returns
294+
*/
295+
worker.redis.getEventRepetitionsFromDigest = jest.fn(async (_projectId, _groupHash) => {
296+
return Promise<1>;
297+
});
292298

293-
const realFlush = worker.buffer.flush;
299+
worker.redis.getProjectNotificationThreshold(async (_projectId) => {
300+
return Promise<1>;
301+
})
294302

295-
worker.buffer.flush = jest.fn((...args) => realFlush.apply(worker.buffer, args));
303+
worker.eventsDb.getConnection = jest.fn();
296304

297305
const message = { ...messageMock };
298-
const channels = ['telegram', 'slack'];
299-
const channelKeyPart = [message.projectId, rule._id];
300306

301307
await worker.handle(message);
302-
await worker.handle(message);
303-
304-
await new Promise((resolve) => setTimeout(() => {
305-
expect(worker.sendEvents).toBeCalledTimes(2);
306-
expect(worker.buffer.flush).toBeCalledTimes(2);
307308

308-
channels.forEach((channel, i) => {
309-
expect(worker.buffer.flush).toHaveBeenNthCalledWith(
310-
i + 1,
311-
[...channelKeyPart, channel]
312-
);
313-
expect(worker.sendEvents).toHaveBeenNthCalledWith(
314-
i + 1,
315-
[...channelKeyPart, channel]
316-
);
317-
});
318-
319-
resolve();
320-
}, 1000));
309+
/**
310+
* It should not be called beacuse event repetitions got from redis
311+
*/
312+
expect(worker.eventsDb.getConnection).not.toBeCalled;
321313

322314
await worker.finish();
323315
});
324316

325-
it('should do nothing if project doesn\'t exist', async () => {
317+
it('should calculate notification threshold using events db if redis has no threshold', async () => {
326318
const worker = new NotifierWorker();
327319

328320
await worker.start();
329321

330-
worker.addEventsToChannels = jest.fn();
331-
332-
const message = { ...messageMock };
333-
334-
const oldMock = dbQueryMock;
322+
worker.redis.getProjectNotificationThreshold = jest.fn(async (_projectId, _groupHash) => {
323+
return Promise<null>;
324+
});
335325

336-
dbQueryMock = jest.fn(() => null);
326+
worker.eventsDb.getConnection = jest.fn();
327+
worker.redis.setProjectNotificationTreshold = jest.fn();
328+
329+
/**
330+
* Check that we connected to the events database to calculate the threshold
331+
*/
332+
expect(worker.eventsDb.getConnection).toBeCalled();
337333

338-
await worker.handle(message);
334+
/**
335+
* Check that we stored calculated threshold in redis
336+
*/
337+
expect(worker.redis.setProjectNotificationTreshold).toBeCalled();
339338

340-
expect(worker.addEventsToChannels).not.toBeCalled();
339+
await worker.finish();
340+
})
341341

342-
dbQueryMock = oldMock;
342+
it('should always add event to redis digest', async () => {
343+
const worker = new NotifierWorker();
343344

344-
await worker.finish();
345-
});
346-
});
345+
await worker.start();
347346

348-
it('should send task to sender workers', async () => {
349-
const worker = new NotifierWorker();
347+
const message = { ...messageMock };
350348

351-
await worker.start();
349+
worker.redis.addEventToDigest = jest.fn();
352350

353-
await worker.start();
351+
worker.handle(message);
354352

355-
worker.addTask = jest.fn();
356-
357-
const message = { ...messageMock };
358-
359-
await worker.handle(message);
360-
361-
await waitForExpect(() => {
362-
expect(worker.addTask).toHaveBeenNthCalledWith(
363-
1,
364-
`sender/telegram`,
365-
{
366-
type: 'event',
367-
payload: {
368-
projectId: message.projectId,
369-
ruleId: rule._id,
370-
events: [ {
371-
key: message.event.groupHash,
372-
count: 1,
373-
} ],
374-
},
375-
}
376-
);
377-
}, 2000);
378-
379-
await waitForExpect(() => {
380-
expect(worker.addTask).toHaveBeenNthCalledWith(
381-
2,
382-
`sender/slack`,
383-
{
384-
type: 'event',
385-
payload: {
386-
projectId: message.projectId,
387-
ruleId: rule._id,
388-
events: [ {
389-
key: message.event.groupHash,
390-
count: 1,
391-
} ],
392-
},
393-
}
394-
);
395-
}, 2000);
353+
expect(worker.redis.addEventToDigest).toBeCalled();
396354

397-
await worker.finish();
355+
await worker.finish();
356+
});
398357
});
399358
});

0 commit comments

Comments
 (0)