Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into feat/mark-repository-…
Browse files Browse the repository at this point in the history
…as-done
  • Loading branch information
adufr committed Feb 19, 2024
2 parents bb609b9 + 7efe0d9 commit 0514a43
Show file tree
Hide file tree
Showing 16 changed files with 203 additions and 28 deletions.
5 changes: 3 additions & 2 deletions src/components/NotificationRow.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ describe('components/Notification.js', () => {
});

it('should open a notification in the browser', () => {
const markNotification = jest.fn();
const removeNotificationFromState = jest.fn();

const props = {
notification: mockedSingleNotification,
Expand All @@ -42,7 +42,7 @@ describe('components/Notification.js', () => {
<AppContext.Provider
value={{
settings: { ...mockSettings, markAsDoneOnOpen: false },
markNotification,
removeNotificationFromState,
accounts: mockAccounts,
}}
>
Expand All @@ -52,6 +52,7 @@ describe('components/Notification.js', () => {

fireEvent.click(getByRole('main'));
expect(shell.openExternal).toHaveBeenCalledTimes(1);
expect(removeNotificationFromState).toHaveBeenCalledTimes(1);
});

it('should open a notification in browser & mark it as done', () => {
Expand Down
4 changes: 4 additions & 0 deletions src/components/NotificationRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const NotificationRow: React.FC<IProps> = ({
const {
settings,
accounts,
removeNotificationFromState,
markNotification,
markNotificationDone,
unsubscribeNotification,
Expand All @@ -33,6 +34,9 @@ export const NotificationRow: React.FC<IProps> = ({

if (settings.markAsDoneOnOpen) {
markNotificationDone(notification.id, hostname);
} else {
// no need to mark as read, github does it by default when opening it
removeNotificationFromState(notification.id, hostname);
}
}, [settings]);

Expand Down
4 changes: 2 additions & 2 deletions src/context/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ describe('context/App.tsx', () => {
participating: true,
playSound: true,
showNotifications: true,
colors: false,
colors: null,
markAsDoneOnOpen: false,
},
);
Expand Down Expand Up @@ -328,7 +328,7 @@ describe('context/App.tsx', () => {
participating: false,
playSound: true,
showNotifications: true,
colors: false,
colors: null,
markAsDoneOnOpen: false,
},
);
Expand Down
5 changes: 4 additions & 1 deletion src/context/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const defaultSettings: SettingsState = {
showNotifications: true,
openAtStartup: false,
appearance: Appearance.SYSTEM,
colors: false,
colors: null,
markAsDoneOnOpen: false,
};

Expand All @@ -51,6 +51,7 @@ interface AppContextState {
notifications: AccountNotifications[];
isFetching: boolean;
requestFailed: boolean;
removeNotificationFromState: (id: string, hostname: string) => void;
fetchNotifications: () => Promise<void>;
markNotification: (id: string, hostname: string) => Promise<void>;
markNotificationDone: (id: string, hostname: string) => Promise<void>;
Expand All @@ -72,6 +73,7 @@ export const AppProvider = ({ children }: { children: React.ReactNode }) => {
notifications,
requestFailed,
isFetching,
removeNotificationFromState,
markNotification,
markNotificationDone,
unsubscribeNotification,
Expand Down Expand Up @@ -218,6 +220,7 @@ export const AppProvider = ({ children }: { children: React.ReactNode }) => {
notifications,
isFetching,
requestFailed,
removeNotificationFromState,
fetchNotifications: fetchNotificationsWithAccounts,
markNotification: markNotificationWithAccounts,
markNotificationDone: markNotificationDoneWithAccounts,
Expand Down
36 changes: 36 additions & 0 deletions src/hooks/useNotifications.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,42 @@ describe('hooks/useNotifications.ts', () => {
});
});

describe('removeNotificationFromState', () => {
it('should remove a notification from state', async () => {
const notifications = [
{ id: 1, title: 'This is a notification.' },
{ id: 2, title: 'This is another one.' },
];

nock('https://api.github.com')
.get('/notifications?participating=false')
.reply(200, notifications);

nock('https://github.gitify.io/api/v3')
.get('/notifications?participating=false')
.reply(200, notifications);

const { result } = renderHook(() => useNotifications(false));

act(() => {
result.current.fetchNotifications(mockAccounts, mockSettings);
});

await waitFor(() => {
expect(result.current.isFetching).toBe(false);
});

act(() => {
result.current.removeNotificationFromState(
result.current.notifications[0].notifications[0].id,
result.current.notifications[0].hostname,
);
});

expect(result.current.notifications[0].notifications.length).toBe(1);
});
});

describe('markNotification', () => {
const id = 'notification-123';

Expand Down
33 changes: 25 additions & 8 deletions src/hooks/useNotifications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { apiRequestAuth } from '../utils/api-requests';
import {
getEnterpriseAccountToken,
generateGitHubAPIUrl,
isEnterpriseHost,
} from '../utils/helpers';
import { removeNotification } from '../utils/remove-notification';
import {
Expand All @@ -19,6 +20,7 @@ import { removeNotifications } from '../utils/remove-notifications';

interface NotificationsState {
notifications: AccountNotifications[];
removeNotificationFromState: (id: string, hostname: string) => void;
fetchNotifications: (
accounts: AuthState,
settings: SettingsState,
Expand Down Expand Up @@ -109,7 +111,7 @@ export const useNotifications = (colors: boolean): NotificationsState => {
]
: [...enterpriseNotifications];

if (!colors) {
if (colors === false) {
setNotifications(data);
triggerNativeNotifications(
notifications,
Expand All @@ -134,9 +136,9 @@ export const useNotifications = (colors: boolean): NotificationsState => {
) {
return notification;
}
const isEnterprise =
accountNotifications.hostname !==
Constants.DEFAULT_AUTH_OPTIONS.hostname;
const isEnterprise = isEnterpriseHost(
accountNotifications.hostname,
);
const token = isEnterprise
? getEnterpriseAccountToken(
accountNotifications.hostname,
Expand Down Expand Up @@ -196,7 +198,7 @@ export const useNotifications = (colors: boolean): NotificationsState => {
async (accounts, id, hostname) => {
setIsFetching(true);

const isEnterprise = hostname !== Constants.DEFAULT_AUTH_OPTIONS.hostname;
const isEnterprise = isEnterpriseHost(hostname);
const token = isEnterprise
? getEnterpriseAccountToken(hostname, accounts.enterpriseAccounts)
: accounts.token;
Expand Down Expand Up @@ -229,7 +231,7 @@ export const useNotifications = (colors: boolean): NotificationsState => {
async (accounts, id, hostname) => {
setIsFetching(true);

const isEnterprise = hostname !== Constants.DEFAULT_AUTH_OPTIONS.hostname;
const isEnterprise = isEnterpriseHost(hostname);
const token = isEnterprise
? getEnterpriseAccountToken(hostname, accounts.enterpriseAccounts)
: accounts.token;
Expand Down Expand Up @@ -262,7 +264,7 @@ export const useNotifications = (colors: boolean): NotificationsState => {
async (accounts, id, hostname) => {
setIsFetching(true);

const isEnterprise = hostname !== Constants.DEFAULT_AUTH_OPTIONS.hostname;
const isEnterprise = isEnterpriseHost(hostname);
const token = isEnterprise
? getEnterpriseAccountToken(hostname, accounts.enterpriseAccounts)
: accounts.token;
Expand All @@ -288,7 +290,7 @@ export const useNotifications = (colors: boolean): NotificationsState => {
async (accounts, repoSlug, hostname) => {
setIsFetching(true);

const isEnterprise = hostname !== Constants.DEFAULT_AUTH_OPTIONS.hostname;
const isEnterprise = isEnterpriseHost(hostname);
const token = isEnterprise
? getEnterpriseAccountToken(hostname, accounts.enterpriseAccounts)
: accounts.token;
Expand Down Expand Up @@ -360,11 +362,26 @@ export const useNotifications = (colors: boolean): NotificationsState => {
[notifications],
);

const removeNotificationFromState = useCallback(
(id, hostname) => {
const updatedNotifications = removeNotification(
id,
notifications,
hostname,
);

setNotifications(updatedNotifications);
setTrayIconColor(updatedNotifications);
},
[notifications],
);

return {
isFetching,
requestFailed,
notifications,

removeNotificationFromState,
fetchNotifications,
markNotification,
markNotificationDone,
Expand Down
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export interface SettingsState {
showNotifications: boolean;
openAtStartup: boolean;
appearance: Appearance;
colors: boolean;
colors: boolean | null;
markAsDoneOnOpen: boolean;
}

Expand Down
3 changes: 3 additions & 0 deletions src/typesGithub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@ export type IssueStateType =
| 'completed'
| 'reopened'
| 'not_planned';

export type PullRequestStateType = 'closed' | 'open' | 'merged' | 'draft';

export type StateType = IssueStateType | PullRequestStateType;

export type ViewerSubscription = 'IGNORED' | 'SUBSCRIBED' | 'UNSUBSCRIBED';

export interface Notification {
Expand Down
18 changes: 18 additions & 0 deletions src/utils/__snapshots__/api-requests.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`apiRequest should make a request with the correct parameters 1`] = `
{
"Accept": "application/json",
"Cache-Control": "no-cache",
"Content-Type": "application/json",
}
`;

exports[`apiRequestAuth should make an authenticated request with the correct parameters 1`] = `
{
"Accept": "application/json",
"Authorization": "token yourAuthToken",
"Cache-Control": "no-cache",
"Content-Type": "application/json",
}
`;
21 changes: 21 additions & 0 deletions src/utils/__snapshots__/github-api.test.ts.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`./utils/github-api.ts should format the notification color 1`] = `"text-red-500"`;

exports[`./utils/github-api.ts should format the notification color 2`] = `"text-purple-500"`;

exports[`./utils/github-api.ts should format the notification color 3`] = `"text-gray-600"`;

exports[`./utils/github-api.ts should format the notification color 4`] = `"text-purple-500"`;

exports[`./utils/github-api.ts should format the notification color 5`] = `"text-gray-300"`;

exports[`./utils/github-api.ts should format the notification color 6`] = `"text-green-500"`;

exports[`./utils/github-api.ts should format the notification color 7`] = `"text-green-500"`;

exports[`./utils/github-api.ts should format the notification color 8`] = `
{
"description": "The reason for this notification is not supported by the app.",
"type": "Unknown",
}
`;

exports[`./utils/github-api.ts should format the notification reason 1`] = `
{
"description": "You were assigned to the issue.",
Expand Down
41 changes: 41 additions & 0 deletions src/utils/api-requests.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import axios from 'axios';
import { apiRequest, apiRequestAuth } from './api-requests';

jest.mock('axios');

describe('apiRequest', () => {
it('should make a request with the correct parameters', async () => {
const url = 'https://example.com';
const method = 'get';
const data = { key: 'value' };

await apiRequest(url, method, data);

expect(axios).toHaveBeenCalledWith({
method,
url,
data,
});

expect(axios.defaults.headers.common).toMatchSnapshot();
});
});

describe('apiRequestAuth', () => {
it('should make an authenticated request with the correct parameters', async () => {
const url = 'https://example.com';
const method = 'get';
const token = 'yourAuthToken';
const data = { key: 'value' };

await apiRequestAuth(url, method, token, data);

expect(axios).toHaveBeenCalledWith({
method,
url,
data,
});

expect(axios.defaults.headers.common).toMatchSnapshot();
});
});
4 changes: 2 additions & 2 deletions src/utils/auth.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BrowserWindow } from '@electron/remote';

import { generateGitHubAPIUrl } from './helpers';
import { generateGitHubAPIUrl, isEnterpriseHost } from './helpers';
import { apiRequest, apiRequestAuth } from '../utils/api-requests';
import { AuthResponse, AuthState, AuthTokenResponse } from '../types';
import { Constants } from '../utils/constants';
Expand Down Expand Up @@ -114,7 +114,7 @@ export const addAccount = (
hostname,
user?: User,
): AuthState => {
if (hostname === Constants.DEFAULT_AUTH_OPTIONS.hostname) {
if (!isEnterpriseHost(hostname)) {
return {
...accounts,
token,
Expand Down
17 changes: 16 additions & 1 deletion src/utils/github-api.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { formatReason, getNotificationTypeIcon } from './github-api';
import {
formatReason,
getNotificationTypeIcon,
getNotificationTypeIconColor,
} from './github-api';
import { Reason, SubjectType } from '../typesGithub';

describe('./utils/github-api.ts', () => {
Expand Down Expand Up @@ -62,4 +66,15 @@ describe('./utils/github-api.ts', () => {
'QuestionIcon',
);
});

it('should format the notification color', () => {
expect(getNotificationTypeIconColor('closed')).toMatchSnapshot();
expect(getNotificationTypeIconColor('completed')).toMatchSnapshot();
expect(getNotificationTypeIconColor('draft')).toMatchSnapshot();
expect(getNotificationTypeIconColor('merged')).toMatchSnapshot();
expect(getNotificationTypeIconColor('not_planned')).toMatchSnapshot();
expect(getNotificationTypeIconColor('open')).toMatchSnapshot();
expect(getNotificationTypeIconColor('reopened')).toMatchSnapshot();
expect(formatReason('something_else_unknown' as Reason)).toMatchSnapshot();
});
});
Loading

0 comments on commit 0514a43

Please sign in to comment.