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

Commit d2f1f1c

Browse files
bighuggiespriscilawebdev
authored andcommitted
refactor: convert Author component to hooks (#150)
1 parent a365ec5 commit d2f1f1c

File tree

4 files changed

+54
-82
lines changed

4 files changed

+54
-82
lines changed
Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,15 @@
11
import React from 'react';
22
import { mount } from 'enzyme';
3-
import Authors from './Author';
43

5-
const mockPackageMeta = jest.fn(() => ({
6-
latest: {
7-
homepage: 'https://verdaccio.tld',
8-
bugs: {
9-
url: 'https://verdaccio.tld/bugs',
10-
},
11-
dist: {
12-
tarball: 'https://verdaccio.tld/download',
13-
},
14-
},
15-
}));
4+
import { DetailContext } from '../../pages/Version';
5+
6+
import Authors from './Author';
167

17-
jest.mock('../../pages/Version', () => ({
18-
DetailContextConsumer: component => {
19-
return component.children({ packageMeta: mockPackageMeta() });
20-
},
21-
}));
8+
const withAuthorComponent = (packageMeta: React.ContextType<typeof DetailContext>['packageMeta']): JSX.Element => (
9+
<DetailContext.Provider value={{ packageMeta }}>
10+
<Authors />
11+
</DetailContext.Provider>
12+
);
2213

2314
describe('<Author /> component', () => {
2415
beforeEach(() => {
@@ -36,13 +27,12 @@ describe('<Author /> component', () => {
3627
url: '',
3728
avatar: 'https://www.gravatar.com/avatar/000000',
3829
},
30+
dist: { fileCount: 0, unpackedSize: 0 },
3931
},
32+
_uplinks: {},
4033
};
4134

42-
// @ts-ignore
43-
mockPackageMeta.mockImplementation(() => packageMeta);
44-
45-
const wrapper = mount(<Authors />);
35+
const wrapper = mount(withAuthorComponent(packageMeta));
4636
expect(wrapper.html()).toMatchSnapshot();
4737
});
4838

@@ -51,14 +41,13 @@ describe('<Author /> component', () => {
5141
latest: {
5242
name: 'verdaccio',
5343
version: '4.0.0',
44+
dist: { fileCount: 0, unpackedSize: 0 },
5445
},
46+
_uplinks: {},
5547
};
5648

57-
// @ts-ignore
58-
mockPackageMeta.mockImplementation(() => packageMeta);
59-
60-
const wrapper = mount(<Authors />);
61-
expect(wrapper.html()).toEqual('');
49+
const wrapper = mount(withAuthorComponent(packageMeta));
50+
expect(wrapper.html()).toBeNull();
6251
});
6352

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

77-
// @ts-ignore
78-
mockPackageMeta.mockImplementation(() => packageMeta);
79-
80-
const wrapper = mount(<Authors />);
68+
const wrapper = mount(withAuthorComponent(packageMeta));
8169
expect(wrapper.html()).toMatchSnapshot();
8270
});
8371
});

src/components/Author/Author.tsx

Lines changed: 30 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,44 @@
1-
import React, { Component, ReactNode, ReactElement } from 'react';
1+
import React, { FC, useContext } from 'react';
22

33
import Avatar from '@material-ui/core/Avatar';
44
import List from '@material-ui/core/List';
55

6-
import { DetailContextConsumer } from '../../pages/Version';
6+
import { DetailContext } from '../../pages/Version';
77
import { Heading, AuthorListItem, AuthorListItemText } from './styles';
88
import { isEmail } from '../../utils/url';
99

10-
class Authors extends Component {
11-
public render(): ReactElement<HTMLElement> {
12-
return (
13-
<DetailContextConsumer>
14-
{context => {
15-
const { packageMeta } = context;
16-
17-
if (!packageMeta) {
18-
return null;
19-
}
20-
21-
return this.renderAuthor(packageMeta);
22-
}}
23-
</DetailContextConsumer>
24-
);
10+
const Authors: FC = () => {
11+
const { packageMeta } = useContext(DetailContext);
12+
13+
if (!packageMeta) {
14+
return null;
2515
}
2616

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

32-
return (
33-
<a href={`mailto:${email}?subject=${packageName}@${version}`} target={'_top'}>
34-
{avatarComponent}
35-
</a>
36-
);
19+
if (!author) {
20+
return null;
3721
}
3822

39-
public renderAuthor = ({ latest }) => {
40-
const { author, name: packageName, version } = latest;
41-
42-
if (!author) {
43-
return null;
44-
}
45-
46-
const avatarComponent = <Avatar alt={author.name} src={author.avatar} />;
47-
return (
48-
<List subheader={<Heading variant={'subtitle1'}>{'Author'}</Heading>}>
49-
<AuthorListItem button={true}>
50-
{this.renderLinkForMail(author.email, avatarComponent, packageName, version)}
51-
<AuthorListItemText primary={author.name} />
52-
</AuthorListItem>
53-
</List>
54-
);
55-
};
56-
}
23+
const { email, name } = author;
24+
25+
const avatarComponent = <Avatar alt={author.name} src={author.avatar} />;
26+
27+
return (
28+
<List subheader={<Heading variant={'subtitle1'}>{'Author'}</Heading>}>
29+
<AuthorListItem button={true}>
30+
{!email || !isEmail(email) ? (
31+
avatarComponent
32+
) : (
33+
<a href={`mailto:${email}?subject=${packageName}@${version}`} target={'_top'}>
34+
{avatarComponent}
35+
</a>
36+
)}
37+
38+
<AuthorListItemText primary={name} />
39+
</AuthorListItem>
40+
</List>
41+
);
42+
};
5743

5844
export default Authors;

src/components/Package/Package.tsx

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import Grid from '@material-ui/core/Grid';
55
import HomeIcon from '@material-ui/icons/Home';
66
import ListItem from '@material-ui/core/ListItem';
77

8-
import { PackageMetaInterface } from 'types/packageMeta';
8+
import { PackageMetaInterface, Author as PackageAuthor } from 'types/packageMeta';
99
import Tag from '../Tag';
1010
import fileSizeSI from '../../utils/file-size';
1111
import { formatDate, formatDateDistance } from '../../utils/package';
@@ -28,11 +28,6 @@ import {
2828
WrapperLink,
2929
} from './styles';
3030
import { isURL } from '../../utils/url';
31-
interface Author {
32-
name: string;
33-
avatar?: string;
34-
email?: string;
35-
}
3631

3732
interface Bugs {
3833
url: string;
@@ -45,7 +40,7 @@ export interface PackageInterface {
4540
name: string;
4641
version: string;
4742
time?: number | string;
48-
author: Author;
43+
author: PackageAuthor;
4944
description?: string;
5045
keywords?: string[];
5146
license?: PackageMetaInterface['latest']['license'];

types/packageMeta.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ export interface PackageMetaInterface {
33
distTags?: DistTags;
44
time?: Time;
55
latest: {
6+
author?: Author;
67
name: string;
78
dist: {
89
fileCount: number;
910
unpackedSize: number;
1011
};
1112
license?: Partial<LicenseInterface> | string;
13+
version: string;
1214
};
1315
_uplinks: {};
1416
}
@@ -41,10 +43,11 @@ export interface Version {
4143
keywords?: string[];
4244
}
4345

44-
interface Author {
46+
export interface Author {
4547
name?: string;
4648
email?: string;
4749
url?: string;
50+
avatar?: string;
4851
}
4952

5053
interface Maintainer {

0 commit comments

Comments
 (0)