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

Commit

Permalink
feat: add browser features to browse by version (#125)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
juanpicado committed Sep 1, 2019
1 parent bbec54d commit 1904179
Show file tree
Hide file tree
Showing 10 changed files with 6,567 additions and 58 deletions.
24 changes: 18 additions & 6 deletions src/components/DetailSidebar/DetailSidebar.tsx
Expand Up @@ -16,6 +16,15 @@ import { DetailContext } from '../../pages/Version';

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

const renderLatestDescription = (description, version, isLatest: boolean = true) => {
return (
<span>
<div>{description}</div>
{version ? <small>{`${isLatest ? 'Latest v' : 'v'}${version}`}</small> : null}
</span>
);
};

const renderCopyCLI = () => <Install />;
const renderMaintainers = () => <Developers type="maintainers" />;
const renderContributors = () => <Developers type="contributors" />;
Expand All @@ -24,22 +33,25 @@ const renderAuthor = () => <Author />;
const renderEngine = () => <Engine />;
const renderDist = () => <Dist />;
const renderActionBar = () => <ActionBar />;
const renderTitle = (packageName, packageMeta) => {
const renderTitle = (packageName, packageVersion, packageMeta) => {
const version = packageVersion ? packageVersion : packageMeta.latest.version;
const isLatest = typeof packageVersion === 'undefined';

return (
<List className="detail-info">
<TitleListItem alignItems="flex-start" button={true}>
<TitleListItemText primary={<b>{packageName}</b>} secondary={packageMeta.latest.description} />
<TitleListItemText primary={<b>{packageName}</b>} secondary={renderLatestDescription(packageMeta.latest.description, version, isLatest)} />
</TitleListItem>
</List>
);
};

function renderSideBar(packageName, packageMeta): ReactElement<HTMLElement> {
function renderSideBar(packageName, packageVersion, packageMeta): ReactElement<HTMLElement> {
return (
<div className={'sidebar-info'}>
<Card>
<CardContent>
{renderTitle(packageName, packageMeta)}
{renderTitle(packageName, packageVersion, packageMeta)}
{renderActionBar()}
{renderCopyCLI()}
{renderRepository()}
Expand All @@ -55,9 +67,9 @@ function renderSideBar(packageName, packageMeta): ReactElement<HTMLElement> {
}

const DetailSidebar = () => {
const { packageName, packageMeta } = React.useContext(DetailContext);
const { packageName, packageMeta, packageVersion } = React.useContext(DetailContext);

return renderSideBar(packageName, packageMeta);
return renderSideBar(packageName, packageVersion, packageMeta);
};

export default DetailSidebar;
76 changes: 52 additions & 24 deletions src/components/Versions/Versions.test.tsx
@@ -1,35 +1,20 @@
import React from 'react';
import { mount } from 'enzyme';
import { MemoryRouter } from 'react-router';

import Versions from './Versions';
import Versions, { LABEL_CURRENT_TAGS, LABEL_VERSION_HISTORY } from './Versions';
import data from './__partials__/data.json';

import { render, cleanup } from '@testing-library/react';

const mockPackageMeta = jest.fn(() => ({
latest: {
versions: {
'1.0.0': {
version: '1.0.0',
},
'2.0.0': {
version: '2.0.0',
},
'3.0.0': {
version: '3.0.0',
},
},
time: {
'1.0.0': '2016-08-26T22:36:41.762Z',
'2.0.0': '2017-08-26T22:36:41.762Z',
'3.0.0': '2018-02-07T06:43:22.801Z',
},
'dist-tags': {
latest: '3.0.0',
},
},
packageName: 'foo',
packageMeta: data,
}));

jest.mock('../../pages/Version', () => ({
DetailContextConsumer: component => {
return component.children({ packageMeta: mockPackageMeta() });
return component.children({ ...mockPackageMeta() });
},
}));

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

afterEach(() => {
cleanup();
});

test('should render the component in default state', () => {
const wrapper = mount(<Versions />);
const wrapper = mount(
<MemoryRouter>
<Versions />
</MemoryRouter>
);
expect(wrapper.html()).toMatchSnapshot();
});

test('should render versions', () => {
const { getByText } = render(
<MemoryRouter>
<Versions />
</MemoryRouter>
);

expect(getByText(LABEL_VERSION_HISTORY)).toBeTruthy();
expect(getByText(LABEL_CURRENT_TAGS)).toBeTruthy();

// pick some versions
expect(getByText('2.3.0')).toBeTruthy();
expect(getByText('canary')).toBeTruthy();
});

test('should not render versions', () => {
const request = {
packageName: 'foo',
};

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

const { queryByText } = render(
<MemoryRouter>
<Versions />
</MemoryRouter>
);

expect(queryByText(LABEL_VERSION_HISTORY)).toBeFalsy();
expect(queryByText(LABEL_CURRENT_TAGS)).toBeFalsy();
});

test.todo('should click on version link');
});
52 changes: 40 additions & 12 deletions src/components/Versions/Versions.tsx
@@ -1,57 +1,85 @@
import React, { ReactElement } from 'react';
import List from '@material-ui/core/List';
import { Link as RouterLink } from 'react-router-dom';
import Link from '@material-ui/core/Link';
import ListItem from '@material-ui/core/ListItem';

import { DetailContextConsumer } from '../../pages/Version';
import { formatDateDistance } from '../../utils/package';
import { DIST_TAGS } from '../../../lib/constants';

import { Heading, Spacer, ListItemText } from './styles';

const NOT_AVAILABLE = 'Not available';
export const NOT_AVAILABLE = 'Not available';
export const LABEL_CURRENT_TAGS = 'Current Tags';
export const LABEL_VERSION_HISTORY = 'Version History';

class Versions extends React.PureComponent {
public render(): ReactElement<HTMLDivElement> {
return (
<DetailContextConsumer>
{context => {
return context && context.packageMeta && this.renderContent(context.packageMeta);
const { packageMeta, packageName } = context;

if (!packageMeta) {
return null;
}

return this.renderContent(packageMeta, packageName);
}}
</DetailContextConsumer>
);
}

public renderPackageList = (packages: {}, isVersion: boolean = false, timeMap: Record<string, {}> = {}): ReactElement<HTMLDivElement> => {
public renderPackageList = (packages: {}, timeMap: Record<string, {}>, packageName): ReactElement<HTMLDivElement> => {
return (
<List>
<List dense={true}>
{Object.keys(packages)
.reverse()
.map(version => (
<ListItem className="version-item" key={version}>
<ListItemText>{version}</ListItemText>
<Link component={RouterLink} to={`/-/web/detail/${packageName}/v/${version}`}>
<ListItemText>{version}</ListItemText>
</Link>
<Spacer />
<ListItemText>{timeMap[version] ? `${formatDateDistance(timeMap[version])} ago` : NOT_AVAILABLE}</ListItemText>
</ListItem>
))}
</List>
);
};

public renderTagList = (packages: {}): ReactElement<HTMLDivElement> => {
return (
<List dense={true}>
{Object.keys(packages)
.reverse()
.map(tag => (
<ListItem className="version-item" key={tag}>
<ListItemText>{tag}</ListItemText>
<Spacer />
{isVersion && <ListItemText>{timeMap[version] ? `${formatDateDistance(timeMap[version])} ago` : NOT_AVAILABLE}</ListItemText>}
{isVersion === false && <ListItemText>{packages[version]}</ListItemText>}
<ListItemText>{packages[tag]}</ListItemText>
</ListItem>
))}
</List>
);
};

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

return (
<>
{distTags && (
<>
<Heading variant="subtitle1">{'Current Tags'}</Heading>
{this.renderPackageList(distTags, false, timeMap)}
<Heading variant="subtitle1">{LABEL_CURRENT_TAGS}</Heading>
{this.renderTagList(distTags)}
</>
)}
{versions && (
<>
<Heading variant="subtitle1">{'Version History'}</Heading>
{this.renderPackageList(versions, true, timeMap)}
<Heading variant="subtitle1">{LABEL_VERSION_HISTORY}</Heading>
{this.renderPackageList(versions, timeMap, packageName)}
</>
)}
</>
Expand Down

0 comments on commit 1904179

Please sign in to comment.