Skip to content
This repository has been archived by the owner on Jan 16, 2022. It is now read-only.

refactor: convert Author component to hooks #150

Merged
merged 10 commits into from
Oct 6, 2019
48 changes: 18 additions & 30 deletions src/components/Author/Author.test.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,15 @@
import React from 'react';
import { mount } from 'enzyme';
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',
},
},
}));
import { DetailContext } from '../../pages/Version';

import Authors from './Author';

jest.mock('../../pages/Version', () => ({
DetailContextConsumer: component => {
return component.children({ packageMeta: mockPackageMeta() });
},
}));
const withAuthorComponent = (packageMeta: React.ContextType<typeof DetailContext>['packageMeta']): JSX.Element => (
<DetailContext.Provider value={{ packageMeta }}>
<Authors />
</DetailContext.Provider>
);

describe('<Author /> component', () => {
beforeEach(() => {
Expand All @@ -36,13 +27,12 @@ describe('<Author /> component', () => {
url: '',
avatar: 'https://www.gravatar.com/avatar/000000',
},
dist: { fileCount: 0, unpackedSize: 0 },
},
_uplinks: {},
};

// @ts-ignore
mockPackageMeta.mockImplementation(() => packageMeta);

const wrapper = mount(<Authors />);
const wrapper = mount(withAuthorComponent(packageMeta));
expect(wrapper.html()).toMatchSnapshot();
});

Expand All @@ -51,14 +41,13 @@ describe('<Author /> component', () => {
latest: {
name: 'verdaccio',
version: '4.0.0',
dist: { fileCount: 0, unpackedSize: 0 },
},
_uplinks: {},
Comment on lines +44 to +46
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are not needed for the test but were missing before. The type error was hidden by using jest.fn

};

// @ts-ignore
mockPackageMeta.mockImplementation(() => packageMeta);

const wrapper = mount(<Authors />);
expect(wrapper.html()).toEqual('');
const wrapper = mount(withAuthorComponent(packageMeta));
expect(wrapper.html()).toBeNull();
juanpicado marked this conversation as resolved.
Show resolved Hide resolved
});

test('should render the component when there is no author email', () => {
Expand All @@ -71,13 +60,12 @@ describe('<Author /> component', () => {
url: '',
avatar: 'https://www.gravatar.com/avatar/000000',
},
dist: { fileCount: 0, unpackedSize: 0 },
},
_uplinks: {},
};

// @ts-ignore
mockPackageMeta.mockImplementation(() => packageMeta);

const wrapper = mount(<Authors />);
const wrapper = mount(withAuthorComponent(packageMeta));
expect(wrapper.html()).toMatchSnapshot();
});
});
74 changes: 30 additions & 44 deletions src/components/Author/Author.tsx
Original file line number Diff line number Diff line change
@@ -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<HTMLElement> {
return (
<DetailContextConsumer>
{context => {
const { packageMeta } = context;

if (!packageMeta) {
return null;
}

return this.renderAuthor(packageMeta);
}}
</DetailContextConsumer>
);
const Authors: FC = () => {
const { packageMeta } = useContext(DetailContext);

if (!packageMeta) {
return null;
}

public renderLinkForMail(email: string, avatarComponent: ReactNode, packageName: string, version: string): ReactElement<HTMLElement> | ReactNode {
if (!email || isEmail(email) === false) {
return avatarComponent;
}
const { author, name: packageName, version } = packageMeta.latest;

return (
<a href={`mailto:${email}?subject=${packageName}@${version}`} target={'_top'}>
{avatarComponent}
</a>
);
if (!author) {
return null;
}

public renderAuthor = ({ latest }) => {
juanpicado marked this conversation as resolved.
Show resolved Hide resolved
const { author, name: packageName, version } = latest;

if (!author) {
return null;
}

const avatarComponent = <Avatar alt={author.name} src={author.avatar} />;
return (
<List subheader={<Heading variant={'subtitle1'}>{'Author'}</Heading>}>
<AuthorListItem button={true}>
{this.renderLinkForMail(author.email, avatarComponent, packageName, version)}
<AuthorListItemText primary={author.name} />
</AuthorListItem>
</List>
);
};
}
const { email, name } = author;

const avatarComponent = <Avatar alt={author.name} src={author.avatar} />;

return (
<List subheader={<Heading variant={'subtitle1'}>{'Author'}</Heading>}>
<AuthorListItem button={true}>
{!email || !isEmail(email) ? (
avatarComponent
) : (
<a href={`mailto:${email}?subject=${packageName}@${version}`} target={'_top'}>
{avatarComponent}
</a>
)}

<AuthorListItemText primary={name} />
</AuthorListItem>
</List>
);
};

export default Authors;
9 changes: 2 additions & 7 deletions src/components/Package/Package.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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;
Expand All @@ -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'];
Expand Down
5 changes: 4 additions & 1 deletion types/packageMeta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ export interface PackageMetaInterface {
distTags?: DistTags;
time?: Time;
latest: {
author?: Author;
bighuggies marked this conversation as resolved.
Show resolved Hide resolved
name: string;
dist: {
fileCount: number;
unpackedSize: number;
};
license?: Partial<LicenseInterface> | string;
version: string;
};
_uplinks: {};
}
Expand Down Expand Up @@ -41,10 +43,11 @@ export interface Version {
keywords?: string[];
}

interface Author {
export interface Author {
name?: string;
email?: string;
url?: string;
avatar?: string;
}

interface Maintainer {
Expand Down