Skip to content

Commit

Permalink
feat(settings): open links in foreground or background (#1376)
Browse files Browse the repository at this point in the history
* feat(settings): open links in foreground or background

* feat(settings): open links in foreground or background

* Merge branch 'main' into feature/system-setting-open-preference

* Merge branch 'main' into feature/system-setting-open-preference
  • Loading branch information
setchy authored Jul 15, 2024
1 parent f51f908 commit e9c7a64
Show file tree
Hide file tree
Showing 22 changed files with 202 additions and 52 deletions.
2 changes: 2 additions & 0 deletions src/__mocks__/state-mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
type GitifyUser,
GroupBy,
type Hostname,
OpenPreference,
type SettingsState,
Theme,
type Token,
Expand Down Expand Up @@ -88,6 +89,7 @@ const mockNotificationSettings = {
};

const mockSystemSettings = {
openLinks: OpenPreference.FOREGROUND,
keyboardShortcut: true,
showNotificationsCountInTray: false,
showNotifications: true,
Expand Down
4 changes: 3 additions & 1 deletion src/components/AccountNotifications.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ describe('components/AccountNotifications.tsx', () => {
});

it('should open profile when clicked', async () => {
const openAccountProfileMock = jest.spyOn(links, 'openAccountProfile');
const openAccountProfileMock = jest
.spyOn(links, 'openAccountProfile')
.mockImplementation();

const props = {
account: mockGitHubCloudAccount,
Expand Down
5 changes: 2 additions & 3 deletions src/components/NotificationRow.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ import * as links from '../utils/links';
import { NotificationRow } from './NotificationRow';

describe('components/NotificationRow.tsx', () => {
beforeEach(() => {
jest.spyOn(links, 'openNotification');
});
jest.spyOn(links, 'openNotification');
jest.spyOn(comms, 'openExternalLink').mockImplementation();

afterEach(() => {
jest.clearAllMocks();
Expand Down
4 changes: 3 additions & 1 deletion src/components/RepositoryNotifications.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ describe('components/Repository.tsx', () => {
});

it('should open the browser when clicking on the repo name', () => {
const openExternalLinkMock = jest.spyOn(comms, 'openExternalLink');
const openExternalLinkMock = jest
.spyOn(comms, 'openExternalLink')
.mockImplementation();

render(
<AppContext.Provider value={{}}>
Expand Down
5 changes: 3 additions & 2 deletions src/components/Sidebar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ jest.mock('react-router-dom', () => ({

describe('components/Sidebar.tsx', () => {
const fetchNotifications = jest.fn();

const openExternalLinkMock = jest.spyOn(comms, 'openExternalLink');
const openExternalLinkMock = jest
.spyOn(comms, 'openExternalLink')
.mockImplementation();

afterEach(() => {
jest.clearAllMocks();
Expand Down
8 changes: 5 additions & 3 deletions src/components/buttons/Button.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { MarkGithubIcon } from '@primer/octicons-react';
import { fireEvent, render, screen } from '@testing-library/react';
import { shell } from 'electron';
import type { Link } from '../../types';
import * as comms from '../../utils/comms';
import { Button, type IButton } from './Button';

describe('components/buttons/Button.tsx', () => {
const openExternalMock = jest.spyOn(shell, 'openExternal');
const openExternalLinkMock = jest
.spyOn(comms, 'openExternalLink')
.mockImplementation();

const props: IButton = {
label: 'button',
Expand Down Expand Up @@ -39,6 +41,6 @@ describe('components/buttons/Button.tsx', () => {
const buttonElement = screen.getByLabelText('button');

fireEvent.click(buttonElement);
expect(openExternalMock).toHaveBeenCalledTimes(1);
expect(openExternalLinkMock).toHaveBeenCalledTimes(1);
});
});
9 changes: 3 additions & 6 deletions src/components/notification/NotificationFooter.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,9 @@ import { GroupBy, type Link } from '../../types';
import type { UserType } from '../../typesGitHub';
import { mockSingleNotification } from '../../utils/api/__mocks__/response-mocks';
import * as comms from '../../utils/comms';
import * as links from '../../utils/links';
import { NotificationFooter } from './NotificationFooter';

describe('components/notification/NotificationFooter.tsx', () => {
beforeEach(() => {
jest.spyOn(links, 'openNotification');
});

afterEach(() => {
jest.clearAllMocks();
});
Expand Down Expand Up @@ -122,7 +117,9 @@ describe('components/notification/NotificationFooter.tsx', () => {
});

it('should open notification user profile', () => {
const openExternalLinkMock = jest.spyOn(comms, 'openExternalLink');
const openExternalLinkMock = jest
.spyOn(comms, 'openExternalLink')
.mockImplementation();

const props = {
notification: {
Expand Down
8 changes: 7 additions & 1 deletion src/components/notification/NotificationHeader.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import * as comms from '../../utils/comms';
import { NotificationHeader } from './NotificationHeader';

describe('components/notification/NotificationHeader.tsx', () => {
afterEach(() => {
jest.clearAllMocks();
});

it('should render itself & its children - group by repositories', async () => {
const props = {
notification: mockSingleNotification,
Expand Down Expand Up @@ -38,7 +42,9 @@ describe('components/notification/NotificationHeader.tsx', () => {
});

it('should open notification user profile - group by date', () => {
const openExternalLinkMock = jest.spyOn(comms, 'openExternalLink');
const openExternalLinkMock = jest
.spyOn(comms, 'openExternalLink')
.mockImplementation();

const props = {
notification: mockSingleNotification,
Expand Down
4 changes: 3 additions & 1 deletion src/components/settings/NotificationSettings.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ describe('routes/components/settings/NotificationSettings.tsx', () => {
});

it('should open official docs for showOnlyParticipating tooltip', async () => {
const openExternalLinkMock = jest.spyOn(comms, 'openExternalLink');
const openExternalLinkMock = jest
.spyOn(comms, 'openExternalLink')
.mockImplementation();

await act(async () => {
render(
Expand Down
4 changes: 3 additions & 1 deletion src/components/settings/SettingsFooter.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ describe('routes/components/settings/SettingsFooter.tsx', () => {
...originalEnv,
NODE_ENV: 'production',
};
const openExternalLinkMock = jest.spyOn(comms, 'openExternalLink');
const openExternalLinkMock = jest
.spyOn(comms, 'openExternalLink')
.mockImplementation();

await act(async () => {
render(
Expand Down
23 changes: 23 additions & 0 deletions src/components/settings/SystemSettings.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,29 @@ describe('routes/components/settings/SystemSettings.tsx', () => {
jest.clearAllMocks();
});

it('should change the open links radio group', async () => {
await act(async () => {
render(
<AppContext.Provider
value={{
auth: mockAuth,
settings: mockSettings,
updateSetting,
}}
>
<MemoryRouter>
<SystemSettings />
</MemoryRouter>
</AppContext.Provider>,
);
});

fireEvent.click(screen.getByLabelText('Background'));

expect(updateSetting).toHaveBeenCalledTimes(1);
expect(updateSetting).toHaveBeenCalledWith('openLinks', 'BACKGROUND');
});

it('should toggle the keyboardShortcut checkbox', async () => {
await act(async () => {
render(
Expand Down
14 changes: 14 additions & 0 deletions src/components/settings/SystemSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { DeviceDesktopIcon } from '@primer/octicons-react';
import { type FC, useContext } from 'react';
import { AppContext } from '../../context/App';
import type { OpenPreference } from '../../types';
import Constants from '../../utils/constants';
import { isLinux, isMacOS } from '../../utils/platform';
import { Checkbox } from '../fields/Checkbox';
import { RadioGroup } from '../fields/RadioGroup';
import { Legend } from './Legend';

export const SystemSettings: FC = () => {
Expand All @@ -12,6 +14,18 @@ export const SystemSettings: FC = () => {
return (
<fieldset>
<Legend icon={DeviceDesktopIcon}>System</Legend>
<RadioGroup
name="openLinks"
label="Open Links:"
value={settings.openLinks}
options={[
{ label: 'Foreground', value: 'FOREGROUND' },
{ label: 'Background', value: 'BACKGROUND' },
]}
onChange={(evt) => {
updateSetting('openLinks', evt.target.value as OpenPreference);
}}
/>
<Checkbox
name="keyboardShortcutEnabled"
label="Enable keyboard shortcut"
Expand Down
2 changes: 2 additions & 0 deletions src/context/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ describe('context/App.tsx', () => {
groupBy: 'REPOSITORY',
filterReasons: [],
zoomPercentage: 100,
openLinks: 'FOREGROUND',
} as SettingsState,
});
});
Expand Down Expand Up @@ -440,6 +441,7 @@ describe('context/App.tsx', () => {
groupBy: 'REPOSITORY',
filterReasons: [],
zoomPercentage: 100,
openLinks: 'FOREGROUND',
} as SettingsState,
});
});
Expand Down
2 changes: 2 additions & 0 deletions src/context/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
type AuthState,
type GitifyError,
GroupBy,
OpenPreference,
type SettingsState,
type SettingsValue,
type Status,
Expand Down Expand Up @@ -69,6 +70,7 @@ const defaultNotificationSettings = {
};

const defaultSystemSettings = {
openLinks: OpenPreference.FOREGROUND,
keyboardShortcut: true,
showNotificationsCountInTray: false,
showNotifications: true,
Expand Down
12 changes: 9 additions & 3 deletions src/routes/Accounts.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ describe('routes/Accounts.tsx', () => {

describe('Account interactions', () => {
it('open profile in external browser', async () => {
const openAccountProfileMock = jest.spyOn(links, 'openAccountProfile');
const openAccountProfileMock = jest
.spyOn(links, 'openAccountProfile')
.mockImplementation();

await act(async () => {
render(
Expand Down Expand Up @@ -101,7 +103,9 @@ describe('routes/Accounts.tsx', () => {
});

it('open host in external browser', async () => {
const openExternalLinkMock = jest.spyOn(comms, 'openExternalLink');
const openExternalLinkMock = jest
.spyOn(comms, 'openExternalLink')
.mockImplementation();

await act(async () => {
render(
Expand All @@ -127,7 +131,9 @@ describe('routes/Accounts.tsx', () => {
});

it('open developer settings in external browser', async () => {
const openExternalLinkMock = jest.spyOn(comms, 'openExternalLink');
const openExternalLinkMock = jest
.spyOn(comms, 'openExternalLink')
.mockImplementation();

await act(async () => {
render(
Expand Down
12 changes: 7 additions & 5 deletions src/routes/LoginWithOAuthApp.test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { fireEvent, render, screen } from '@testing-library/react';
import { shell } from 'electron';
import { MemoryRouter } from 'react-router-dom';
import { AppContext } from '../context/App';
import type { AuthState, ClientID, ClientSecret, Hostname } from '../types';
import * as comms from '../utils/comms';
import { LoginWithOAuthApp, validate } from './LoginWithOAuthApp';

const mockNavigate = jest.fn();
Expand All @@ -12,7 +12,9 @@ jest.mock('react-router-dom', () => ({
}));

describe('routes/LoginWithOAuthApp.tsx', () => {
const openExternalMock = jest.spyOn(shell, 'openExternal');
const openExternalLinkMock = jest
.spyOn(comms, 'openExternalLink')
.mockImplementation();

const mockAuth: AuthState = {
accounts: [],
Expand Down Expand Up @@ -84,7 +86,7 @@ describe('routes/LoginWithOAuthApp.tsx', () => {

fireEvent.click(screen.getByText('Create new OAuth App'));

expect(openExternalMock).toHaveBeenCalledTimes(0);
expect(openExternalLinkMock).toHaveBeenCalledTimes(0);
});

it('should open in browser if hostname configured', async () => {
Expand All @@ -102,7 +104,7 @@ describe('routes/LoginWithOAuthApp.tsx', () => {

fireEvent.click(screen.getByText('Create new OAuth App'));

expect(openExternalMock).toHaveBeenCalledTimes(1);
expect(openExternalLinkMock).toHaveBeenCalledTimes(1);
});
});

Expand Down Expand Up @@ -143,6 +145,6 @@ describe('routes/LoginWithOAuthApp.tsx', () => {

fireEvent.click(screen.getByLabelText('GitHub Docs'));

expect(openExternalMock).toHaveBeenCalledTimes(1);
expect(openExternalLinkMock).toHaveBeenCalledTimes(1);
});
});
13 changes: 7 additions & 6 deletions src/routes/LoginWithPersonalAccessToken.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import {
screen,
waitFor,
} from '@testing-library/react';
import { shell } from 'electron';
import { MemoryRouter } from 'react-router-dom';
import { AppContext } from '../context/App';
import * as comms from '../utils/comms';
import {
LoginWithPersonalAccessToken,
validate,
Expand All @@ -20,9 +20,10 @@ jest.mock('react-router-dom', () => ({
}));

describe('routes/LoginWithPersonalAccessToken.tsx', () => {
const openExternalMock = jest.spyOn(shell, 'openExternal');

const mockValidateToken = jest.fn();
const openExternalLinkMock = jest
.spyOn(comms, 'openExternalLink')
.mockImplementation();

afterEach(() => {
jest.clearAllMocks();
Expand Down Expand Up @@ -88,7 +89,7 @@ describe('routes/LoginWithPersonalAccessToken.tsx', () => {

fireEvent.click(screen.getByText('Generate a PAT'));

expect(openExternalMock).toHaveBeenCalledTimes(0);
expect(openExternalLinkMock).toHaveBeenCalledTimes(0);
});

it('should open in browser if hostname configured', async () => {
Expand All @@ -104,7 +105,7 @@ describe('routes/LoginWithPersonalAccessToken.tsx', () => {

fireEvent.click(screen.getByText('Generate a PAT'));

expect(openExternalMock).toHaveBeenCalledTimes(1);
expect(openExternalLinkMock).toHaveBeenCalledTimes(1);
});
});

Expand Down Expand Up @@ -198,6 +199,6 @@ describe('routes/LoginWithPersonalAccessToken.tsx', () => {

fireEvent.click(screen.getByLabelText('GitHub Docs'));

expect(openExternalMock).toHaveBeenCalledTimes(1);
expect(openExternalLinkMock).toHaveBeenCalledTimes(1);
});
});
Loading

0 comments on commit e9c7a64

Please sign in to comment.