Skip to content

Commit 3cd4238

Browse files
authored
Raise test coverage to 100% (#403)
* ignore development code block * test untested cases * test notification and login states * test clicking back * test restoreSetting method * add settings test for single account * correct typo mockedNotificationsRecuderData * test no new notifications * test for no new notifications * test for empty response list * remove dead debug code * return proper CI_ACTIVITY * snapshot updated * unnecessary mock of redux-logger
1 parent d4dea9b commit 3cd4238

File tree

14 files changed

+136
-59
lines changed

14 files changed

+136
-59
lines changed

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@
147147
"nock": "^12.0.3",
148148
"prettier": "=2.0.2",
149149
"react-test-renderer": "=16.13.1",
150-
"redux-logger": "=3.0.6",
151150
"redux-mock-store": "=1.5.4",
152151
"ts-jest": "^25.3.1",
153152
"webpack": "^4.42.1",

src/js/__mocks__/mockedData.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ export const mockedEnterpriseNotifications = [
251251
} as Notification,
252252
];
253253

254-
export const mockedNotificationsRecuderData = [
254+
export const mockedNotificationsReducerData = [
255255
{
256256
hostname: 'github.com',
257257
notifications: mockedGithubNotifications,

src/js/__mocks__/redux-logger.js

Lines changed: 0 additions & 5 deletions
This file was deleted.

src/js/components/sidebar.test.tsx

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,20 +42,39 @@ describe('components/Sidebar.tsx', () => {
4242
clock.clearAllTimers();
4343
});
4444

45-
it('should test the mapStateToProps method', () => {
45+
describe('mapStateToProps', () => {
4646
const state = {
4747
auth: {
4848
token: '12345',
4949
enterpriseAccounts: mockedEnterpriseAccounts,
5050
} as AuthState,
5151
notifications: {
52-
response: [],
52+
response: [{ hostname: 'Dolores', notifications: [{}, {}] }],
5353
},
5454
} as AppState;
5555

56-
const mappedProps = mapStateToProps(state);
57-
58-
expect(mappedProps.isEitherLoggedIn).toBeTruthy();
56+
it('should accept a provided token', () => {
57+
const mappedProps = mapStateToProps(state);
58+
expect(mappedProps.isEitherLoggedIn).toBeTruthy();
59+
expect(mappedProps.connectedAccounts).toBe(2);
60+
});
61+
62+
it('should count notification lengths', () => {
63+
const mappedProps = mapStateToProps(state);
64+
expect(mappedProps.notificationsCount).toBe(2);
65+
});
66+
67+
it('should accept a null token', () => {
68+
const mappedProps = mapStateToProps({
69+
...state,
70+
auth: {
71+
...state.auth,
72+
token: null,
73+
},
74+
});
75+
expect(mappedProps.isEitherLoggedIn).toBeTruthy();
76+
expect(mappedProps.connectedAccounts).toBe(1);
77+
});
5978
});
6079

6180
it('should render itself & its children (logged in)', () => {

src/js/middleware/notifications.test.ts

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ import * as actions from '../actions';
22
import * as comms from '../utils/comms';
33
import {
44
mockedGithubNotifications,
5-
mockedNotificationsRecuderData,
5+
mockedNotificationsReducerData,
66
} from '../__mocks__/mockedData';
77
import notificationsMiddleware from './notifications';
88
import NativeNotifications from '../utils/notifications';
99

1010
// Keep 3 notifications
1111
// Ps. To receive 4 on actions.NOTIFICATIONS.SUCCESS,
12-
const mockedNotifications = mockedNotificationsRecuderData.map(
12+
const mockedNotifications = mockedNotificationsReducerData.map(
1313
(account, accountIndex) => {
1414
if (accountIndex === 0) {
1515
return {
@@ -22,25 +22,27 @@ const mockedNotifications = mockedNotificationsRecuderData.map(
2222
}
2323
);
2424

25-
const createFakeStore = () => ({
25+
const DEFAULT_STORE = {
26+
notifications: {
27+
response: mockedNotifications,
28+
},
29+
settings: {
30+
playSound: false,
31+
showNotifications: false,
32+
},
33+
};
34+
35+
const createFakeStore = (storeData) => ({
2636
getState() {
27-
return {
28-
notifications: {
29-
response: mockedNotifications,
30-
},
31-
settings: {
32-
playSound: false,
33-
showNotifications: false,
34-
},
35-
};
37+
return storeData;
3638
},
3739
});
3840

39-
const dispatchWithStoreOf = (_, action) => {
41+
const dispatchWithStoreOf = (storeData, action) => {
4042
let dispatched = null;
41-
const dispatch = notificationsMiddleware(createFakeStore())(
42-
(actionAttempt) => (dispatched = actionAttempt)
43-
);
43+
const dispatch = notificationsMiddleware(
44+
createFakeStore({ ...DEFAULT_STORE, ...storeData })
45+
)((actionAttempt) => (dispatched = actionAttempt));
4446
dispatch(action);
4547
return dispatched;
4648
};
@@ -54,7 +56,7 @@ describe('middleware/notifications.js', () => {
5456
it('should raise notifications (native & sound, update tray icon, set badge)', () => {
5557
const action = {
5658
type: actions.NOTIFICATIONS.SUCCESS,
57-
payload: mockedNotificationsRecuderData,
59+
payload: mockedNotificationsReducerData,
5860
};
5961

6062
expect(dispatchWithStoreOf({}, action)).toEqual(action);
@@ -93,4 +95,44 @@ describe('middleware/notifications.js', () => {
9395
expect(comms.updateTrayIcon).toHaveBeenCalledTimes(1);
9496
expect(comms.updateTrayIcon).toHaveBeenCalledWith(2);
9597
});
98+
99+
it('should update tray icon with no notifications', () => {
100+
const noNewNotifications = mockedNotificationsReducerData.map((host) => ({
101+
...host,
102+
notifications: [],
103+
}));
104+
const action = {
105+
type: actions.NOTIFICATIONS.SUCCESS,
106+
payload: noNewNotifications,
107+
};
108+
dispatchWithStoreOf(
109+
{
110+
...DEFAULT_STORE,
111+
notifications: {
112+
response: noNewNotifications,
113+
},
114+
},
115+
action
116+
);
117+
expect(comms.updateTrayIcon).toHaveBeenCalledTimes(1);
118+
expect(comms.updateTrayIcon).toHaveBeenCalledWith(0);
119+
});
120+
121+
it('should show 0 notifications if no accounts logged in', () => {
122+
const action = {
123+
type: actions.NOTIFICATIONS.SUCCESS,
124+
payload: mockedNotificationsReducerData,
125+
};
126+
dispatchWithStoreOf(
127+
{
128+
...DEFAULT_STORE,
129+
notifications: {
130+
response: [],
131+
},
132+
},
133+
action
134+
);
135+
expect(comms.updateTrayIcon).toHaveBeenCalledTimes(1);
136+
expect(comms.updateTrayIcon).toHaveBeenCalledWith(4);
137+
});
96138
});

src/js/routes/enterprise-login.test.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ describe('routes/enterprise-login.js', () => {
2929
new BrowserWindow().loadURL.mockReset();
3030
spyOn(ipcRenderer, 'send');
3131
props.dispatch.mockReset();
32+
props.history.goBack = jest.fn();
3233
});
3334

3435
it('should test the mapStateToProps method', () => {
@@ -57,6 +58,19 @@ describe('routes/enterprise-login.js', () => {
5758
expect(tree).toMatchSnapshot();
5859
});
5960

61+
it('let us go back', () => {
62+
props.history.goBack = jest.fn();
63+
const { getByLabelText } = render(
64+
<Provider store={createStore(() => {})}>
65+
<MemoryRouter>
66+
<EnterpriseLogin {...props} />
67+
</MemoryRouter>
68+
</Provider>
69+
);
70+
fireEvent.click(getByLabelText('Go Back'));
71+
expect(props.history.goBack).toHaveBeenCalledTimes(1);
72+
});
73+
6074
it('should validate the form values', () => {
6175
let values;
6276
const emptyValues = {

src/js/routes/notifications.test.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as React from 'react';
22
import * as TestRenderer from 'react-test-renderer';
33

44
import { AppState, NotificationsState } from '../../types/reducers';
5-
import { mockedNotificationsRecuderData } from '../__mocks__/mockedData';
5+
import { mockedNotificationsReducerData } from '../__mocks__/mockedData';
66
import { NotificationsRoute, mapStateToProps } from './notifications';
77

88
jest.mock('../components/account-notifications', () => ({
@@ -20,7 +20,7 @@ jest.mock('../components/oops', () => ({
2020
describe('routes/notifications.ts', () => {
2121
const props = {
2222
failed: false,
23-
accountNotifications: mockedNotificationsRecuderData,
23+
accountNotifications: mockedNotificationsReducerData,
2424
notificationsCount: 4,
2525
hasMultipleAccounts: true,
2626
hasNotifications: true,
@@ -29,7 +29,7 @@ describe('routes/notifications.ts', () => {
2929
it('should test the mapStateToProps method', () => {
3030
const state = {
3131
notifications: {
32-
response: mockedNotificationsRecuderData,
32+
response: mockedNotificationsReducerData,
3333
failed: false,
3434
} as NotificationsState,
3535
} as AppState;
@@ -38,7 +38,7 @@ describe('routes/notifications.ts', () => {
3838

3939
expect(mappedProps.failed).toBeFalsy();
4040
expect(mappedProps.accountNotifications).toEqual(
41-
mockedNotificationsRecuderData
41+
mockedNotificationsReducerData
4242
);
4343
expect(mappedProps.hasNotifications).toBeTruthy();
4444
expect(mappedProps.notificationsCount).toBe(4);

src/js/routes/settings.test.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ describe('routes/settings.tsx', () => {
4242
props.history.replace.mockReset();
4343
});
4444

45-
it('should test the mapStateToProps method', () => {
45+
describe('mapStateToProps', () => {
4646
const state = {
4747
auth: {
4848
token: '123-456',
@@ -52,11 +52,24 @@ describe('routes/settings.tsx', () => {
5252
participating: false,
5353
} as SettingsState,
5454
} as AppState;
55+
it('should test the method', () => {
56+
const mappedProps = mapStateToProps(state);
5557

56-
const mappedProps = mapStateToProps(state);
58+
expect(mappedProps.hasMultipleAccounts).toBeTruthy();
59+
expect(mappedProps.settings.participating).toBeFalsy();
60+
});
61+
62+
it('should recognize when only one account logged in', () => {
63+
const mappedProps = mapStateToProps({
64+
...state,
65+
auth: {
66+
...state.auth,
67+
token: null,
68+
},
69+
});
5770

58-
expect(mappedProps.hasMultipleAccounts).toBeTruthy();
59-
expect(mappedProps.settings.participating).toBeFalsy();
71+
expect(mappedProps.hasMultipleAccounts).toBeFalsy();
72+
});
6073
});
6174

6275
it('should render itself & its children', () => {

src/js/store/configureStore.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ import notificationsMiddlware from '../middleware/notifications';
1212
import rootReducer from '../reducers';
1313
import settingsMiddleware from '../middleware/settings';
1414

15-
const isDev = false;
16-
1715
export default function configureStore() {
1816
const engine = filter(createEngine(constants.STORAGE_KEY), [
1917
'settings',
@@ -34,13 +32,6 @@ export default function configureStore() {
3432
storageMiddleware,
3533
];
3634

37-
if (isDev) {
38-
const { createLogger } = require('redux-logger');
39-
const logger = createLogger({ collapsed: true });
40-
middlewares.push(logger);
41-
console.log('adss');
42-
}
43-
4435
let store = createStore(
4536
rootReducer,
4637
undefined,

src/js/utils/__snapshots__/github-api.test.ts.snap

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ Object {
7878
`;
7979

8080
exports[`./utils/github-api.ts should format the notification reason 12`] = `
81+
Object {
82+
"description": "A GitHub Actions workflow run was triggered for your repository",
83+
"type": "Workflow Run",
84+
}
85+
`;
86+
87+
exports[`./utils/github-api.ts should format the notification reason 13`] = `
8188
Object {
8289
"description": "The reason for this notification is not supported by the app.",
8390
"type": "Unknown",

0 commit comments

Comments
 (0)