Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/components/fields/Checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ interface IFieldCheckbox {
checked: boolean;
onChange: any;
placeholder?: string;
disabled?: boolean;
}

export const FieldCheckbox = (props: IFieldCheckbox) => {
Expand All @@ -18,13 +19,15 @@ export const FieldCheckbox = (props: IFieldCheckbox) => {
className="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
checked={props.checked}
onChange={props.onChange}
disabled={props.disabled}
/>
</div>

<div className="ml-3 text-sm">
<label
htmlFor={props.name}
className="font-medium text-gray-700 dark:text-gray-200"
style={{ textDecoration: props.disabled && 'line-through' }}
>
{props.label}
</label>
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 @@ -264,7 +264,7 @@ describe('context/App.tsx', () => {
participating: true,
playSound: true,
showNotifications: true,
colors: true,
colors: false,
},
);
});
Expand Down Expand Up @@ -302,7 +302,7 @@ describe('context/App.tsx', () => {
participating: false,
playSound: true,
showNotifications: true,
colors: true,
colors: false,
},
);
});
Expand Down
2 changes: 1 addition & 1 deletion src/context/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const defaultSettings: SettingsState = {
markOnClick: false,
openAtStartup: false,
appearance: Appearance.SYSTEM,
colors: true,
colors: false,
};

interface AppContextState {
Expand Down
108 changes: 96 additions & 12 deletions src/routes/Settings.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const { ipcRenderer } = require('electron');

import { SettingsRoute } from './Settings';
import { AppContext } from '../context/App';
import { mockSettings } from '../__mocks__/mock-state';
import { mockAccounts, mockSettings } from '../__mocks__/mock-state';

const mockNavigate = jest.fn();
jest.mock('react-router-dom', () => ({
Expand All @@ -31,7 +31,9 @@ describe('routes/Settings.tsx', () => {

await act(async () => {
tree = TestRenderer.create(
<AppContext.Provider value={{ settings: mockSettings }}>
<AppContext.Provider
value={{ settings: mockSettings, accounts: mockAccounts }}
>
<MemoryRouter>
<SettingsRoute />
</MemoryRouter>
Expand All @@ -48,7 +50,11 @@ describe('routes/Settings.tsx', () => {
await act(async () => {
const { getByLabelText: getByLabelTextLocal } = render(
<AppContext.Provider
value={{ settings: mockSettings, logout: logoutMock }}
value={{
settings: mockSettings,
accounts: mockAccounts,
logout: logoutMock,
}}
>
<Router location={history.location} navigator={history}>
<SettingsRoute />
Expand All @@ -73,7 +79,9 @@ describe('routes/Settings.tsx', () => {

await act(async () => {
const { getByLabelText: getByLabelTextLocal } = render(
<AppContext.Provider value={{ settings: mockSettings }}>
<AppContext.Provider
value={{ settings: mockSettings, accounts: mockAccounts }}
>
<Router location={history.location} navigator={history}>
<SettingsRoute />
</Router>
Expand All @@ -91,7 +99,13 @@ describe('routes/Settings.tsx', () => {

await act(async () => {
const { getByLabelText: getByLabelTextLocal } = render(
<AppContext.Provider value={{ settings: mockSettings, updateSetting }}>
<AppContext.Provider
value={{
settings: mockSettings,
accounts: mockAccounts,
updateSetting,
}}
>
<MemoryRouter>
<SettingsRoute />
</MemoryRouter>
Expand All @@ -113,7 +127,13 @@ describe('routes/Settings.tsx', () => {

await act(async () => {
const { getByLabelText: getByLabelTextLocal } = render(
<AppContext.Provider value={{ settings: mockSettings, updateSetting }}>
<AppContext.Provider
value={{
settings: mockSettings,
accounts: mockAccounts,
updateSetting,
}}
>
<MemoryRouter>
<SettingsRoute />
</MemoryRouter>
Expand All @@ -135,7 +155,13 @@ describe('routes/Settings.tsx', () => {

await act(async () => {
const { getByLabelText: getByLabelTextLocal } = render(
<AppContext.Provider value={{ settings: mockSettings, updateSetting }}>
<AppContext.Provider
value={{
settings: mockSettings,
accounts: mockAccounts,
updateSetting,
}}
>
<MemoryRouter>
<SettingsRoute />
</MemoryRouter>
Expand All @@ -157,7 +183,13 @@ describe('routes/Settings.tsx', () => {

await act(async () => {
const { getByLabelText: getByLabelTextLocal } = render(
<AppContext.Provider value={{ settings: mockSettings, updateSetting }}>
<AppContext.Provider
value={{
settings: mockSettings,
accounts: mockAccounts,
updateSetting,
}}
>
<MemoryRouter>
<SettingsRoute />
</MemoryRouter>
Expand All @@ -179,7 +211,13 @@ describe('routes/Settings.tsx', () => {

await act(async () => {
const { getByLabelText: getByLabelTextLocal } = render(
<AppContext.Provider value={{ settings: mockSettings, updateSetting }}>
<AppContext.Provider
value={{
settings: mockSettings,
accounts: mockAccounts,
updateSetting,
}}
>
<MemoryRouter>
<SettingsRoute />
</MemoryRouter>
Expand All @@ -201,7 +239,13 @@ describe('routes/Settings.tsx', () => {

await act(async () => {
const { getByLabelText: getByLabelTextLocal } = render(
<AppContext.Provider value={{ settings: mockSettings, updateSetting }}>
<AppContext.Provider
value={{
settings: mockSettings,
accounts: mockAccounts,
updateSetting,
}}
>
<MemoryRouter>
<SettingsRoute />
</MemoryRouter>
Expand All @@ -221,7 +265,9 @@ describe('routes/Settings.tsx', () => {

await act(async () => {
const { getByLabelText: getByLabelTextLocal } = render(
<AppContext.Provider value={{ settings: mockSettings }}>
<AppContext.Provider
value={{ settings: mockSettings, accounts: mockAccounts }}
>
<Router location={history.location} navigator={history}>
<SettingsRoute />
</Router>
Expand All @@ -241,7 +287,9 @@ describe('routes/Settings.tsx', () => {

await act(async () => {
const { getByLabelText: getByLabelTextLocal } = render(
<AppContext.Provider value={{ settings: mockSettings }}>
<AppContext.Provider
value={{ settings: mockSettings, accounts: mockAccounts }}
>
<MemoryRouter>
<SettingsRoute />
</MemoryRouter>
Expand All @@ -253,4 +301,40 @@ describe('routes/Settings.tsx', () => {
fireEvent.click(getByLabelText('Quit Gitify'));
expect(ipcRenderer.send).toHaveBeenCalledWith('app-quit');
});

it('should not be able to disable colors', async () => {
let queryByLabelText;
jest.mock('../utils/helpers', () => ({
...jest.requireActual('../utils/helpers'),
apiRequestAuth: jest.fn().mockResolvedValue({
headers: {
'x-oauth-scopes': 'repo, notifications',
},
}),
}));

await act(async () => {
const { queryByLabelText: queryByLabelLocal } = render(
<AppContext.Provider
value={{
settings: mockSettings,
accounts: mockAccounts,
}}
>
<MemoryRouter>
<SettingsRoute />
</MemoryRouter>
</AppContext.Provider>,
);
queryByLabelText = queryByLabelLocal;
});

console.log(
queryByLabelText('Use GitHub-like state colors (requires re-auth)'),
);

expect(
queryByLabelText('Use GitHub-like state colors (requires re-auth)'),
).toBeDefined();
});
});
34 changes: 31 additions & 3 deletions src/routes/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@ import { IconLogOut } from '../icons/Logout';
import { IconQuit } from '../icons/Quit';
import { updateTrayIcon } from '../utils/comms';
import { setAppearance } from '../utils/appearance';
import { apiRequestAuth } from '../utils/api-requests';
import { generateGitHubAPIUrl } from '../utils/helpers';
import Constants from '../utils/constants';

export const SettingsRoute: React.FC = () => {
const { settings, updateSetting, logout } = useContext(AppContext);
const { accounts, settings, updateSetting, logout } = useContext(AppContext);
const navigate = useNavigate();

const [isLinux, setIsLinux] = useState<boolean>(false);
const [appVersion, setAppVersion] = useState<string | null>(null);
const [colorScope, setColorScope] = useState<boolean>(false);

useEffect(() => {
ipcRenderer.invoke('get-platform').then((result: string) => {
Expand All @@ -28,6 +32,27 @@ export const SettingsRoute: React.FC = () => {
ipcRenderer.invoke('get-app-version').then((result: string) => {
setAppVersion(result);
});

(async () => {
const response = await apiRequestAuth(
`${generateGitHubAPIUrl(Constants.DEFAULT_AUTH_OPTIONS.hostname)}`,
'GET',
accounts.token,
);

console.log(JSON.stringify(response.headers));
const missingScopes = Constants.AUTH_SCOPE.filter((scope) => {
return !response.headers['x-oauth-scopes'].includes(scope);
});
if (missingScopes.length > 0) {
new Notification('Gitify - Permissions', {
body:
'You need to grant all the permissions to use this app. Missing scopes: ' +
missingScopes.join(', ') +
'.',
});
} else setColorScope(true);
})();
}, []);

ipcRenderer.on('update-native-theme', (_, updatedAppearance: Appearance) => {
Expand Down Expand Up @@ -84,9 +109,12 @@ export const SettingsRoute: React.FC = () => {

<FieldCheckbox
name="colors"
label="Use colors to indicate state"
checked={settings.colors}
label={`Use GitHub-like state colors${
!colorScope ? ' (requires re-auth)' : ''
}`}
checked={colorScope && settings.colors}
onChange={(evt) => updateSetting('colors', evt.target.checked)}
disabled={!colorScope}
/>
<FieldCheckbox
name="showOnlyParticipating"
Expand Down
33 changes: 32 additions & 1 deletion src/routes/__snapshots__/Settings.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ exports[`routes/Settings.tsx should render itself & its children 1`] = `
<input
checked={false}
className="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
disabled={true}
id="colors"
onChange={[Function]}
type="checkbox"
Expand All @@ -139,8 +140,13 @@ exports[`routes/Settings.tsx should render itself & its children 1`] = `
<label
className="font-medium text-gray-700 dark:text-gray-200"
htmlFor="colors"
style={
{
"textDecoration": "line-through",
}
}
>
Use colors to indicate state
Use GitHub-like state colors (requires re-auth)
</label>
</div>
</div>
Expand All @@ -164,6 +170,11 @@ exports[`routes/Settings.tsx should render itself & its children 1`] = `
<label
className="font-medium text-gray-700 dark:text-gray-200"
htmlFor="showOnlyParticipating"
style={
{
"textDecoration": undefined,
}
}
>
Show only participating
</label>
Expand All @@ -189,6 +200,11 @@ exports[`routes/Settings.tsx should render itself & its children 1`] = `
<label
className="font-medium text-gray-700 dark:text-gray-200"
htmlFor="playSound"
style={
{
"textDecoration": undefined,
}
}
>
Play sound
</label>
Expand All @@ -214,6 +230,11 @@ exports[`routes/Settings.tsx should render itself & its children 1`] = `
<label
className="font-medium text-gray-700 dark:text-gray-200"
htmlFor="showNotifications"
style={
{
"textDecoration": undefined,
}
}
>
Show notifications
</label>
Expand All @@ -239,6 +260,11 @@ exports[`routes/Settings.tsx should render itself & its children 1`] = `
<label
className="font-medium text-gray-700 dark:text-gray-200"
htmlFor="onClickMarkAsRead"
style={
{
"textDecoration": undefined,
}
}
>
Mark as read on click
</label>
Expand All @@ -264,6 +290,11 @@ exports[`routes/Settings.tsx should render itself & its children 1`] = `
<label
className="font-medium text-gray-700 dark:text-gray-200"
htmlFor="openAtStartUp"
style={
{
"textDecoration": undefined,
}
}
>
Open at startup
</label>
Expand Down