Skip to content

Commit

Permalink
feat: support discussion state types (#827)
Browse files Browse the repository at this point in the history
* feat: support discussion states

* refactor graphql search interface to be generic.

* refactor mocks out
  • Loading branch information
setchy authored Feb 29, 2024
1 parent df1a204 commit 73d0077
Show file tree
Hide file tree
Showing 8 changed files with 635 additions and 230 deletions.
429 changes: 258 additions & 171 deletions src/__mocks__/mockedData.ts

Large diffs are not rendered by default.

217 changes: 206 additions & 11 deletions src/hooks/useNotifications.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import axios from 'axios';
import nock from 'nock';

import { mockAccounts, mockSettings } from '../__mocks__/mock-state';
import { mockedUser } from '../__mocks__/mockedData';
import {
mockedDiscussionNotifications,
mockedUser,
} from '../__mocks__/mockedData';
import { AuthState } from '../types';
import { useNotifications } from './useNotifications';

Expand Down Expand Up @@ -191,28 +194,43 @@ describe('hooks/useNotifications.ts', () => {
const notifications = [
{
id: 1,
title: 'This is a notification.',
subject: { type: 'Issue', url: 'https://api.github.com/1' },
subject: {
title: 'This is a notification.',
type: 'Issue',
url: 'https://api.github.com/1',
},
},
{
id: 2,
title: 'A merged PR.',
subject: { type: 'PullRequest', url: 'https://api.github.com/2' },
subject: {
title: 'A merged PR.',
type: 'PullRequest',
url: 'https://api.github.com/2',
},
},
{
id: 3,
title: 'A closed PR.',
subject: { type: 'PullRequest', url: 'https://api.github.com/3' },
subject: {
title: 'A closed PR.',
type: 'PullRequest',
url: 'https://api.github.com/3',
},
},
{
id: 4,
title: 'A draft PR.',
subject: { type: 'PullRequest', url: 'https://api.github.com/4' },
subject: {
title: 'A draft PR.',
type: 'PullRequest',
url: 'https://api.github.com/4',
},
},
{
id: 5,
title: 'A draft PR.',
subject: { type: 'PullRequest', url: 'https://api.github.com/5' },
subject: {
title: 'A draft PR.',
type: 'PullRequest',
url: 'https://api.github.com/5',
},
},
];

Expand Down Expand Up @@ -266,6 +284,183 @@ describe('hooks/useNotifications.ts', () => {
result.current.notifications[0].notifications[4].subject.state,
).toBe('draft');
});

it('should fetch discussion notifications with success - with colors', async () => {
const accounts: AuthState = {
...mockAccounts,
enterpriseAccounts: [],
user: mockedUser,
};

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

nock('https://api.github.com')
.post('/graphql')
.reply(200, {
data: {
search: {
edges: [
{
node: {
title: 'This is an answered discussion',
viewerSubscription: 'SUBSCRIBED',
stateReason: null,
isAnswered: true,
},
},
],
},
},
})
.post('/graphql')
.reply(200, {
data: {
search: {
edges: [
{
node: {
title: 'This is a duplicate discussion',
viewerSubscription: 'SUBSCRIBED',
stateReason: 'DUPLICATE',
isAnswered: false,
},
},
],
},
},
})
.post('/graphql')
.reply(200, {
data: {
search: {
edges: [
{
node: {
title: 'This is an open discussion',
viewerSubscription: 'SUBSCRIBED',
stateReason: null,
isAnswered: false,
},
},
{
node: {
title: 'This is an open discussion',
viewerSubscription: 'IGNORED',
stateReason: null,
isAnswered: false,
},
},
],
},
},
})
.post('/graphql')
.reply(200, {
data: {
search: {
edges: [
{
node: {
title: 'This is nm outdated discussion',
viewerSubscription: 'SUBSCRIBED',
stateReason: 'OUTDATED',
isAnswered: false,
},
},
],
},
},
})
.post('/graphql')
.reply(200, {
data: {
search: {
edges: [
{
node: {
title: 'This is a reopened discussion',
viewerSubscription: 'SUBSCRIBED',
stateReason: 'REOPENED',
isAnswered: false,
},
},
],
},
},
})
.post('/graphql')
.reply(200, {
data: {
search: {
edges: [
{
node: {
title: 'This is a resolved discussion',
viewerSubscription: 'SUBSCRIBED',
stateReason: 'RESOLVED',
isAnswered: false,
},
},
],
},
},
})
.post('/graphql')
.reply(200, {
data: {
search: {
edges: [
{
node: {
title: 'unknown search result',
viewerSubscription: 'SUBSCRIBED',
stateReason: null,
isAnswered: false,
},
},
],
},
},
});

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

act(() => {
result.current.fetchNotifications(accounts, {
...mockSettings,
colors: true,
});
});

expect(result.current.isFetching).toBe(true);

await waitFor(() => {
expect(result.current.notifications[0].hostname).toBe('github.com');
});

const resultNotifications = result.current.notifications[0];

expect(resultNotifications.notifications.length).toBe(7);
expect(resultNotifications.notifications[0].subject.state).toBe(
'ANSWERED',
);
expect(resultNotifications.notifications[1].subject.state).toBe(
'DUPLICATE',
);
expect(resultNotifications.notifications[2].subject.state).toBe('OPEN');
expect(resultNotifications.notifications[3].subject.state).toBe(
'OUTDATED',
);
expect(resultNotifications.notifications[4].subject.state).toBe(
'REOPENED',
);
expect(resultNotifications.notifications[5].subject.state).toBe(
'RESOLVED',
);
expect(resultNotifications.notifications[6].subject.state).toBe('OPEN');
});
});
});

Expand Down
70 changes: 42 additions & 28 deletions src/hooks/useNotifications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
getEnterpriseAccountToken,
generateGitHubAPIUrl,
isEnterpriseHost,
getDiscussionState,
} from '../utils/helpers';
import { removeNotification } from '../utils/remove-notification';
import {
Expand Down Expand Up @@ -130,12 +131,6 @@ export const useNotifications = (colors: boolean): NotificationsState => {
notifications: await axios.all<Notification>(
accountNotifications.notifications.map(
async (notification: Notification) => {
if (
notification.subject.type !== 'PullRequest' &&
notification.subject.type !== 'Issue'
) {
return notification;
}
const isEnterprise = isEnterpriseHost(
accountNotifications.hostname,
);
Expand All @@ -146,28 +141,47 @@ export const useNotifications = (colors: boolean): NotificationsState => {
)
: accounts.token;

const cardinalData = (
await apiRequestAuth(
notification.subject.url,
'GET',
token,
)
).data;

const state =
cardinalData.state === 'closed'
? cardinalData.state_reason ||
(cardinalData.merged && 'merged') ||
'closed'
: (cardinalData.draft && 'draft') || 'open';

return {
...notification,
subject: {
...notification.subject,
state,
},
};
switch (notification.subject.type) {
case 'Discussion':
const discussionState = await getDiscussionState(
notification,
token,
);

return {
...notification,
subject: {
...notification.subject,
state: discussionState,
},
};
case 'Issue':
case 'PullRequest':
const cardinalData = (
await apiRequestAuth(
notification.subject.url,
'GET',
token,
)
).data;

const state =
cardinalData.state === 'closed'
? cardinalData.state_reason ||
(cardinalData.merged && 'merged') ||
'closed'
: (cardinalData.draft && 'draft') || 'open';

return {
...notification,
subject: {
...notification.subject,
state,
},
};
default:
return notification;
}
},
),
),
Expand Down
Loading

0 comments on commit 73d0077

Please sign in to comment.