Skip to content

Commit ab8db60

Browse files
authored
fix: include repetitionId in notification event URLs for Telegram, Slack, and Loop (#544)
1 parent 3092d39 commit ab8db60

8 files changed

Lines changed: 148 additions & 6 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "hawk.workers",
33
"private": true,
4-
"version": "0.1.3",
4+
"version": "0.1.4",
55
"description": "Hawk workers",
66
"repository": "git@github.com:codex-team/hawk.workers.git",
77
"license": "BUSL-1.1",

workers/loop/src/templates/event.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ function renderBacktrace(event: GroupedEventDBScheme): string {
3939
export default function render(tplData: EventsTemplateVariables): string {
4040
const eventInfo = tplData.events[0] as TemplateEventData;
4141
const event = eventInfo.event;
42-
const eventURL = tplData.host + '/project/' + tplData.project._id + '/event/' + event._id + '/';
42+
const repetitionId = eventInfo.repetitionId;
43+
const eventURL = tplData.host + '/project/' + tplData.project._id + '/event/' + event._id + '/' + (repetitionId ? repetitionId + '/overview' : '');
4344
let location = 'Неизвестное место';
4445

4546
if (event.payload.backtrace && event.payload.backtrace.length > 0) {

workers/loop/tests/provider.test.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,54 @@ describe('LoopProvider', () => {
137137
expect(message).toBeDefined();
138138
});
139139

140+
/**
141+
* Event URL should include repetitionId when provided
142+
*/
143+
describe('event URL contains correct repetitionId', () => {
144+
const eventId = new ObjectId('5d206f7f9aaf7c0071d64597');
145+
const projectId = new ObjectId('5d206f7f9aaf7c0071d64596');
146+
const host = 'https://garage.hawk.so';
147+
148+
const basePayload = {
149+
events: [ {
150+
event: {
151+
_id: eventId,
152+
totalCount: 1,
153+
timestamp: Date.now(),
154+
payload: { title: 'Err', backtrace: [] },
155+
} as DecodedGroupedEvent,
156+
daysRepeated: 1,
157+
newCount: 1,
158+
} ],
159+
period: 60,
160+
host,
161+
hostOfStatic: '',
162+
project: {
163+
_id: projectId,
164+
token: 'tok',
165+
name: 'P',
166+
workspaceId: projectId,
167+
uidAdded: projectId,
168+
notifications: [],
169+
} as ProjectDBScheme,
170+
};
171+
172+
it('should include repetitionId and /overview in URL when repetitionId is set', () => {
173+
const repetitionId = '5d206f7f9aaf7c0071d64599';
174+
const payload = { ...basePayload, events: [ { ...basePayload.events[0], repetitionId } ] };
175+
const message = templates.EventTpl(payload);
176+
177+
expect(message).toContain(`/event/${eventId}/${repetitionId}/overview`);
178+
});
179+
180+
it('should omit repetitionId from URL when repetitionId is not set', () => {
181+
const message = templates.EventTpl(basePayload);
182+
183+
expect(message).toContain(`/event/${eventId}/`);
184+
expect(message).not.toContain('/overview');
185+
});
186+
});
187+
140188
/**
141189
* Check that rendering of a several events message works without errors
142190
*/

workers/slack/src/templates/event.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ function renderBacktrace(event: GroupedEventDBScheme): string {
4545
export default function render(tplData: EventsTemplateVariables): IncomingWebhookSendArguments {
4646
const eventInfo = tplData.events[0] as TemplateEventData;
4747
const event = eventInfo.event;
48-
const eventURL = getEventUrl(tplData.host, tplData.project, event);
48+
const eventURL = getEventUrl(tplData.host, tplData.project, event, eventInfo.repetitionId);
4949
const location = getEventLocation(event);
5050

5151
const blocks = [

workers/slack/src/templates/utils.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,12 @@ export function getEventLocation(event: DecodedGroupedEvent): string {
3232
* @param host - garage host. Also, can be accessed from process.env.GARAGE_URL
3333
* @param project - parent project
3434
* @param event - event to compose its URL
35+
* @param repetitionId - id of the specific repetition that triggered the notification
3536
*/
36-
export function getEventUrl(host: string, project: ProjectDBScheme, event: GroupedEventDBScheme): string {
37-
return host + '/project/' + project._id + '/event/' + event._id + '/';
37+
export function getEventUrl(host: string, project: ProjectDBScheme, event: GroupedEventDBScheme, repetitionId?: string | null): string {
38+
const base = host + '/project/' + project._id + '/event/' + event._id + '/';
39+
40+
return repetitionId ? base + repetitionId + '/overview' : base;
3841
}
3942

4043
/**

workers/slack/tests/utils.test.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { ObjectId } from 'mongodb';
2+
import { ProjectDBScheme, GroupedEventDBScheme } from '@hawk.so/types';
3+
import { getEventUrl } from '../src/templates/utils';
4+
5+
const project = {
6+
_id: new ObjectId('5d206f7f9aaf7c0071d64596'),
7+
token: 'project-token',
8+
name: 'Project',
9+
workspaceId: new ObjectId('5d206f7f9aaf7c0071d64596'),
10+
uidAdded: new ObjectId('5d206f7f9aaf7c0071d64596'),
11+
notifications: [],
12+
} as ProjectDBScheme;
13+
14+
const event = {
15+
_id: new ObjectId('5d206f7f9aaf7c0071d64597'),
16+
payload: { title: 'Error' },
17+
} as unknown as GroupedEventDBScheme;
18+
19+
const host = 'https://garage.hawk.so';
20+
21+
describe('getEventUrl', () => {
22+
it('should return base URL with trailing slash when no repetitionId', () => {
23+
const url = getEventUrl(host, project, event);
24+
25+
expect(url).toBe(`${host}/project/${project._id}/event/${event._id}/`);
26+
});
27+
28+
it('should return base URL with trailing slash when repetitionId is null', () => {
29+
const url = getEventUrl(host, project, event, null);
30+
31+
expect(url).toBe(`${host}/project/${project._id}/event/${event._id}/`);
32+
});
33+
34+
it('should append repetitionId and /overview when repetitionId is provided', () => {
35+
const repetitionId = '5d206f7f9aaf7c0071d64599';
36+
const url = getEventUrl(host, project, event, repetitionId);
37+
38+
expect(url).toBe(`${host}/project/${project._id}/event/${event._id}/${repetitionId}/overview`);
39+
});
40+
});

workers/telegram/src/templates/event.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import type { EventsTemplateVariables, TemplateEventData } from 'hawk-worker-sen
88
export default function render(tplData: EventsTemplateVariables): string {
99
const eventInfo = tplData.events[0] as TemplateEventData;
1010
const event = eventInfo.event;
11-
const eventURL = tplData.host + '/project/' + tplData.project._id + '/event/' + event._id + '/';
11+
const repetitionId = eventInfo.repetitionId;
12+
const eventURL = tplData.host + '/project/' + tplData.project._id + '/event/' + event._id + '/' + (repetitionId ? repetitionId + '/overview' : '');
1213
let location = '';
1314

1415
if (event.payload.backtrace && event.payload.backtrace.length > 0) {

workers/telegram/tests/provider.test.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { EventNotification, SeveralEventsNotification } from 'hawk-worker-sender
22
import { DecodedGroupedEvent, ProjectDBScheme } from '@hawk.so/types';
33
import TelegramProvider from 'hawk-worker-telegram/src/provider';
44
import templates from '../src/templates';
5+
import EventTpl from '../src/templates/event';
56
import { ObjectId } from 'mongodb';
67

78
/**
@@ -64,6 +65,54 @@ describe('TelegramProvider', () => {
6465

6566
expect(message).toBeDefined();
6667
});
68+
/**
69+
* Event URL should include repetitionId when provided
70+
*/
71+
describe('event URL contains correct repetitionId', () => {
72+
const eventId = new ObjectId('5d206f7f9aaf7c0071d64597');
73+
const projectId = new ObjectId('5d206f7f9aaf7c0071d64596');
74+
const host = 'https://garage.hawk.so';
75+
76+
const basePayload = {
77+
events: [ {
78+
event: {
79+
_id: eventId,
80+
totalCount: 1,
81+
timestamp: Date.now(),
82+
payload: { title: 'Err', backtrace: [] },
83+
} as DecodedGroupedEvent,
84+
daysRepeated: 1,
85+
newCount: 1,
86+
} ],
87+
period: 60,
88+
host,
89+
hostOfStatic: '',
90+
project: {
91+
_id: projectId,
92+
token: 'tok',
93+
name: 'P',
94+
workspaceId: projectId,
95+
uidAdded: projectId,
96+
notifications: [],
97+
} as ProjectDBScheme,
98+
};
99+
100+
it('should include repetitionId and /overview in URL when repetitionId is set', () => {
101+
const repetitionId = '5d206f7f9aaf7c0071d64599';
102+
const payload = { ...basePayload, events: [ { ...basePayload.events[0], repetitionId } ] };
103+
const message = EventTpl(payload);
104+
105+
expect(message).toContain(`/event/${eventId}/${repetitionId}/overview`);
106+
});
107+
108+
it('should omit repetitionId from URL when repetitionId is not set', () => {
109+
const message = EventTpl(basePayload);
110+
111+
expect(message).toContain(`/event/${eventId}/`);
112+
expect(message).not.toContain('/overview');
113+
});
114+
});
115+
67116
/**
68117
* Check that rendering of a several events message works without errors
69118
*/

0 commit comments

Comments
 (0)