mirror of
https://github.com/verdaccio/verdaccio.git
synced 2024-11-08 23:25:51 +01:00
Merge branch 'feat-new-detail-page' of github.com:verdaccio/verdaccio into feat-new-detail-page
This commit is contained in:
commit
495ec89da4
67
.babelrc
67
.babelrc
@ -1,68 +1,3 @@
|
|||||||
{
|
{
|
||||||
"env": {
|
"presets": [["@verdaccio", {"flow": true}]]
|
||||||
"ui": {
|
|
||||||
"presets": [
|
|
||||||
"@babel/react",
|
|
||||||
"@babel/flow",
|
|
||||||
["@babel/env",{
|
|
||||||
"targets": {
|
|
||||||
"browsers": [
|
|
||||||
"last 5 versions",
|
|
||||||
"FireFox >= 44",
|
|
||||||
"Safari >= 7",
|
|
||||||
"Explorer 11",
|
|
||||||
"last 4 Edge versions"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
],
|
|
||||||
"plugins": [
|
|
||||||
"react-hot-loader/babel",
|
|
||||||
"@babel/transform-runtime",
|
|
||||||
"@babel/proposal-class-properties",
|
|
||||||
"@babel/plugin-proposal-object-rest-spread",
|
|
||||||
"@babel/syntax-dynamic-import",
|
|
||||||
"emotion"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"test": {
|
|
||||||
"presets": [["@babel/env", {
|
|
||||||
"targets": {
|
|
||||||
"node": "6.10"
|
|
||||||
}
|
|
||||||
}], "@babel/flow",
|
|
||||||
"@babel/react"],
|
|
||||||
"plugins": [
|
|
||||||
"@babel/plugin-proposal-class-properties",
|
|
||||||
"@babel/plugin-proposal-object-rest-spread",
|
|
||||||
"babel-plugin-dynamic-import-node",
|
|
||||||
"emotion"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"registry": {
|
|
||||||
"presets": [
|
|
||||||
["@babel/env", {
|
|
||||||
"targets": {
|
|
||||||
"node": "6.10"
|
|
||||||
}
|
|
||||||
}], "@babel/flow"],
|
|
||||||
"plugins": [
|
|
||||||
"@babel/plugin-proposal-object-rest-spread",
|
|
||||||
"@babel/proposal-class-properties"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"registry-docker": {
|
|
||||||
"presets": [
|
|
||||||
["@babel/env", {
|
|
||||||
"targets": {
|
|
||||||
"node": "10"
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
"@babel/flow"],
|
|
||||||
"plugins": [
|
|
||||||
"@babel/plugin-proposal-object-rest-spread",
|
|
||||||
"@babel/proposal-class-properties"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -14,3 +14,4 @@ Dockerfile
|
|||||||
*.scss
|
*.scss
|
||||||
*.png
|
*.png
|
||||||
*.jpg
|
*.jpg
|
||||||
|
test/unit/partials/
|
||||||
|
38
CHANGELOG.md
38
CHANGELOG.md
@ -66,6 +66,42 @@ All notable changes to this project will be documented in this file. See [standa
|
|||||||
* replaced lunr by lunr-mutable ([#915](https://github.com/verdaccio/verdaccio/issues/915)) ([1602840](https://github.com/verdaccio/verdaccio/commit/1602840))
|
* replaced lunr by lunr-mutable ([#915](https://github.com/verdaccio/verdaccio/issues/915)) ([1602840](https://github.com/verdaccio/verdaccio/commit/1602840))
|
||||||
* verdaccio update notification on CLI ([#988](https://github.com/verdaccio/verdaccio/issues/988)) ([#998](https://github.com/verdaccio/verdaccio/issues/998)) ([bc04703](https://github.com/verdaccio/verdaccio/commit/bc04703))
|
* verdaccio update notification on CLI ([#988](https://github.com/verdaccio/verdaccio/issues/988)) ([#998](https://github.com/verdaccio/verdaccio/issues/998)) ([bc04703](https://github.com/verdaccio/verdaccio/commit/bc04703))
|
||||||
|
|
||||||
|
<a name="3.11.1"></a>
|
||||||
|
## [3.11.1](https://github.com/verdaccio/verdaccio/compare/v3.11.0...v3.11.1) (2019-01-31)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* don’t make change if `time` fields match ([#1167](https://github.com/verdaccio/verdaccio/issues/1167)) ([e62ef8d](https://github.com/verdaccio/verdaccio/commit/e62ef8d))
|
||||||
|
* don’t packages that have no uplinks after reading ([#1204](https://github.com/verdaccio/verdaccio/issues/1204)) ([95686be](https://github.com/verdaccio/verdaccio/commit/95686be))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="3.11.0"></a>
|
||||||
|
# [3.11.0](https://github.com/verdaccio/verdaccio/compare/v3.10.2...v3.11.0) (2019-01-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* introduce server keepAliveTimeout into config files ([a359055](https://github.com/verdaccio/verdaccio/commit/a359055))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="3.10.2"></a>
|
||||||
|
## [3.10.2](https://github.com/verdaccio/verdaccio/compare/v3.10.1...v3.10.2) (2019-01-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add logic to catch clause ([#1183](https://github.com/verdaccio/verdaccio/issues/1183)) ([056d396](https://github.com/verdaccio/verdaccio/commit/056d396))
|
||||||
|
* adds _id to normalise metadata ([#1194](https://github.com/verdaccio/verdaccio/issues/1194)) ([e2fa581](https://github.com/verdaccio/verdaccio/commit/e2fa581))
|
||||||
|
* remove some unneeded checks ([#1182](https://github.com/verdaccio/verdaccio/issues/1182)) ([ab56d75](https://github.com/verdaccio/verdaccio/commit/ab56d75))
|
||||||
|
* remove unused object ([#1185](https://github.com/verdaccio/verdaccio/issues/1185)) ([e9b3907](https://github.com/verdaccio/verdaccio/commit/e9b3907))
|
||||||
|
* remove unused parameters from processBody method invocation ([#1184](https://github.com/verdaccio/verdaccio/issues/1184)) ([064f7cf](https://github.com/verdaccio/verdaccio/commit/064f7cf))
|
||||||
|
* remove use of comma separator ([#1186](https://github.com/verdaccio/verdaccio/issues/1186)) ([f20fefa](https://github.com/verdaccio/verdaccio/commit/f20fefa))
|
||||||
|
* remove useless assignment to local variable emailCopy ([#1181](https://github.com/verdaccio/verdaccio/issues/1181)) ([13b8347](https://github.com/verdaccio/verdaccio/commit/13b8347))
|
||||||
|
|
||||||
|
|
||||||
<a name="3.10.1"></a>
|
<a name="3.10.1"></a>
|
||||||
## [3.10.1](https://github.com/verdaccio/verdaccio/compare/v3.10.0...v3.10.1) (2018-12-20)
|
## [3.10.1](https://github.com/verdaccio/verdaccio/compare/v3.10.0...v3.10.1) (2018-12-20)
|
||||||
|
|
||||||
@ -1165,4 +1201,4 @@ in [#108](https://github.com/verdaccio/verdaccio/pull/108)
|
|||||||
## 22 May 2013, version 0.0.0
|
## 22 May 2013, version 0.0.0
|
||||||
|
|
||||||
- first commits
|
- first commits
|
||||||
|
|
||||||
|
@ -61,6 +61,12 @@ packages:
|
|||||||
# if package is not available locally, proxy requests to 'npmjs' registry
|
# if package is not available locally, proxy requests to 'npmjs' registry
|
||||||
proxy: npmjs
|
proxy: npmjs
|
||||||
|
|
||||||
|
# You can specify HTTP/1.1 server keep alive timeout in seconds for incomming connections.
|
||||||
|
# A value of 0 makes the http server behave similarly to Node.js versions prior to 8.0.0, which did not have a keep-alive timeout.
|
||||||
|
# WORKAROUND: Through given configuration you can workaround following issue https://github.com/verdaccio/verdaccio/issues/301. Set to 0 in case 60 is not enought.
|
||||||
|
server:
|
||||||
|
keepAliveTimeout: 60
|
||||||
|
|
||||||
# To use `npm audit` uncomment the following section
|
# To use `npm audit` uncomment the following section
|
||||||
middlewares:
|
middlewares:
|
||||||
audit:
|
audit:
|
||||||
|
66
package.json
66
package.json
@ -16,77 +16,49 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@verdaccio/file-locking": "0.0.7",
|
"@verdaccio/file-locking": "0.0.7",
|
||||||
"@verdaccio/local-storage": "1.2.0",
|
"@verdaccio/local-storage": "2.0.0-beta.1",
|
||||||
"@verdaccio/streams": "1.0.0",
|
"@verdaccio/streams": "2.0.0-beta.0",
|
||||||
"JSONStream": "1.3.4",
|
"JSONStream": "1.3.5",
|
||||||
"async": "2.6.1",
|
"async": "2.6.1",
|
||||||
"body-parser": "1.18.3",
|
"body-parser": "1.18.3",
|
||||||
"bunyan": "1.8.12",
|
"bunyan": "1.8.12",
|
||||||
"chalk": "2.4.1",
|
"chalk": "2.4.2",
|
||||||
"commander": "2.18.0",
|
"commander": "2.19.0",
|
||||||
"compression": "1.7.3",
|
"compression": "1.7.3",
|
||||||
"cookies": "0.7.2",
|
"cookies": "0.7.3",
|
||||||
"cors": "2.8.4",
|
"cors": "2.8.5",
|
||||||
"date-fns": "1.29.0",
|
"date-fns": "1.30.1",
|
||||||
"express": "4.16.3",
|
"express": "4.16.4",
|
||||||
"global": "4.3.2",
|
"global": "4.3.2",
|
||||||
"handlebars": "4.0.12",
|
"handlebars": "4.0.12",
|
||||||
"http-errors": "1.7.1",
|
"http-errors": "1.7.1",
|
||||||
"js-base64": "2.4.9",
|
"js-base64": "2.5.1",
|
||||||
"js-string-escape": "1.0.1",
|
"js-string-escape": "1.0.1",
|
||||||
"js-yaml": "3.12.0",
|
"js-yaml": "3.12.1",
|
||||||
"jsonwebtoken": "8.3.0",
|
"jsonwebtoken": "8.4.0",
|
||||||
"lockfile": "1.0.4",
|
"lockfile": "1.0.4",
|
||||||
"lodash": "4.17.11",
|
"lodash": "4.17.11",
|
||||||
"lunr-mutable-indexes": "2.3.1",
|
"lunr-mutable-indexes": "2.3.2",
|
||||||
"marked": "0.5.1",
|
"marked": "0.6.0",
|
||||||
"mime": "2.3.1",
|
"mime": "2.4.0",
|
||||||
"minimatch": "3.0.4",
|
"minimatch": "3.0.4",
|
||||||
"mkdirp": "0.5.1",
|
"mkdirp": "0.5.1",
|
||||||
"mv": "2.1.1",
|
"mv": "2.1.1",
|
||||||
"pkginfo": "0.4.1",
|
"pkginfo": "0.4.1",
|
||||||
"request": "2.88.0",
|
"request": "2.88.0",
|
||||||
"semver": "5.5.1",
|
"semver": "5.6.0",
|
||||||
"verdaccio-audit": "1.1.0",
|
"verdaccio-audit": "1.1.0",
|
||||||
"verdaccio-htpasswd": "1.0.1",
|
"verdaccio-htpasswd": "2.0.0-beta.0",
|
||||||
"verror": "1.10.0"
|
"verror": "1.10.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "7.2.3",
|
|
||||||
"@babel/core": "7.2.2",
|
|
||||||
"@babel/node": "7.2.2",
|
|
||||||
"@babel/plugin-proposal-class-properties": "7.2.3",
|
|
||||||
"@babel/plugin-proposal-decorators": "7.2.3",
|
|
||||||
"@babel/plugin-proposal-export-namespace-from": "7.2.0",
|
|
||||||
"@babel/plugin-proposal-function-sent": "7.2.0",
|
|
||||||
"@babel/plugin-proposal-json-strings": "7.2.0",
|
|
||||||
"@babel/plugin-proposal-numeric-separator": "7.2.0",
|
|
||||||
"@babel/plugin-proposal-object-rest-spread": "7.2.0",
|
|
||||||
"@babel/plugin-proposal-throw-expressions": "7.2.0",
|
|
||||||
"@babel/plugin-syntax-dynamic-import": "7.2.0",
|
|
||||||
"@babel/plugin-syntax-import-meta": "7.2.0",
|
|
||||||
"@babel/plugin-transform-async-to-generator": "7.2.0",
|
|
||||||
"@babel/plugin-transform-classes": "7.2.2",
|
|
||||||
"@babel/plugin-transform-runtime": "7.2.0",
|
|
||||||
"@babel/polyfill": "7.2.3",
|
|
||||||
"@babel/preset-env": "7.2.3",
|
|
||||||
"@babel/preset-flow": "7.0.0",
|
|
||||||
"@babel/preset-react": "7.0.0",
|
|
||||||
"@babel/register": "7.0.0",
|
|
||||||
"@babel/runtime": "^7.2.0",
|
|
||||||
"@commitlint/cli": "7.2.1",
|
"@commitlint/cli": "7.2.1",
|
||||||
"@commitlint/config-conventional": "7.1.2",
|
"@commitlint/config-conventional": "7.1.2",
|
||||||
"@material-ui/core": "3.9.0",
|
"@material-ui/core": "3.9.0",
|
||||||
"@material-ui/icons": "3.0.2",
|
"@material-ui/icons": "3.0.2",
|
||||||
|
"@verdaccio/babel-preset": "0.0.4",
|
||||||
"@verdaccio/types": "4.1.4",
|
"@verdaccio/types": "4.1.4",
|
||||||
"autosuggest-highlight": "3.1.1",
|
"autosuggest-highlight": "3.1.1",
|
||||||
"babel-core": "7.0.0-bridge.0",
|
|
||||||
"babel-eslint": "10.0.1",
|
|
||||||
"babel-jest": "23.6.0",
|
|
||||||
"babel-loader": "8.0.4",
|
|
||||||
"babel-plugin-dynamic-import-node": "2.2.0",
|
|
||||||
"babel-plugin-emotion": "9.2.10",
|
|
||||||
"babel-plugin-flow-runtime": "0.17.0",
|
|
||||||
"bundlesize": "0.17.0",
|
"bundlesize": "0.17.0",
|
||||||
"codecov": "3.1.0",
|
"codecov": "3.1.0",
|
||||||
"cross-env": "5.2.0",
|
"cross-env": "5.2.0",
|
||||||
@ -154,7 +126,7 @@
|
|||||||
"typeface-roboto": "0.0.54",
|
"typeface-roboto": "0.0.54",
|
||||||
"url-loader": "1.1.1",
|
"url-loader": "1.1.1",
|
||||||
"verdaccio-auth-memory": "0.0.4",
|
"verdaccio-auth-memory": "0.0.4",
|
||||||
"verdaccio-memory": "1.0.3",
|
"verdaccio-memory": "2.0.0-beta.0",
|
||||||
"webpack": "4.20.2",
|
"webpack": "4.20.2",
|
||||||
"webpack-bundle-analyzer": "3.0.2",
|
"webpack-bundle-analyzer": "3.0.2",
|
||||||
"webpack-cli": "3.1.1",
|
"webpack-cli": "3.1.1",
|
||||||
|
@ -12,6 +12,7 @@ import express from 'express';
|
|||||||
import { combineBaseUrl, getWebProtocol } from '../../lib/utils';
|
import { combineBaseUrl, getWebProtocol } from '../../lib/utils';
|
||||||
import Search from '../../lib/search';
|
import Search from '../../lib/search';
|
||||||
import { HEADERS, HTTP_STATUS, WEB_TITLE } from '../../lib/constants';
|
import { HEADERS, HTTP_STATUS, WEB_TITLE } from '../../lib/constants';
|
||||||
|
import { spliceURL } from '../../utils/string';
|
||||||
|
|
||||||
const { securityIframe } = require('../middleware');
|
const { securityIframe } = require('../middleware');
|
||||||
/* eslint new-cap:off */
|
/* eslint new-cap:off */
|
||||||
@ -52,9 +53,8 @@ module.exports = function(config, auth, storage) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/', function(req, res) {
|
function renderHTML(req, res) {
|
||||||
const installPath = _.get(config, 'url_prefix', '');
|
const base = combineBaseUrl(getWebProtocol(req.get(HEADERS.FORWARDED_PROTO), req.protocol), req.get('host'), config.url_prefix);
|
||||||
const base = combineBaseUrl(getWebProtocol(req.get(HEADERS.FORWARDED_PROTO), req.protocol), req.get('host'), installPath);
|
|
||||||
const webPage = template
|
const webPage = template
|
||||||
.replace(/ToReplaceByVerdaccio/g, base)
|
.replace(/ToReplaceByVerdaccio/g, base)
|
||||||
.replace(/ToReplaceByTitle/g, _.get(config, 'web.title') ? config.web.title : WEB_TITLE)
|
.replace(/ToReplaceByTitle/g, _.get(config, 'web.title') ? config.web.title : WEB_TITLE)
|
||||||
@ -64,6 +64,20 @@ module.exports = function(config, auth, storage) {
|
|||||||
res.setHeader('Content-Type', 'text/html');
|
res.setHeader('Content-Type', 'text/html');
|
||||||
|
|
||||||
res.send(webPage);
|
res.send(webPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
router.get('/-/web/:pkg', function(req, res) {
|
||||||
|
renderHTML(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/-/verdaccio/logo', function(req, res) {
|
||||||
|
const installPath = _.get(config, 'url_prefix', '');
|
||||||
|
|
||||||
|
res.send(_.get(config, 'web.logo') || spliceURL(installPath, '/-/static/logo.png'));
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/', function(req, res) {
|
||||||
|
renderHTML(req, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
return router;
|
return router;
|
||||||
|
5
src/lib/bootstrap.js
vendored
5
src/lib/bootstrap.js
vendored
@ -48,7 +48,10 @@ function startVerdaccio(config: any, cliListen: string, configPath: string, pkgV
|
|||||||
// http
|
// http
|
||||||
webServer = http.createServer(app);
|
webServer = http.createServer(app);
|
||||||
}
|
}
|
||||||
|
if (config.server && config.server.keepAliveTimeout) {
|
||||||
|
// $FlowFixMe library definition for node is not up to date (doesn't contain recent 8.0 changes)
|
||||||
|
webServer.keepAliveTimeout = config.server.keepAliveTimeout;
|
||||||
|
}
|
||||||
unlinkAddressPath(addr);
|
unlinkAddressPath(addr);
|
||||||
|
|
||||||
callback(webServer, addr, pkgName, pkgVersion);
|
callback(webServer, addr, pkgName, pkgVersion);
|
||||||
|
@ -102,8 +102,10 @@ export const API_ERROR = {
|
|||||||
CONFIG_BAD_FORMAT: 'config file must be an object',
|
CONFIG_BAD_FORMAT: 'config file must be an object',
|
||||||
BAD_USERNAME_PASSWORD: 'bad username/password, access denied',
|
BAD_USERNAME_PASSWORD: 'bad username/password, access denied',
|
||||||
NO_PACKAGE: 'no such package available',
|
NO_PACKAGE: 'no such package available',
|
||||||
|
PACKAGE_CANNOT_BE_ADDED: 'this package cannot be added',
|
||||||
BAD_DATA: 'bad data',
|
BAD_DATA: 'bad data',
|
||||||
NOT_ALLOWED: 'not allowed to access package',
|
NOT_ALLOWED: 'not allowed to access package',
|
||||||
|
NOT_ALLOWED_PUBLISH: 'not allowed to publish package',
|
||||||
INTERNAL_SERVER_ERROR: 'internal server error',
|
INTERNAL_SERVER_ERROR: 'internal server error',
|
||||||
UNKNOWN_ERROR: 'unknown error',
|
UNKNOWN_ERROR: 'unknown error',
|
||||||
NOT_PACKAGE_UPLINK: 'package does not exist on uplink',
|
NOT_PACKAGE_UPLINK: 'package does not exist on uplink',
|
||||||
|
@ -169,7 +169,7 @@ class LocalStorage implements IStorage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('time' in packageInfo) {
|
if ('time' in packageInfo && !_.isEqual(packageLocalJson.time, packageInfo.time)) {
|
||||||
packageLocalJson.time = packageInfo.time;
|
packageLocalJson.time = packageInfo.time;
|
||||||
change = true;
|
change = true;
|
||||||
}
|
}
|
||||||
@ -631,29 +631,6 @@ class LocalStorage implements IStorage {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_getCustomPackageLocalStorages() {
|
|
||||||
const storages = {};
|
|
||||||
|
|
||||||
// add custom storage if exist
|
|
||||||
if (this.config.storage) {
|
|
||||||
storages[this.config.storage] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { packages } = this.config;
|
|
||||||
|
|
||||||
if (packages) {
|
|
||||||
const listPackagesConf = Object.keys(packages);
|
|
||||||
|
|
||||||
listPackagesConf.map(pkg => {
|
|
||||||
if (packages[pkg].storage) {
|
|
||||||
storages[packages[pkg].storage] = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return storages;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Walks through each package and calls `on_package` on them.
|
* Walks through each package and calls `on_package` on them.
|
||||||
* @param {*} onPackage
|
* @param {*} onPackage
|
||||||
|
@ -45,6 +45,10 @@ export function normalizePackage(pkg: Package) {
|
|||||||
pkg._rev = STORAGE.DEFAULT_REVISION;
|
pkg._rev = STORAGE.DEFAULT_REVISION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_.isString(pkg._id) === false) {
|
||||||
|
pkg._id = pkg.name;
|
||||||
|
}
|
||||||
|
|
||||||
// normalize dist-tags
|
// normalize dist-tags
|
||||||
normalizeDistTags(pkg);
|
normalizeDistTags(pkg);
|
||||||
|
|
||||||
@ -93,7 +97,7 @@ export function normalizeContributors(contributors: Array<Author>): Array<Author
|
|||||||
return contributors;
|
return contributors;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WHITELIST = ['_rev', 'name', 'versions', 'dist-tags', 'readme', 'time'];
|
export const WHITELIST = ['_rev', 'name', 'versions', 'dist-tags', 'readme', 'time', '_id'];
|
||||||
|
|
||||||
export function cleanUpLinksRef(keepUpLinkData: boolean, result: Package): Package {
|
export function cleanUpLinksRef(keepUpLinkData: boolean, result: Package): Package {
|
||||||
const propertyToKeep = [...WHITELIST];
|
const propertyToKeep = [...WHITELIST];
|
||||||
|
@ -497,6 +497,10 @@ class Storage implements IStorageHandler {
|
|||||||
return callback(ErrorCode.getNotFound(API_ERROR.NO_PACKAGE), null, upLinksErrors);
|
return callback(ErrorCode.getNotFound(API_ERROR.NO_PACKAGE), null, upLinksErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (upLinks.length === 0) {
|
||||||
|
return callback(null, packageInfo);
|
||||||
|
}
|
||||||
|
|
||||||
self.localStorage.updateVersions(name, packageInfo, function(err, packageJsonLocal: Package) {
|
self.localStorage.updateVersions(name, packageInfo, function(err, packageJsonLocal: Package) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
@ -4,16 +4,16 @@ import isNil from 'lodash/isNil';
|
|||||||
import storage from './utils/storage';
|
import storage from './utils/storage';
|
||||||
import { makeLogin, isTokenExpire } from './utils/login';
|
import { makeLogin, isTokenExpire } from './utils/login';
|
||||||
|
|
||||||
import Footer from './components/Footer';
|
|
||||||
import Loading from './components/Loading';
|
import Loading from './components/Loading';
|
||||||
import LoginModal from './components/Login';
|
import LoginModal from './components/Login';
|
||||||
import Header from './components/Header';
|
import Header from './components/Header';
|
||||||
import { Container, Content } from './components/Layout';
|
import { Container, Content } from './components/Layout';
|
||||||
import Route from './router';
|
import RouterApp from './router';
|
||||||
import API from './utils/api';
|
import API from './utils/api';
|
||||||
import './styles/typeface-roboto.scss';
|
import './styles/typeface-roboto.scss';
|
||||||
import './styles/main.scss';
|
import './styles/main.scss';
|
||||||
import 'normalize.css';
|
import 'normalize.css';
|
||||||
|
import Footer from './components/Footer';
|
||||||
|
|
||||||
export const AppContext = React.createContext();
|
export const AppContext = React.createContext();
|
||||||
|
|
||||||
@ -67,7 +67,8 @@ export default class App extends Component {
|
|||||||
isLoading: false,
|
isLoading: false,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.handleShowAlertDialog({
|
// FIXME: add dialog
|
||||||
|
console.error({
|
||||||
title: 'Warning',
|
title: 'Warning',
|
||||||
message: `Unable to load package list: ${error.message}`,
|
message: `Unable to load package list: ${error.message}`,
|
||||||
});
|
});
|
||||||
@ -140,15 +141,14 @@ export default class App extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { isLoading, isUserLoggedIn, packages } = this.state;
|
const { isLoading, isUserLoggedIn, packages, logoUrl, user, scope } = this.state;
|
||||||
return (
|
return (
|
||||||
<Container isLoading={isLoading}>
|
<Container isLoading={isLoading}>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<Loading />
|
<Loading />
|
||||||
) : (
|
) : (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<AppContextProvider value={{isUserLoggedIn, packages}}>
|
<AppContextProvider value={{isUserLoggedIn, packages, logoUrl, user, scope}}>
|
||||||
{this.renderHeader()}
|
|
||||||
{this.renderContent()}
|
{this.renderContent()}
|
||||||
</AppContextProvider>
|
</AppContextProvider>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
@ -175,7 +175,11 @@ export default class App extends Component {
|
|||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Content>
|
<Content>
|
||||||
<Route></Route>
|
<RouterApp
|
||||||
|
onLogout={this.handleLogout}
|
||||||
|
onToggleLoginModal={this.handleToggleLoginModal}>
|
||||||
|
{this.renderHeader()}
|
||||||
|
</RouterApp>
|
||||||
</Content>
|
</Content>
|
||||||
<Footer />
|
<Footer />
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
@ -34,7 +34,7 @@ class DepDetail extends Component<any, any> {
|
|||||||
const { onLoading, history } = this.props;
|
const { onLoading, history } = this.props;
|
||||||
|
|
||||||
onLoading();
|
onLoading();
|
||||||
history.push(`/version/${name}`);
|
history.push(`/-/web/version/${name}`);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import type { Node } from 'react';
|
import type { Node } from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import Button from '@material-ui/core/Button/index';
|
import Button from '@material-ui/core/Button/index';
|
||||||
import IconButton from '@material-ui/core/IconButton/index';
|
import IconButton from '@material-ui/core/IconButton/index';
|
||||||
@ -17,7 +18,7 @@ import AccountCircle from '@material-ui/icons/AccountCircle';
|
|||||||
import { default as IconSearch } from '@material-ui/icons/Search';
|
import { default as IconSearch } from '@material-ui/icons/Search';
|
||||||
|
|
||||||
import { getRegistryURL } from '../../utils/url';
|
import { getRegistryURL } from '../../utils/url';
|
||||||
import Link from '../Link';
|
import ExternalLink from '../Link';
|
||||||
import Logo from '../Logo';
|
import Logo from '../Logo';
|
||||||
import RegistryInfoDialog from '../RegistryInfoDialog';
|
import RegistryInfoDialog from '../RegistryInfoDialog';
|
||||||
import Label from '../Label';
|
import Label from '../Label';
|
||||||
@ -138,7 +139,7 @@ class Header extends Component<IProps, IState> {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case 'help':
|
case 'help':
|
||||||
content = (
|
content = (
|
||||||
<IconButton blank={true} color={'inherit'} component={Link} to={'https://verdaccio.org/docs/en/installation'}>
|
<IconButton blank={true} color={'inherit'} component={ExternalLink} to={'https://verdaccio.org/docs/en/installation'}>
|
||||||
<Help />
|
<Help />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
);
|
);
|
||||||
|
@ -9,7 +9,9 @@ export const Content = styled.div`
|
|||||||
&& {
|
&& {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
1
src/webui/components/NotFound/img/package.svg
Normal file
1
src/webui/components/NotFound/img/package.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 495.2 495.2"><path fill="#d38c0d" d="M325.6 224.4L495.2 126 325.6 28.4l-168.8 99.2z"/><g fill="#efbb67"><path d="M170.4 224.4l168-97.6-168-98.4L0 126.8z"/><path d="M416 368.4l-168 98.4-168-98.4v-196L248 74l168 98.4z"/></g><path fill="#d38c0d" d="M248 74l168 98.4v196l-168 98.4"/><path fill="#efbb67" d="M326.4 314.8L495.2 218l-169.6-98.4L156 218z"/><path fill="#d38c0d" d="M170.4 316.4l168.8-99.2-168.8-97.6L0 218z"/><path fill="#704a0e" d="M248.8 270.8L416 172.4 248.8 74 78.4 172.4z"/><path fill="#513307" d="M248.8 270.8L416 172.4 248.8 74"/><path fill="#2d1c05" d="M248.8 270.8l36-21.6-36-20.8-36 20.8z"/><g fill="#0dd396"><path d="M368 379.6l40-23.2v-12.8l-40 23.2zM368 356.4l40-23.2v-12.8l-40 23.2zM368 333.2l40-23.2v-13.6l-40 24z"/></g></svg>
|
After Width: | Height: | Size: 802 B |
@ -1,21 +1,53 @@
|
|||||||
/**
|
/**
|
||||||
* @prettier
|
* @prettier
|
||||||
* @flow
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Wrapper } from './styles';
|
import { withRouter } from 'react-router-dom';
|
||||||
import { IProps } from './types';
|
import withWidth, { isWidthUp } from '@material-ui/core/withWidth/index';
|
||||||
|
import ListItem from '@material-ui/core/ListItem/index';
|
||||||
|
import Typography from '@material-ui/core/Typography/index';
|
||||||
|
import { Wrapper, Inner, EmptyPackage, Heading, Card, List } from './styles';
|
||||||
|
import PackageImg from './img/package.svg';
|
||||||
|
|
||||||
const NotFound = ({ pkg }: IProps) => (
|
// eslint-disable-next-line react/prop-types
|
||||||
<Wrapper>
|
const NotFound = ({ history, width }) => {
|
||||||
<h1>
|
const handleGoTo = to => () => {
|
||||||
{'Error 404 - '}
|
history.push(to);
|
||||||
{pkg}
|
};
|
||||||
</h1>
|
|
||||||
<hr />
|
|
||||||
<p>{'Oops, The package you are trying to access does not exist.'}</p>
|
|
||||||
</Wrapper>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default NotFound;
|
const handleGoBack = () => () => {
|
||||||
|
history.goBack();
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderList = () => (
|
||||||
|
<List>
|
||||||
|
<ListItem button={true} divider={true} onClick={handleGoTo('/')}>
|
||||||
|
{'Home'}
|
||||||
|
</ListItem>
|
||||||
|
<ListItem button={true} divider={true} onClick={handleGoBack()}>
|
||||||
|
{'Back'}
|
||||||
|
</ListItem>
|
||||||
|
</List>
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderSubTitle = () => (
|
||||||
|
<Typography variant={'subtitle1'}>
|
||||||
|
<div>{"The page you're looking for doesn't exist."}</div>
|
||||||
|
<div>{'Perhaps these links will help find what you are looking for:'}</div>
|
||||||
|
</Typography>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Wrapper>
|
||||||
|
<Inner>
|
||||||
|
<EmptyPackage alt={'404 - Page not found'} src={PackageImg} />
|
||||||
|
<Heading variant={isWidthUp('sm', width) ? 'h2' : 'h4'}>{"Sorry, we couldn't find it..."}</Heading>
|
||||||
|
{renderSubTitle()}
|
||||||
|
<Card>{renderList()}</Card>
|
||||||
|
</Inner>
|
||||||
|
</Wrapper>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default withRouter(withWidth()(NotFound));
|
||||||
|
@ -4,16 +4,43 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import styled from 'react-emotion';
|
import styled from 'react-emotion';
|
||||||
|
import Typography from '@material-ui/core/Typography/index';
|
||||||
|
import { default as MuiList } from '@material-ui/core/List/index';
|
||||||
|
import { default as MuiCard } from '@material-ui/core/Card/index';
|
||||||
|
|
||||||
import { fontSize, lineHeight } from '../../utils/styles/sizes';
|
export const Wrapper = styled('div')`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
flex: 1;
|
||||||
|
padding: 16px;
|
||||||
|
`;
|
||||||
|
|
||||||
export const Wrapper = styled.div`
|
export const Inner = styled('div')`
|
||||||
|
max-width: 650px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const EmptyPackage = styled('img')`
|
||||||
|
width: 150px;
|
||||||
|
margin: 0 auto;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Heading = styled(Typography)`
|
||||||
&& {
|
&& {
|
||||||
font-size: ${fontSize.md};
|
color: #4b5e40;
|
||||||
line-height: ${lineHeight.xl};
|
|
||||||
border: none;
|
|
||||||
outline: none;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const List = styled(MuiList)`
|
||||||
|
&& {
|
||||||
|
padding: 0;
|
||||||
|
color: #4b5e40;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Card = styled(MuiCard)`
|
||||||
|
margin-top: 24px;
|
||||||
|
`;
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
/**
|
|
||||||
* @prettier
|
|
||||||
* @flow
|
|
||||||
*/
|
|
||||||
|
|
||||||
export interface IProps {
|
|
||||||
pkg: string;
|
|
||||||
}
|
|
@ -80,7 +80,7 @@ const Package = ({ name: label, version, time, author: { name, avatar }, descrip
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WrapperLink className={'package'} to={`version/${label}`}>
|
<WrapperLink className={'package'} to={`/-/web/version/${label}`}>
|
||||||
<Header>
|
<Header>
|
||||||
{renderMainInfo()}
|
{renderMainInfo()}
|
||||||
<Overview>
|
<Overview>
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import type { Node } from 'react';
|
import type { Node } from 'react';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import { default as IconSearch } from '@material-ui/icons/Search';
|
import { default as IconSearch } from '@material-ui/icons/Search';
|
||||||
import InputAdornment from '@material-ui/core/InputAdornment';
|
import InputAdornment from '@material-ui/core/InputAdornment';
|
||||||
@ -13,7 +14,6 @@ import debounce from 'lodash/debounce';
|
|||||||
import API from '../../utils/api';
|
import API from '../../utils/api';
|
||||||
import AutoComplete from '../AutoComplete';
|
import AutoComplete from '../AutoComplete';
|
||||||
import colors from '../../utils/styles/colors';
|
import colors from '../../utils/styles/colors';
|
||||||
import { getDetailPageURL } from '../../utils/url';
|
|
||||||
|
|
||||||
import { IProps, IState } from './types';
|
import { IProps, IState } from './types';
|
||||||
import type { cancelAllSearchRequests, handlePackagesClearRequested, handleSearch, handleClickSearch, handleFetchPackages, onBlur } from './types';
|
import type { cancelAllSearchRequests, handlePackagesClearRequested, handleSearch, handleClickSearch, handleFetchPackages, onBlur } from './types';
|
||||||
@ -24,7 +24,7 @@ const CONSTANTS = {
|
|||||||
ABORT_ERROR: 'AbortError',
|
ABORT_ERROR: 'AbortError',
|
||||||
};
|
};
|
||||||
|
|
||||||
class Search extends Component<IProps, IState> {
|
export class Search extends Component<IProps, IState> {
|
||||||
requestList: Array<any>;
|
requestList: Array<any>;
|
||||||
|
|
||||||
constructor(props: IProps) {
|
constructor(props: IProps) {
|
||||||
@ -92,13 +92,15 @@ class Search extends Component<IProps, IState> {
|
|||||||
* When an user select any package by clicking or pressing return key.
|
* When an user select any package by clicking or pressing return key.
|
||||||
*/
|
*/
|
||||||
handleClickSearch: handleClickSearch = (event, { suggestionValue, method }) => {
|
handleClickSearch: handleClickSearch = (event, { suggestionValue, method }) => {
|
||||||
|
const { history } = this.props;
|
||||||
// stops event bubbling
|
// stops event bubbling
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case 'click':
|
case 'click':
|
||||||
case 'enter':
|
case 'enter':
|
||||||
this.setState({ search: '' });
|
this.setState({ search: '' });
|
||||||
window.location.assign(getDetailPageURL(suggestionValue));
|
// $FlowFixMe
|
||||||
|
history.push(`/-/web/version/${suggestionValue}`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -181,4 +183,4 @@ class Search extends Component<IProps, IState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Search;
|
export default withRouter(Search);
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export interface IProps {}
|
export interface IProps {
|
||||||
|
history?: any;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IState {
|
export interface IState {
|
||||||
search: string;
|
search: string;
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
* @prettier
|
* @prettier
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { createHashHistory } from 'history';
|
import { createBrowserHistory } from 'history';
|
||||||
|
|
||||||
const history = createHashHistory();
|
const history = createBrowserHistory();
|
||||||
|
|
||||||
// Listen for changes to the current location.
|
// Listen for changes to the current location.
|
||||||
history.listen((location, action) => {
|
history.listen((location, action) => {
|
||||||
|
@ -9,6 +9,7 @@ import Loading from '../../components/Loading';
|
|||||||
import DetailContainer from '../../components/DetailContainer';
|
import DetailContainer from '../../components/DetailContainer';
|
||||||
import DetailSidebar from '../../components/DetailSidebar';
|
import DetailSidebar from '../../components/DetailSidebar';
|
||||||
import { callDetailPage } from '../../utils/calls';
|
import { callDetailPage } from '../../utils/calls';
|
||||||
|
import { getRouterPackageName } from '../../utils/package';
|
||||||
|
|
||||||
export const DetailContext = React.createContext();
|
export const DetailContext = React.createContext();
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ class VersionPage extends Component<any, any> {
|
|||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
readMe: '',
|
readMe: '',
|
||||||
packageName: this.getPackageName(props),
|
packageName: getRouterPackageName(props.match),
|
||||||
packageMeta: null,
|
packageMeta: null,
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
notFound: false,
|
notFound: false,
|
||||||
@ -32,13 +33,6 @@ class VersionPage extends Component<any, any> {
|
|||||||
await this.loadPackageInfo();
|
await this.loadPackageInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
getPackageName(props: any = this.props): string {
|
|
||||||
const { match } = props;
|
|
||||||
const packageName = match.params.package;
|
|
||||||
|
|
||||||
return packageName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* eslint no-unused-vars: 0 */
|
/* eslint no-unused-vars: 0 */
|
||||||
async componentDidUpdate(nextProps: any, prevState: any) {
|
async componentDidUpdate(nextProps: any, prevState: any) {
|
||||||
const { packageName } = this.state;
|
const { packageName } = this.state;
|
||||||
@ -56,7 +50,7 @@ class VersionPage extends Component<any, any> {
|
|||||||
|
|
||||||
static getDerivedStateFromProps(nextProps: any, prevState: any) {
|
static getDerivedStateFromProps(nextProps: any, prevState: any) {
|
||||||
const { match } = nextProps;
|
const { match } = nextProps;
|
||||||
const packageName = match.params.package;
|
const packageName = getRouterPackageName(match);
|
||||||
|
|
||||||
if (packageName !== prevState.packageName) {
|
if (packageName !== prevState.packageName) {
|
||||||
try {
|
try {
|
||||||
|
@ -3,39 +3,52 @@
|
|||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
/* eslint react/jsx-max-depth:0 */
|
||||||
|
|
||||||
|
import React, { Component, Fragment } from 'react';
|
||||||
import { Router, Route, Switch } from 'react-router-dom';
|
import { Router, Route, Switch } from 'react-router-dom';
|
||||||
import { AppContextConsumer } from './app';
|
import { AppContextConsumer } from './app';
|
||||||
|
|
||||||
import { asyncComponent } from './utils/asyncComponent';
|
import { asyncComponent } from './utils/asyncComponent';
|
||||||
import history from './history';
|
import history from './history';
|
||||||
|
import Header from './components/Header';
|
||||||
|
|
||||||
|
const NotFound = asyncComponent(() => import('./components/NotFound'));
|
||||||
const DetailPackage = asyncComponent(() => import('./pages/detail'));
|
const DetailPackage = asyncComponent(() => import('./pages/detail'));
|
||||||
const VersionPackage = asyncComponent(() => import('./pages/version'));
|
const VersionPackage = asyncComponent(() => import('./pages/version'));
|
||||||
const HomePage = asyncComponent(() => import('./pages/home'));
|
const HomePage = asyncComponent(() => import('./pages/home'));
|
||||||
|
|
||||||
interface IProps {
|
class RouterApp extends Component<any, any> {
|
||||||
isUserLoggedIn: boolean;
|
|
||||||
packages: Array<Object>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IState {}
|
|
||||||
|
|
||||||
class RouterApp extends Component<IProps, IState> {
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
<Switch>
|
<Fragment>
|
||||||
<Route exact={true} path={'/'} render={this.renderHomePage} />
|
{this.renderHeader()}
|
||||||
<Route exact={true} path={'/detail/@:scope/:package'} render={this.renderDetailPage} />
|
<Switch>
|
||||||
<Route exact={true} path={'/detail/:package'} render={this.renderDetailPage} />
|
<Route exact={true} path={'/'} render={this.renderHomePage} />
|
||||||
<Route exact={true} path={'/version/@:scope/:package'} render={this.renderVersionPage} />
|
<Route exact={true} path={'/-/web/detail/@:scope/:package'} render={this.renderDetailPage} />
|
||||||
<Route exact={true} path={'/version/:package'} render={this.renderVersionPage} />
|
<Route exact={true} path={'/-/web/detail/:package'} render={this.renderDetailPage} />
|
||||||
</Switch>
|
<Route exact={true} path={'/-/web/version/@:scope/:package'} render={this.renderVersionPage} />
|
||||||
|
<Route exact={true} path={'/-/web/version/:package'} render={this.renderVersionPage} />
|
||||||
|
<Route component={NotFound} />
|
||||||
|
</Switch>
|
||||||
|
</Fragment>
|
||||||
</Router>
|
</Router>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderHeader = () => {
|
||||||
|
const { onLogout, onToggleLoginModal } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppContextConsumer>
|
||||||
|
{function renderConsumerVersionPage({ logoUrl, scope, user }) {
|
||||||
|
return <Header logo={logoUrl} onLogout={onLogout} onToggleLoginModal={onToggleLoginModal} scope={scope} username={user.username} />;
|
||||||
|
}}
|
||||||
|
</AppContextConsumer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
renderHomePage = () => {
|
renderHomePage = () => {
|
||||||
return (
|
return (
|
||||||
<AppContextConsumer>
|
<AppContextConsumer>
|
||||||
|
@ -106,3 +106,13 @@ export function formatDate(lastUpdate) {
|
|||||||
export function formatDateDistance(lastUpdate) {
|
export function formatDateDistance(lastUpdate) {
|
||||||
return distanceInWordsToNow(new Date(lastUpdate));
|
return distanceInWordsToNow(new Date(lastUpdate));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getRouterPackageName(match) {
|
||||||
|
const packageName = match.params.package;
|
||||||
|
const scope = match.params.scope;
|
||||||
|
if (scope) {
|
||||||
|
return `@${scope}/${packageName}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return packageName;
|
||||||
|
}
|
||||||
|
@ -8,5 +8,5 @@ export function getRegistryURL() {
|
|||||||
* @param {string} packageName
|
* @param {string} packageName
|
||||||
*/
|
*/
|
||||||
export function getDetailPageURL(packageName) {
|
export function getDetailPageURL(packageName) {
|
||||||
return `${getRegistryURL()}/#/detail/${packageName}`;
|
return `${getRegistryURL()}/-/web/version/${packageName}`;
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
const scopedPackageMetadata = require('./partials/pkg-scoped');
|
const scopedPackageMetadata = require('./partials/pkg-scoped');
|
||||||
const protectedPackageMetadata = require('./partials/pkg-protected');
|
const protectedPackageMetadata = require('./partials/pkg-protected');
|
||||||
|
|
||||||
describe('/ (Verdaccio Page)', () => {
|
describe.skip('/ (Verdaccio Page)', () => {
|
||||||
let page;
|
let page;
|
||||||
// this might be increased based on the delays included in all test
|
// this might be increased based on the delays included in all test
|
||||||
jest.setTimeout(200000);
|
jest.setTimeout(200000);
|
||||||
@ -139,7 +139,7 @@ describe('/ (Verdaccio Page)', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should contains last sync information', async () => {
|
test('should contains last sync information', async () => {
|
||||||
const versionList = await page.$$('.sidebar-info .last-sync-item');
|
const versionList = await page.$$('.sidebar-info .detail-info');
|
||||||
expect(versionList).toHaveLength(3);
|
expect(versionList).toHaveLength(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -13,17 +13,17 @@ export default function(server) {
|
|||||||
* Check whether the user is allowed to fetch packages
|
* Check whether the user is allowed to fetch packages
|
||||||
* @param auth {object} disable auth
|
* @param auth {object} disable auth
|
||||||
* @param pkg {string} package name
|
* @param pkg {string} package name
|
||||||
* @param ok {boolean}
|
* @param status {boolean}
|
||||||
*/
|
*/
|
||||||
function checkAccess(auth, pkg, ok) {
|
function checkAccess(auth, pkg, status) {
|
||||||
test(
|
test(
|
||||||
`${(ok ? 'allows' : 'forbids')} access ${auth} to ${pkg}`, () => {
|
`${(status ? 'allows' : 'forbids')} access ${auth} to ${pkg}`, () => {
|
||||||
server.authstr = auth ? buildAccesToken(auth) : undefined;
|
server.authstr = auth ? buildAccesToken(auth) : undefined;
|
||||||
const req = server.getPackage(pkg);
|
const req = server.getPackage(pkg);
|
||||||
|
|
||||||
if (ok) {
|
if (status === HTTP_STATUS.NOT_FOUND) {
|
||||||
return req.status(HTTP_STATUS.NOT_FOUND).body_error(API_ERROR.NO_PACKAGE);
|
return req.status(HTTP_STATUS.NOT_FOUND).body_error(API_ERROR.NO_PACKAGE);
|
||||||
} else {
|
} else if (status === HTTP_STATUS.FORBIDDEN) {
|
||||||
return req.status(HTTP_STATUS.FORBIDDEN).body_error(API_ERROR.NOT_ALLOWED);
|
return req.status(HTTP_STATUS.FORBIDDEN).body_error(API_ERROR.NOT_ALLOWED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -34,16 +34,20 @@ export default function(server) {
|
|||||||
* Check whether the user is allowed to publish packages
|
* Check whether the user is allowed to publish packages
|
||||||
* @param auth {object} disable auth
|
* @param auth {object} disable auth
|
||||||
* @param pkg {string} package name
|
* @param pkg {string} package name
|
||||||
* @param ok {boolean}
|
* @param status {boolean}
|
||||||
*/
|
*/
|
||||||
function checkPublish(auth, pkg, ok) {
|
function checkPublish(auth, pkg, status) {
|
||||||
test(`${(ok ? 'allows' : 'forbids')} publish ${auth} to ${pkg}`, () => {
|
test(`${(status ? 'allows' : 'forbids')} publish ${auth} to ${pkg}`, () => {
|
||||||
server.authstr = auth ? buildAccesToken(auth) : undefined;
|
server.authstr = auth ? buildAccesToken(auth) : undefined;
|
||||||
const req = server.putPackage(pkg, require('../fixtures/package')(pkg));
|
const req = server.putPackage(pkg, require('../fixtures/package')(pkg));
|
||||||
if (ok) {
|
if (status === HTTP_STATUS.NOT_FOUND) {
|
||||||
return req.status(HTTP_STATUS.NOT_FOUND).body_error(/this package cannot be added/);
|
return req.status(HTTP_STATUS.NOT_FOUND).body_error(API_ERROR.PACKAGE_CANNOT_BE_ADDED);
|
||||||
} else {
|
} else if (status === HTTP_STATUS.FORBIDDEN) {
|
||||||
return req.status(HTTP_STATUS.FORBIDDEN).body_error(/not allowed to publish package/);
|
return req.status(HTTP_STATUS.FORBIDDEN).body_error(API_ERROR.NOT_ALLOWED_PUBLISH);
|
||||||
|
} else if (status === HTTP_STATUS.CREATED) {
|
||||||
|
return req.status(HTTP_STATUS.CREATED);
|
||||||
|
} else if (status === HTTP_STATUS.CONFLICT) {
|
||||||
|
return req.status(HTTP_STATUS.CONFLICT);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -60,39 +64,39 @@ export default function(server) {
|
|||||||
const testOnlyAuth = 'test-only-auth';
|
const testOnlyAuth = 'test-only-auth';
|
||||||
|
|
||||||
describe('all are allowed to access', () => {
|
describe('all are allowed to access', () => {
|
||||||
checkAccess(validCredentials, testAccessOnly, true);
|
checkAccess(validCredentials, testAccessOnly, HTTP_STATUS.NOT_FOUND);
|
||||||
checkAccess(undefined, testAccessOnly, true);
|
checkAccess(undefined, testAccessOnly, HTTP_STATUS.NOT_FOUND);
|
||||||
checkAccess(badCredentials, testAccessOnly, true);
|
checkAccess(badCredentials, testAccessOnly, HTTP_STATUS.NOT_FOUND);
|
||||||
checkPublish(validCredentials, testAccessOnly, false);
|
checkPublish(validCredentials, testAccessOnly, HTTP_STATUS.FORBIDDEN);
|
||||||
checkPublish(undefined, testAccessOnly, false);
|
checkPublish(undefined, testAccessOnly, HTTP_STATUS.FORBIDDEN);
|
||||||
checkPublish(badCredentials, testAccessOnly, false);
|
checkPublish(badCredentials, testAccessOnly, HTTP_STATUS.FORBIDDEN);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('all are allowed to publish', () => {
|
describe('all are allowed to publish', () => {
|
||||||
checkAccess(validCredentials, testPublishOnly, false);
|
checkAccess(validCredentials, testPublishOnly, HTTP_STATUS.FORBIDDEN);
|
||||||
checkAccess(undefined, testPublishOnly, false);
|
checkAccess(undefined, testPublishOnly, HTTP_STATUS.FORBIDDEN);
|
||||||
checkAccess(badCredentials, testPublishOnly, false);
|
checkAccess(badCredentials, testPublishOnly, HTTP_STATUS.FORBIDDEN);
|
||||||
checkPublish(validCredentials, testPublishOnly, true);
|
checkPublish(validCredentials, testPublishOnly, HTTP_STATUS.CREATED);
|
||||||
checkPublish(undefined, testPublishOnly, true);
|
checkPublish(undefined, testPublishOnly, HTTP_STATUS.CONFLICT);
|
||||||
checkPublish(badCredentials, testPublishOnly, true);
|
checkPublish(badCredentials, testPublishOnly, HTTP_STATUS.CONFLICT);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('only user "test" is allowed to publish and access', () => {
|
describe('only user "test" is allowed to publish and access', () => {
|
||||||
checkAccess(validCredentials, testOnlyTest, true);
|
checkAccess(validCredentials, testOnlyTest, HTTP_STATUS.NOT_FOUND);
|
||||||
checkAccess(undefined, testOnlyTest, false);
|
checkAccess(undefined, testOnlyTest, HTTP_STATUS.FORBIDDEN);
|
||||||
checkAccess(badCredentials, testOnlyTest, false);
|
checkAccess(badCredentials, testOnlyTest, HTTP_STATUS.FORBIDDEN);
|
||||||
checkPublish(validCredentials, testOnlyTest, true);
|
checkPublish(validCredentials, testOnlyTest, HTTP_STATUS.CREATED);
|
||||||
checkPublish(undefined, testOnlyTest, false);
|
checkPublish(undefined, testOnlyTest, HTTP_STATUS.FORBIDDEN);
|
||||||
checkPublish(badCredentials, testOnlyTest, false);
|
checkPublish(badCredentials, testOnlyTest, HTTP_STATUS.FORBIDDEN);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('only authenticated users are allowed', () => {
|
describe('only authenticated users are allowed', () => {
|
||||||
checkAccess(validCredentials, testOnlyAuth, true);
|
checkAccess(validCredentials, testOnlyAuth, HTTP_STATUS.NOT_FOUND);
|
||||||
checkAccess(undefined, testOnlyAuth, false);
|
checkAccess(undefined, testOnlyAuth, HTTP_STATUS.FORBIDDEN);
|
||||||
checkAccess(badCredentials, testOnlyAuth, false);
|
checkAccess(badCredentials, testOnlyAuth, HTTP_STATUS.FORBIDDEN);
|
||||||
checkPublish(validCredentials, testOnlyAuth, true);
|
checkPublish(validCredentials, testOnlyAuth, HTTP_STATUS.CREATED);
|
||||||
checkPublish(undefined, testOnlyAuth, false);
|
checkPublish(undefined, testOnlyAuth, HTTP_STATUS.FORBIDDEN);
|
||||||
checkPublish(badCredentials, testOnlyAuth, false);
|
checkPublish(badCredentials, testOnlyAuth, HTTP_STATUS.FORBIDDEN);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ export default function (server, server2) {
|
|||||||
|
|
||||||
const PKG_NAME = 'test-nullstorage2';
|
const PKG_NAME = 'test-nullstorage2';
|
||||||
const PKG_VERSION = '0.0.1';
|
const PKG_VERSION = '0.0.1';
|
||||||
|
// const TARBALL = `${PKG_NAME}-file.name`;
|
||||||
|
|
||||||
describe('should test a scenario when tarball is being fetch from uplink', () => {
|
describe('should test a scenario when tarball is being fetch from uplink', () => {
|
||||||
|
|
||||||
@ -38,8 +39,7 @@ export default function (server, server2) {
|
|||||||
|
|
||||||
describe(`should succesfully publish ${PKG_NAME} package on server2`, () => {
|
describe(`should succesfully publish ${PKG_NAME} package on server2`, () => {
|
||||||
beforeAll(function() {
|
beforeAll(function() {
|
||||||
return server2.putTarball(PKG_NAME, TARBALL, getBinary())
|
return server2.putTarball(PKG_NAME, TARBALL, getBinary()).status(HTTP_STATUS.CREATED).body_ok(/.*/);
|
||||||
.status(HTTP_STATUS.CREATED).body_ok(/.*/);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeAll(function() {
|
beforeAll(function() {
|
||||||
|
@ -19,6 +19,7 @@ uplinks:
|
|||||||
timeout: 100ms
|
timeout: 100ms
|
||||||
server2:
|
server2:
|
||||||
url: http://localhost:55552/
|
url: http://localhost:55552/
|
||||||
|
maxage: 0
|
||||||
server3:
|
server3:
|
||||||
url: http://localhost:55553/
|
url: http://localhost:55553/
|
||||||
baduplink:
|
baduplink:
|
||||||
@ -88,7 +89,7 @@ packages:
|
|||||||
access: $all
|
access: $all
|
||||||
publish: $all
|
publish: $all
|
||||||
proxy: server2
|
proxy: server2
|
||||||
storage: false
|
storage: sub_storage
|
||||||
|
|
||||||
'baduplink':
|
'baduplink':
|
||||||
access: $all
|
access: $all
|
||||||
@ -98,22 +99,22 @@ packages:
|
|||||||
'test-access-only':
|
'test-access-only':
|
||||||
access: $all
|
access: $all
|
||||||
publish: nobody
|
publish: nobody
|
||||||
storage: false
|
storage: sub_storage
|
||||||
|
|
||||||
'test-publish-only':
|
'test-publish-only':
|
||||||
access: nobody
|
access: nobody
|
||||||
publish: $all
|
publish: $all
|
||||||
storage: false
|
storage: sub_storage
|
||||||
|
|
||||||
'test-only-test':
|
'test-only-test':
|
||||||
access: test
|
access: test
|
||||||
publish: test
|
publish: test
|
||||||
storage: false
|
storage: sub_storage
|
||||||
|
|
||||||
'test-only-auth':
|
'test-only-auth':
|
||||||
access: $authenticated
|
access: $authenticated
|
||||||
publish: $authenticated
|
publish: $authenticated
|
||||||
storage: false
|
storage: sub_storage
|
||||||
|
|
||||||
'*':
|
'*':
|
||||||
access: test $anonymous
|
access: test $anonymous
|
||||||
|
@ -25,6 +25,13 @@ describe('LocalStorage', () => {
|
|||||||
const pkgNameScoped = `@scope/${pkgName}-scope`;
|
const pkgNameScoped = `@scope/${pkgName}-scope`;
|
||||||
const tarballName: string = `${pkgName}-add-tarball-1.0.4.tgz`;
|
const tarballName: string = `${pkgName}-add-tarball-1.0.4.tgz`;
|
||||||
const tarballName2: string = `${pkgName}-add-tarball-1.0.5.tgz`;
|
const tarballName2: string = `${pkgName}-add-tarball-1.0.5.tgz`;
|
||||||
|
|
||||||
|
const getStorage = (LocalStorageClass = LocalStorage) => {
|
||||||
|
const config: Config = new AppConfig(configExample);
|
||||||
|
config.self_path = path.join('../partials/store');
|
||||||
|
return new LocalStorageClass(config, Logger.logger);
|
||||||
|
}
|
||||||
|
|
||||||
const getPackageMetadataFromStore = (pkgName: string) => {
|
const getPackageMetadataFromStore = (pkgName: string) => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
storage.getPackageMetadata(pkgName, (err, data ) => {
|
storage.getPackageMetadata(pkgName, (err, data ) => {
|
||||||
@ -76,10 +83,7 @@ describe('LocalStorage', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
const config: Config = new AppConfig(configExample);
|
storage = getStorage();
|
||||||
config.self_path = path.join('../partials/store');
|
|
||||||
|
|
||||||
storage = new LocalStorage(config, Logger.logger);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should be defined', () => {
|
test('should be defined', () => {
|
||||||
@ -249,16 +253,27 @@ describe('LocalStorage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('LocalStorage::updateVersions', () => {
|
describe('LocalStorage::updateVersions', () => {
|
||||||
test('should update versions from external source', async (done) => {
|
const metadata = JSON.parse(readMetadata('metadata-update-versions-tags'));
|
||||||
const metadata = JSON.parse(readMetadata('metadata-update-versions-tags'));
|
const pkgName = 'add-update-versions-test-1';
|
||||||
const pkgName = 'add-update-versions-test-1';
|
const version = '1.0.2';
|
||||||
const version = '1.0.2';
|
let _storage;
|
||||||
await addPackageToStore(pkgName, generatePackageTemplate(pkgName));
|
beforeEach(done => {
|
||||||
await addNewVersion(pkgName, '1.0.1');
|
class MockLocalStorage extends LocalStorage {}
|
||||||
await addNewVersion(pkgName, version);
|
// $FlowFixMe
|
||||||
|
MockLocalStorage.prototype._writePackage = jest.fn(LocalStorage.prototype._writePackage)
|
||||||
|
_storage = getStorage(MockLocalStorage);
|
||||||
|
rimRaf(path.join(configExample.storage, pkgName), async () => {
|
||||||
|
await addPackageToStore(pkgName, generatePackageTemplate(pkgName));
|
||||||
|
await addNewVersion(pkgName, '1.0.1');
|
||||||
|
await addNewVersion(pkgName, version);
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
storage.updateVersions(pkgName, metadata, (err, data) => {
|
test('should update versions from external source', async (done) => {
|
||||||
|
_storage.updateVersions(pkgName, metadata, (err, data) => {
|
||||||
expect(err).toBeNull();
|
expect(err).toBeNull();
|
||||||
|
expect(_storage._writePackage).toHaveBeenCalledTimes(1);
|
||||||
expect(data.versions['1.0.1']).toBeDefined();
|
expect(data.versions['1.0.1']).toBeDefined();
|
||||||
expect(data.versions[version]).toBeDefined();
|
expect(data.versions[version]).toBeDefined();
|
||||||
expect(data.versions['1.0.4']).toBeDefined();
|
expect(data.versions['1.0.4']).toBeDefined();
|
||||||
@ -273,6 +288,17 @@ describe('LocalStorage', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should not update if the metadata match', done => {
|
||||||
|
_storage.updateVersions(pkgName, metadata, e => {
|
||||||
|
expect(e).toBeNull()
|
||||||
|
_storage.updateVersions(pkgName, metadata, err => {
|
||||||
|
expect(err).toBeNull()
|
||||||
|
expect(_storage._writePackage).toHaveBeenCalledTimes(1);
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('LocalStorage::changePackage', () => {
|
describe('LocalStorage::changePackage', () => {
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import fs from 'fs';
|
||||||
|
import rimraf from 'rimraf';
|
||||||
// $FlowFixMe
|
// $FlowFixMe
|
||||||
import configExample from '../partials/config/index';
|
import configExample from '../partials/config/index';
|
||||||
import AppConfig from '../../../src/lib/config';
|
import AppConfig from '../../../src/lib/config';
|
||||||
@ -16,12 +18,12 @@ import {DOMAIN_SERVERS} from '../../functional/config.functional';
|
|||||||
|
|
||||||
setup(configExample.logs);
|
setup(configExample.logs);
|
||||||
|
|
||||||
|
const storagePath = path.join(__dirname, '../partials/store/test-storage-store.spec');
|
||||||
const mockServerPort: number = 55548;
|
const mockServerPort: number = 55548;
|
||||||
const generateStorage = async function(port = mockServerPort, configDefault = configExample) {
|
const generateStorage = async function(port = mockServerPort, configDefault = configExample) {
|
||||||
const storageConfig = _.clone(configDefault);
|
const storageConfig = _.clone(configDefault);
|
||||||
const storage = path.join(__dirname, '../partials/store/test-storage-store.spec');
|
|
||||||
storageConfig.self_path = __dirname;
|
storageConfig.self_path = __dirname;
|
||||||
storageConfig.storage = storage;
|
storageConfig.storage = storagePath;
|
||||||
storageConfig.uplinks = {
|
storageConfig.uplinks = {
|
||||||
npmjs: {
|
npmjs: {
|
||||||
url: `http://${DOMAIN_SERVERS}:${port}`
|
url: `http://${DOMAIN_SERVERS}:${port}`
|
||||||
@ -37,8 +39,11 @@ const generateStorage = async function(port = mockServerPort, configDefault = co
|
|||||||
describe('StorageTest', () => {
|
describe('StorageTest', () => {
|
||||||
let mockRegistry;
|
let mockRegistry;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(done => {
|
||||||
mockRegistry = await mockServer(mockServerPort).init();
|
rimraf(storagePath, async () => {
|
||||||
|
mockRegistry = await mockServer(mockServerPort).init();
|
||||||
|
done()
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(function(done) {
|
afterAll(function(done) {
|
||||||
@ -90,5 +95,21 @@ describe('StorageTest', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should not touch if the package exists and has no uplinks', async (done) => {
|
||||||
|
const storage: IStorageHandler = await generateStorage();
|
||||||
|
const metadataSource = path.join(__dirname, '../partials/metadata');
|
||||||
|
const metadataPath = path.join(storagePath, 'npm_test/package.json');
|
||||||
|
fs.mkdirSync(path.join(storagePath, 'npm_test'));
|
||||||
|
fs.writeFileSync(metadataPath, fs.readFileSync(metadataSource));
|
||||||
|
const metadata = JSON.parse(fs.readFileSync(metadataPath).toString());
|
||||||
|
// $FlowFixMe
|
||||||
|
storage.localStorage.updateVersions = jest.fn(storage.localStorage.updateVersions);
|
||||||
|
storage._syncUplinksMetadata('npm_test', metadata, {}, (err) => {
|
||||||
|
expect(err).toBeNull();
|
||||||
|
expect(storage.localStorage.updateVersions).not.toHaveBeenCalled();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -82,7 +82,13 @@
|
|||||||
"beta": "1.0.2",
|
"beta": "1.0.2",
|
||||||
"next": "1.0.4"
|
"next": "1.0.4"
|
||||||
},
|
},
|
||||||
"time": {},
|
"time": {
|
||||||
|
"modified": "2019-01-29T03:20:04.000Z",
|
||||||
|
"created": "2019-01-29T03:20:00.000Z",
|
||||||
|
"1.0.1": "2019-01-29T03:20:01.000Z",
|
||||||
|
"1.0.2": "2019-01-29T03:20:02.000Z",
|
||||||
|
"1.0.4": "2019-01-29T03:20:04.000Z"
|
||||||
|
},
|
||||||
"_distfiles": {},
|
"_distfiles": {},
|
||||||
"_attachments": {},
|
"_attachments": {},
|
||||||
"_uplinks": {},
|
"_uplinks": {},
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,5 +1,5 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`<Header /> component with logged in state should load the component in logged in state 1`] = `"<div><header class=\\"MuiPaper-root-10 MuiPaper-elevation4-16 MuiAppBar-root-1 MuiAppBar-positionStatic-5 MuiAppBar-colorPrimary-8 css-1jzwe6w e1ctrp128\\"><div class=\\"MuiToolbar-root-37 MuiToolbar-regular-39 MuiToolbar-gutters-38 css-1pwdmmq e1ctrp120\\"><div class=\\"MuiToolbar-root-37 MuiToolbar-regular-39 MuiToolbar-gutters-38 css-1vacr9s e1ctrp123\\"><a href=\\"/\\" target=\\"_self\\" style=\\"margin-right: 1em;\\"><div class=\\"css-12nq0oo e18wxr160\\"></div></a></div><div class=\\"MuiToolbar-root-37 MuiToolbar-regular-39 MuiToolbar-gutters-38 css-m61s5i e1ctrp122\\"><a href=\\"https://verdaccio.org/docs/en/installation\\" target=\\"_blank\\" class=\\"MuiButtonBase-root-55 MuiIconButton-root-49 MuiIconButton-colorInherit-50\\" tabindex=\\"0\\" role=\\"button\\" title=\\"Documentation\\"><span class=\\"MuiIconButton-label-54\\"><svg class=\\"MuiSvgIcon-root-58\\" focusable=\\"false\\" viewBox=\\"0 0 24 24\\" aria-hidden=\\"true\\" role=\\"presentation\\"><path fill=\\"none\\" d=\\"M0 0h24v24H0z\\"></path><path d=\\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z\\"></path></svg></span><span class=\\"MuiTouchRipple-root-85\\"></span></a><button class=\\"MuiButtonBase-root-55 MuiIconButton-root-49 MuiIconButton-colorInherit-50\\" tabindex=\\"0\\" type=\\"button\\" id=\\"header--button-registryInfo\\" title=\\"Registry Information\\"><span class=\\"MuiIconButton-label-54\\"><svg class=\\"MuiSvgIcon-root-58\\" focusable=\\"false\\" viewBox=\\"0 0 24 24\\" aria-hidden=\\"true\\" role=\\"presentation\\"><path fill=\\"none\\" d=\\"M0 0h24v24H0z\\"></path><path d=\\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z\\"></path></svg></span><span class=\\"MuiTouchRipple-root-85\\"></span></button><button class=\\"MuiButtonBase-root-55 MuiIconButton-root-49 MuiIconButton-colorInherit-50\\" tabindex=\\"0\\" type=\\"button\\" id=\\"header--button-account\\"><span class=\\"MuiIconButton-label-54\\"><svg class=\\"MuiSvgIcon-root-58\\" focusable=\\"false\\" viewBox=\\"0 0 24 24\\" aria-hidden=\\"true\\" role=\\"presentation\\"><path d=\\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14.2c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.94-3.5 3.22-6 3.22z\\"></path><path fill=\\"none\\" d=\\"M0 0h24v24H0z\\"></path></svg></span><span class=\\"MuiTouchRipple-root-85\\"></span></button></div></div></header></div>"`;
|
exports[`<Header /> component with logged in state should load the component in logged in state 1`] = `"<div><header class=\\"MuiPaper-root-10 MuiPaper-elevation4-16 MuiAppBar-root-1 MuiAppBar-positionStatic-5 MuiAppBar-colorPrimary-8 css-1jzwe6w e1ctrp128\\"><div class=\\"MuiToolbar-root-37 MuiToolbar-regular-39 MuiToolbar-gutters-38 css-1pwdmmq e1ctrp120\\"><div class=\\"MuiToolbar-root-37 MuiToolbar-regular-39 MuiToolbar-gutters-38 css-1vacr9s e1ctrp123\\"><a style=\\"margin-right:1em\\" href=\\"/\\"><div class=\\"css-12nq0oo e18wxr160\\"></div></a></div><div class=\\"MuiToolbar-root-37 MuiToolbar-regular-39 MuiToolbar-gutters-38 css-m61s5i e1ctrp122\\"><a href=\\"https://verdaccio.org/docs/en/installation\\" target=\\"_blank\\" class=\\"MuiButtonBase-root-55 MuiIconButton-root-49 MuiIconButton-colorInherit-50\\" tabindex=\\"0\\" role=\\"button\\" title=\\"Documentation\\"><span class=\\"MuiIconButton-label-54\\"><svg class=\\"MuiSvgIcon-root-58\\" focusable=\\"false\\" viewBox=\\"0 0 24 24\\" aria-hidden=\\"true\\" role=\\"presentation\\"><path fill=\\"none\\" d=\\"M0 0h24v24H0z\\"></path><path d=\\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z\\"></path></svg></span></a><button class=\\"MuiButtonBase-root-55 MuiIconButton-root-49 MuiIconButton-colorInherit-50\\" tabindex=\\"0\\" type=\\"button\\" id=\\"header--button-registryInfo\\" title=\\"Registry Information\\"><span class=\\"MuiIconButton-label-54\\"><svg class=\\"MuiSvgIcon-root-58\\" focusable=\\"false\\" viewBox=\\"0 0 24 24\\" aria-hidden=\\"true\\" role=\\"presentation\\"><path fill=\\"none\\" d=\\"M0 0h24v24H0z\\"></path><path d=\\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z\\"></path></svg></span></button><button class=\\"MuiButtonBase-root-55 MuiIconButton-root-49 MuiIconButton-colorInherit-50\\" tabindex=\\"0\\" type=\\"button\\" id=\\"header--button-account\\"><span class=\\"MuiIconButton-label-54\\"><svg class=\\"MuiSvgIcon-root-58\\" focusable=\\"false\\" viewBox=\\"0 0 24 24\\" aria-hidden=\\"true\\" role=\\"presentation\\"><path d=\\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14.2c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.94-3.5 3.22-6 3.22z\\"></path><path fill=\\"none\\" d=\\"M0 0h24v24H0z\\"></path></svg></span></button></div></div></header></div>"`;
|
||||||
|
|
||||||
exports[`<Header /> component with logged out state should load the component in logged out state 1`] = `"<div><header class=\\"MuiPaper-root-10 MuiPaper-elevation4-16 MuiAppBar-root-1 MuiAppBar-positionStatic-5 MuiAppBar-colorPrimary-8 css-1jzwe6w e1ctrp128\\"><div class=\\"MuiToolbar-root-37 MuiToolbar-regular-39 MuiToolbar-gutters-38 css-1pwdmmq e1ctrp120\\"><div class=\\"MuiToolbar-root-37 MuiToolbar-regular-39 MuiToolbar-gutters-38 css-1vacr9s e1ctrp123\\"><a href=\\"/\\" target=\\"_self\\" style=\\"margin-right: 1em;\\"><div class=\\"css-12nq0oo e18wxr160\\"></div></a></div><div class=\\"MuiToolbar-root-37 MuiToolbar-regular-39 MuiToolbar-gutters-38 css-m61s5i e1ctrp122\\"><a href=\\"https://verdaccio.org/docs/en/installation\\" target=\\"_blank\\" class=\\"MuiButtonBase-root-55 MuiIconButton-root-49 MuiIconButton-colorInherit-50\\" tabindex=\\"0\\" role=\\"button\\" title=\\"Documentation\\"><span class=\\"MuiIconButton-label-54\\"><svg class=\\"MuiSvgIcon-root-58\\" focusable=\\"false\\" viewBox=\\"0 0 24 24\\" aria-hidden=\\"true\\" role=\\"presentation\\"><path fill=\\"none\\" d=\\"M0 0h24v24H0z\\"></path><path d=\\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z\\"></path></svg></span><span class=\\"MuiTouchRipple-root-85\\"></span></a><button class=\\"MuiButtonBase-root-55 MuiIconButton-root-49 MuiIconButton-colorInherit-50\\" tabindex=\\"0\\" type=\\"button\\" id=\\"header--button-registryInfo\\" title=\\"Registry Information\\"><span class=\\"MuiIconButton-label-54\\"><svg class=\\"MuiSvgIcon-root-58\\" focusable=\\"false\\" viewBox=\\"0 0 24 24\\" aria-hidden=\\"true\\" role=\\"presentation\\"><path fill=\\"none\\" d=\\"M0 0h24v24H0z\\"></path><path d=\\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z\\"></path></svg></span><span class=\\"MuiTouchRipple-root-85\\"></span></button><button class=\\"MuiButtonBase-root-55 MuiButton-root-113 MuiButton-text-115 MuiButton-flat-118 MuiButton-colorInherit-134\\" tabindex=\\"0\\" type=\\"button\\" id=\\"header--button-login\\"><span class=\\"MuiButton-label-114\\">Login</span><span class=\\"MuiTouchRipple-root-85\\"></span></button></div></div></header></div>"`;
|
exports[`<Header /> component with logged out state should load the component in logged out state 1`] = `"<div><header class=\\"MuiPaper-root-10 MuiPaper-elevation4-16 MuiAppBar-root-1 MuiAppBar-positionStatic-5 MuiAppBar-colorPrimary-8 css-1jzwe6w e1ctrp128\\"><div class=\\"MuiToolbar-root-37 MuiToolbar-regular-39 MuiToolbar-gutters-38 css-1pwdmmq e1ctrp120\\"><div class=\\"MuiToolbar-root-37 MuiToolbar-regular-39 MuiToolbar-gutters-38 css-1vacr9s e1ctrp123\\"><a style=\\"margin-right:1em\\" href=\\"/\\"><div class=\\"css-12nq0oo e18wxr160\\"></div></a></div><div class=\\"MuiToolbar-root-37 MuiToolbar-regular-39 MuiToolbar-gutters-38 css-m61s5i e1ctrp122\\"><a href=\\"https://verdaccio.org/docs/en/installation\\" target=\\"_blank\\" class=\\"MuiButtonBase-root-55 MuiIconButton-root-49 MuiIconButton-colorInherit-50\\" tabindex=\\"0\\" role=\\"button\\" title=\\"Documentation\\"><span class=\\"MuiIconButton-label-54\\"><svg class=\\"MuiSvgIcon-root-58\\" focusable=\\"false\\" viewBox=\\"0 0 24 24\\" aria-hidden=\\"true\\" role=\\"presentation\\"><path fill=\\"none\\" d=\\"M0 0h24v24H0z\\"></path><path d=\\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z\\"></path></svg></span></a><button class=\\"MuiButtonBase-root-55 MuiIconButton-root-49 MuiIconButton-colorInherit-50\\" tabindex=\\"0\\" type=\\"button\\" id=\\"header--button-registryInfo\\" title=\\"Registry Information\\"><span class=\\"MuiIconButton-label-54\\"><svg class=\\"MuiSvgIcon-root-58\\" focusable=\\"false\\" viewBox=\\"0 0 24 24\\" aria-hidden=\\"true\\" role=\\"presentation\\"><path fill=\\"none\\" d=\\"M0 0h24v24H0z\\"></path><path d=\\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z\\"></path></svg></span></button><button class=\\"MuiButtonBase-root-55 MuiButton-root-85 MuiButton-text-87 MuiButton-flat-90 MuiButton-colorInherit-106\\" tabindex=\\"0\\" type=\\"button\\" id=\\"header--button-login\\"><span class=\\"MuiButton-label-86\\">Login</span></button></div></div></header></div>"`;
|
||||||
|
@ -1,5 +1,163 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`<NotFound /> component should load the component in default state 1`] = `"<div class=\\"css-24p7uw e1gvymku0\\"><h1>Error 404 - test</h1><hr><p>Oops, The package you are trying to access does not exist.</p></div>"`;
|
exports[`<NotFound /> component should load the component in default state 1`] = `
|
||||||
|
ShallowWrapper {
|
||||||
exports[`<NotFound /> component should set html from props 1`] = `"<div class=\\"css-24p7uw e1gvymku0\\"><h1>Error 404 - verdaccio</h1><hr/><p>Oops, The package you are trying to access does not exist.</p></div>"`;
|
Symbol(enzyme.__root__): ShallowWrapper {
|
||||||
|
Symbol(enzyme.__root__): [Circular],
|
||||||
|
Symbol(enzyme.__unrendered__): <BrowserRouter>
|
||||||
|
<withRouter(WithTheme(WithWidth(NotFound))) />
|
||||||
|
</BrowserRouter>,
|
||||||
|
Symbol(enzyme.__renderer__): Object {
|
||||||
|
"batchedUpdates": [Function],
|
||||||
|
"getNode": [Function],
|
||||||
|
"render": [Function],
|
||||||
|
"simulateError": [Function],
|
||||||
|
"simulateEvent": [Function],
|
||||||
|
"unmount": [Function],
|
||||||
|
},
|
||||||
|
Symbol(enzyme.__node__): Object {
|
||||||
|
"instance": null,
|
||||||
|
"key": undefined,
|
||||||
|
"nodeType": "class",
|
||||||
|
"props": Object {
|
||||||
|
"children": <withRouter(WithTheme(WithWidth(NotFound))) />,
|
||||||
|
"history": Object {
|
||||||
|
"action": "POP",
|
||||||
|
"block": [Function],
|
||||||
|
"createHref": [Function],
|
||||||
|
"go": [Function],
|
||||||
|
"goBack": [Function],
|
||||||
|
"goForward": [Function],
|
||||||
|
"length": 1,
|
||||||
|
"listen": [Function],
|
||||||
|
"location": Object {
|
||||||
|
"hash": "",
|
||||||
|
"pathname": "/",
|
||||||
|
"search": "",
|
||||||
|
"state": undefined,
|
||||||
|
},
|
||||||
|
"push": [Function],
|
||||||
|
"replace": [Function],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"ref": null,
|
||||||
|
"rendered": Object {
|
||||||
|
"instance": null,
|
||||||
|
"key": undefined,
|
||||||
|
"nodeType": "function",
|
||||||
|
"props": Object {},
|
||||||
|
"ref": null,
|
||||||
|
"rendered": null,
|
||||||
|
"type": [Function],
|
||||||
|
},
|
||||||
|
"type": [Function],
|
||||||
|
},
|
||||||
|
Symbol(enzyme.__nodes__): Array [
|
||||||
|
Object {
|
||||||
|
"instance": null,
|
||||||
|
"key": undefined,
|
||||||
|
"nodeType": "class",
|
||||||
|
"props": Object {
|
||||||
|
"children": <withRouter(WithTheme(WithWidth(NotFound))) />,
|
||||||
|
"history": Object {
|
||||||
|
"action": "POP",
|
||||||
|
"block": [Function],
|
||||||
|
"createHref": [Function],
|
||||||
|
"go": [Function],
|
||||||
|
"goBack": [Function],
|
||||||
|
"goForward": [Function],
|
||||||
|
"length": 1,
|
||||||
|
"listen": [Function],
|
||||||
|
"location": Object {
|
||||||
|
"hash": "",
|
||||||
|
"pathname": "/",
|
||||||
|
"search": "",
|
||||||
|
"state": undefined,
|
||||||
|
},
|
||||||
|
"push": [Function],
|
||||||
|
"replace": [Function],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"ref": null,
|
||||||
|
"rendered": Object {
|
||||||
|
"instance": null,
|
||||||
|
"key": undefined,
|
||||||
|
"nodeType": "function",
|
||||||
|
"props": Object {},
|
||||||
|
"ref": null,
|
||||||
|
"rendered": null,
|
||||||
|
"type": [Function],
|
||||||
|
},
|
||||||
|
"type": [Function],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
Symbol(enzyme.__options__): Object {
|
||||||
|
"adapter": ReactSixteenAdapter {
|
||||||
|
"options": Object {
|
||||||
|
"enableComponentDidUpdateOnSetState": true,
|
||||||
|
"lifecycles": Object {
|
||||||
|
"componentDidUpdate": Object {
|
||||||
|
"onSetState": true,
|
||||||
|
},
|
||||||
|
"getDerivedStateFromProps": true,
|
||||||
|
"getSnapshotBeforeUpdate": true,
|
||||||
|
"setState": Object {
|
||||||
|
"skipsComponentDidUpdateOnNullish": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"attachTo": undefined,
|
||||||
|
"hydrateIn": undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Symbol(enzyme.__unrendered__): null,
|
||||||
|
Symbol(enzyme.__renderer__): Object {
|
||||||
|
"batchedUpdates": [Function],
|
||||||
|
"getNode": [Function],
|
||||||
|
"render": [Function],
|
||||||
|
"simulateError": [Function],
|
||||||
|
"simulateEvent": [Function],
|
||||||
|
"unmount": [Function],
|
||||||
|
},
|
||||||
|
Symbol(enzyme.__node__): Object {
|
||||||
|
"instance": null,
|
||||||
|
"key": undefined,
|
||||||
|
"nodeType": "function",
|
||||||
|
"props": Object {},
|
||||||
|
"ref": null,
|
||||||
|
"rendered": null,
|
||||||
|
"type": [Function],
|
||||||
|
},
|
||||||
|
Symbol(enzyme.__nodes__): Array [
|
||||||
|
Object {
|
||||||
|
"instance": null,
|
||||||
|
"key": undefined,
|
||||||
|
"nodeType": "function",
|
||||||
|
"props": Object {},
|
||||||
|
"ref": null,
|
||||||
|
"rendered": null,
|
||||||
|
"type": [Function],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
Symbol(enzyme.__options__): Object {
|
||||||
|
"adapter": ReactSixteenAdapter {
|
||||||
|
"options": Object {
|
||||||
|
"enableComponentDidUpdateOnSetState": true,
|
||||||
|
"lifecycles": Object {
|
||||||
|
"componentDidUpdate": Object {
|
||||||
|
"onSetState": true,
|
||||||
|
},
|
||||||
|
"getDerivedStateFromProps": true,
|
||||||
|
"getSnapshotBeforeUpdate": true,
|
||||||
|
"setState": Object {
|
||||||
|
"skipsComponentDidUpdateOnNullish": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"attachTo": undefined,
|
||||||
|
"hydrateIn": undefined,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// 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\\"><a class=\\"package css-zrrjf6 e11fsc2k16\\" href=\\"version/verdaccio\\"><div class=\\"css-esn5nr e11fsc2k0\\"><span class=\\"css-1e6w198 e11fsc2k2\\"><span class=\\"css-bxt2bt e11fsc2k1\\">verdaccio</span><span class=\\"css-17xn9wj e11fsc2k5\\">v1.0.0</span></span><span class=\\"css-1dq57rh e11fsc2k4\\"><span class=\\"css-19brcdm e11fsc2k3\\"><svg class=\\"e11fsc2k6 css-y8pkl4 ej4jd2o0\\"><title>Time</title><use xlink:href=\\"[object Object]#time\\"></use></svg><span class=\\"css-1qw5qv3 e11fsc2k7\\">Published on 21.07.2018, 22:11:12 •</span>6 months ago</span></span></div><div class=\\"css-tywa7u e11fsc2k9\\"><div class=\\"css-hnjjgz e11fsc2k8\\"><div class=\\"css-15496ft e11fsc2k12\\"><div class=\\"MuiAvatar-root-128 MuiAvatar-colorDefault-129 css-1to0t9u e11fsc2k13\\">S</div><span class=\\"css-1xj37ub e11fsc2k11\\"><div class=\\"e11fsc2k10 css-1xe0n7g e1pneb170\\">Sam</div></span></div></div><div class=\\"css-hnjjgz e11fsc2k8\\"><div class=\\"css-1b14dls e11fsc2k14\\">Private NPM repository</div></div></div></a><a class=\\"package css-zrrjf6 e11fsc2k16\\" href=\\"version/abc\\"><div class=\\"css-esn5nr e11fsc2k0\\"><span class=\\"css-1e6w198 e11fsc2k2\\"><span class=\\"css-bxt2bt e11fsc2k1\\">abc</span><span class=\\"css-17xn9wj e11fsc2k5\\">v1.0.1</span></span><span class=\\"css-1dq57rh e11fsc2k4\\"><span class=\\"css-19brcdm e11fsc2k3\\"><svg class=\\"e11fsc2k6 css-y8pkl4 ej4jd2o0\\"><title>Time</title><use xlink:href=\\"[object Object]#time\\"></use></svg><span class=\\"css-1qw5qv3 e11fsc2k7\\">Published on 21.07.2018, 22:11:12 •</span>6 months ago</span></span></div><div class=\\"css-tywa7u e11fsc2k9\\"><div class=\\"css-hnjjgz e11fsc2k8\\"><div class=\\"css-15496ft e11fsc2k12\\"><div class=\\"MuiAvatar-root-128 MuiAvatar-colorDefault-129 css-1to0t9u e11fsc2k13\\">R</div><span class=\\"css-1xj37ub e11fsc2k11\\"><div class=\\"e11fsc2k10 css-1xe0n7g e1pneb170\\">Rose</div></span></div></div><div class=\\"css-hnjjgz e11fsc2k8\\"><div class=\\"css-1b14dls e11fsc2k14\\">abc description</div></div></div></a><a class=\\"package css-zrrjf6 e11fsc2k16\\" href=\\"version/xyz\\"><div class=\\"css-esn5nr e11fsc2k0\\"><span class=\\"css-1e6w198 e11fsc2k2\\"><span class=\\"css-bxt2bt e11fsc2k1\\">xyz</span><span class=\\"css-17xn9wj e11fsc2k5\\">v1.1.0</span></span><span class=\\"css-1dq57rh e11fsc2k4\\"><span class=\\"css-19brcdm e11fsc2k3\\"><svg class=\\"e11fsc2k6 css-y8pkl4 ej4jd2o0\\"><title>Time</title><use xlink:href=\\"[object Object]#time\\"></use></svg><span class=\\"css-1qw5qv3 e11fsc2k7\\">Published on Invalid Date •</span>almost NaN years ago</span></span></div><div class=\\"css-tywa7u e11fsc2k9\\"><div class=\\"css-hnjjgz e11fsc2k8\\"><div class=\\"css-15496ft e11fsc2k12\\"><div class=\\"MuiAvatar-root-128 MuiAvatar-colorDefault-129 css-1to0t9u e11fsc2k13\\">M</div><span class=\\"css-1xj37ub e11fsc2k11\\"><div class=\\"e11fsc2k10 css-1xe0n7g e1pneb170\\">Martin</div></span></div></div><div class=\\"css-hnjjgz e11fsc2k8\\"><div class=\\"css-1b14dls e11fsc2k14\\">xyz description</div></div></div></a></div></div>"`;
|
exports[`<PackageList /> component should load the component with packages 1`] = `"<div class=\\"package-list-items\\"><div class=\\"pkgContainer\\"><a class=\\"package css-zrrjf6 e11fsc2k16\\" href=\\"/-/web/version/verdaccio\\"><div class=\\"css-esn5nr e11fsc2k0\\"><span class=\\"css-1e6w198 e11fsc2k2\\"><span class=\\"css-bxt2bt e11fsc2k1\\">verdaccio</span><span class=\\"css-17xn9wj e11fsc2k5\\">v1.0.0</span></span><span class=\\"css-1dq57rh e11fsc2k4\\"><span class=\\"css-19brcdm e11fsc2k3\\"><svg class=\\"e11fsc2k6 css-y8pkl4 ej4jd2o0\\"><title>Time</title><use xlink:href=\\"[object Object]#time\\"></use></svg><span class=\\"css-1qw5qv3 e11fsc2k7\\">Published on 21.07.2018, 22:11:12 •</span>7 months ago</span></span></div><div class=\\"css-tywa7u e11fsc2k9\\"><div class=\\"css-hnjjgz e11fsc2k8\\"><div class=\\"css-15496ft e11fsc2k12\\"><div class=\\"MuiAvatar-root-128 MuiAvatar-colorDefault-129 css-1to0t9u e11fsc2k13\\">S</div><span class=\\"css-1xj37ub e11fsc2k11\\"><div class=\\"e11fsc2k10 css-1xe0n7g e1pneb170\\">Sam</div></span></div></div><div class=\\"css-hnjjgz e11fsc2k8\\"><div class=\\"css-1b14dls e11fsc2k14\\">Private NPM repository</div></div></div></a><a class=\\"package css-zrrjf6 e11fsc2k16\\" href=\\"/-/web/version/abc\\"><div class=\\"css-esn5nr e11fsc2k0\\"><span class=\\"css-1e6w198 e11fsc2k2\\"><span class=\\"css-bxt2bt e11fsc2k1\\">abc</span><span class=\\"css-17xn9wj e11fsc2k5\\">v1.0.1</span></span><span class=\\"css-1dq57rh e11fsc2k4\\"><span class=\\"css-19brcdm e11fsc2k3\\"><svg class=\\"e11fsc2k6 css-y8pkl4 ej4jd2o0\\"><title>Time</title><use xlink:href=\\"[object Object]#time\\"></use></svg><span class=\\"css-1qw5qv3 e11fsc2k7\\">Published on 21.07.2018, 22:11:12 •</span>7 months ago</span></span></div><div class=\\"css-tywa7u e11fsc2k9\\"><div class=\\"css-hnjjgz e11fsc2k8\\"><div class=\\"css-15496ft e11fsc2k12\\"><div class=\\"MuiAvatar-root-128 MuiAvatar-colorDefault-129 css-1to0t9u e11fsc2k13\\">R</div><span class=\\"css-1xj37ub e11fsc2k11\\"><div class=\\"e11fsc2k10 css-1xe0n7g e1pneb170\\">Rose</div></span></div></div><div class=\\"css-hnjjgz e11fsc2k8\\"><div class=\\"css-1b14dls e11fsc2k14\\">abc description</div></div></div></a><a class=\\"package css-zrrjf6 e11fsc2k16\\" href=\\"/-/web/version/xyz\\"><div class=\\"css-esn5nr e11fsc2k0\\"><span class=\\"css-1e6w198 e11fsc2k2\\"><span class=\\"css-bxt2bt e11fsc2k1\\">xyz</span><span class=\\"css-17xn9wj e11fsc2k5\\">v1.1.0</span></span><span class=\\"css-1dq57rh e11fsc2k4\\"><span class=\\"css-19brcdm e11fsc2k3\\"><svg class=\\"e11fsc2k6 css-y8pkl4 ej4jd2o0\\"><title>Time</title><use xlink:href=\\"[object Object]#time\\"></use></svg><span class=\\"css-1qw5qv3 e11fsc2k7\\">Published on Invalid Date •</span>almost NaN years ago</span></span></div><div class=\\"css-tywa7u e11fsc2k9\\"><div class=\\"css-hnjjgz e11fsc2k8\\"><div class=\\"css-15496ft e11fsc2k12\\"><div class=\\"MuiAvatar-root-128 MuiAvatar-colorDefault-129 css-1to0t9u e11fsc2k13\\">M</div><span class=\\"css-1xj37ub e11fsc2k11\\"><div class=\\"e11fsc2k10 css-1xe0n7g e1pneb170\\">Martin</div></span></div></div><div class=\\"css-hnjjgz e11fsc2k8\\"><div class=\\"css-1b14dls e11fsc2k14\\">xyz description</div></div></div></a></div></div>"`;
|
||||||
|
@ -4,11 +4,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { mount } from 'enzyme';
|
import { BrowserRouter as Router } from 'react-router-dom';
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
import Header from '../../../../src/webui/components/Header';
|
import Header from '../../../../src/webui/components/Header';
|
||||||
|
|
||||||
describe('<Header /> component with logged in state', () => {
|
describe('<Header /> component with logged in state', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
|
let routerWrapper;
|
||||||
|
let instance;
|
||||||
let props;
|
let props;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -20,7 +23,13 @@ describe('<Header /> component with logged in state', () => {
|
|||||||
scope: 'test scope',
|
scope: 'test scope',
|
||||||
withoutSearch: true,
|
withoutSearch: true,
|
||||||
};
|
};
|
||||||
wrapper = mount(<Header {...props} />);
|
routerWrapper = shallow(
|
||||||
|
<Router>
|
||||||
|
<Header {...props} />
|
||||||
|
</Router>
|
||||||
|
);
|
||||||
|
wrapper = routerWrapper.find(Header).dive();
|
||||||
|
instance = wrapper.instance();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should load the component in logged in state', () => {
|
test('should load the component in logged in state', () => {
|
||||||
@ -30,13 +39,12 @@ describe('<Header /> component with logged in state', () => {
|
|||||||
registryUrl: 'http://localhost',
|
registryUrl: 'http://localhost',
|
||||||
showMobileNavBar: false,
|
showMobileNavBar: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(wrapper.state()).toEqual(state);
|
expect(wrapper.state()).toEqual(state);
|
||||||
expect(wrapper.html()).toMatchSnapshot();
|
expect(routerWrapper.html()).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('handleLoggedInMenu: set anchorEl to html element value in state', () => {
|
test('handleLoggedInMenu: set anchorEl to html element value in state', () => {
|
||||||
const { handleLoggedInMenu } = wrapper.instance();
|
|
||||||
|
|
||||||
// creates a sample menu
|
// creates a sample menu
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
const text = document.createTextNode('sample menu');
|
const text = document.createTextNode('sample menu');
|
||||||
@ -46,13 +54,15 @@ describe('<Header /> component with logged in state', () => {
|
|||||||
currentTarget: div,
|
currentTarget: div,
|
||||||
};
|
};
|
||||||
|
|
||||||
handleLoggedInMenu(event);
|
instance.handleLoggedInMenu(event);
|
||||||
expect(wrapper.state('anchorEl')).toEqual(div);
|
expect(wrapper.state('anchorEl')).toEqual(div);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('<Header /> component with logged out state', () => {
|
describe('<Header /> component with logged out state', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
|
let routerWrapper;
|
||||||
|
let instance;
|
||||||
let props;
|
let props;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -63,7 +73,13 @@ describe('<Header /> component with logged out state', () => {
|
|||||||
logo: '',
|
logo: '',
|
||||||
withoutSearch: true,
|
withoutSearch: true,
|
||||||
};
|
};
|
||||||
wrapper = mount(<Header {...props} />);
|
routerWrapper = shallow(
|
||||||
|
<Router>
|
||||||
|
<Header {...props} />
|
||||||
|
</Router>
|
||||||
|
);
|
||||||
|
wrapper = routerWrapper.find(Header).dive();
|
||||||
|
instance = wrapper.instance();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should load the component in logged out state', () => {
|
test('should load the component in logged out state', () => {
|
||||||
@ -74,30 +90,26 @@ describe('<Header /> component with logged out state', () => {
|
|||||||
showMobileNavBar: false,
|
showMobileNavBar: false,
|
||||||
};
|
};
|
||||||
expect(wrapper.state()).toEqual(state);
|
expect(wrapper.state()).toEqual(state);
|
||||||
expect(wrapper.html()).toMatchSnapshot();
|
expect(routerWrapper.html()).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('handleLoggedInMenuClose: set anchorEl value to null in state', () => {
|
test('handleLoggedInMenuClose: set anchorEl value to null in state', () => {
|
||||||
const { handleLoggedInMenuClose } = wrapper.instance();
|
instance.handleLoggedInMenuClose();
|
||||||
handleLoggedInMenuClose();
|
|
||||||
expect(wrapper.state('anchorEl')).toBeNull();
|
expect(wrapper.state('anchorEl')).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('handleOpenRegistryInfoDialog: set openInfoDialog to be truthy in state', () => {
|
test('handleOpenRegistryInfoDialog: set openInfoDialog to be truthy in state', () => {
|
||||||
const { handleOpenRegistryInfoDialog } = wrapper.instance();
|
instance.handleOpenRegistryInfoDialog();
|
||||||
handleOpenRegistryInfoDialog();
|
|
||||||
expect(wrapper.state('openInfoDialog')).toBeTruthy();
|
expect(wrapper.state('openInfoDialog')).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('handleCloseRegistryInfoDialog: set openInfoDialog to be falsy in state', () => {
|
test('handleCloseRegistryInfoDialog: set openInfoDialog to be falsy in state', () => {
|
||||||
const { handleCloseRegistryInfoDialog } = wrapper.instance();
|
instance.handleCloseRegistryInfoDialog();
|
||||||
handleCloseRegistryInfoDialog();
|
|
||||||
expect(wrapper.state('openInfoDialog')).toBeFalsy();
|
expect(wrapper.state('openInfoDialog')).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('handleToggleLogin: close/open popover menu', () => {
|
test('handleToggleLogin: close/open popover menu', () => {
|
||||||
const { handleToggleLogin } = wrapper.instance();
|
instance.handleToggleLogin();
|
||||||
handleToggleLogin();
|
|
||||||
expect(wrapper.state('anchorEl')).toBeNull();
|
expect(wrapper.state('anchorEl')).toBeNull();
|
||||||
expect(props.onToggleLoginModal).toHaveBeenCalled();
|
expect(props.onToggleLoginModal).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
@ -3,26 +3,25 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow, mount } from 'enzyme';
|
import { BrowserRouter as Router } from 'react-router-dom';
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
import NotFound from '../../../../src/webui/components/NotFound/index';
|
import NotFound from '../../../../src/webui/components/NotFound/index';
|
||||||
|
|
||||||
console.error = jest.fn();
|
console.error = jest.fn();
|
||||||
|
|
||||||
describe('<NotFound /> component', () => {
|
describe('<NotFound /> component', () => {
|
||||||
test('should load the component in default state', () => {
|
let routerWrapper;
|
||||||
const wrapper = mount(<NotFound pkg={"test"} />);
|
beforeEach(() => {
|
||||||
expect(wrapper.html()).toMatchSnapshot();
|
routerWrapper = shallow(
|
||||||
|
<Router>
|
||||||
|
<NotFound />
|
||||||
|
</Router>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should set html from props', () => {
|
|
||||||
const props = {
|
test('should load the component in default state', () => {
|
||||||
pkg: 'verdaccio'
|
expect(routerWrapper.find(NotFound)).toMatchSnapshot();
|
||||||
};
|
|
||||||
const wrapper = shallow(<NotFound {...props} />);
|
|
||||||
expect(wrapper.find('h1').text()).toEqual('Error 404 - verdaccio');
|
|
||||||
expect(wrapper.find('p').text()).toEqual(
|
|
||||||
'Oops, The package you are trying to access does not exist.'
|
|
||||||
);
|
|
||||||
expect(wrapper.html()).toMatchSnapshot();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { mount } from 'enzyme';
|
import { mount } from 'enzyme';
|
||||||
|
|
||||||
import Search from '../../../../src/webui/components/Search/index';
|
import { Search } from '../../../../src/webui/components/Search/index';
|
||||||
|
|
||||||
const SEARCH_FILE_PATH = '../../../../src/webui/components/Search/index';
|
const SEARCH_FILE_PATH = '../../../../src/webui/components/Search/index';
|
||||||
const API_FILE_PATH = '../../../../src/webui/utils/api';
|
const API_FILE_PATH = '../../../../src/webui/utils/api';
|
||||||
@ -121,7 +121,7 @@ describe('<Search /> component: mocks specific tests ', () => {
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const Search = require(SEARCH_FILE_PATH).default;
|
const Search = require(SEARCH_FILE_PATH).Search;
|
||||||
const component = mount(<Search />);
|
const component = mount(<Search />);
|
||||||
component.setState({ search: 'verdaccio' });
|
component.setState({ search: 'verdaccio' });
|
||||||
const { handleFetchPackages } = component.instance();
|
const { handleFetchPackages } = component.instance();
|
||||||
@ -138,7 +138,7 @@ describe('<Search /> component: mocks specific tests ', () => {
|
|||||||
|
|
||||||
jest.doMock(API_FILE_PATH, () => ({ request: jest.fn(() => Promise.reject(apiResponse)) }));
|
jest.doMock(API_FILE_PATH, () => ({ request: jest.fn(() => Promise.reject(apiResponse)) }));
|
||||||
|
|
||||||
const Search = require(SEARCH_FILE_PATH).default;
|
const Search = require(SEARCH_FILE_PATH).Search;
|
||||||
const component = mount(<Search />);
|
const component = mount(<Search />);
|
||||||
component.setState({ search: 'verdaccio' });
|
component.setState({ search: 'verdaccio' });
|
||||||
const { handleFetchPackages } = component.instance();
|
const { handleFetchPackages } = component.instance();
|
||||||
@ -159,7 +159,7 @@ describe('<Search /> component: mocks specific tests ', () => {
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const Search = require(SEARCH_FILE_PATH).default;
|
const Search = require(SEARCH_FILE_PATH).Search;
|
||||||
const component = mount(<Search />);
|
const component = mount(<Search />);
|
||||||
component.setState({ search: 'verdaccio' });
|
component.setState({ search: 'verdaccio' });
|
||||||
const { handleFetchPackages } = component.instance();
|
const { handleFetchPackages } = component.instance();
|
||||||
@ -175,20 +175,19 @@ describe('<Search /> component: mocks specific tests ', () => {
|
|||||||
jest.doMock(URL_FILE_PATH, () => ({ getDetailPageURL }));
|
jest.doMock(URL_FILE_PATH, () => ({ getDetailPageURL }));
|
||||||
|
|
||||||
const suggestionValue = [];
|
const suggestionValue = [];
|
||||||
const Search = require(SEARCH_FILE_PATH).default;
|
const Search = require(SEARCH_FILE_PATH).Search;
|
||||||
const component = mount(<Search />);
|
const pushHandler = jest.fn();
|
||||||
|
const component = mount(<Search history={{ push: pushHandler }} />);
|
||||||
const { handleClickSearch } = component.instance();
|
const { handleClickSearch } = component.instance();
|
||||||
|
|
||||||
// click
|
// click
|
||||||
handleClickSearch(event, { suggestionValue, method: 'click' });
|
handleClickSearch(event, { suggestionValue, method: 'click' });
|
||||||
expect(event.stopPropagation).toHaveBeenCalled();
|
expect(event.stopPropagation).toHaveBeenCalled();
|
||||||
expect(getDetailPageURL).toHaveBeenCalledWith(suggestionValue);
|
expect(pushHandler).toHaveBeenCalledTimes(1);
|
||||||
expect(window.location.assign).toHaveBeenCalledWith('detail/page/url');
|
|
||||||
|
|
||||||
// return key
|
// return key
|
||||||
handleClickSearch(event, { suggestionValue, method: 'enter' });
|
handleClickSearch(event, { suggestionValue, method: 'enter' });
|
||||||
expect(event.stopPropagation).toHaveBeenCalled();
|
expect(event.stopPropagation).toHaveBeenCalled();
|
||||||
expect(getDetailPageURL).toHaveBeenCalledWith(suggestionValue);
|
expect(pushHandler).toHaveBeenCalledTimes(2);
|
||||||
expect(window.location.assign).toHaveBeenCalledWith('detail/page/url');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
BIN
yarn.lock
BIN
yarn.lock
Binary file not shown.
Loading…
Reference in New Issue
Block a user