refactor: <Package /> , <Footer /> and package sidebar code refactoring

refactor: variable naming
This commit is contained in:
ayusharma 2018-07-21 20:49:10 +02:00
parent 4a6383d05f
commit 263b0f78a9
33 changed files with 605 additions and 353 deletions

View File

@ -42,7 +42,8 @@ module.exports = {
moduleNameMapper: {
'\\.(scss)$': '<rootDir>/node_modules/identity-obj-proxy',
'github-markdown-css': '<rootDir>/node_modules/identity-obj-proxy',
'\\.(png)$': '<rootDir>/node_modules/identity-obj-proxy'
'\\.(png)$': '<rootDir>/node_modules/identity-obj-proxy',
'\\.(svg)$': '<rootDir>/test/unit/empty.js'
},
transformIgnorePatterns: [
'<rootDir>/node_modules/(?!react-syntax-highlighter)'

View File

@ -10,14 +10,7 @@
},
"rules": {
"require-jsdoc": 0,
"no-console": [
1,
{
"allow": [
"log"
]
}
],
"no-console": 2,
"no-unused-vars": [
2,
{

View File

@ -1,4 +1,4 @@
import React from 'react';
import React, {Component} from 'react';
import classes from './footer.scss';
import logo from './logo.svg';
@ -12,7 +12,7 @@ import nicaraguaFlag from './flags/nicaragua-1f1f3-1f1ee.svg';
import pakistanFlag from './flags/pakistan-1f1f5-1f1f0.svg';
import spainFlag from './flags/spain-1f1ea-1f1f8.svg';
export default class Footer extends React.Component {
export default class Footer extends Component {
constructor(props) {
super(props);
this.handleEarthIconClick = this.handleEarthIconClick.bind(this);

View File

@ -2,81 +2,51 @@ import React from 'react';
import PropTypes from 'prop-types';
import {Tag} from 'element-react';
import {Link} from 'react-router-dom';
import isNil from 'lodash/isNil';
import {formatDateDistance} from '../../utils/DateUtils';
import {formatDateDistance} from '../../utils/package';
import classes from './package.scss';
export default class Package extends React.Component {
static propTypes = {
package: PropTypes.object
}
render() {
const {package: pkg} = this.props;
return (
<section className={classes.package}>
<Link to={`detail/${pkg.name}`}>
<div className={classes.header}>
{this.renderTitle(pkg)}
{this.renderAuthor(pkg)}
</div>
<div className={classes.footer}>
{this.renderDescription(pkg)}
</div>
<div className={classes.details}>
{this.renderPublished(pkg)}
{this.renderLicense(pkg)}
</div>
</Link>
</section>
);
}
renderPublished(pkg) {
return (<div className={classes.homepage}>
{pkg.time ? `Published ${formatDateDistance(pkg.time)} ago`: ''}
</div>);
}
renderLicense(pkg) {
if (pkg.license) {
return (<div className={classes.license}>
{pkg.license}
</div>);
}
return null;
}
renderDescription(pkg) {
return (
<p className={classes.description}>
{pkg.description}
</p>
);
}
renderTitle(pkg) {
return (
<div className={classes.title}>
<h1>
{pkg.name} {this.renderTag(pkg)}
</h1>
const Package = ({name, version, author, description, license, time}) => {
return (<section className={classes.package}>
<Link to={`detail/${name}`}>
<div className={classes.header}>
<div className={classes.title}>
<h1>
{name} <Tag type="gray">v{version}</Tag>
</h1>
</div>
<div role="author" className={classes.author}>
{ author ? `By: ${author}`: ''}
</div>
</div>
);
}
<div className={classes.footer}>
<p className={classes.description}>
{description}
</p>
</div>
<div className={classes.details}>
<div className={classes.homepage}>
{time ? `Published ${formatDateDistance(time)} ago` : ''}
</div>
<div className={classes.license}>
{license}
</div>
</div>
</Link>
</section>);
};
renderTag(pkg) {
return <Tag type="gray">v{pkg.version}</Tag>;
}
Package.propTypes = {
name: PropTypes.string,
version: PropTypes.string,
author: PropTypes.string,
description: PropTypes.string,
license: PropTypes.string,
time: PropTypes.oneOfType([
PropTypes.string,
PropTypes.instanceOf(Date)
])
};
renderAuthor(pkg) {
if (isNil(pkg.author) || isNil(pkg.author.name)) {
return;
}
return <div role="author" className={classes.author}>{`By: ${pkg.author.name}`}</div>;
}
}
export default Package;

View File

@ -6,27 +6,22 @@ import Readme from '../Readme';
import classes from './packageDetail.scss';
const PackageDetail = (props) => {
const displayState = (readMe) => {
if (isNil(readMe)) {
return;
}
return <Readme readMe={readMe}/>;
};
const displayState = (readMe) => {
return !isNil(readMe) ? <Readme readMe={readMe} /> : '';
};
const PackageDetail = ({packageName, readMe}) => {
return (
<div className={classes.pkgDetail}>
<h1 className={ classes.title }>{ props.package }</h1>
<div className={classes.readme}>
{displayState(props.readMe)}
</div>
<h1 className={classes.title}>{packageName}</h1>
<div className={classes.readme}>{displayState(readMe)}</div>
</div>
);
};
PackageDetail.propTypes = {
readMe: PropTypes.string,
package: PropTypes.string.isRequired
packageName: PropTypes.string.isRequired
};
export default PackageDetail;

View File

@ -5,6 +5,7 @@ import isEmpty from 'lodash/isEmpty';
import Package from '../Package';
import Help from '../Help';
import NoItems from '../NoItems';
import {formatAuthor, formatLicense} from '../../utils/package';
import classes from './packageList.scss';
@ -12,14 +13,14 @@ export default class PackageList extends React.Component {
static propTypes = {
packages: PropTypes.array,
help: PropTypes.bool
}
};
render() {
return (
<div className="package-list-items">
<div className={classes.pkgContainer}>
{this.renderTitle()}
{this.isTherePackages() ? this.renderList(): this.renderOptions()}
{this.isTherePackages() ? this.renderList() : this.renderOptions()}
</div>
</div>
);
@ -30,13 +31,20 @@ export default class PackageList extends React.Component {
return;
}
return <h1 className={ classes.listTitle }>Available Packages</h1>;
return <h1 className={classes.listTitle}>Available Packages</h1>;
}
renderList() {
return this.props.packages.map((pkg, i)=> (
<li key={i}><Package package={pkg} /></li>
));
return this.props.packages.map((pkg, i) => {
const {name, version, description, time} = pkg;
const author = formatAuthor(pkg.author);
const license = formatLicense(pkg.license);
return (
<li key={i}>
<Package {...{name, version, author, description, license, time}} />
</li>
);
});
}
renderOptions() {
@ -48,14 +56,19 @@ export default class PackageList extends React.Component {
}
renderNoItems() {
return <NoItems className="package-no-items" text={'No items were found with that query'}/>;
return (
<NoItems
className="package-no-items"
text={'No items were found with that query'}
/>
);
}
renderHelp() {
if (this.props.help === false) {
return;
}
return <Help/>;
return <Help />;
}
isTherePackages() {

View File

@ -1,10 +1,17 @@
import React from 'react';
import PropTypes from 'prop-types';
import get from 'lodash/get';
import LastSync from './modules/LastSync';
import Maintainers from './modules/Maintainers';
import Dependencies from './modules/Dependencies';
import Infos from './modules/Infos';
import {
formatLicense,
formatRepository,
getLastUpdatedPackageTime,
getRecentReleases
} from '../../utils/package';
import API from '../../utils/api';
export default class PackageSidebar extends React.Component {
@ -23,7 +30,7 @@ export default class PackageSidebar extends React.Component {
await this.loadPackageData(this.props.packageName);
}
async componentWillReceiveProps(newProps) {
async UNSAFE_componentWillReceiveProps(newProps) {
if (newProps.packageName !== this.props.packageName) {
await this.loadPackageData(newProps.packageName);
}
@ -38,7 +45,6 @@ export default class PackageSidebar extends React.Component {
this.setState({
failed: true
});
return;
}
this.setState({
@ -49,14 +55,46 @@ export default class PackageSidebar extends React.Component {
render() {
let {packageMeta} = this.state;
return packageMeta ?
(<aside className="sidebar-info">
<LastSync packageMeta={packageMeta} />
<Infos packageMeta={packageMeta} />
<Maintainers packageMeta={packageMeta} />
<Dependencies packageMeta={packageMeta} />
{/* Package management module? Help us implement it! */}
</aside>):
(<aside className="sidebar-loading">Loading package information...</aside>);
if (packageMeta) {
const {time, _uplinks} = packageMeta;
// Infos component
const license = formatLicense(get(packageMeta, 'latest.license', null));
const repository = formatRepository(
get(packageMeta, 'latest.repository', null)
);
const homepage = get(packageMeta, 'latest.homepage', null);
// Lastsync component
const recentReleases = getRecentReleases(time);
const lastUpdated = getLastUpdatedPackageTime(_uplinks);
// Dependencies component
const dependencies = get(packageMeta, 'latest.dependencies', {});
// Maintainers component
return (
<aside className="sidebar-info">
{time && (
<LastSync
recentReleases={recentReleases}
lastUpdated={lastUpdated}
/>
)}
<Infos
homepage={homepage}
repository={repository}
license={license}
/>
{/* TODO: Refacor later, when we decide to show only maintainers/authors */}
<Maintainers packageMeta={packageMeta} />
<Dependencies dependencies={dependencies} />
{/* Package management module? Help us implement it! */}
</aside>
);
}
return (
<aside className="sidebar-loading">Loading package information...</aside>
);
}
}

View File

@ -1,47 +1,46 @@
import React from 'react';
import PropTypes from 'prop-types';
import get from 'lodash/get';
import Module from '../../Module';
import classes from './style.scss';
import {getDetailPageURL} from '../../../../utils/url';
import ModuleContentPlaceholder from '../../ModuleContentPlaceholder';
export default class Dependencies extends React.Component {
static propTypes = {
packageMeta: PropTypes.object.isRequired
};
import classes from './style.scss';
get dependencies() {
return get(this, 'props.packageMeta.latest.dependencies', {});
}
const renderDependenciesList = (dependencies, dependenciesList) => {
return (
<ul>
{dependenciesList.map((dependenceName, index) => {
return (
<li
className="dependency-item"
key={index}
title={`Depend on version: ${dependencies[dependenceName]}`}
>
<a href={getDetailPageURL(dependenceName)}>{dependenceName}</a>
{index < dependenciesList.length - 1 && <span>,&nbsp;</span>}
</li>
);
})}
</ul>
);
};
render() {
let dependencies = this.dependencies;
let dependenciesList = Object.keys(dependencies);
const Dependencies = ({dependencies = {}}) => {
const dependenciesList = Object.keys(dependencies);
return (
<Module title="Dependencies" className={classes.dependenciesModule}>
{dependenciesList.length > 1 ? (
renderDependenciesList(dependencies, dependenciesList)
) : (
<ModuleContentPlaceholder text="Zero Dependencies!" />
)}
</Module>
);
};
if (!dependenciesList.length) {
return <ModuleContentPlaceholder text="Zero Dependencies!"/>;
}
Dependencies.propTypes = {
dependencies: PropTypes.object
};
return (
<Module
title="Dependencies"
className={classes.dependenciesModule}
>
<ul>
{
dependenciesList.map((dependenceName, index) => {
return (
<li className="dependency-item" key={index} title={`Depend on version: ${dependencies[dependenceName]}`}>
<a href={getDetailPageURL(dependenceName)}>{dependenceName}</a>
{index < dependenciesList.length - 1 && <span>,&nbsp;</span>}
</li>
);
})
}
</ul>
</Module>
);
}
}
export default Dependencies;

View File

@ -1,69 +1,37 @@
import React from 'react';
import PropTypes from 'prop-types';
import get from 'lodash/get';
import Module from '../../Module';
import isString from 'lodash/isString';
import isNil from 'lodash/isNil';
import ModuleContentPlaceholder from '../../ModuleContentPlaceholder';
import classes from './style.scss';
export default class Infos extends React.Component {
static propTypes = {
packageMeta: PropTypes.object.isRequired
};
const renderSection = (title, url) => (
<li>
<span>{title}</span>
<a href={url} target="_blank">
{url}
</a>
</li>
);
get infos() {
const homepage = this.normalizeInfo(get(this, 'props.packageMeta.latest.homepage', null));
const repo = this.normalizeInfo(get(this, 'props.packageMeta.latest.repository', null));
const license = get(this, 'props.packageMeta.latest.license', 'N/A');
const Infos = ({homepage, repository, license}) => {
const showInfo = homepage || repository || license;
return <Module title="Infos" className={classes.infosModule}>
{showInfo ? <ul>
{homepage && renderSection('Homepage', homepage)}
{repository && renderSection('Repository', repository)}
{license && <li>
<span>License</span>
<span>{license}</span>
</li>}
</ul> : <ModuleContentPlaceholder text="Not Available!" />}
</Module>;
};
return {homepage, repo, license};
}
Infos.propTypes = {
homepage: PropTypes.string,
repository: PropTypes.string,
license: PropTypes.string
};
normalizeInfo(infoObj) {
if (isString(infoObj)) {
return {url: infoObj};
} else if (isNil(infoObj)) {
return {url: ''};
}
infoObj.url = this.normalizeGitUrl(infoObj);
return infoObj;
}
normalizeGitUrl(infoObj) {
return infoObj.url.replace(/^git\+/, '');
}
render() {
const infos = this.infos;
if (infos.homepage.url === '' && infos.repo.url === '' && infos.license === 'N/A') {
return '';
}
return (
<Module
title="Infos"
className={classes.infosModule}
>
<ul>
{infos.homepage.url && this.renderSection('Homepage', infos.homepage.url)}
{infos.repo.url && this.renderSection('Repository', infos.repo.url)}
{infos.license &&
<li><span>License</span><span>{infos.license}</span></li>
}
</ul>
</Module>
);
}
renderSection(title, url) {
return (
<li><span>{title}</span><a href={url} target="_blank">{url}</a></li>
);
}
}
export default Infos;

View File

@ -1,61 +1,45 @@
import React from 'react';
import PropTypes from 'prop-types';
import propTypes from 'prop-types';
import Module from '../../Module';
import {formatDate} from '../../../../utils/DateUtils';
import ModuleContentPlaceholder from '../../ModuleContentPlaceholder';
import classes from './style.scss';
export default class LastSync extends React.Component {
static propTypes = {
packageMeta: PropTypes.object.isRequired
};
const renderRecentReleases = (recentReleases) => {
return (
<ul>
{recentReleases.map((versionInfo) => {
const {version, time} = versionInfo;
return (
<li className="last-sync-item" key={version}>
<span>{version}</span>
<span>{time}</span>
</li>
);
})}
</ul>
);
};
get lastUpdate() {
let lastUpdate = 0;
Object.keys(this.props.packageMeta._uplinks).forEach((upLinkName) => {
const status = this.props.packageMeta._uplinks[upLinkName];
const LastSync = ({recentReleases = [], lastUpdated = ''}) => {
return (
<Module
title="Last Sync"
description={lastUpdated}
className={classes.releasesModule}
>
{recentReleases.length ? (
renderRecentReleases(recentReleases)
) : (
<ModuleContentPlaceholder text="Not Available!" />
)}
</Module>
);
};
if (status.fetched > lastUpdate) {
lastUpdate = status.fetched;
}
});
LastSync.propTypes = {
recentReleases: propTypes.array,
lastUpdated: propTypes.string
};
const time = formatDate(lastUpdate);
return lastUpdate ? time : '';
}
get recentReleases() {
let recentReleases = Object.keys(this.props.packageMeta.time).map((version) => {
const time = formatDate(this.props.packageMeta.time[version]);
return {version, time};
});
return recentReleases.slice(recentReleases.length - 3, recentReleases.length).reverse();
}
render() {
if (!this.props.packageMeta.time) {
return null;
}
return (
<Module
title="Last Sync"
description={this.lastUpdate}
className={classes.releasesModule}
>
<ul>
{this.recentReleases.map((versionInfo) => {
return (
<li className="last-sync-item" key={versionInfo.version}>
<span>{versionInfo.version}</span>
<span>{versionInfo.time}</span>
</li>
);
})}
</ul>
</Module>
);
}
}
export default LastSync;

View File

@ -3,11 +3,16 @@ import PropTypes from 'prop-types';
import get from 'lodash/get';
import filter from 'lodash/filter';
import size from 'lodash/size';
import has from 'lodash/has';
import uniqBy from 'lodash/uniqBy';
import Module from '../../Module';
import MaintainerInfo from './MaintainerInfo';
import ModuleContentPlaceholder from '../../ModuleContentPlaceholder';
import classes from './style.scss';
import MaintainerInfo from './MaintainerInfo';
const CONTRIBUTORS_TO_SHOW = 5;
export default class Maintainers extends React.Component {
static propTypes = {
@ -44,7 +49,10 @@ export default class Maintainers extends React.Component {
return [];
}
return uniqBy(this.contributors, (contributor) => contributor.name).slice(0, 5);
return uniqBy(this.contributors, (contributor) => contributor.name).slice(
0,
CONTRIBUTORS_TO_SHOW
);
}
handleShowAllContributors() {
@ -56,26 +64,33 @@ export default class Maintainers extends React.Component {
renderContributors() {
if (!this.contributors) return null;
return (this.showAllContributors ? this.contributors : this.uniqueContributors)
.map((contributor, index) => {
return <MaintainerInfo
return (this.showAllContributors
? this.contributors
: this.uniqueContributors
).map((contributor, index) => {
return (
<MaintainerInfo
key={index}
title="Contributors"
name={contributor.name}
avatar={contributor.avatar}/>;
});
avatar={contributor.avatar}
/>
);
});
}
render() {
let author = this.author;
renderAuthorAndContributors(author) {
return (
<Module
title="Maintainers"
className={classes.maintainersModule}
>
<div>
<ul className="maintainer-author">
{author && <MaintainerInfo title="Author" name={author.name} avatar={author.avatar}/>}
{author &&
author.name && (
<MaintainerInfo
title="Author"
name={author.name}
avatar={author.avatar}
/>
)}
{this.renderContributors()}
</ul>
{!this.showAllContributors && (
@ -87,6 +102,20 @@ export default class Maintainers extends React.Component {
Show all contributor
</button>
)}
</div>
);
}
render() {
let author = this.author;
const contributors = this.renderContributors();
return (
<Module title="Maintainers" className={classes.maintainersModule}>
{contributors.length || has(author, 'name') ? (
this.renderAuthorAndContributors(author)
) : (
<ModuleContentPlaceholder text="Not Available!" />
)}
</Module>
);
}

View File

@ -68,7 +68,7 @@ export default class Detail extends React.Component {
}
return (
<div className={classes.twoColumn}>
<PackageDetail readMe={readMe} package={this.packageName}/>
<PackageDetail readMe={readMe} packageName={this.packageName}/>
<PackageSidebar packageName={this.packageName} />
</div>
);

View File

@ -1,12 +0,0 @@
export const TIMEFORMAT = 'YYYY/MM/DD, HH:mm:ss';
import format from 'date-fns/format';
import distanceInWordsToNow from 'date-fns/distance_in_words_to_now';
export function formatDate(lastUpdate) {
return format(new Date(lastUpdate), TIMEFORMAT);
}
export function formatDateDistance(lastUpdate) {
return distanceInWordsToNow(new Date(lastUpdate));
}

View File

@ -0,0 +1,92 @@
import isString from 'lodash/isString';
import isObject from 'lodash/isObject';
export const TIMEFORMAT = 'YYYY/MM/DD, HH:mm:ss';
import format from 'date-fns/format';
import distanceInWordsToNow from 'date-fns/distance_in_words_to_now';
/**
* Formats license field for webui.
* @see https://docs.npmjs.com/files/package.json#license
*/
export function formatLicense(license) {
if (isString(license)) {
return license;
}
if (isObject(license) && license.type) {
return license.type;
}
return null;
}
/**
* Formats repository field for webui.
* @see https://docs.npmjs.com/files/package.json#repository
*/
export function formatRepository(repository) {
if (isString(repository)) {
return repository;
}
if (isObject(repository) && repository.url) {
return repository.url;
}
return null;
}
/**
* Formats author field for webui.
* @see https://docs.npmjs.com/files/package.json#author
*/
export function formatAuthor(author) {
if (isString(author)) {
return author;
}
if (isObject(author) && author.name) {
return author.name;
}
return null;
}
/**
* For <LastSync /> component
* @param {array} uplinks
*/
export function getLastUpdatedPackageTime(uplinks = {}) {
let lastUpdate = 0;
Object.keys(uplinks).forEach((upLinkName) => {
const status = uplinks[upLinkName];
if (status.fetched > lastUpdate) {
lastUpdate = status.fetched;
}
});
return lastUpdate ? formatDate(lastUpdate) : '';
}
/**
* For <LastSync /> component
* @param {Object} time
* @returns {Array} last 3 releases
*/
export function getRecentReleases(time = {}) {
const recent = Object.keys(time).map((version) => ({
version,
time: formatDate(time[version])
}));
return recent.slice(recent.length - 3, recent.length).reverse();
}
export function formatDate(lastUpdate) {
return format(new Date(lastUpdate), TIMEFORMAT);
}
export function formatDateDistance(lastUpdate) {
return distanceInWordsToNow(new Date(lastUpdate));
}

1
test/unit/empty.js Normal file
View File

@ -0,0 +1 @@
export default {};

View File

@ -7,3 +7,5 @@ import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });
global.__APP_VERSION__ = '1.0.0';

View File

@ -1,3 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<PackageSidebar /> : <Dependencies /> should load the package and match snapshot 1`] = `"<div class=\\"module dependenciesModule\\"><h2 class=\\"moduleTitle\\">Dependencies</h2><div><ul><li class=\\"dependency-item\\" title=\\"Depend on version: 0.0.3\\"><a href=\\"http://localhost/#/detail/@verdaccio/file-locking\\">@verdaccio/file-locking</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: 0.0.2\\"><a href=\\"http://localhost/#/detail/@verdaccio/streams\\">@verdaccio/streams</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^1.1.1\\"><a href=\\"http://localhost/#/detail/JSONStream\\">JSONStream</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^1.1.2\\"><a href=\\"http://localhost/#/detail/apache-md5\\">apache-md5</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^2.0.1\\"><a href=\\"http://localhost/#/detail/async\\">async</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^1.15.0\\"><a href=\\"http://localhost/#/detail/body-parser\\">body-parser</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^1.8.0\\"><a href=\\"http://localhost/#/detail/bunyan\\">bunyan</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^2.0.1\\"><a href=\\"http://localhost/#/detail/chalk\\">chalk</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^2.11.0\\"><a href=\\"http://localhost/#/detail/commander\\">commander</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: 1.6.2\\"><a href=\\"http://localhost/#/detail/compression\\">compression</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^0.7.0\\"><a href=\\"http://localhost/#/detail/cookies\\">cookies</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^2.8.3\\"><a href=\\"http://localhost/#/detail/cors\\">cors</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: 4.15.3\\"><a href=\\"http://localhost/#/detail/express\\">express</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^4.3.2\\"><a href=\\"http://localhost/#/detail/global\\">global</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: 4.0.5\\"><a href=\\"http://localhost/#/detail/handlebars\\">handlebars</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^1.4.0\\"><a href=\\"http://localhost/#/detail/http-errors\\">http-errors</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: 1.0.1\\"><a href=\\"http://localhost/#/detail/js-string-escape\\">js-string-escape</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^3.6.0\\"><a href=\\"http://localhost/#/detail/js-yaml\\">js-yaml</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^7.4.1\\"><a href=\\"http://localhost/#/detail/jsonwebtoken\\">jsonwebtoken</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^1.0.1\\"><a href=\\"http://localhost/#/detail/lockfile\\">lockfile</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: 4.17.4\\"><a href=\\"http://localhost/#/detail/lodash\\">lodash</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^0.7.0\\"><a href=\\"http://localhost/#/detail/lunr\\">lunr</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: 0.3.6\\"><a href=\\"http://localhost/#/detail/marked\\">marked</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^1.3.6\\"><a href=\\"http://localhost/#/detail/mime\\">mime</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^3.0.2\\"><a href=\\"http://localhost/#/detail/minimatch\\">minimatch</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^0.5.1\\"><a href=\\"http://localhost/#/detail/mkdirp\\">mkdirp</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^0.4.0\\"><a href=\\"http://localhost/#/detail/pkginfo\\">pkginfo</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^2.72.0\\"><a href=\\"http://localhost/#/detail/request\\">request</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^5.1.0\\"><a href=\\"http://localhost/#/detail/semver\\">semver</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^1.0.0\\"><a href=\\"http://localhost/#/detail/unix-crypt-td-js\\">unix-crypt-td-js</a></li></ul></div></div>"`;
exports[`<PackageSidebar /> : <Dependencies /> should load dependencies 1`] = `"<div class=\\"module dependenciesModule\\"><h2 class=\\"moduleTitle\\">Dependencies</h2><div><ul><li class=\\"dependency-item\\" title=\\"Depend on version: 0.0.3\\"><a href=\\"http://localhost/#/detail/@verdaccio/file-locking\\">@verdaccio/file-locking</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: 0.0.2\\"><a href=\\"http://localhost/#/detail/@verdaccio/streams\\">@verdaccio/streams</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^1.1.1\\"><a href=\\"http://localhost/#/detail/JSONStream\\">JSONStream</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^1.1.2\\"><a href=\\"http://localhost/#/detail/apache-md5\\">apache-md5</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^2.0.1\\"><a href=\\"http://localhost/#/detail/async\\">async</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^1.15.0\\"><a href=\\"http://localhost/#/detail/body-parser\\">body-parser</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^1.8.0\\"><a href=\\"http://localhost/#/detail/bunyan\\">bunyan</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^2.0.1\\"><a href=\\"http://localhost/#/detail/chalk\\">chalk</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^2.11.0\\"><a href=\\"http://localhost/#/detail/commander\\">commander</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: 1.6.2\\"><a href=\\"http://localhost/#/detail/compression\\">compression</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^0.7.0\\"><a href=\\"http://localhost/#/detail/cookies\\">cookies</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^2.8.3\\"><a href=\\"http://localhost/#/detail/cors\\">cors</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: 4.15.3\\"><a href=\\"http://localhost/#/detail/express\\">express</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^4.3.2\\"><a href=\\"http://localhost/#/detail/global\\">global</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: 4.0.5\\"><a href=\\"http://localhost/#/detail/handlebars\\">handlebars</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^1.4.0\\"><a href=\\"http://localhost/#/detail/http-errors\\">http-errors</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: 1.0.1\\"><a href=\\"http://localhost/#/detail/js-string-escape\\">js-string-escape</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^3.6.0\\"><a href=\\"http://localhost/#/detail/js-yaml\\">js-yaml</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^7.4.1\\"><a href=\\"http://localhost/#/detail/jsonwebtoken\\">jsonwebtoken</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^1.0.1\\"><a href=\\"http://localhost/#/detail/lockfile\\">lockfile</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: 4.17.4\\"><a href=\\"http://localhost/#/detail/lodash\\">lodash</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^0.7.0\\"><a href=\\"http://localhost/#/detail/lunr\\">lunr</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: 0.3.6\\"><a href=\\"http://localhost/#/detail/marked\\">marked</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^1.3.6\\"><a href=\\"http://localhost/#/detail/mime\\">mime</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^3.0.2\\"><a href=\\"http://localhost/#/detail/minimatch\\">minimatch</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^0.5.1\\"><a href=\\"http://localhost/#/detail/mkdirp\\">mkdirp</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^0.4.0\\"><a href=\\"http://localhost/#/detail/pkginfo\\">pkginfo</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^2.72.0\\"><a href=\\"http://localhost/#/detail/request\\">request</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^5.1.0\\"><a href=\\"http://localhost/#/detail/semver\\">semver</a><span>, </span></li><li class=\\"dependency-item\\" title=\\"Depend on version: ^1.0.0\\"><a href=\\"http://localhost/#/detail/unix-crypt-td-js\\">unix-crypt-td-js</a></li></ul></div></div>"`;
exports[`<PackageSidebar /> : <Dependencies /> should load the package without dependecnies 1`] = `"<div class=\\"module dependenciesModule\\"><h2 class=\\"moduleTitle\\">Dependencies</h2><div><p class=\\"emptyPlaceholder\\">Zero Dependencies!</p></div></div>"`;

View File

@ -1,3 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<PackageSidebar /> : <Infos /> should load the Info component and match snapshot 1`] = `"<div class=\\"module infosModule\\"><h2 class=\\"moduleTitle\\">Infos</h2><div><ul><li><span>Homepage</span><a href=\\"https://github.com/verdaccio/verdaccio#readme\\" target=\\"_blank\\">https://github.com/verdaccio/verdaccio#readme</a></li><li><span>Repository</span><a href=\\"git://github.com/verdaccio/verdaccio.git\\" target=\\"_blank\\">git://github.com/verdaccio/verdaccio.git</a></li><li><span>License</span><span>WTFPL</span></li></ul></div></div>"`;
exports[`<PackageSidebar /> : <Infos /> should load the Info component with homepage only 1`] = `"<div class=\\"module infosModule\\"><h2 class=\\"moduleTitle\\">Infos</h2><div><ul><li><span>Homepage</span><a href=\\"https://www.verdaccio.org\\" target=\\"_blank\\">https://www.verdaccio.org</a></li></ul></div></div>"`;
exports[`<PackageSidebar /> : <Infos /> should load the Info component with license only 1`] = `"<div class=\\"module infosModule\\"><h2 class=\\"moduleTitle\\">Infos</h2><div><ul><li><span>License</span><span>MIT</span></li></ul></div></div>"`;
exports[`<PackageSidebar /> : <Infos /> should load the Info component with props 1`] = `"<div class=\\"module infosModule\\"><h2 class=\\"moduleTitle\\">Infos</h2><div><ul><li><span>Homepage</span><a href=\\"https://www.verdaccio.org\\" target=\\"_blank\\">https://www.verdaccio.org</a></li><li><span>Repository</span><a href=\\"https://github.com/verdaccio/verdaccio\\" target=\\"_blank\\">https://github.com/verdaccio/verdaccio</a></li><li><span>License</span><span>MIT</span></li></ul></div></div>"`;
exports[`<PackageSidebar /> : <Infos /> should load the Info component with repository only 1`] = `"<div class=\\"module infosModule\\"><h2 class=\\"moduleTitle\\">Infos</h2><div><ul><li><span>Repository</span><a href=\\"https://github.com/verdaccio/verdaccio\\" target=\\"_blank\\">https://github.com/verdaccio/verdaccio</a></li></ul></div></div>"`;
exports[`<PackageSidebar /> : <Infos /> should load the component without props 1`] = `"<div class=\\"module infosModule\\"><h2 class=\\"moduleTitle\\">Infos</h2><div><p class=\\"emptyPlaceholder\\">Not Available!</p></div></div>"`;

View File

@ -1,3 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<PackageSidebar /> : <LastSync /> should check the default props condition 1`] = `"<div class=\\"module releasesModule\\"><h2 class=\\"moduleTitle\\">Last Sync</h2><div><p class=\\"emptyPlaceholder\\">Not Available!</p></div></div>"`;
exports[`<PackageSidebar /> : <LastSync /> should load the LastSync component and match snapshot 1`] = `"<div class=\\"module releasesModule\\"><h2 class=\\"moduleTitle\\">Last Sync<span>2017/12/14, 15:43:52</span></h2><div><ul><li class=\\"last-sync-item\\"><span>2.7.1</span><span>2017/12/14, 15:43:27</span></li><li class=\\"last-sync-item\\"><span>2.7.0</span><span>2017/12/05, 23:25:06</span></li><li class=\\"last-sync-item\\"><span>2.6.6</span><span>2017/11/08, 22:47:16</span></li></ul></div></div>"`;

View File

@ -1,3 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<PackageSidebar /> : <Maintainers /> should match with the props 1`] = `"<div class=\\"module maintainersModule\\"><h2 class=\\"moduleTitle\\">Maintainers</h2><div><ul class=\\"maintainer-author\\"><div class=\\"maintainer\\" title=\\"User NPM\\"><img src=\\"https://www.gravatar.com/avatar/a5a236ba477ee98908600c40cda74f4a\\" alt=\\"Author User NPM's avatar\\" title=\\"Author User NPM's avatar\\"><span class=\\"maintainer-name\\">User NPM</span></div><div class=\\"maintainer\\" title=\\"030\\"><img src=\\"https://www.gravatar.com/avatar/4ef03c2bf8d8689527903212d96fb45b\\" alt=\\"Contributors 030's avatar\\" title=\\"Contributors 030's avatar\\"><span class=\\"maintainer-name\\">030</span></div><div class=\\"maintainer\\" title=\\"Alex Vernacchia\\"><img src=\\"https://www.gravatar.com/avatar/06975001f7f2be7052bcf978700c6112\\" alt=\\"Contributors Alex Vernacchia's avatar\\" title=\\"Contributors Alex Vernacchia's avatar\\"><span class=\\"maintainer-name\\">Alex Vernacchia</span></div><div class=\\"maintainer\\" title=\\"Alexander Makarenko\\"><img src=\\"https://www.gravatar.com/avatar/d9acfc4ed4e49a436738ff26a722dce4\\" alt=\\"Contributors Alexander Makarenko's avatar\\" title=\\"Contributors Alexander Makarenko's avatar\\"><span class=\\"maintainer-name\\">Alexander Makarenko</span></div><div class=\\"maintainer\\" title=\\"Alexandre-io\\"><img src=\\"https://www.gravatar.com/avatar/2e095c7cfd278f72825d0fed6e12e3b1\\" alt=\\"Contributors Alexandre-io's avatar\\" title=\\"Contributors Alexandre-io's avatar\\"><span class=\\"maintainer-name\\">Alexandre-io</span></div><div class=\\"maintainer\\" title=\\"Aram Drevekenin\\"><img src=\\"https://www.gravatar.com/avatar/371edff6d79c39bb9e36bde39d41a4b0\\" alt=\\"Contributors Aram Drevekenin's avatar\\" title=\\"Contributors Aram Drevekenin's avatar\\"><span class=\\"maintainer-name\\">Aram Drevekenin</span></div></ul><button class=\\"showAllContributors\\" title=\\"Current list only show the author and first 5 contributors unique by name\\">Show all contributor</button></div></div>"`;
exports[`<PackageSidebar /> : <Maintainers /> should match with the props 1`] = `"<div class=\\"module maintainersModule\\"><h2 class=\\"moduleTitle\\">Maintainers</h2><div><div><ul class=\\"maintainer-author\\"><div class=\\"maintainer\\" title=\\"User NPM\\"><img src=\\"https://www.gravatar.com/avatar/a5a236ba477ee98908600c40cda74f4a\\" alt=\\"Author User NPM's avatar\\" title=\\"Author User NPM's avatar\\"><span class=\\"maintainer-name\\">User NPM</span></div><div class=\\"maintainer\\" title=\\"030\\"><img src=\\"https://www.gravatar.com/avatar/4ef03c2bf8d8689527903212d96fb45b\\" alt=\\"Contributors 030's avatar\\" title=\\"Contributors 030's avatar\\"><span class=\\"maintainer-name\\">030</span></div><div class=\\"maintainer\\" title=\\"Alex Vernacchia\\"><img src=\\"https://www.gravatar.com/avatar/06975001f7f2be7052bcf978700c6112\\" alt=\\"Contributors Alex Vernacchia's avatar\\" title=\\"Contributors Alex Vernacchia's avatar\\"><span class=\\"maintainer-name\\">Alex Vernacchia</span></div><div class=\\"maintainer\\" title=\\"Alexander Makarenko\\"><img src=\\"https://www.gravatar.com/avatar/d9acfc4ed4e49a436738ff26a722dce4\\" alt=\\"Contributors Alexander Makarenko's avatar\\" title=\\"Contributors Alexander Makarenko's avatar\\"><span class=\\"maintainer-name\\">Alexander Makarenko</span></div><div class=\\"maintainer\\" title=\\"Alexandre-io\\"><img src=\\"https://www.gravatar.com/avatar/2e095c7cfd278f72825d0fed6e12e3b1\\" alt=\\"Contributors Alexandre-io's avatar\\" title=\\"Contributors Alexandre-io's avatar\\"><span class=\\"maintainer-name\\">Alexandre-io</span></div><div class=\\"maintainer\\" title=\\"Aram Drevekenin\\"><img src=\\"https://www.gravatar.com/avatar/371edff6d79c39bb9e36bde39d41a4b0\\" alt=\\"Contributors Aram Drevekenin's avatar\\" title=\\"Contributors Aram Drevekenin's avatar\\"><span class=\\"maintainer-name\\">Aram Drevekenin</span></div></ul><button class=\\"showAllContributors\\" title=\\"Current list only show the author and first 5 contributors unique by name\\">Show all contributor</button></div></div></div>"`;

View File

@ -3,22 +3,13 @@
*/
import React from 'react';
import { mount, shallow } from 'enzyme';
import { shallow } from 'enzyme';
import Dependencies from '../../../../../src/webui/components/PackageSidebar/modules/Dependencies/index';
import { packageMeta } from '../store/packageMeta';
console.error = jest.fn();
describe('<PackageSidebar /> : <Dependencies />', () => {
it('should throw error for the required props', () => {
mount(<Dependencies />);
expect(console.error).toBeCalled();
});
it('getter: should get dependencies from package meta', () => {
const wrapper = mount(<Dependencies packageMeta={packageMeta} />);
const dependencies = wrapper.instance().dependencies;
const result = {
it('should load dependencies', () => {
const dependencies = {
'@verdaccio/file-locking': '0.0.3',
'@verdaccio/streams': '0.0.2',
JSONStream: '^1.1.1',
@ -50,11 +41,12 @@ describe('<PackageSidebar /> : <Dependencies />', () => {
semver: '^5.1.0',
'unix-crypt-td-js': '^1.0.0'
};
expect(dependencies).toEqual(result);
const wrapper = shallow(<Dependencies dependencies={dependencies} />);
expect(wrapper.html()).toMatchSnapshot();
});
it('should load the package and match snapshot', () => {
const wrapper = shallow(<Dependencies packageMeta={packageMeta} />);
it('should load the package without dependecnies', () => {
const wrapper = shallow(<Dependencies />);
expect(wrapper.html()).toMatchSnapshot();
});
});

View File

@ -3,27 +3,44 @@
*/
import React from 'react';
import { mount, shallow } from 'enzyme';
import { shallow } from 'enzyme';
import Infos from '../../../../../src/webui/components/PackageSidebar/modules/Infos/index';
import { packageMeta } from '../store/packageMeta';
console.error = jest.fn();
describe('<PackageSidebar /> : <Infos />', () => {
it('should load the component and check getter: info with package data', () => {
const wrapper = mount(<Infos packageMeta={packageMeta} />);
const instance = wrapper.instance();
const result = {
repo: { type: 'git', url: 'git://github.com/verdaccio/verdaccio.git' },
homepage: { url: 'https://github.com/verdaccio/verdaccio#readme' },
license: 'WTFPL'
};
expect(instance.infos).toEqual(result);
it('should load the component without props', () => {
const wrapper = shallow(<Infos/>);
expect(wrapper.html()).toMatchSnapshot();
});
it('should load the Info component and match snapshot', () => {
const wrapper = shallow(<Infos packageMeta={packageMeta} />);
it('should load the Info component with props', () => {
const props = {
homepage: 'https://www.verdaccio.org',
license: 'MIT',
repository: 'https://github.com/verdaccio/verdaccio'
}
const wrapper = shallow(<Infos {...props}/>);
expect(wrapper.html()).toMatchSnapshot();
});
it('should load the Info component with homepage only', () => {
const props = {
homepage: 'https://www.verdaccio.org'
}
const wrapper = shallow(<Infos {...props} />);
expect(wrapper.html()).toMatchSnapshot();
});
it('should load the Info component with license only', () => {
const props = {
license: 'MIT',
}
const wrapper = shallow(<Infos {...props} />);
expect(wrapper.html()).toMatchSnapshot();
});
it('should load the Info component with repository only', () => {
const props = { repository: 'https://github.com/verdaccio/verdaccio' };
const wrapper = shallow(<Infos {...props} />);
expect(wrapper.html()).toMatchSnapshot();
});
});

View File

@ -3,28 +3,25 @@
*/
import React from 'react';
import { mount, shallow } from 'enzyme';
import { shallow } from 'enzyme';
import LastSync from '../../../../../src/webui/components/PackageSidebar/modules/LastSync/index';
import { packageMeta } from '../store/packageMeta';
console.error = jest.fn();
describe('<PackageSidebar /> : <LastSync />', () => {
it('should load the component and check getters: lastUpdate, recentReleases with package data', () => {
const wrapper = mount(<LastSync packageMeta={packageMeta} />);
const instance = wrapper.instance();
const result = [
{ time: '2017/12/14, 15:43:27', version: '2.7.1' },
{ time: '2017/12/05, 23:25:06', version: '2.7.0' },
{ time: '2017/11/08, 22:47:16', version: '2.6.6' }
];
const lastUpdated = '2017/12/14, 15:43:52';
expect(instance.lastUpdate).toEqual(lastUpdated);
expect(instance.recentReleases).toEqual(result);
it('should check the default props condition', () => {
const wrapper = shallow(<LastSync/>);
expect(wrapper.html()).toMatchSnapshot();
});
it('should load the LastSync component and match snapshot', () => {
const wrapper = shallow(<LastSync packageMeta={packageMeta} />);
const props = {
lastUpdated: '2017/12/14, 15:43:52',
recentReleases: [
{ time: '2017/12/14, 15:43:27', version: '2.7.1' },
{ time: '2017/12/05, 23:25:06', version: '2.7.0' },
{ time: '2017/11/08, 22:47:16', version: '2.6.6' }
]
};
const wrapper = shallow(<LastSync {...props}/>);
expect(wrapper.html()).toMatchSnapshot();
});
});

View File

@ -7,8 +7,6 @@ import { mount } from 'enzyme';
import Maintainers from '../../../../../src/webui/components/PackageSidebar/modules/Maintainers/index';
import { packageMeta } from '../store/packageMeta';
console.error = jest.fn();
describe('<PackageSidebar /> : <Maintainers />', () => {
let wrapper;
let instance;

View File

@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<Footer /> component should load the inital state of Footer component 1`] = `"<div class=\\"wrap\\"><footer class=\\"container footer false\\"><span>Made with&nbsp;</span><span>❤</span><span>&nbsp;on</span><img class=\\"earth emoji\\" src=\\"[object Object]\\" alt=\\"Earth\\"><div class=\\"tooltip\\"><img src=\\"[object Object]\\" alt=\\"Brazil\\" title=\\"Brazil\\" class=\\"emoji\\"><img src=\\"[object Object]\\" alt=\\"China\\" title=\\"China\\" class=\\"emoji\\"><img src=\\"[object Object]\\" alt=\\"India\\" title=\\"India\\" class=\\"emoji\\"><img src=\\"[object Object]\\" alt=\\"Nicaragua\\" title=\\"Nicaragua\\" class=\\"emoji\\"><img src=\\"[object Object]\\" alt=\\"Pakistan\\" title=\\"Pakistan\\" class=\\"emoji\\"><img src=\\"[object Object]\\" alt=\\"Spain\\" title=\\"Spain\\" class=\\"emoji\\"></div><div class=\\"right\\">Powered by&nbsp;<a href=\\"http://www.verdaccio.org/\\"><img class=\\"logo\\" src=\\"[object Object]\\" alt=\\"Verdaccio\\" title=\\"Verdaccio\\"></a>&nbsp;/&nbsp;1.0.0</div></footer></div>"`;

View File

@ -1,3 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<Package /> component should load the component 1`] = `"<section class=\\"package\\"><a href=\\"detail/verdaccio\\"><div class=\\"header\\"><div class=\\"title\\"><h1>verdaccio <span class=\\"el-tag el-tag--gray\\">v1.0.0</span></h1></div><div role=\\"author\\" class=\\"author\\">By: Sam</div></div><div class=\\"footer\\"><p class=\\"description\\">Private NPM repository</p></div><div class=\\"details\\"><div class=\\"homepage\\">Published about 1 month ago</div><div class=\\"license\\">MIT</div></div></a></section>"`;
exports[`<Package /> component should load the component without author 1`] = `"<section class=\\"package\\"><a href=\\"detail/verdaccio\\"><div class=\\"header\\"><div class=\\"title\\"><h1>verdaccio <span class=\\"el-tag el-tag--gray\\">v1.0.0</span></h1></div><div role=\\"author\\" class=\\"author\\"></div></div><div class=\\"footer\\"><p class=\\"description\\">Private NPM repository</p></div><div class=\\"details\\"><div class=\\"homepage\\">Published about 1 month ago</div><div class=\\"license\\">MIT</div></div></a></section>"`;

View File

@ -1,3 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<PackageList /> component should load the component with packages 1`] = `"<div class=\\"package-list-items\\"><div class=\\"pkgContainer\\"><h1 class=\\"listTitle\\">Available Packages</h1><li><section class=\\"package\\"><a href=\\"detail/verdaccio\\"><div class=\\"header\\"><div class=\\"title\\"><h1>verdaccio <span class=\\"el-tag el-tag--gray\\">v1.0.0</span></h1></div><div role=\\"author\\" class=\\"author\\">By: Sam</div></div><div class=\\"footer\\"><p class=\\"description\\">Private NPM repository</p></div><div class=\\"details\\"><div class=\\"homepage\\">Published less than a minute ago</div></div></a></section></li><li><section class=\\"package\\"><a href=\\"detail/abc\\"><div class=\\"header\\"><div class=\\"title\\"><h1>abc <span class=\\"el-tag el-tag--gray\\">v1.0.1</span></h1></div><div role=\\"author\\" class=\\"author\\">By: Rose</div></div><div class=\\"footer\\"><p class=\\"description\\">abc description</p></div><div class=\\"details\\"><div class=\\"homepage\\">Published less than a minute ago</div></div></a></section></li><li><section class=\\"package\\"><a href=\\"detail/xyz\\"><div class=\\"header\\"><div class=\\"title\\"><h1>xyz <span class=\\"el-tag el-tag--gray\\">v1.1.0</span></h1></div><div role=\\"author\\" class=\\"author\\">By: Martin</div></div><div class=\\"footer\\"><p class=\\"description\\">xyz description</p></div><div class=\\"details\\"><div class=\\"homepage\\"></div></div></a></section></li></div></div>"`;
exports[`<PackageList /> component should load the component with packages 1`] = `"<div class=\\"package-list-items\\"><div class=\\"pkgContainer\\"><h1 class=\\"listTitle\\">Available Packages</h1><li><section class=\\"package\\"><a href=\\"detail/verdaccio\\"><div class=\\"header\\"><div class=\\"title\\"><h1>verdaccio <span class=\\"el-tag el-tag--gray\\">v1.0.0</span></h1></div><div role=\\"author\\" class=\\"author\\">By: Sam</div></div><div class=\\"footer\\"><p class=\\"description\\">Private NPM repository</p></div><div class=\\"details\\"><div class=\\"homepage\\">Published less than a minute ago</div><div class=\\"license\\"></div></div></a></section></li><li><section class=\\"package\\"><a href=\\"detail/abc\\"><div class=\\"header\\"><div class=\\"title\\"><h1>abc <span class=\\"el-tag el-tag--gray\\">v1.0.1</span></h1></div><div role=\\"author\\" class=\\"author\\">By: Rose</div></div><div class=\\"footer\\"><p class=\\"description\\">abc description</p></div><div class=\\"details\\"><div class=\\"homepage\\">Published less than a minute ago</div><div class=\\"license\\"></div></div></a></section></li><li><section class=\\"package\\"><a href=\\"detail/xyz\\"><div class=\\"header\\"><div class=\\"title\\"><h1>xyz <span class=\\"el-tag el-tag--gray\\">v1.1.0</span></h1></div><div role=\\"author\\" class=\\"author\\">By: Martin</div></div><div class=\\"footer\\"><p class=\\"description\\">xyz description</p></div><div class=\\"details\\"><div class=\\"homepage\\"></div><div class=\\"license\\"></div></div></a></section></li></div></div>"`;

View File

@ -0,0 +1,22 @@
import React from 'react';
import { mount } from 'enzyme';
import Footer from '../../../../src/webui/components/Footer/index';
describe('<Footer /> component', () => {
let wrapper;
beforeEach(() => {
wrapper = mount(<Footer />);
});
it('should load the inital state of Footer component', () => {
expect(wrapper.html()).toMatchSnapshot();
});
it('should hover the earth in footer', () => {
const earth = wrapper.find('img[alt="Earth"]');
earth.simulate('click');
expect(wrapper.state('showAuthorsGeographic')).toEqual(true);
});
});

View File

@ -25,19 +25,14 @@ describe('<Package /> component', () => {
time: dateOneMonthAgo(),
license: 'MIT',
description: 'Private NPM repository',
author: { name: 'Sam' }
author: 'Sam'
};
const wrapper = mount(
<BrowserRouter>
<Package package={props} />
<Package {...props}/>
</BrowserRouter>
);
// renderAuthor method
const renderAuthor = wrapper.find(Package).instance().renderAuthor;
expect(renderAuthor({ author: {} })).toBeUndefined();
expect(renderAuthor({ author: { name: 'sam' } })).toBeDefined();
// integration expectations
expect(wrapper.find('a').prop('href')).toEqual('detail/verdaccio');
expect(wrapper.find('h1').text()).toEqual('verdaccio v1.0.0');
@ -50,4 +45,27 @@ describe('<Package /> component', () => {
expect(wrapper.find('.license').text()).toMatch(/MIT/);
expect(wrapper.html()).toMatchSnapshot();
});
it('should load the component without author', () => {
const props = {
name: 'verdaccio',
version: '1.0.0',
time: dateOneMonthAgo(),
license: 'MIT',
description: 'Private NPM repository'
};
const wrapper = mount(
<BrowserRouter>
<Package {...props} />
</BrowserRouter>
);
// integration expectations
expect(
wrapper.find('div').filterWhere(n => n.prop('role') === 'author')
.text()
).toEqual('');
expect(wrapper.html()).toMatchSnapshot();
});
});

View File

@ -18,7 +18,7 @@ describe('<PackageDetail /> component', () => {
it('should load the component', () => {
const props = {
readMe: 'Test readme',
package: WEB_TITLE
packageName: WEB_TITLE
};
const wrapper = shallow(<PackageDetail {...props} />);

View File

@ -53,7 +53,11 @@ export const packageMeta = {
'2.7.0': '2017-12-05T23:25:06.372Z',
'2.7.1': '2017-12-14T15:43:27.317Z'
},
_uplinks: { npmjs: { etag: '"5a272ad2-4f6b1"', fetched: 1513266232741 } },
_uplinks: {
abc: { etag: 'ddfdxjn8m8n6gn70-8m', fetched: 1532297472000},
npmjs: { etag: '"5a272ad2-4f6b1"', fetched: 1513266232741 },
xyz: { etag: '564748hydydygs-s7ehj', fetched: 1532124672000}
},
_rev: '16-ba1b806df0298246',
_attachments: {},
latest: {

View File

@ -0,0 +1,110 @@
import {
formatLicense,
formatRepository,
formatAuthor,
formatDate,
formatDateDistance,
getLastUpdatedPackageTime,
getRecentReleases
} from '../../../../src/webui/utils/package';
import { packageMeta } from '../components/store/packageMeta';
describe('formatLicense', () => {
it('should check license field different values', () => {
expect(formatLicense('MIT')).toEqual('MIT');
});
it('should check license field for object value', () => {
const license = { type: 'ISC', url: 'https://opensource.org/licenses/ISC' };
expect(formatLicense(license)).toEqual('ISC');
});
it('should check license field for other value', () => {
expect(formatLicense(null)).toBeNull();
expect(formatLicense({})).toBeNull();
expect(formatLicense([])).toBeNull();
});
});
describe('formatRepository', () => {
it('should check repository field different values', () => {
const repository = 'https://github.com/verdaccio/verdaccio';
expect(formatRepository(repository)).toEqual(repository);
});
it('should check repository field for object value', () => {
const license = {
type: 'git',
url: 'https://github.com/verdaccio/verdaccio'
};
expect(formatRepository(license)).toEqual(license.url);
});
it('should check repository field for other value', () => {
expect(formatRepository(null)).toBeNull();
expect(formatRepository({})).toBeNull();
expect(formatRepository([])).toBeNull();
});
});
describe('formatAuthor', () => {
it('should check author field different values', () => {
const author = 'verdaccioNpm';
expect(formatAuthor(author)).toEqual(author);
});
it('should check author field for object value', () => {
const license = {
name: 'Verdaccion NPM',
email: 'verdaccio@verdaccio.org',
url: 'https://verdaccio.org'
};
expect(formatAuthor(license)).toEqual('Verdaccion NPM');
});
it('should check author field for other value', () => {
expect(formatAuthor(null)).toBeNull();
expect(formatAuthor({})).toBeNull();
expect(formatAuthor([])).toBeNull();
});
});
describe('formatDate', () => {
it('should format the date', () => {
const date = 1532211072138;
expect(formatDate(date)).toEqual('2018/07/21, 22:11:12');
});
});
describe('formatDateDistance', () => {
it('should calculate the distance', () => {
const dateOneMonthAgo = () => {
const date = new Date();
date.setMonth(date.getMonth() - 1);
return date;
};
const date = dateOneMonthAgo();
expect(formatDateDistance(date)).toEqual('about 1 month');
});
});
describe('getLastUpdatedPackageTime', () => {
it('should get the last update time', () => {
const lastUpdated = packageMeta._uplinks;
expect(getLastUpdatedPackageTime(lastUpdated)).toEqual(
'2018/07/22, 22:11:12'
);
});
it('should get the last update time for blank uplink', () => {
const lastUpdated = {};
expect(getLastUpdatedPackageTime(lastUpdated)).toEqual('');
});
});
describe('getRecentReleases', () => {
it('should get the recent releases', () => {
const { time } = packageMeta;
const result = [
{ time: '2017/12/14, 15:43:27', version: '2.7.1' },
{ time: '2017/12/05, 23:25:06', version: '2.7.0' },
{ time: '2017/11/08, 22:47:16', version: '2.6.6' }
];
expect(getRecentReleases(time)).toEqual(result);
expect(getRecentReleases()).toEqual([]);
});
});

View File

@ -30,6 +30,10 @@ new WebpackDevServer(compiler, {
chunks: true,
chunkModules: false,
},
proxy: [{
context: ['/-/verdaccio/logo', '/-/verdaccio/packages', '/-/static/logo.png'],
target: 'http://localhost:4873',
}],
}).listen(4872, 'localhost', function(err) {
if (err) {
return console.log(err);