From d2f1f1c06a90ecc985c155db4d31718e766044d8 Mon Sep 17 00:00:00 2001 From: Andrew Hughson Date: Sun, 6 Oct 2019 14:44:48 +0100 Subject: [PATCH] refactor: convert Author component to hooks (#150) --- src/components/Author/Author.test.tsx | 48 +++++++------------ src/components/Author/Author.tsx | 68 +++++++++++---------------- src/components/Package/Package.tsx | 9 +--- types/packageMeta.ts | 5 +- 4 files changed, 51 insertions(+), 79 deletions(-) diff --git a/src/components/Author/Author.test.tsx b/src/components/Author/Author.test.tsx index 69f1394..3122db5 100644 --- a/src/components/Author/Author.test.tsx +++ b/src/components/Author/Author.test.tsx @@ -1,24 +1,15 @@ import React from 'react'; import { mount } from 'enzyme'; + +import { DetailContext } from '../../pages/Version'; + import Authors from './Author'; -const mockPackageMeta = jest.fn(() => ({ - latest: { - homepage: 'https://verdaccio.tld', - bugs: { - url: 'https://verdaccio.tld/bugs', - }, - dist: { - tarball: 'https://verdaccio.tld/download', - }, - }, -})); - -jest.mock('../../pages/Version', () => ({ - DetailContextConsumer: component => { - return component.children({ packageMeta: mockPackageMeta() }); - }, -})); +const withAuthorComponent = (packageMeta: React.ContextType['packageMeta']): JSX.Element => ( + + + +); describe(' component', () => { beforeEach(() => { @@ -36,13 +27,12 @@ describe(' component', () => { url: '', avatar: 'https://www.gravatar.com/avatar/000000', }, + dist: { fileCount: 0, unpackedSize: 0 }, }, + _uplinks: {}, }; - // @ts-ignore - mockPackageMeta.mockImplementation(() => packageMeta); - - const wrapper = mount(); + const wrapper = mount(withAuthorComponent(packageMeta)); expect(wrapper.html()).toMatchSnapshot(); }); @@ -51,14 +41,13 @@ describe(' component', () => { latest: { name: 'verdaccio', version: '4.0.0', + dist: { fileCount: 0, unpackedSize: 0 }, }, + _uplinks: {}, }; - // @ts-ignore - mockPackageMeta.mockImplementation(() => packageMeta); - - const wrapper = mount(); - expect(wrapper.html()).toEqual(''); + const wrapper = mount(withAuthorComponent(packageMeta)); + expect(wrapper.html()).toBeNull(); }); test('should render the component when there is no author email', () => { @@ -71,13 +60,12 @@ describe(' component', () => { url: '', avatar: 'https://www.gravatar.com/avatar/000000', }, + dist: { fileCount: 0, unpackedSize: 0 }, }, + _uplinks: {}, }; - // @ts-ignore - mockPackageMeta.mockImplementation(() => packageMeta); - - const wrapper = mount(); + const wrapper = mount(withAuthorComponent(packageMeta)); expect(wrapper.html()).toMatchSnapshot(); }); }); diff --git a/src/components/Author/Author.tsx b/src/components/Author/Author.tsx index 4a64bbe..f5a3225 100644 --- a/src/components/Author/Author.tsx +++ b/src/components/Author/Author.tsx @@ -1,58 +1,44 @@ -import React, { Component, ReactNode, ReactElement } from 'react'; +import React, { FC, useContext } from 'react'; import Avatar from '@material-ui/core/Avatar'; import List from '@material-ui/core/List'; -import { DetailContextConsumer } from '../../pages/Version'; +import { DetailContext } from '../../pages/Version'; import { Heading, AuthorListItem, AuthorListItemText } from './styles'; import { isEmail } from '../../utils/url'; -class Authors extends Component { - public render(): ReactElement { - return ( - - {context => { - const { packageMeta } = context; +const Authors: FC = () => { + const { packageMeta } = useContext(DetailContext); - if (!packageMeta) { - return null; - } - - return this.renderAuthor(packageMeta); - }} - - ); + if (!packageMeta) { + return null; } - public renderLinkForMail(email: string, avatarComponent: ReactNode, packageName: string, version: string): ReactElement | ReactNode { - if (!email || isEmail(email) === false) { - return avatarComponent; - } + const { author, name: packageName, version } = packageMeta.latest; - return ( - - {avatarComponent} - - ); + if (!author) { + return null; } - public renderAuthor = ({ latest }) => { - const { author, name: packageName, version } = latest; + const { email, name } = author; - if (!author) { - return null; - } + const avatarComponent = ; - const avatarComponent = ; - return ( - {'Author'}}> - - {this.renderLinkForMail(author.email, avatarComponent, packageName, version)} - - - - ); - }; -} + return ( + {'Author'}}> + + {!email || !isEmail(email) ? ( + avatarComponent + ) : ( + + {avatarComponent} + + )} + + + + + ); +}; export default Authors; diff --git a/src/components/Package/Package.tsx b/src/components/Package/Package.tsx index ebf07ba..bcbb4a5 100644 --- a/src/components/Package/Package.tsx +++ b/src/components/Package/Package.tsx @@ -5,7 +5,7 @@ import Grid from '@material-ui/core/Grid'; import HomeIcon from '@material-ui/icons/Home'; import ListItem from '@material-ui/core/ListItem'; -import { PackageMetaInterface } from 'types/packageMeta'; +import { PackageMetaInterface, Author as PackageAuthor } from 'types/packageMeta'; import Tag from '../Tag'; import fileSizeSI from '../../utils/file-size'; import { formatDate, formatDateDistance } from '../../utils/package'; @@ -28,11 +28,6 @@ import { WrapperLink, } from './styles'; import { isURL } from '../../utils/url'; -interface Author { - name: string; - avatar?: string; - email?: string; -} interface Bugs { url: string; @@ -45,7 +40,7 @@ export interface PackageInterface { name: string; version: string; time?: number | string; - author: Author; + author: PackageAuthor; description?: string; keywords?: string[]; license?: PackageMetaInterface['latest']['license']; diff --git a/types/packageMeta.ts b/types/packageMeta.ts index 9ca70cb..4a615f6 100644 --- a/types/packageMeta.ts +++ b/types/packageMeta.ts @@ -3,12 +3,14 @@ export interface PackageMetaInterface { distTags?: DistTags; time?: Time; latest: { + author?: Author; name: string; dist: { fileCount: number; unpackedSize: number; }; license?: Partial | string; + version: string; }; _uplinks: {}; } @@ -41,10 +43,11 @@ export interface Version { keywords?: string[]; } -interface Author { +export interface Author { name?: string; email?: string; url?: string; + avatar?: string; } interface Maintainer {