From e1597189ac24004883b3644989c0bea90fc511fe Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Wed, 19 Jun 2024 07:29:17 -0400 Subject: [PATCH 1/3] feat: avatar component --- src/components/Avatar.test.tsx | 38 +++ src/components/Avatar.tsx | 32 +++ src/components/NotificationRow.tsx | 9 +- src/components/RepositoryNotifications.tsx | 16 +- .../__snapshots__/Avatar.test.tsx.snap | 238 ++++++++++++++++++ .../NotificationRow.test.tsx.snap | 12 +- .../RepositoryNotifications.test.tsx.snap | 14 +- 7 files changed, 331 insertions(+), 28 deletions(-) create mode 100644 src/components/Avatar.test.tsx create mode 100644 src/components/Avatar.tsx create mode 100644 src/components/__snapshots__/Avatar.test.tsx.snap diff --git a/src/components/Avatar.test.tsx b/src/components/Avatar.test.tsx new file mode 100644 index 000000000..7cbbb08f8 --- /dev/null +++ b/src/components/Avatar.test.tsx @@ -0,0 +1,38 @@ +import { MarkGithubIcon } from '@primer/octicons-react'; +import { render } from '@testing-library/react'; +import { Avatar, type IAvatar } from './Avatar'; + +describe('components/Avatar.tsx', () => { + it('should render small avatar', () => { + const props: IAvatar = { + defaultIcon: MarkGithubIcon, + title: 'test', + url: 'https://avatars.githubusercontent.com/u/583231?v=4', + size: 'small', + }; + const tree = render(); + expect(tree).toMatchSnapshot(); + }); + + it('should render medium avatar', () => { + const props: IAvatar = { + defaultIcon: MarkGithubIcon, + title: 'test', + url: 'https://avatars.githubusercontent.com/u/583231?v=4', + size: 'medium', + }; + const tree = render(); + expect(tree).toMatchSnapshot(); + }); + + it('should render default icon when no url', () => { + const props: IAvatar = { + defaultIcon: MarkGithubIcon, + title: 'test', + url: null, + size: 'small', + }; + const tree = render(); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/src/components/Avatar.tsx b/src/components/Avatar.tsx new file mode 100644 index 000000000..6d089bb4b --- /dev/null +++ b/src/components/Avatar.tsx @@ -0,0 +1,32 @@ +import type { Icon } from '@primer/octicons-react'; +import type { FC } from 'react'; +import { cn } from '../utils/cn'; + +export interface IAvatar { + title: string; + url: string | null; + size: 'small' | 'medium'; + defaultIcon: Icon; +} + +export const Avatar: FC = (props: IAvatar) => { + if (props.url) { + return ( + {`${props.title}'s + ); + } + + return ( + + ); +}; diff --git a/src/components/NotificationRow.tsx b/src/components/NotificationRow.tsx index 5c7c86f19..745883585 100644 --- a/src/components/NotificationRow.tsx +++ b/src/components/NotificationRow.tsx @@ -30,6 +30,7 @@ import { } from '../utils/icons'; import { openNotification, openUserProfile } from '../utils/links'; import { formatReason } from '../utils/reason'; +import { Avatar } from './Avatar'; import { PillButton } from './buttons/PillButton'; interface INotificationRow { @@ -141,11 +142,11 @@ export const NotificationRow: FC = ({ }} className="flex-shrink-0" > - {`${notification.subject.user.login}'s ) : ( diff --git a/src/components/RepositoryNotifications.tsx b/src/components/RepositoryNotifications.tsx index 1aadf16f9..c55e2d86a 100644 --- a/src/components/RepositoryNotifications.tsx +++ b/src/components/RepositoryNotifications.tsx @@ -9,6 +9,7 @@ import { type FC, useCallback, useContext, useState } from 'react'; import { AppContext } from '../context/App'; import type { Notification } from '../typesGitHub'; import { openRepository } from '../utils/links'; +import { Avatar } from './Avatar'; import { NotificationRow } from './NotificationRow'; interface IRepositoryNotifications { @@ -55,15 +56,12 @@ export const RepositoryNotifications: FC = ({ onClick={toggleRepositoryNotifications} >
- {avatarUrl ? ( - {`${repoName}'s - ) : ( - - )} + openRepository(repoNotifications[0].repository)} diff --git a/src/components/__snapshots__/Avatar.test.tsx.snap b/src/components/__snapshots__/Avatar.test.tsx.snap new file mode 100644 index 000000000..e12913de8 --- /dev/null +++ b/src/components/__snapshots__/Avatar.test.tsx.snap @@ -0,0 +1,238 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`components/Avatar.tsx should render default icon when no url 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+ +
+ , + "container":
+ +
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`components/Avatar.tsx should render medium avatar 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+ test's avatar +
+ , + "container":
+ test's avatar +
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`components/Avatar.tsx should render small avatar 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+ test's avatar +
+ , + "container":
+ test's avatar +
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; diff --git a/src/components/__snapshots__/NotificationRow.test.tsx.snap b/src/components/__snapshots__/NotificationRow.test.tsx.snap index 1ade8bac3..fa2df90e4 100644 --- a/src/components/__snapshots__/NotificationRow.test.tsx.snap +++ b/src/components/__snapshots__/NotificationRow.test.tsx.snap @@ -4683,9 +4683,8 @@ exports[`components/NotificationRow.tsx should render itself & its children 1`] > gitify-app's avatar
gitify-app's avatar
gitify-app's avatar
gitify-app's avatar
gitify-app/notifications-test's avatar gitify-app/notifications-test's avatar
- { +describe('components/icons/AvatarIcon.tsx', () => { it('should render small avatar', () => { const props: IAvatar = { defaultIcon: MarkGithubIcon, @@ -10,7 +10,7 @@ describe('components/Avatar.tsx', () => { url: 'https://avatars.githubusercontent.com/u/583231?v=4', size: 'small', }; - const tree = render(); + const tree = render(); expect(tree).toMatchSnapshot(); }); @@ -21,7 +21,7 @@ describe('components/Avatar.tsx', () => { url: 'https://avatars.githubusercontent.com/u/583231?v=4', size: 'medium', }; - const tree = render(); + const tree = render(); expect(tree).toMatchSnapshot(); }); @@ -32,7 +32,7 @@ describe('components/Avatar.tsx', () => { url: null, size: 'small', }; - const tree = render(); + const tree = render(); expect(tree).toMatchSnapshot(); }); }); diff --git a/src/components/Avatar.tsx b/src/components/icons/AvatarIcon.tsx similarity index 86% rename from src/components/Avatar.tsx rename to src/components/icons/AvatarIcon.tsx index 6d089bb4b..8137c3d0d 100644 --- a/src/components/Avatar.tsx +++ b/src/components/icons/AvatarIcon.tsx @@ -1,6 +1,6 @@ import type { Icon } from '@primer/octicons-react'; import type { FC } from 'react'; -import { cn } from '../utils/cn'; +import { cn } from '../../utils/cn'; export interface IAvatar { title: string; @@ -9,7 +9,7 @@ export interface IAvatar { defaultIcon: Icon; } -export const Avatar: FC = (props: IAvatar) => { +export const AvatarIcon: FC = (props: IAvatar) => { if (props.url) { return ( @@ -91,7 +91,7 @@ exports[`components/Avatar.tsx should render default icon when no url 1`] = ` } `; -exports[`components/Avatar.tsx should render medium avatar 1`] = ` +exports[`components/icons/AvatarIcon.tsx should render medium avatar 1`] = ` { "asFragment": [Function], "baseElement": @@ -164,7 +164,7 @@ exports[`components/Avatar.tsx should render medium avatar 1`] = ` } `; -exports[`components/Avatar.tsx should render small avatar 1`] = ` +exports[`components/icons/AvatarIcon.tsx should render small avatar 1`] = ` { "asFragment": [Function], "baseElement": From 37615facaf9fa99b60deb83779146eaa83fbdc28 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Wed, 19 Jun 2024 08:18:36 -0400 Subject: [PATCH 3/3] feat: avatar component --- src/components/icons/AvatarIcon.test.tsx | 8 ++++---- src/components/icons/AvatarIcon.tsx | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/icons/AvatarIcon.test.tsx b/src/components/icons/AvatarIcon.test.tsx index 25e0c600f..4bb3c6c31 100644 --- a/src/components/icons/AvatarIcon.test.tsx +++ b/src/components/icons/AvatarIcon.test.tsx @@ -1,10 +1,10 @@ import { MarkGithubIcon } from '@primer/octicons-react'; import { render } from '@testing-library/react'; -import { AvatarIcon, type IAvatar } from './AvatarIcon'; +import { AvatarIcon, type IAvatarIcon } from './AvatarIcon'; describe('components/icons/AvatarIcon.tsx', () => { it('should render small avatar', () => { - const props: IAvatar = { + const props: IAvatarIcon = { defaultIcon: MarkGithubIcon, title: 'test', url: 'https://avatars.githubusercontent.com/u/583231?v=4', @@ -15,7 +15,7 @@ describe('components/icons/AvatarIcon.tsx', () => { }); it('should render medium avatar', () => { - const props: IAvatar = { + const props: IAvatarIcon = { defaultIcon: MarkGithubIcon, title: 'test', url: 'https://avatars.githubusercontent.com/u/583231?v=4', @@ -26,7 +26,7 @@ describe('components/icons/AvatarIcon.tsx', () => { }); it('should render default icon when no url', () => { - const props: IAvatar = { + const props: IAvatarIcon = { defaultIcon: MarkGithubIcon, title: 'test', url: null, diff --git a/src/components/icons/AvatarIcon.tsx b/src/components/icons/AvatarIcon.tsx index 8137c3d0d..08881ec76 100644 --- a/src/components/icons/AvatarIcon.tsx +++ b/src/components/icons/AvatarIcon.tsx @@ -2,14 +2,14 @@ import type { Icon } from '@primer/octicons-react'; import type { FC } from 'react'; import { cn } from '../../utils/cn'; -export interface IAvatar { +export interface IAvatarIcon { title: string; url: string | null; size: 'small' | 'medium'; defaultIcon: Icon; } -export const AvatarIcon: FC = (props: IAvatar) => { +export const AvatarIcon: FC = (props: IAvatarIcon) => { if (props.url) { return (