Skip to content

Commit a6fbbca

Browse files
authored
refactor: notification handlers (#2159)
* refactor: notification handlers Signed-off-by: Adam Setch <[email protected]> * refactor: notification handlers Signed-off-by: Adam Setch <[email protected]> * refactor: notification handlers Signed-off-by: Adam Setch <[email protected]> * refactor: notification handlers Signed-off-by: Adam Setch <[email protected]> * refactor: notification handlers Signed-off-by: Adam Setch <[email protected]> * refactor: notification handlers Signed-off-by: Adam Setch <[email protected]> * refactor: notification handlers Signed-off-by: Adam Setch <[email protected]> * refactor: notification handlers Signed-off-by: Adam Setch <[email protected]> * refactor: notification handlers Signed-off-by: Adam Setch <[email protected]> * fix sonar issues Signed-off-by: Adam Setch <[email protected]> * fix sonar issues Signed-off-by: Adam Setch <[email protected]> --------- Signed-off-by: Adam Setch <[email protected]>
1 parent 2c359fd commit a6fbbca

38 files changed

+2932
-2466
lines changed

src/renderer/__helpers__/jest.setup.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import '@testing-library/jest-dom';
2-
32
import { TextDecoder, TextEncoder } from 'node:util';
43

54
/**

src/renderer/__mocks__/notifications-mocks.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { AccountNotifications } from '../types';
2+
import type { StateType, Subject, SubjectType } from '../typesGitHub';
23
import {
34
mockEnterpriseNotifications,
45
mockGitHubNotifications,
@@ -28,3 +29,17 @@ export const mockSingleAccountNotifications: AccountNotifications[] = [
2829
error: null,
2930
},
3031
];
32+
33+
export function createSubjectMock(mocks: {
34+
title?: string;
35+
type?: SubjectType;
36+
state?: StateType;
37+
}): Subject {
38+
return {
39+
title: mocks.title ?? 'Mock Subject',
40+
type: mocks.type ?? ('Unknown' as SubjectType),
41+
state: mocks.state ?? ('Unknown' as StateType),
42+
url: null,
43+
latest_comment_url: null,
44+
};
45+
}

src/renderer/components/notifications/NotificationRow.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,9 @@ import type { Notification } from '../../typesGitHub';
99
import { cn } from '../../utils/cn';
1010
import { isMarkAsDoneFeatureSupported } from '../../utils/features';
1111
import { formatForDisplay } from '../../utils/helpers';
12-
import {
13-
getNotificationTypeIcon,
14-
getNotificationTypeIconColor,
15-
} from '../../utils/icons';
12+
import { getNotificationTypeIconColor } from '../../utils/icons';
1613
import { openNotification } from '../../utils/links';
14+
import { createNotificationHandler } from '../../utils/notifications/handlers';
1715
import { HoverButton } from '../primitives/HoverButton';
1816
import { HoverGroup } from '../primitives/HoverGroup';
1917
import { NotificationFooter } from './NotificationFooter';
@@ -73,7 +71,9 @@ export const NotificationRow: FC<INotificationRow> = ({
7371
unsubscribeNotification(notification);
7472
};
7573

76-
const NotificationIcon = getNotificationTypeIcon(notification.subject);
74+
const handler = createNotificationHandler(notification);
75+
76+
const NotificationIcon = handler.getIcon(notification.subject);
7777
const iconColor = getNotificationTypeIconColor(notification.subject);
7878

7979
const notificationType = formatForDisplay([

src/renderer/utils/__snapshots__/icons.test.ts.snap

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/renderer/utils/helpers.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,9 @@ import type { Notification } from '../typesGitHub';
1010
import { getHtmlUrl, getLatestDiscussion } from './api/client';
1111
import type { PlatformType } from './auth/types';
1212
import { Constants } from './constants';
13-
import {
14-
getCheckSuiteAttributes,
15-
getClosestDiscussionCommentOrReply,
16-
getWorkflowRunAttributes,
17-
} from './subject';
13+
import { getCheckSuiteAttributes } from './notifications/handlers/checkSuite';
14+
import { getClosestDiscussionCommentOrReply } from './notifications/handlers/discussion';
15+
import { getWorkflowRunAttributes } from './notifications/handlers/workflowRun';
1816

1917
export function getPlatformFromHostname(hostname: string): PlatformType {
2018
return hostname.endsWith(Constants.DEFAULT_AUTH_OPTIONS.hostname)

src/renderer/utils/icons.test.ts

Lines changed: 0 additions & 195 deletions
Original file line numberDiff line numberDiff line change
@@ -17,207 +17,12 @@ import type {
1717
import {
1818
getAuthMethodIcon,
1919
getDefaultUserIcon,
20-
getNotificationTypeIcon,
2120
getNotificationTypeIconColor,
2221
getPlatformIcon,
2322
getPullRequestReviewIcon,
2423
} from './icons';
2524

2625
describe('renderer/utils/icons.ts', () => {
27-
describe('getNotificationTypeIcon - should get the notification type icon', () => {
28-
expect(
29-
getNotificationTypeIcon(
30-
createSubjectMock({ type: 'CheckSuite', state: null }),
31-
).displayName,
32-
).toBe('RocketIcon');
33-
34-
expect(
35-
getNotificationTypeIcon(
36-
createSubjectMock({
37-
type: 'CheckSuite',
38-
state: 'cancelled',
39-
}),
40-
).displayName,
41-
).toBe('StopIcon');
42-
43-
expect(
44-
getNotificationTypeIcon(
45-
createSubjectMock({
46-
type: 'CheckSuite',
47-
state: 'failure',
48-
}),
49-
).displayName,
50-
).toBe('XIcon');
51-
52-
expect(
53-
getNotificationTypeIcon(
54-
createSubjectMock({
55-
type: 'CheckSuite',
56-
state: 'skipped',
57-
}),
58-
).displayName,
59-
).toBe('SkipIcon');
60-
61-
expect(
62-
getNotificationTypeIcon(
63-
createSubjectMock({
64-
type: 'CheckSuite',
65-
state: 'success',
66-
}),
67-
).displayName,
68-
).toBe('CheckIcon');
69-
70-
expect(
71-
getNotificationTypeIcon(createSubjectMock({ type: 'Commit' }))
72-
.displayName,
73-
).toBe('GitCommitIcon');
74-
75-
expect(
76-
getNotificationTypeIcon(createSubjectMock({ type: 'Discussion' }))
77-
.displayName,
78-
).toBe('CommentDiscussionIcon');
79-
80-
expect(
81-
getNotificationTypeIcon(
82-
createSubjectMock({ type: 'Discussion', state: 'DUPLICATE' }),
83-
).displayName,
84-
).toBe('DiscussionDuplicateIcon');
85-
86-
expect(
87-
getNotificationTypeIcon(
88-
createSubjectMock({ type: 'Discussion', state: 'OUTDATED' }),
89-
).displayName,
90-
).toBe('DiscussionOutdatedIcon');
91-
92-
expect(
93-
getNotificationTypeIcon(
94-
createSubjectMock({ type: 'Discussion', state: 'RESOLVED' }),
95-
).displayName,
96-
).toBe('DiscussionClosedIcon');
97-
98-
expect(
99-
getNotificationTypeIcon(createSubjectMock({ type: 'Issue' })).displayName,
100-
).toBe('IssueOpenedIcon');
101-
102-
expect(
103-
getNotificationTypeIcon(
104-
createSubjectMock({ type: 'Issue', state: 'draft' }),
105-
).displayName,
106-
).toBe('IssueDraftIcon');
107-
108-
expect(
109-
getNotificationTypeIcon(
110-
createSubjectMock({
111-
type: 'Issue',
112-
state: 'closed',
113-
}),
114-
).displayName,
115-
).toBe('IssueClosedIcon');
116-
117-
expect(
118-
getNotificationTypeIcon(
119-
createSubjectMock({
120-
type: 'Issue',
121-
state: 'completed',
122-
}),
123-
).displayName,
124-
).toBe('IssueClosedIcon');
125-
126-
expect(
127-
getNotificationTypeIcon(
128-
createSubjectMock({
129-
type: 'Issue',
130-
state: 'not_planned',
131-
}),
132-
).displayName,
133-
).toBe('SkipIcon');
134-
135-
expect(
136-
getNotificationTypeIcon(
137-
createSubjectMock({
138-
type: 'Issue',
139-
state: 'reopened',
140-
}),
141-
).displayName,
142-
).toBe('IssueReopenedIcon');
143-
144-
expect(
145-
getNotificationTypeIcon(createSubjectMock({ type: 'PullRequest' }))
146-
.displayName,
147-
).toBe('GitPullRequestIcon');
148-
149-
expect(
150-
getNotificationTypeIcon(
151-
createSubjectMock({
152-
type: 'PullRequest',
153-
state: 'draft',
154-
}),
155-
).displayName,
156-
).toBe('GitPullRequestDraftIcon');
157-
158-
expect(
159-
getNotificationTypeIcon(
160-
createSubjectMock({
161-
type: 'PullRequest',
162-
state: 'closed',
163-
}),
164-
).displayName,
165-
).toBe('GitPullRequestClosedIcon');
166-
167-
expect(
168-
getNotificationTypeIcon(
169-
createSubjectMock({
170-
type: 'PullRequest',
171-
state: 'merged',
172-
}),
173-
).displayName,
174-
).toBe('GitMergeIcon');
175-
176-
expect(
177-
getNotificationTypeIcon(
178-
createSubjectMock({
179-
type: 'Release',
180-
}),
181-
).displayName,
182-
).toBe('TagIcon');
183-
184-
expect(
185-
getNotificationTypeIcon(
186-
createSubjectMock({
187-
type: 'RepositoryDependabotAlertsThread',
188-
}),
189-
).displayName,
190-
).toBe('AlertIcon');
191-
192-
expect(
193-
getNotificationTypeIcon(
194-
createSubjectMock({
195-
type: 'RepositoryInvitation',
196-
}),
197-
).displayName,
198-
).toBe('MailIcon');
199-
200-
expect(
201-
getNotificationTypeIcon(
202-
createSubjectMock({
203-
type: 'RepositoryVulnerabilityAlert',
204-
}),
205-
).displayName,
206-
).toBe('AlertIcon');
207-
208-
expect(
209-
getNotificationTypeIcon(
210-
createSubjectMock({
211-
type: 'WorkflowRun',
212-
}),
213-
).displayName,
214-
).toBe('RocketIcon');
215-
216-
expect(getNotificationTypeIcon(createSubjectMock({})).displayName).toBe(
217-
'QuestionIcon',
218-
);
219-
});
220-
22126
describe('getNotificationTypeIconColor', () => {
22227
it('should format the notification color for check suite', () => {
22328
expect(

src/renderer/utils/icons.ts

Lines changed: 0 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,17 @@
11
import type { FC } from 'react';
22

33
import {
4-
AlertIcon,
54
AppsIcon,
65
CheckIcon,
7-
CommentDiscussionIcon,
86
CommentIcon,
9-
DiscussionClosedIcon,
10-
DiscussionDuplicateIcon,
11-
DiscussionOutdatedIcon,
127
FeedPersonIcon,
138
FileDiffIcon,
14-
GitCommitIcon,
15-
GitMergeIcon,
16-
GitPullRequestClosedIcon,
17-
GitPullRequestDraftIcon,
18-
GitPullRequestIcon,
19-
IssueClosedIcon,
20-
IssueDraftIcon,
21-
IssueOpenedIcon,
22-
IssueReopenedIcon,
239
KeyIcon,
24-
MailIcon,
2510
MarkGithubIcon,
2611
type OcticonProps,
2712
OrganizationIcon,
2813
PersonIcon,
29-
QuestionIcon,
30-
RocketIcon,
3114
ServerIcon,
32-
SkipIcon,
33-
StopIcon,
34-
TagIcon,
35-
XIcon,
3615
} from '@primer/octicons-react';
3716

3817
import { IconColor, type PullRequestApprovalIcon } from '../types';
@@ -43,74 +22,6 @@ import type {
4322
} from '../typesGitHub';
4423
import type { AuthMethod, PlatformType } from './auth/types';
4524

46-
export function getNotificationTypeIcon(subject: Subject): FC<OcticonProps> {
47-
switch (subject.type) {
48-
case 'CheckSuite':
49-
switch (subject.state) {
50-
case 'cancelled':
51-
return StopIcon;
52-
case 'failure':
53-
return XIcon;
54-
case 'skipped':
55-
return SkipIcon;
56-
case 'success':
57-
return CheckIcon;
58-
default:
59-
return RocketIcon;
60-
}
61-
case 'Commit':
62-
return GitCommitIcon;
63-
case 'Discussion':
64-
switch (subject.state) {
65-
case 'DUPLICATE':
66-
return DiscussionDuplicateIcon;
67-
case 'OUTDATED':
68-
return DiscussionOutdatedIcon;
69-
case 'RESOLVED':
70-
return DiscussionClosedIcon;
71-
default:
72-
return CommentDiscussionIcon;
73-
}
74-
case 'Issue':
75-
switch (subject.state) {
76-
case 'draft':
77-
return IssueDraftIcon;
78-
case 'closed':
79-
case 'completed':
80-
return IssueClosedIcon;
81-
case 'not_planned':
82-
return SkipIcon;
83-
case 'reopened':
84-
return IssueReopenedIcon;
85-
default:
86-
return IssueOpenedIcon;
87-
}
88-
case 'PullRequest':
89-
switch (subject.state) {
90-
case 'draft':
91-
return GitPullRequestDraftIcon;
92-
case 'closed':
93-
return GitPullRequestClosedIcon;
94-
case 'merged':
95-
return GitMergeIcon;
96-
default:
97-
return GitPullRequestIcon;
98-
}
99-
case 'Release':
100-
return TagIcon;
101-
case 'RepositoryDependabotAlertsThread':
102-
return AlertIcon;
103-
case 'RepositoryInvitation':
104-
return MailIcon;
105-
case 'RepositoryVulnerabilityAlert':
106-
return AlertIcon;
107-
case 'WorkflowRun':
108-
return RocketIcon;
109-
default:
110-
return QuestionIcon;
111-
}
112-
}
113-
11425
export function getNotificationTypeIconColor(subject: Subject): IconColor {
11526
switch (subject.state) {
11627
case 'open':

0 commit comments

Comments
 (0)