diff --git a/.gitignore b/.gitignore index d3525a4ac..78cd442e0 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,4 @@ temp/ dist/ build/ +.vscode/settings.json diff --git a/package.json b/package.json index 2d2866130..da4b15e1b 100644 --- a/package.json +++ b/package.json @@ -125,7 +125,7 @@ "react-transition-group": "^4.4.1", "tailwindcss": "^2.0.2", "ts-loader": "^9.4.2", - "typescript": "^4.1.3" + "typescript": "^4.6.2" }, "devDependencies": { "@testing-library/react": "^11.2.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 749834904..ddbfa5106 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -49,7 +49,7 @@ dependencies: version: 5.0.1(react-dom@16.14.0)(react@16.14.0) react-final-form: specifier: ^6.4.0 - version: 6.4.0(final-form@4.20.1)(react@16.14.0)(typescript@4.1.3) + version: 6.4.0(final-form@4.20.1)(react@16.14.0)(typescript@4.6.2) react-router: specifier: ^5.3.4 version: 5.3.4(react@16.14.0) @@ -64,10 +64,10 @@ dependencies: version: 2.0.2(autoprefixer@10.1.0)(postcss@8.4.23) ts-loader: specifier: ^9.4.2 - version: 9.4.2(typescript@4.1.3)(webpack@5.83.1) + version: 9.4.2(typescript@4.6.2)(webpack@5.83.1) typescript: - specifier: ^4.1.3 - version: 4.1.3 + specifier: ^4.6.2 + version: 4.6.2 devDependencies: '@testing-library/react': @@ -129,7 +129,7 @@ devDependencies: version: 3.3.3(webpack@5.83.1) ts-jest: specifier: ^26.4.4 - version: 26.4.4(jest@26.6.3)(typescript@4.1.3) + version: 26.4.4(jest@26.6.3)(typescript@4.6.2) webpack: specifier: ^5.83.1 version: 5.83.1(webpack-cli@5.1.1) @@ -4969,7 +4969,7 @@ packages: react-dom: 16.14.0(react@16.14.0) dev: false - /react-final-form@6.4.0(final-form@4.20.1)(react@16.14.0)(typescript@4.1.3): + /react-final-form@6.4.0(final-form@4.20.1)(react@16.14.0)(typescript@4.6.2): resolution: {integrity: sha512-M7J7f0pnoj0o8sBq3iG6jsWJEh08pNUyl2D4wBC9SJvCNkGdol2UdyjMiEFYD3rz9LIFzQqFSG0kbRBCadqzhA==} peerDependencies: final-form: ^4.19.0 @@ -4978,7 +4978,7 @@ packages: '@babel/runtime': 7.21.5 final-form: 4.20.1 react: 16.14.0 - ts-essentials: 6.0.7(typescript@4.1.3) + ts-essentials: 6.0.7(typescript@4.6.2) transitivePeerDependencies: - typescript dev: false @@ -5879,15 +5879,15 @@ packages: utf8-byte-length: 1.0.4 dev: true - /ts-essentials@6.0.7(typescript@4.1.3): + /ts-essentials@6.0.7(typescript@4.6.2): resolution: {integrity: sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw==} peerDependencies: typescript: '>=3.7.0' dependencies: - typescript: 4.1.3 + typescript: 4.6.2 dev: false - /ts-jest@26.4.4(jest@26.6.3)(typescript@4.1.3): + /ts-jest@26.4.4(jest@26.6.3)(typescript@4.6.2): resolution: {integrity: sha512-3lFWKbLxJm34QxyVNNCgXX1u4o/RV0myvA2y2Bxm46iGIjKlaY0own9gIckbjZJPn+WaJEnfPPJ20HHGpoq4yg==} engines: {node: '>= 10'} hasBin: true @@ -5906,11 +5906,11 @@ packages: make-error: 1.3.6 mkdirp: 1.0.4 semver: 7.5.1 - typescript: 4.1.3 + typescript: 4.6.2 yargs-parser: 20.2.9 dev: true - /ts-loader@9.4.2(typescript@4.1.3)(webpack@5.83.1): + /ts-loader@9.4.2(typescript@4.6.2)(webpack@5.83.1): resolution: {integrity: sha512-OmlC4WVmFv5I0PpaxYb+qGeGOdm5giHU7HwDDUjw59emP2UYMHy9fFSDcYgSNoH8sXcj4hGCSEhlDZ9ULeDraA==} engines: {node: '>=12.0.0'} peerDependencies: @@ -5921,7 +5921,7 @@ packages: enhanced-resolve: 5.14.0 micromatch: 4.0.5 semver: 7.5.1 - typescript: 4.1.3 + typescript: 4.6.2 webpack: 5.83.1(webpack-cli@5.1.1) dev: false @@ -5981,8 +5981,8 @@ packages: /typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - /typescript@4.1.3: - resolution: {integrity: sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==} + /typescript@4.6.2: + resolution: {integrity: sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==} engines: {node: '>=4.2.0'} hasBin: true diff --git a/src/__mocks__/electron.js b/src/__mocks__/electron.js index 56a5502e9..83fd9ad4c 100644 --- a/src/__mocks__/electron.js +++ b/src/__mocks__/electron.js @@ -27,19 +27,27 @@ window.localStorage = { window.alert = jest.fn(); -const browserWindow = { - loadURL: jest.fn(), - webContents: { +let instance; + +class BrowserWindow { + constructor() { + if (!instance) { + instance = this; + } + return instance; + } + loadURL = jest.fn(); + webContents = { on: () => {}, session: { clearStorageData: jest.fn(), }, - }, - on: () => {}, - close: jest.fn(), - hide: jest.fn(), - destroy: jest.fn(), -}; + }; + on() {} + close = jest.fn(); + hide = jest.fn(); + destroy = jest.fn(); +} const dialog = { showErrorBox: jest.fn(), @@ -47,7 +55,7 @@ const dialog = { module.exports = { remote: { - BrowserWindow: () => browserWindow, + BrowserWindow: BrowserWindow, dialog: dialog, process: { platform: 'darwin', @@ -57,7 +65,7 @@ module.exports = { getLoginItemSettings: jest.fn(), setLoginItemSettings: () => {}, }, - getCurrentWindow: jest.fn(() => browserWindow), + getCurrentWindow: jest.fn(() => instance || new BrowserWindow()), }, ipcRenderer: { send: jest.fn(), diff --git a/src/__mocks__/mockedData.ts b/src/__mocks__/mockedData.ts index f1afdc857..7ce0f56b2 100644 --- a/src/__mocks__/mockedData.ts +++ b/src/__mocks__/mockedData.ts @@ -1,5 +1,5 @@ import { AccountNotifications, EnterpriseAccount } from '../types'; -import { Notification, Repository, User } from '../typesGithub'; +import { Notification, Repository, User, GraphQLSearch } from '../typesGithub'; export const mockedEnterpriseAccounts: EnterpriseAccount[] = [ { @@ -275,3 +275,116 @@ export const mockedSingleAccountNotifications: AccountNotifications[] = [ notifications: [mockedSingleNotification], }, ]; + +export const mockedGraphQLResponse: GraphQLSearch = { + data: { + data: { + search: { + edges: [ + { + node: { + viewerSubscription: 'SUBSCRIBED', + title: '1.16.0', + url: 'https://github.com/manosim/notifications-test/discussions/612', + comments: { + edges: [ + { + node: { + databaseId: 2215656, + createdAt: '2022-02-20T18:33:39Z', + replies: { + edges: [], + }, + }, + }, + { + node: { + databaseId: 2217789, + createdAt: '2022-02-21T03:30:42Z', + replies: { + edges: [], + }, + }, + }, + { + node: { + databaseId: 2223243, + createdAt: '2022-02-21T18:26:27Z', + replies: { + edges: [ + { + node: { + databaseId: 2232922, + createdAt: '2022-02-23T00:57:58Z', + }, + }, + ], + }, + }, + }, + { + node: { + databaseId: 2232921, + createdAt: '2022-02-23T00:57:49Z', + replies: { + edges: [], + }, + }, + }, + { + node: { + databaseId: 2258799, + createdAt: '2022-02-27T01:22:20Z', + replies: { + edges: [ + { + node: { + databaseId: 2300902, + createdAt: '2022-03-05T17:43:52Z', + }, + }, + ], + }, + }, + }, + { + node: { + databaseId: 2297637, + createdAt: '2022-03-04T20:39:44Z', + replies: { + edges: [ + { + node: { + databaseId: 2300893, + createdAt: '2022-03-05T17:41:04Z', + }, + }, + ], + }, + }, + }, + { + node: { + databaseId: 2299763, + createdAt: '2022-03-05T11:05:42Z', + replies: { + edges: [ + { + node: { + databaseId: 2300895, + createdAt: '2022-03-05T17:41:44Z', + }, + }, + ], + }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + }, +}; diff --git a/src/components/NotificationRow.tsx b/src/components/NotificationRow.tsx index c129e5afb..3420e3ee8 100644 --- a/src/components/NotificationRow.tsx +++ b/src/components/NotificationRow.tsx @@ -1,5 +1,3 @@ -const { shell } = require('electron'); - import React, { useCallback, useContext } from 'react'; import { formatDistanceToNow, parseISO } from 'date-fns'; import { CheckIcon, MuteIcon } from '@primer/octicons-react'; @@ -10,6 +8,7 @@ import { getNotificationTypeIconColor, } from '../utils/github-api'; import { generateGitHubWebUrl } from '../utils/helpers'; +import { openInBrowser } from '../utils/helpers'; import { Notification } from '../typesGithub'; import { AppContext } from '../context/App'; @@ -22,8 +21,8 @@ export const NotificationRow: React.FC = ({ notification, hostname, }) => { - const { settings, accounts } = useContext(AppContext); - const { markNotification, unsubscribeNotification } = useContext(AppContext); + const { settings, accounts, markNotification, unsubscribeNotification } = + useContext(AppContext); const pressTitle = useCallback(() => { openBrowser(); @@ -33,17 +32,10 @@ export const NotificationRow: React.FC = ({ } }, [settings]); - const openBrowser = useCallback(() => { - // Some Notification types from GitHub are missing urls in their subjects. - if (notification.subject.url) { - const url = generateGitHubWebUrl( - notification.subject.url, - notification.id, - accounts.user?.id - ); - shell.openExternal(url); - } - }, [notification]); + const openBrowser = useCallback( + () => openInBrowser(notification, accounts), + [notification] + ); const unsubscribe = (event: React.MouseEvent) => { // Don't trigger onClick of parent element. diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index c5cf4e712..5081e077b 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -1,7 +1,7 @@ import * as Octicons from '@primer/octicons-react'; import { ipcRenderer, shell } from 'electron'; import React, { useCallback, useContext, useMemo } from 'react'; -import { useHistory } from 'react-router-dom'; +import { useHistory, useLocation } from 'react-router-dom'; import { Logo } from '../components/Logo'; import { AppContext } from '../context/App'; @@ -12,6 +12,7 @@ import { Constants } from '../utils/constants'; export const Sidebar: React.FC = () => { const history = useHistory(); + const location = useLocation(); const { isLoggedIn } = useContext(AppContext); const { notifications, fetchNotifications } = useContext(AppContext); @@ -64,7 +65,10 @@ export const Sidebar: React.FC = () => { <>