From 4f6745fdb05cffc2de4159b3a9cfa97b3f96dc8c Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Fri, 10 May 2024 17:04:48 -0400 Subject: [PATCH 1/4] refactor(discussions): search syntax --- src/utils/api/client.ts | 5 +++-- src/utils/api/graphql/utils.test.ts | 17 +++++++++++++++ src/utils/api/graphql/utils.ts | 14 +++++++++++++ src/utils/api/utils.test.ts | 32 +---------------------------- src/utils/api/utils.ts | 12 ----------- src/utils/helpers.ts | 22 ++++++++------------ 6 files changed, 43 insertions(+), 59 deletions(-) create mode 100644 src/utils/api/graphql/utils.test.ts create mode 100644 src/utils/api/graphql/utils.ts diff --git a/src/utils/api/client.ts b/src/utils/api/client.ts index 3401851dc..b2970cc13 100644 --- a/src/utils/api/client.ts +++ b/src/utils/api/client.ts @@ -20,7 +20,8 @@ import { apiRequestAuth } from './request'; import { print } from 'graphql/language/printer'; import Constants from '../constants'; import { QUERY_SEARCH_DISCUSSIONS } from './graphql/discussions'; -import { formatSearchQueryString, getGitHubAPIBaseUrl } from './utils'; +import { formatAsGitHubSearchSyntax } from './graphql/utils'; +import { getGitHubAPIBaseUrl } from './utils'; /** * Get Hypermedia links to resources accessible in GitHub's REST API @@ -249,7 +250,7 @@ export async function searchDiscussions( return apiRequestAuth(Constants.GITHUB_API_GRAPHQL_URL, 'POST', token, { query: print(QUERY_SEARCH_DISCUSSIONS), variables: { - queryStatement: formatSearchQueryString( + queryStatement: formatAsGitHubSearchSyntax( notification.repository.full_name, notification.subject.title, notification.updated_at, diff --git a/src/utils/api/graphql/utils.test.ts b/src/utils/api/graphql/utils.test.ts new file mode 100644 index 000000000..aff94beab --- /dev/null +++ b/src/utils/api/graphql/utils.test.ts @@ -0,0 +1,17 @@ +import { formatAsGitHubSearchSyntax } from './utils'; + +describe('utils/api/graphql/utils.ts', () => { + describe('formatAsGitHubCodeSearchSyntax', () => { + test('formats search query string correctly', () => { + const result = formatAsGitHubSearchSyntax( + 'exampleRepo', + 'exampleTitle', + '2024-02-20T12:00:00.000Z', + ); + + expect(result).toBe( + 'exampleTitle in:title repo:exampleRepo updated:>2024-02-20T10:00:00.000Z', + ); + }); + }); +}); diff --git a/src/utils/api/graphql/utils.ts b/src/utils/api/graphql/utils.ts new file mode 100644 index 000000000..05aa4aedb --- /dev/null +++ b/src/utils/api/graphql/utils.ts @@ -0,0 +1,14 @@ +import { subHours } from 'date-fns'; + +const SEARCH_RESULTS_WINDOW_HOURS = 2; + +export function formatAsGitHubSearchSyntax( + repo: string, + title: string, + lastUpdated: string, +): string { + return `${title} in:title repo:${repo} updated:>${subHours( + lastUpdated, + SEARCH_RESULTS_WINDOW_HOURS, + ).toISOString()}`; +} diff --git a/src/utils/api/utils.test.ts b/src/utils/api/utils.test.ts index 54af2e1ea..551b3caf6 100644 --- a/src/utils/api/utils.test.ts +++ b/src/utils/api/utils.test.ts @@ -1,8 +1,4 @@ -import { - addHours, - formatSearchQueryString, - getGitHubAPIBaseUrl, -} from './utils'; +import { getGitHubAPIBaseUrl } from './utils'; describe('utils/api/utils.ts', () => { describe('generateGitHubAPIUrl', () => { @@ -16,30 +12,4 @@ describe('utils/api/utils.ts', () => { expect(result.toString()).toBe('https://github.manos.im/api/v3/'); }); }); - - describe('formatSearchQueryString', () => { - test('formats search query string correctly', () => { - const result = formatSearchQueryString( - 'exampleRepo', - 'exampleTitle', - '2024-02-20T12:00:00.000Z', - ); - - expect(result).toBe( - 'exampleTitle in:title repo:exampleRepo updated:>2024-02-20T10:00:00.000Z', - ); - }); - }); - - describe('addHours', () => { - test('adds hours correctly for positive values', () => { - const result = addHours('2024-02-20T12:00:00.000Z', 3); - expect(result).toBe('2024-02-20T15:00:00.000Z'); - }); - - test('adds hours correctly for negative values', () => { - const result = addHours('2024-02-20T12:00:00.000Z', -2); - expect(result).toBe('2024-02-20T10:00:00.000Z'); - }); - }); }); diff --git a/src/utils/api/utils.ts b/src/utils/api/utils.ts index 954704b07..3b35b300e 100644 --- a/src/utils/api/utils.ts +++ b/src/utils/api/utils.ts @@ -10,15 +10,3 @@ export function getGitHubAPIBaseUrl(hostname: string): URL { } return url; } - -export function formatSearchQueryString( - repo: string, - title: string, - lastUpdated: string, -): string { - return `${title} in:title repo:${repo} updated:>${addHours(lastUpdated, -2)}`; -} - -export function addHours(date: string, hours: number): string { - return new Date(new Date(date).getTime() + hours * 36e5).toISOString(); -} diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index b6501bd61..966a693a9 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -99,9 +99,7 @@ async function getDiscussionUrl( if (discussion) { url.href = discussion.url; - const comments = discussion.comments.nodes; - - const latestComment = getLatestDiscussionComment(comments); + const latestComment = getLatestDiscussionComment(discussion.comments.nodes); if (latestComment) { url.hash = `#discussioncomment-${latestComment.databaseId}`; @@ -118,24 +116,20 @@ export async function fetchDiscussion( try { const response = await searchDiscussions(notification, token); - let discussions = - response.data?.data.search.nodes.filter( - (discussion) => discussion.title === notification.subject.title, - ) || []; - - if (discussions.length > 1) { - discussions = discussions.filter( - (discussion) => discussion.viewerSubscription === 'SUBSCRIBED', - ); - } + const discussions = response.data?.data.search.nodes.filter( + (discussion) => + discussion.title === notification.subject.title && + discussion.viewerSubscription === 'SUBSCRIBED', + ); - return discussions[0]; + return discussions[0] ?? null; } catch (err) {} } export function getLatestDiscussionComment( comments: DiscussionComment[], ): DiscussionComment | null { + console.log('ADAM - comments: ', JSON.stringify(comments)); if (!comments || comments.length === 0) { return null; } From 7dedec977c2da63407d8dbf49680f068ec0f99a7 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Fri, 10 May 2024 17:07:59 -0400 Subject: [PATCH 2/4] refactor(discussions): search syntax --- src/utils/helpers.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index 966a693a9..6c47c31ba 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -129,7 +129,6 @@ export async function fetchDiscussion( export function getLatestDiscussionComment( comments: DiscussionComment[], ): DiscussionComment | null { - console.log('ADAM - comments: ', JSON.stringify(comments)); if (!comments || comments.length === 0) { return null; } From 358c0f7c0580b1d61a396710e7748b4e3e3892f5 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Fri, 10 May 2024 17:23:09 -0400 Subject: [PATCH 3/4] refactor(discussions): search syntax --- src/utils/api/client.ts | 3 +-- src/utils/api/graphql/utils.test.ts | 10 ++-------- src/utils/api/graphql/utils.ts | 10 +--------- src/utils/helpers.ts | 4 +--- 4 files changed, 5 insertions(+), 22 deletions(-) diff --git a/src/utils/api/client.ts b/src/utils/api/client.ts index b2970cc13..20f288556 100644 --- a/src/utils/api/client.ts +++ b/src/utils/api/client.ts @@ -253,9 +253,8 @@ export async function searchDiscussions( queryStatement: formatAsGitHubSearchSyntax( notification.repository.full_name, notification.subject.title, - notification.updated_at, ), - firstDiscussions: 10, + firstDiscussions: 5, lastComments: 1, lastReplies: 1, }, diff --git a/src/utils/api/graphql/utils.test.ts b/src/utils/api/graphql/utils.test.ts index aff94beab..5d1439888 100644 --- a/src/utils/api/graphql/utils.test.ts +++ b/src/utils/api/graphql/utils.test.ts @@ -3,15 +3,9 @@ import { formatAsGitHubSearchSyntax } from './utils'; describe('utils/api/graphql/utils.ts', () => { describe('formatAsGitHubCodeSearchSyntax', () => { test('formats search query string correctly', () => { - const result = formatAsGitHubSearchSyntax( - 'exampleRepo', - 'exampleTitle', - '2024-02-20T12:00:00.000Z', - ); + const result = formatAsGitHubSearchSyntax('exampleRepo', 'exampleTitle'); - expect(result).toBe( - 'exampleTitle in:title repo:exampleRepo updated:>2024-02-20T10:00:00.000Z', - ); + expect(result).toBe('exampleTitle in:title repo:exampleRepo'); }); }); }); diff --git a/src/utils/api/graphql/utils.ts b/src/utils/api/graphql/utils.ts index 05aa4aedb..6cc36a0d7 100644 --- a/src/utils/api/graphql/utils.ts +++ b/src/utils/api/graphql/utils.ts @@ -1,14 +1,6 @@ -import { subHours } from 'date-fns'; - -const SEARCH_RESULTS_WINDOW_HOURS = 2; - export function formatAsGitHubSearchSyntax( repo: string, title: string, - lastUpdated: string, ): string { - return `${title} in:title repo:${repo} updated:>${subHours( - lastUpdated, - SEARCH_RESULTS_WINDOW_HOURS, - ).toISOString()}`; + return `${title} in:title repo:${repo}`; } diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index 6c47c31ba..fa4e5ad87 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -117,9 +117,7 @@ export async function fetchDiscussion( const response = await searchDiscussions(notification, token); const discussions = response.data?.data.search.nodes.filter( - (discussion) => - discussion.title === notification.subject.title && - discussion.viewerSubscription === 'SUBSCRIBED', + (discussion) => discussion.title === notification.subject.title, ); return discussions[0] ?? null; From c62f9ce6b2e30b4a6616475e9aae2bcec37efc3e Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Sun, 12 May 2024 07:14:02 -0400 Subject: [PATCH 4/4] refactor: remove unnecessary logic --- src/__mocks__/mockedData.ts | 15 ---------- src/hooks/useNotifications.test.ts | 1 - src/typesGitHub.ts | 3 -- src/utils/api/client.ts | 2 +- src/utils/api/graphql/discussions.ts | 1 - src/utils/helpers.ts | 6 +--- src/utils/subject.test.ts | 45 ++++------------------------ 7 files changed, 8 insertions(+), 65 deletions(-) diff --git a/src/__mocks__/mockedData.ts b/src/__mocks__/mockedData.ts index f035be230..fc70b37cf 100644 --- a/src/__mocks__/mockedData.ts +++ b/src/__mocks__/mockedData.ts @@ -426,7 +426,6 @@ export const mockedGraphQLResponse: GraphQLSearch = { search: { nodes: [ { - viewerSubscription: 'SUBSCRIBED', title: '1.16.0', isAnswered: false, stateReason: 'OPEN', @@ -439,20 +438,6 @@ export const mockedGraphQLResponse: GraphQLSearch = { }, comments: mockDiscussionComments, }, - { - viewerSubscription: 'IGNORED', - title: '1.16.0', - isAnswered: false, - stateReason: 'ANSWERED', - url: 'https://github.com/gitify-app/notifications-test/discussions/123', - author: { - login: 'discussion-creator', - url: 'https://github.com/discussion-creator', - avatar_url: 'https://avatars.githubusercontent.com/u/123456789?v=4', - type: 'User', - }, - comments: mockDiscussionComments, - }, ], }, }, diff --git a/src/hooks/useNotifications.test.ts b/src/hooks/useNotifications.test.ts index 053cf0cdf..11b96b296 100644 --- a/src/hooks/useNotifications.test.ts +++ b/src/hooks/useNotifications.test.ts @@ -319,7 +319,6 @@ describe('hooks/useNotifications.ts', () => { nodes: [ { title: 'This is a Discussion.', - viewerSubscription: 'SUBSCRIBED', stateReason: null, isAnswered: true, url: 'https://github.com/gitify-app/notifications-test/discussions/612', diff --git a/src/typesGitHub.ts b/src/typesGitHub.ts index 397dc2e92..3dcbac6a4 100644 --- a/src/typesGitHub.ts +++ b/src/typesGitHub.ts @@ -59,8 +59,6 @@ export type StateType = | IssueStateReasonType | PullRequestStateType; -export type ViewerSubscription = 'IGNORED' | 'SUBSCRIBED' | 'UNSUBSCRIBED'; - export type CheckSuiteStatus = | 'action_required' | 'cancelled' @@ -450,7 +448,6 @@ export interface GraphQLSearch { } export interface Discussion { - viewerSubscription: ViewerSubscription; title: string; stateReason: DiscussionStateType; isAnswered: boolean; diff --git a/src/utils/api/client.ts b/src/utils/api/client.ts index 20f288556..432e98d77 100644 --- a/src/utils/api/client.ts +++ b/src/utils/api/client.ts @@ -254,7 +254,7 @@ export async function searchDiscussions( notification.repository.full_name, notification.subject.title, ), - firstDiscussions: 5, + firstDiscussions: 1, lastComments: 1, lastReplies: 1, }, diff --git a/src/utils/api/graphql/discussions.ts b/src/utils/api/graphql/discussions.ts index 3679367dd..fe6d2aa1c 100644 --- a/src/utils/api/graphql/discussions.ts +++ b/src/utils/api/graphql/discussions.ts @@ -31,7 +31,6 @@ export const QUERY_SEARCH_DISCUSSIONS = gql` search(query:$queryStatement, type: DISCUSSION, first: $firstDiscussions) { nodes { ... on Discussion { - viewerSubscription title stateReason isAnswered diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index fa4e5ad87..ac4cc52c5 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -116,11 +116,7 @@ export async function fetchDiscussion( try { const response = await searchDiscussions(notification, token); - const discussions = response.data?.data.search.nodes.filter( - (discussion) => discussion.title === notification.subject.title, - ); - - return discussions[0] ?? null; + return response.data?.data.search.nodes[0] ?? null; } catch (err) {} } diff --git a/src/utils/subject.test.ts b/src/utils/subject.test.ts index 560252ba3..de6e5e4b0 100644 --- a/src/utils/subject.test.ts +++ b/src/utils/subject.test.ts @@ -12,7 +12,6 @@ import type { DiscussionStateType, Notification, Repository, - ViewerSubscription, } from '../typesGitHub'; import { getCheckSuiteAttributes, @@ -239,7 +238,7 @@ describe('utils/subject.ts', () => { .reply(200, { data: { search: { - nodes: [mockDiscussionNode('SUBSCRIBED', null, true)], + nodes: [mockDiscussionNode(null, true)], }, }, }); @@ -266,7 +265,7 @@ describe('utils/subject.ts', () => { .reply(200, { data: { search: { - nodes: [mockDiscussionNode('SUBSCRIBED', 'DUPLICATE', false)], + nodes: [mockDiscussionNode('DUPLICATE', false)], }, }, }); @@ -293,7 +292,7 @@ describe('utils/subject.ts', () => { .reply(200, { data: { search: { - nodes: [mockDiscussionNode('SUBSCRIBED', null, false)], + nodes: [mockDiscussionNode(null, false)], }, }, }); @@ -320,7 +319,7 @@ describe('utils/subject.ts', () => { .reply(200, { data: { search: { - nodes: [mockDiscussionNode('SUBSCRIBED', 'OUTDATED', false)], + nodes: [mockDiscussionNode('OUTDATED', false)], }, }, }); @@ -347,7 +346,7 @@ describe('utils/subject.ts', () => { .reply(200, { data: { search: { - nodes: [mockDiscussionNode('SUBSCRIBED', 'REOPENED', false)], + nodes: [mockDiscussionNode('REOPENED', false)], }, }, }); @@ -374,7 +373,7 @@ describe('utils/subject.ts', () => { .reply(200, { data: { search: { - nodes: [mockDiscussionNode('SUBSCRIBED', 'RESOLVED', true)], + nodes: [mockDiscussionNode('RESOLVED', true)], }, }, }); @@ -394,36 +393,6 @@ describe('utils/subject.ts', () => { }, }); }); - - it('filtered response by subscribed', async () => { - nock('https://api.github.com') - .post('/graphql') - .reply(200, { - data: { - search: { - nodes: [ - mockDiscussionNode('SUBSCRIBED', null, false), - mockDiscussionNode('IGNORED', null, true), - ], - }, - }, - }); - - const result = await getGitifySubjectDetails( - mockNotification, - mockAccounts.token, - ); - - expect(result).toEqual({ - state: 'OPEN', - user: { - login: mockDiscussionAuthor.login, - html_url: mockDiscussionAuthor.url, - avatar_url: mockDiscussionAuthor.avatar_url, - type: mockDiscussionAuthor.type, - }, - }); - }); }); describe('Issues', () => { @@ -1176,14 +1145,12 @@ describe('utils/subject.ts', () => { }); function mockDiscussionNode( - subscription: ViewerSubscription, state: DiscussionStateType, isAnswered: boolean, ): Discussion { return { title: 'This is a mocked discussion', url: 'https://github.com/gitify-app/notifications-test/discussions/1', - viewerSubscription: subscription, stateReason: state, isAnswered: isAnswered, author: mockDiscussionAuthor,