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

Commit 1904179

Browse files
authored
feat: add browser features to browse by version (#125)
* feat: add browser features to browse by version * chore: verify whether version exist * chore: add link on versions * chore: udpate imports * chore: use mui links * test: add unit test * chore: Add todo list * chore: remove imports
1 parent bbec54d commit 1904179

File tree

10 files changed

+6567
-58
lines changed

10 files changed

+6567
-58
lines changed

src/components/DetailSidebar/DetailSidebar.tsx

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@ import { DetailContext } from '../../pages/Version';
1616

1717
import { TitleListItem, TitleListItemText } from './styles';
1818

19+
const renderLatestDescription = (description, version, isLatest: boolean = true) => {
20+
return (
21+
<span>
22+
<div>{description}</div>
23+
{version ? <small>{`${isLatest ? 'Latest v' : 'v'}${version}`}</small> : null}
24+
</span>
25+
);
26+
};
27+
1928
const renderCopyCLI = () => <Install />;
2029
const renderMaintainers = () => <Developers type="maintainers" />;
2130
const renderContributors = () => <Developers type="contributors" />;
@@ -24,22 +33,25 @@ const renderAuthor = () => <Author />;
2433
const renderEngine = () => <Engine />;
2534
const renderDist = () => <Dist />;
2635
const renderActionBar = () => <ActionBar />;
27-
const renderTitle = (packageName, packageMeta) => {
36+
const renderTitle = (packageName, packageVersion, packageMeta) => {
37+
const version = packageVersion ? packageVersion : packageMeta.latest.version;
38+
const isLatest = typeof packageVersion === 'undefined';
39+
2840
return (
2941
<List className="detail-info">
3042
<TitleListItem alignItems="flex-start" button={true}>
31-
<TitleListItemText primary={<b>{packageName}</b>} secondary={packageMeta.latest.description} />
43+
<TitleListItemText primary={<b>{packageName}</b>} secondary={renderLatestDescription(packageMeta.latest.description, version, isLatest)} />
3244
</TitleListItem>
3345
</List>
3446
);
3547
};
3648

37-
function renderSideBar(packageName, packageMeta): ReactElement<HTMLElement> {
49+
function renderSideBar(packageName, packageVersion, packageMeta): ReactElement<HTMLElement> {
3850
return (
3951
<div className={'sidebar-info'}>
4052
<Card>
4153
<CardContent>
42-
{renderTitle(packageName, packageMeta)}
54+
{renderTitle(packageName, packageVersion, packageMeta)}
4355
{renderActionBar()}
4456
{renderCopyCLI()}
4557
{renderRepository()}
@@ -55,9 +67,9 @@ function renderSideBar(packageName, packageMeta): ReactElement<HTMLElement> {
5567
}
5668

5769
const DetailSidebar = () => {
58-
const { packageName, packageMeta } = React.useContext(DetailContext);
70+
const { packageName, packageMeta, packageVersion } = React.useContext(DetailContext);
5971

60-
return renderSideBar(packageName, packageMeta);
72+
return renderSideBar(packageName, packageVersion, packageMeta);
6173
};
6274

6375
export default DetailSidebar;
Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,20 @@
11
import React from 'react';
22
import { mount } from 'enzyme';
3+
import { MemoryRouter } from 'react-router';
34

4-
import Versions from './Versions';
5+
import Versions, { LABEL_CURRENT_TAGS, LABEL_VERSION_HISTORY } from './Versions';
6+
import data from './__partials__/data.json';
7+
8+
import { render, cleanup } from '@testing-library/react';
59

610
const mockPackageMeta = jest.fn(() => ({
7-
latest: {
8-
versions: {
9-
'1.0.0': {
10-
version: '1.0.0',
11-
},
12-
'2.0.0': {
13-
version: '2.0.0',
14-
},
15-
'3.0.0': {
16-
version: '3.0.0',
17-
},
18-
},
19-
time: {
20-
'1.0.0': '2016-08-26T22:36:41.762Z',
21-
'2.0.0': '2017-08-26T22:36:41.762Z',
22-
'3.0.0': '2018-02-07T06:43:22.801Z',
23-
},
24-
'dist-tags': {
25-
latest: '3.0.0',
26-
},
27-
},
11+
packageName: 'foo',
12+
packageMeta: data,
2813
}));
2914

3015
jest.mock('../../pages/Version', () => ({
3116
DetailContextConsumer: component => {
32-
return component.children({ packageMeta: mockPackageMeta() });
17+
return component.children({ ...mockPackageMeta() });
3318
},
3419
}));
3520

@@ -38,8 +23,51 @@ describe('<Version /> component', () => {
3823
jest.resetModules();
3924
});
4025

26+
afterEach(() => {
27+
cleanup();
28+
});
29+
4130
test('should render the component in default state', () => {
42-
const wrapper = mount(<Versions />);
31+
const wrapper = mount(
32+
<MemoryRouter>
33+
<Versions />
34+
</MemoryRouter>
35+
);
4336
expect(wrapper.html()).toMatchSnapshot();
4437
});
38+
39+
test('should render versions', () => {
40+
const { getByText } = render(
41+
<MemoryRouter>
42+
<Versions />
43+
</MemoryRouter>
44+
);
45+
46+
expect(getByText(LABEL_VERSION_HISTORY)).toBeTruthy();
47+
expect(getByText(LABEL_CURRENT_TAGS)).toBeTruthy();
48+
49+
// pick some versions
50+
expect(getByText('2.3.0')).toBeTruthy();
51+
expect(getByText('canary')).toBeTruthy();
52+
});
53+
54+
test('should not render versions', () => {
55+
const request = {
56+
packageName: 'foo',
57+
};
58+
59+
// @ts-ignore
60+
mockPackageMeta.mockImplementation(() => request);
61+
62+
const { queryByText } = render(
63+
<MemoryRouter>
64+
<Versions />
65+
</MemoryRouter>
66+
);
67+
68+
expect(queryByText(LABEL_VERSION_HISTORY)).toBeFalsy();
69+
expect(queryByText(LABEL_CURRENT_TAGS)).toBeFalsy();
70+
});
71+
72+
test.todo('should click on version link');
4573
});

src/components/Versions/Versions.tsx

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,85 @@
11
import React, { ReactElement } from 'react';
22
import List from '@material-ui/core/List';
3+
import { Link as RouterLink } from 'react-router-dom';
4+
import Link from '@material-ui/core/Link';
35
import ListItem from '@material-ui/core/ListItem';
46

57
import { DetailContextConsumer } from '../../pages/Version';
68
import { formatDateDistance } from '../../utils/package';
79
import { DIST_TAGS } from '../../../lib/constants';
10+
811
import { Heading, Spacer, ListItemText } from './styles';
912

10-
const NOT_AVAILABLE = 'Not available';
13+
export const NOT_AVAILABLE = 'Not available';
14+
export const LABEL_CURRENT_TAGS = 'Current Tags';
15+
export const LABEL_VERSION_HISTORY = 'Version History';
1116

1217
class Versions extends React.PureComponent {
1318
public render(): ReactElement<HTMLDivElement> {
1419
return (
1520
<DetailContextConsumer>
1621
{context => {
17-
return context && context.packageMeta && this.renderContent(context.packageMeta);
22+
const { packageMeta, packageName } = context;
23+
24+
if (!packageMeta) {
25+
return null;
26+
}
27+
28+
return this.renderContent(packageMeta, packageName);
1829
}}
1930
</DetailContextConsumer>
2031
);
2132
}
2233

23-
public renderPackageList = (packages: {}, isVersion: boolean = false, timeMap: Record<string, {}> = {}): ReactElement<HTMLDivElement> => {
34+
public renderPackageList = (packages: {}, timeMap: Record<string, {}>, packageName): ReactElement<HTMLDivElement> => {
2435
return (
25-
<List>
36+
<List dense={true}>
2637
{Object.keys(packages)
2738
.reverse()
2839
.map(version => (
2940
<ListItem className="version-item" key={version}>
30-
<ListItemText>{version}</ListItemText>
41+
<Link component={RouterLink} to={`/-/web/detail/${packageName}/v/${version}`}>
42+
<ListItemText>{version}</ListItemText>
43+
</Link>
44+
<Spacer />
45+
<ListItemText>{timeMap[version] ? `${formatDateDistance(timeMap[version])} ago` : NOT_AVAILABLE}</ListItemText>
46+
</ListItem>
47+
))}
48+
</List>
49+
);
50+
};
51+
52+
public renderTagList = (packages: {}): ReactElement<HTMLDivElement> => {
53+
return (
54+
<List dense={true}>
55+
{Object.keys(packages)
56+
.reverse()
57+
.map(tag => (
58+
<ListItem className="version-item" key={tag}>
59+
<ListItemText>{tag}</ListItemText>
3160
<Spacer />
32-
{isVersion && <ListItemText>{timeMap[version] ? `${formatDateDistance(timeMap[version])} ago` : NOT_AVAILABLE}</ListItemText>}
33-
{isVersion === false && <ListItemText>{packages[version]}</ListItemText>}
61+
<ListItemText>{packages[tag]}</ListItemText>
3462
</ListItem>
3563
))}
3664
</List>
3765
);
3866
};
3967

40-
public renderContent(packageMeta): ReactElement<HTMLDivElement> {
68+
public renderContent(packageMeta, packageName): ReactElement<HTMLDivElement> {
4169
const { versions = {}, time: timeMap = {}, [DIST_TAGS]: distTags = {} } = packageMeta;
4270

4371
return (
4472
<>
4573
{distTags && (
4674
<>
47-
<Heading variant="subtitle1">{'Current Tags'}</Heading>
48-
{this.renderPackageList(distTags, false, timeMap)}
75+
<Heading variant="subtitle1">{LABEL_CURRENT_TAGS}</Heading>
76+
{this.renderTagList(distTags)}
4977
</>
5078
)}
5179
{versions && (
5280
<>
53-
<Heading variant="subtitle1">{'Version History'}</Heading>
54-
{this.renderPackageList(versions, true, timeMap)}
81+
<Heading variant="subtitle1">{LABEL_VERSION_HISTORY}</Heading>
82+
{this.renderPackageList(versions, timeMap, packageName)}
5583
</>
5684
)}
5785
</>

0 commit comments

Comments
 (0)