Skip to content

Commit fedbfbe

Browse files
authored
feat: support multiple accounts (#1201)
* feat: support multiple accounts * feat: update header * refactor: use account uuid * update snapshots * feat: correctly raise native notifications * pass account instead of hostname * fix * Merge remote-tracking branch 'origin/main' into refactor/accounts-auth-token * update tests
1 parent b017186 commit fedbfbe

22 files changed

+438
-401
lines changed

src/components/AccountNotifications.test.tsx

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
import { render } from '@testing-library/react';
1+
import { act, fireEvent, render, screen } from '@testing-library/react';
2+
import { mockGitHubCloudAccount } from '../__mocks__/state-mocks';
23
import { mockGitHubNotifications } from '../utils/api/__mocks__/response-mocks';
4+
import * as links from '../utils/links';
35
import { AccountNotifications } from './AccountNotifications';
46

57
jest.mock('./Repository', () => ({
@@ -9,7 +11,7 @@ jest.mock('./Repository', () => ({
911
describe('components/AccountNotifications.tsx', () => {
1012
it('should render itself (github.com with notifications)', () => {
1113
const props = {
12-
hostname: 'github.com',
14+
account: mockGitHubCloudAccount,
1315
notifications: mockGitHubNotifications,
1416
showAccountHostname: true,
1517
};
@@ -20,12 +22,31 @@ describe('components/AccountNotifications.tsx', () => {
2022

2123
it('should render itself (github.com without notifications)', () => {
2224
const props = {
23-
hostname: 'github.com',
25+
account: mockGitHubCloudAccount,
2426
notifications: [],
2527
showAccountHostname: true,
2628
};
2729

2830
const tree = render(<AccountNotifications {...props} />);
2931
expect(tree).toMatchSnapshot();
3032
});
33+
34+
it('should open profile when clicked', async () => {
35+
const openAccountProfileMock = jest.spyOn(links, 'openAccountProfile');
36+
37+
const props = {
38+
account: mockGitHubCloudAccount,
39+
notifications: [],
40+
showAccountHostname: true,
41+
};
42+
43+
await act(async () => {
44+
render(<AccountNotifications {...props} />);
45+
});
46+
47+
fireEvent.click(screen.getByTitle('Open Profile'));
48+
49+
expect(openAccountProfileMock).toHaveBeenCalledTimes(1);
50+
expect(openAccountProfileMock).toHaveBeenCalledWith(mockGitHubCloudAccount);
51+
});
3152
});

src/components/AccountNotifications.tsx

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
import { ChevronDownIcon, ChevronLeftIcon } from '@primer/octicons-react';
2+
import type { Account } from '../types';
23
import type { Notification } from '../typesGitHub';
4+
import { openAccountProfile } from '../utils/links';
35
import { RepositoryNotifications } from './Repository';
6+
import { PlatformIcon } from './icons/PlatformIcon';
47

58
interface IProps {
6-
hostname: string;
9+
account: Account;
710
notifications: Notification[];
811
showAccountHostname: boolean;
912
}
1013

1114
export const AccountNotifications = (props: IProps) => {
12-
const { hostname, showAccountHostname, notifications } = props;
15+
const { account, showAccountHostname, notifications } = props;
1316

1417
const groupedNotifications = Object.values(
1518
notifications.reduce(
@@ -28,9 +31,20 @@ export const AccountNotifications = (props: IProps) => {
2831
return (
2932
<>
3033
{showAccountHostname && (
31-
<div className="flex items-center justify-between py-2 px-3 bg-gray-300 dark:bg-gray-darkest dark:text-white text-sm">
32-
{hostname}
33-
<Chevron size={20} />
34+
<div className="flex items-center justify-between py-2 px-3 bg-gray-300 dark:bg-gray-darkest dark:text-white text-sm text-semibold">
35+
<div>
36+
<PlatformIcon type={account.platform} size={16} />
37+
<button
38+
type="button"
39+
title="Open Profile"
40+
onClick={() => openAccountProfile(account)}
41+
>
42+
@{account.user.login}
43+
</button>
44+
</div>
45+
<div>
46+
<Chevron size={20} />
47+
</div>
3448
</div>
3549
)}
3650

@@ -40,7 +54,7 @@ export const AccountNotifications = (props: IProps) => {
4054
return (
4155
<RepositoryNotifications
4256
key={repoSlug}
43-
hostname={hostname}
57+
account={account}
4458
repoName={repoSlug}
4559
repoNotifications={repoNotifications}
4660
/>

src/components/NotificationRow.test.tsx

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { fireEvent, render, screen } from '@testing-library/react';
2-
import { mockAuth, mockSettings } from '../__mocks__/state-mocks';
2+
import {
3+
mockAuth,
4+
mockGitHubCloudAccount,
5+
mockSettings,
6+
} from '../__mocks__/state-mocks';
37
import { AppContext } from '../context/App';
48
import type { Milestone, UserType } from '../typesGitHub';
59
import { mockSingleNotification } from '../utils/api/__mocks__/response-mocks';
@@ -23,7 +27,7 @@ describe('components/NotificationRow.tsx', () => {
2327

2428
const props = {
2529
notification: mockSingleNotification,
26-
hostname: 'github.com',
30+
account: mockGitHubCloudAccount,
2731
};
2832

2933
const tree = render(
@@ -44,7 +48,7 @@ describe('components/NotificationRow.tsx', () => {
4448

4549
const props = {
4650
notification: mockNotification,
47-
hostname: 'github.com',
51+
account: mockGitHubCloudAccount,
4852
};
4953

5054
const tree = render(
@@ -65,7 +69,7 @@ describe('components/NotificationRow.tsx', () => {
6569

6670
const props = {
6771
notification: mockNotification,
68-
hostname: 'github.com',
72+
account: mockGitHubCloudAccount,
6973
};
7074

7175
const tree = render(
@@ -88,7 +92,7 @@ describe('components/NotificationRow.tsx', () => {
8892

8993
const props = {
9094
notification: mockNotification,
91-
hostname: 'github.com',
95+
account: mockGitHubCloudAccount,
9296
};
9397

9498
const tree = render(
@@ -115,7 +119,7 @@ describe('components/NotificationRow.tsx', () => {
115119

116120
const props = {
117121
notification: mockNotification,
118-
hostname: 'github.com',
122+
account: mockGitHubCloudAccount,
119123
};
120124

121125
const tree = render(
@@ -140,7 +144,7 @@ describe('components/NotificationRow.tsx', () => {
140144

141145
const props = {
142146
notification: mockNotification,
143-
hostname: 'github.com',
147+
account: mockGitHubCloudAccount,
144148
};
145149

146150
const tree = render(
@@ -167,7 +171,7 @@ describe('components/NotificationRow.tsx', () => {
167171

168172
const props = {
169173
notification: mockNotification,
170-
hostname: 'github.com',
174+
account: mockGitHubCloudAccount,
171175
};
172176

173177
const tree = render(
@@ -192,7 +196,7 @@ describe('components/NotificationRow.tsx', () => {
192196

193197
const props = {
194198
notification: mockNotification,
195-
hostname: 'github.com',
199+
account: mockGitHubCloudAccount,
196200
};
197201

198202
const tree = render(
@@ -217,7 +221,7 @@ describe('components/NotificationRow.tsx', () => {
217221

218222
const props = {
219223
notification: mockNotification,
220-
hostname: 'github.com',
224+
account: mockGitHubCloudAccount,
221225
};
222226

223227
const tree = render(
@@ -244,7 +248,7 @@ describe('components/NotificationRow.tsx', () => {
244248

245249
const props = {
246250
notification: mockNotification,
247-
hostname: 'github.com',
251+
account: mockGitHubCloudAccount,
248252
};
249253

250254
const tree = render(
@@ -274,7 +278,7 @@ describe('components/NotificationRow.tsx', () => {
274278

275279
const props = {
276280
notification: mockNotification,
277-
hostname: 'github.com',
281+
account: mockGitHubCloudAccount,
278282
};
279283

280284
const tree = render(
@@ -302,7 +306,7 @@ describe('components/NotificationRow.tsx', () => {
302306

303307
const props = {
304308
notification: mockNotification,
305-
hostname: 'github.com',
309+
account: mockGitHubCloudAccount,
306310
};
307311

308312
const tree = render(
@@ -325,7 +329,7 @@ describe('components/NotificationRow.tsx', () => {
325329

326330
const props = {
327331
notification: mockSingleNotification,
328-
hostname: 'github.com',
332+
account: mockGitHubCloudAccount,
329333
};
330334

331335
render(
@@ -350,7 +354,7 @@ describe('components/NotificationRow.tsx', () => {
350354

351355
const props = {
352356
notification: mockSingleNotification,
353-
hostname: 'github.com',
357+
account: mockGitHubCloudAccount,
354358
};
355359

356360
render(
@@ -375,7 +379,7 @@ describe('components/NotificationRow.tsx', () => {
375379

376380
const props = {
377381
notification: mockSingleNotification,
378-
hostname: 'github.com',
382+
account: mockGitHubCloudAccount,
379383
};
380384

381385
render(
@@ -400,7 +404,7 @@ describe('components/NotificationRow.tsx', () => {
400404

401405
const props = {
402406
notification: mockSingleNotification,
403-
hostname: 'github.com',
407+
account: mockGitHubCloudAccount,
404408
};
405409

406410
render(
@@ -423,7 +427,7 @@ describe('components/NotificationRow.tsx', () => {
423427

424428
const props = {
425429
notification: mockSingleNotification,
426-
hostname: 'github.com',
430+
account: mockGitHubCloudAccount,
427431
};
428432

429433
render(
@@ -443,7 +447,7 @@ describe('components/NotificationRow.tsx', () => {
443447

444448
const props = {
445449
notification: mockSingleNotification,
446-
hostname: 'github.com',
450+
account: mockGitHubCloudAccount,
447451
};
448452

449453
render(
@@ -477,7 +481,7 @@ describe('components/NotificationRow.tsx', () => {
477481
reviews: null,
478482
},
479483
},
480-
hostname: 'github.com',
484+
account: mockGitHubCloudAccount,
481485
};
482486

483487
render(

src/components/NotificationRow.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { type FC, type MouseEvent, useCallback, useContext } from 'react';
1212

1313
import { AppContext } from '../context/App';
1414
import { PILL_CLASS_NAME } from '../styles/gitify';
15-
import { IconColor } from '../types';
15+
import { type Account, IconColor } from '../types';
1616
import type { Notification } from '../typesGitHub';
1717
import {
1818
formatForDisplay,
@@ -27,11 +27,11 @@ import { openNotification, openUserProfile } from '../utils/links';
2727
import { formatReason } from '../utils/reason';
2828

2929
interface IProps {
30-
hostname: string;
30+
account: Account;
3131
notification: Notification;
3232
}
3333

34-
export const NotificationRow: FC<IProps> = ({ notification, hostname }) => {
34+
export const NotificationRow: FC<IProps> = ({ notification, account }) => {
3535
const {
3636
auth,
3737
settings,
@@ -46,18 +46,18 @@ export const NotificationRow: FC<IProps> = ({ notification, hostname }) => {
4646
openNotification(notification);
4747

4848
if (settings.markAsDoneOnOpen) {
49-
markNotificationDone(notification.id, hostname);
49+
markNotificationDone(notification);
5050
} else {
5151
// no need to mark as read, github does it by default when opening it
52-
removeNotificationFromState(settings, notification.id, hostname);
52+
removeNotificationFromState(settings, notification);
5353
}
5454
}, [notifications, notification, auth, settings]); // notifications required here to prevent weird state issues
5555

5656
const unsubscribeFromThread = (event: MouseEvent<HTMLElement>) => {
5757
// Don't trigger onClick of parent element.
5858
event.stopPropagation();
5959

60-
unsubscribeNotification(notification.id, hostname);
60+
unsubscribeNotification(notification);
6161
};
6262

6363
const reason = formatReason(notification.reason);
@@ -225,7 +225,7 @@ export const NotificationRow: FC<IProps> = ({ notification, hostname }) => {
225225
type="button"
226226
className="focus:outline-none h-full hover:text-green-500"
227227
title="Mark as Done"
228-
onClick={() => markNotificationDone(notification.id, hostname)}
228+
onClick={() => markNotificationDone(notification)}
229229
>
230230
<CheckIcon size={16} aria-label="Mark as Done" />
231231
</button>
@@ -243,7 +243,7 @@ export const NotificationRow: FC<IProps> = ({ notification, hostname }) => {
243243
type="button"
244244
className="focus:outline-none h-full hover:text-green-500"
245245
title="Mark as Read"
246-
onClick={() => markNotificationRead(notification.id, hostname)}
246+
onClick={() => markNotificationRead(notification)}
247247
>
248248
<ReadIcon size={14} aria-label="Mark as Read" />
249249
</button>

src/components/Repository.test.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { fireEvent, render, screen } from '@testing-library/react';
2+
import { mockGitHubCloudAccount } from '../__mocks__/state-mocks';
23
import { AppContext } from '../context/App';
3-
import { mockGitHubNotifications } from '../utils/api/__mocks__/response-mocks';
4+
import {
5+
mockGitHubNotifications,
6+
mockSingleNotification,
7+
} from '../utils/api/__mocks__/response-mocks';
48
import * as comms from '../utils/comms';
59
import { RepositoryNotifications } from './Repository';
610

@@ -13,7 +17,7 @@ describe('components/Repository.tsx', () => {
1317
const markRepoNotificationsDone = jest.fn();
1418

1519
const props = {
16-
hostname: 'github.com',
20+
account: mockGitHubCloudAccount,
1721
repoName: 'gitify-app/notifications-test',
1822
repoNotifications: mockGitHubNotifications,
1923
};
@@ -58,8 +62,7 @@ describe('components/Repository.tsx', () => {
5862
fireEvent.click(screen.getByTitle('Mark Repository as Read'));
5963

6064
expect(markRepoNotificationsRead).toHaveBeenCalledWith(
61-
'gitify-app/notifications-test',
62-
'github.com',
65+
mockSingleNotification,
6366
);
6467
});
6568

@@ -73,8 +76,7 @@ describe('components/Repository.tsx', () => {
7376
fireEvent.click(screen.getByTitle('Mark Repository as Done'));
7477

7578
expect(markRepoNotificationsDone).toHaveBeenCalledWith(
76-
'gitify-app/notifications-test',
77-
'github.com',
79+
mockSingleNotification,
7880
);
7981
});
8082

0 commit comments

Comments
 (0)