mirror of
https://github.com/SomboChea/ui
synced 2026-01-12 06:05:43 +07:00
feat: migrating flow to typescript (#47)
This PR convert the code base to Typescript, the changes are the following: - migrate code base to Typescript (3.4.x) - enable `eslint` and `@typescript-eslint/eslint-plugin` (warnings still need to be addressed in future pull request - update relevant dependencies for this PR (linting, etc) - enable `bundlezise` (it was disabled for some reason) * refactor: refactoring to typescript * refactor: migrating to typescript * refactor: applied feedbacks * fix: fixed conflicts * refactored: changed registry * refactor: updated registry & removed unnecessary lib * fix: fixed registry ur * fix: fixed page load * refactor: refactored footer wip * refactor: converting to ts..wip * refactor: converting to ts. wip * refactor: converting to ts. wip * refactor: converting to ts * refactor: converting to ts * fix: fixed load errors * refactor: converted files to ts * refactor: removed flow from tests * fix: removed transpiled files * refactor: added ts-ignore * fix: fixed errors * fix: fixed types * fix: fixing jest import -.- * fix: fixing lint errors * fix: fixing lint errors * fix: fixed lint errors * refactor: removed unnecessary tsconfig's config * fix: fixing errors * fix: fixed warning * fix: fixed test * refactor: wip * refactor: wip * refactor: wip * fix: fixing tests: wip * wip * wip * fix: fixed search test * wip * fix: fixing lint errors * fix: re-added stylelint * refactor: updated stylelint script * fix: fixed: 'styles.js' were found. * fix: fixed Search tests * chore: enable eslint eslint needs expecitely to know which file has to lint, by default is JS, in this case we need also ts,tsx files eslint . --ext .js,.ts * chore: vcode eslint settings * chore: restore eslint previous conf * chore: clean jest config * chore: fix eslint warnings * chore: eslint errors cleared chore: clean warnings chore: remove github actions test phases chore: remove dupe rule * chore: update handler name * chore: restore logo from img to url css prop - loading images with css is more performant than using img html tags, switching this might be a breaking change - restore no-empty-source seems the linting do not accept false - update snapshots - remove @material-ui/styles * chore: update stylelint linting * chore: update stylelint linting * chore: fix a mistake on move tabs to a function * chore: eanble bundlezie * chore: use default_executor in circleci * chore: update readme
This commit is contained in:
committed by
Juan Picado @jotadeveloper
parent
7d1764458b
commit
6b5d0b7e2e
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"extends": [
|
||||
"eslint:recommended"
|
||||
],
|
||||
"env": {
|
||||
"node": true,
|
||||
"mocha": true,
|
||||
"es6": true
|
||||
},
|
||||
"globals": {
|
||||
"jsdom": true
|
||||
},
|
||||
"rules": {
|
||||
"valid-jsdoc": 0,
|
||||
"no-redeclare": 1,
|
||||
"jest/consistent-test-it": ["error", {"fn": "test"}],
|
||||
"jest/no-jasmine-globals": 2,
|
||||
"no-console": [
|
||||
2,
|
||||
{
|
||||
"allow": [
|
||||
"log",
|
||||
"error"
|
||||
]
|
||||
}
|
||||
],
|
||||
"no-useless-escape": 0
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
// @flow
|
||||
|
||||
export interface IVerdaccioConfig {
|
||||
storagePath: string;
|
||||
configPath: string;
|
||||
domainPath: string;
|
||||
port: number;
|
||||
}
|
||||
|
||||
export interface IRequestPromise {
|
||||
status(reason: any): any;
|
||||
body_ok(reason: any): any;
|
||||
body_error(reason: any): any;
|
||||
request(reason: any): any;
|
||||
response(reason: any): any;
|
||||
send(reason: any): any;
|
||||
}
|
||||
|
||||
export interface IServerProcess {
|
||||
bridge: IServerBridge;
|
||||
config: IVerdaccioConfig;
|
||||
childFork: any;
|
||||
isDebug: boolean;
|
||||
silence: boolean;
|
||||
init(): Promise<any>;
|
||||
stop(): void;
|
||||
}
|
||||
|
||||
declare class verdaccio$PromiseAssert<IRequestPromise> extends Promise<any> {
|
||||
constructor(options: any): IRequestPromise;
|
||||
}
|
||||
|
||||
export interface IServerBridge {
|
||||
url: string;
|
||||
userAgent: string;
|
||||
authstr: string;
|
||||
request(options: any): typeof verdaccio$PromiseAssert;
|
||||
auth(name: string, password: string): IRequestPromise;
|
||||
logout(token: string): Promise<any>;
|
||||
auth(name: string, password: string): IRequestPromise;
|
||||
getPackage(name: string): Promise<any>;
|
||||
putPackage(name: string, data: any): Promise<any>;
|
||||
putVersion(name: string, version: string, data: any): Promise<any>;
|
||||
getTarball(name: string, filename: string): Promise<any>;
|
||||
putTarball(name: string, filename: string, data: any): Promise<any>;
|
||||
removeTarball(name: string): Promise<any>;
|
||||
removeSingleTarball(name: string, filename: string): Promise<any>;
|
||||
addTag(name: string, tag: string, version: string): Promise<any>;
|
||||
putTarballIncomplete(name: string, filename: string, data: any, size: number, cb: Function): Promise<any>;
|
||||
addPackage(name: string): Promise<any>;
|
||||
whoami(): Promise<any>;
|
||||
ping(): Promise<any>;
|
||||
debug(): IRequestPromise;
|
||||
}
|
||||
5
test/unit/.eslintrc
Normal file
5
test/unit/.eslintrc
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-console": 0
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import storage from '../../src/webui/utils/storage';
|
||||
import App from '../../src/webui/app';
|
||||
|
||||
import { generateTokenWithTimeRange } from './components/__mocks__/token';
|
||||
|
||||
jest.mock('../../src/webui/utils/storage', () => {
|
||||
class LocalStorageMock {
|
||||
constructor() {
|
||||
this.store = {};
|
||||
}
|
||||
clear() {
|
||||
this.store = {};
|
||||
}
|
||||
getItem(key) {
|
||||
return this.store[key] || null;
|
||||
}
|
||||
setItem(key, value) {
|
||||
this.store[key] = value.toString();
|
||||
}
|
||||
removeItem(key) {
|
||||
delete this.store[key];
|
||||
}
|
||||
}
|
||||
return new LocalStorageMock();
|
||||
});
|
||||
|
||||
jest.mock('../../src/webui/utils/api', () => ({
|
||||
request: require('./components/__mocks__/api').default.request
|
||||
}));
|
||||
|
||||
describe('App', () => {
|
||||
let wrapper;
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = mount(<App />);
|
||||
});
|
||||
|
||||
test('toggleLoginModal: should toggle the value in state', () => {
|
||||
const { handleToggleLoginModal } = wrapper.instance();
|
||||
expect(wrapper.state().showLoginModal).toBeFalsy();
|
||||
handleToggleLoginModal();
|
||||
expect(wrapper.state('showLoginModal')).toBeTruthy();
|
||||
expect(wrapper.state('error')).toEqual({});
|
||||
});
|
||||
|
||||
test('isUserAlreadyLoggedIn: token already available in storage', async () => {
|
||||
|
||||
storage.setItem('username', 'verdaccio');
|
||||
storage.setItem('token', generateTokenWithTimeRange(24));
|
||||
const { isUserAlreadyLoggedIn } = wrapper.instance();
|
||||
|
||||
isUserAlreadyLoggedIn();
|
||||
|
||||
expect(wrapper.state('user').username).toEqual('verdaccio');
|
||||
});
|
||||
|
||||
test('handleLogout - logouts the user and clear localstorage', async () => {
|
||||
const { handleLogout } = wrapper.instance();
|
||||
storage.setItem('username', 'verdaccio');
|
||||
storage.setItem('token', 'xxxx.TOKEN.xxxx');
|
||||
|
||||
await handleLogout();
|
||||
expect(wrapper.state('user')).toEqual({});
|
||||
expect(wrapper.state('isUserLoggedIn')).toBeFalsy();
|
||||
});
|
||||
|
||||
test('handleDoLogin - login the user successfully', async () => {
|
||||
const { handleDoLogin } = wrapper.instance();
|
||||
await handleDoLogin('sam', '1234');
|
||||
const result = {
|
||||
username: 'sam',
|
||||
token: 'TEST_TOKEN'
|
||||
};
|
||||
expect(wrapper.state('isUserLoggedIn')).toBeTruthy();
|
||||
expect(wrapper.state('showLoginModal')).toBeFalsy();
|
||||
expect(storage.getItem('username')).toEqual('sam');
|
||||
expect(storage.getItem('token')).toEqual('TEST_TOKEN');
|
||||
expect(wrapper.state('user')).toEqual(result);
|
||||
});
|
||||
|
||||
test('handleDoLogin - authentication failure', async () => {
|
||||
const { handleDoLogin } = wrapper.instance();
|
||||
await handleDoLogin('sam', '12345');
|
||||
const result = {
|
||||
description: 'bad username/password, access denied',
|
||||
title: 'Unable to login',
|
||||
type: 'error'
|
||||
};
|
||||
expect(wrapper.state('user')).toEqual({});
|
||||
expect(wrapper.state('error')).toEqual(result);
|
||||
});
|
||||
});
|
||||
@@ -1,48 +0,0 @@
|
||||
/**
|
||||
* API Mocks for WebUI
|
||||
*/
|
||||
import logo from '../store/logo';
|
||||
import login from '../store/login';
|
||||
import { packageMeta } from '../store/packageMeta';
|
||||
import { packageInformation } from '../store/package';
|
||||
|
||||
/**
|
||||
* Register mock api endpoints
|
||||
* @param {string} endpoint
|
||||
* @returns {Promise}
|
||||
*/
|
||||
const register = (url, method = 'get', options = {}) => {
|
||||
|
||||
if (url === 'login' && method.toLocaleLowerCase() === 'post') {
|
||||
return login(options);
|
||||
}
|
||||
|
||||
if (url === 'logo' && method.toLocaleLowerCase() === 'get') {
|
||||
return logo();
|
||||
}
|
||||
|
||||
if (url === 'sidebar/verdaccio' && method.toLocaleLowerCase() === 'get') {
|
||||
return new Promise(function(resolve) {
|
||||
resolve(packageMeta);
|
||||
});
|
||||
}
|
||||
|
||||
if (url === 'packages' && method.toLocaleLowerCase() === 'get') {
|
||||
return new Promise(function (resolve) {
|
||||
resolve(packageInformation);
|
||||
});
|
||||
}
|
||||
|
||||
throw Error(`URL not found: ${url}`);
|
||||
};
|
||||
|
||||
/**
|
||||
* Bind API methods
|
||||
*/
|
||||
class API {
|
||||
request() {
|
||||
return register.call(null, ...arguments);
|
||||
}
|
||||
}
|
||||
|
||||
export default new API;
|
||||
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* Token Utility
|
||||
*/
|
||||
|
||||
import { Base64 } from 'js-base64';
|
||||
import addHours from 'date-fns/add_hours';
|
||||
|
||||
export function generateTokenWithTimeRange (limit = 0) {
|
||||
const payload = {
|
||||
username: 'verdaccio',
|
||||
exp: Number.parseInt(addHours(new Date(), limit).getTime() / 1000, 10)
|
||||
};
|
||||
return `xxxxxx.${Base64.encode(JSON.stringify(payload))}.xxxxxx`;
|
||||
}
|
||||
|
||||
export function generateTokenWithExpirationAsString () {
|
||||
const payload = { username: 'verdaccio', exp: 'I am not a number' };
|
||||
return `xxxxxx.${Base64.encode(payload)}.xxxxxx`;
|
||||
}
|
||||
|
||||
export function generateTokenWithOutExpiration (){
|
||||
const payload = {
|
||||
username: 'verdaccio'
|
||||
};
|
||||
return `xxxxxx.${Base64.encode(JSON.stringify(payload))}.xxxxxx`;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<CopyToClipBoard /> component render the component 1`] = `"<div class=\\"css-1mta3t8 e1mfrkg70\\"><span class=\\"css-1m8aenu e1mfrkg71\\">copy text</span><button class=\\"MuiButtonBase-root-15 MuiIconButton-root-9 css-56v3u0 e1mfrkg72\\" tabindex=\\"0\\" type=\\"button\\" title=\\"Copy to Clipboard\\"><span class=\\"MuiIconButton-label-14\\"><svg class=\\"MuiSvgIcon-root-18\\" focusable=\\"false\\" viewBox=\\"0 0 24 24\\" aria-hidden=\\"true\\" role=\\"presentation\\"><path fill=\\"none\\" d=\\"M0 0h24v24H0z\\"></path><path d=\\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm-1 4l6 6v10c0 1.1-.9 2-2 2H7.99C6.89 23 6 22.1 6 21l.01-14c0-1.1.89-2 1.99-2h7zm-1 7h5.5L14 6.5V12z\\"></path></svg></span></button></div>"`;
|
||||
@@ -1,3 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<Footer /> component should load the initial state of Footer component 1`] = `"<div class=\\"css-i0nj2g e19gp4r80\\"><div class=\\"css-hzfs9b e19gp4r81\\"><div class=\\"css-d8nsp7 e19gp4r82\\"> Made with<span class=\\"css-1so4oe0 e19gp4r87\\">♥</span>on<span class=\\"css-1ie354y e19gp4r84\\"><svg class=\\"e19gp4r85 css-1kgp95j e9byyw50\\"><title>Earth</title><use xlink:href=\\"[object Object]#earth\\"></use></svg><span class=\\"css-1v4n0q4 e19gp4r86\\"><svg class=\\"e19gp4r88 css-f1ndto e9byyw50\\"><title>Spain</title><use xlink:href=\\"[object Object]#spain\\"></use></svg><svg class=\\"e19gp4r88 css-f1ndto e9byyw50\\"><title>Nicaragua</title><use xlink:href=\\"[object Object]#nicaragua\\"></use></svg><svg class=\\"e19gp4r88 css-f1ndto e9byyw50\\"><title>India</title><use xlink:href=\\"[object Object]#india\\"></use></svg><svg class=\\"e19gp4r88 css-f1ndto e9byyw50\\"><title>Brazil</title><use xlink:href=\\"[object Object]#brazil\\"></use></svg><svg class=\\"e19gp4r88 css-f1ndto e9byyw50\\"><title>China</title><use xlink:href=\\"[object Object]#china\\"></use></svg><svg class=\\"e19gp4r88 css-f1ndto e9byyw50\\"><title>Austria</title><use xlink:href=\\"[object Object]#austria\\"></use></svg></span></span></div><div class=\\"css-1wbzdyy e19gp4r83\\">Powered by<span class=\\"e19gp4r88 css-i15wza e9byyw51\\" title=\\"Verdaccio\\"><img alt=\\"Verdaccio\\" src=\\"[object Object]\\" class=\\"css-1ncdhax e9byyw52\\"></span>/ v.1.0.0</div></div></div>"`;
|
||||
@@ -1,5 +0,0 @@
|
||||
// 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-k4mg52 e1yrof0d8\\"><div class=\\"MuiToolbar-root-37 MuiToolbar-regular-39 MuiToolbar-gutters-38 css-1pwdmmq e1yrof0d0\\"><div class=\\"MuiToolbar-root-37 MuiToolbar-regular-39 MuiToolbar-gutters-38 css-1vacr9s e1yrof0d3\\"><a style=\\"margin-right:1em\\" href=\\"/\\"><div class=\\"css-12nq0oo e1nk49ti0\\"></div></a></div><div class=\\"MuiToolbar-root-37 MuiToolbar-regular-39 MuiToolbar-gutters-38 css-m61s5i e1yrof0d2\\"><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-k4mg52 e1yrof0d8\\"><div class=\\"MuiToolbar-root-37 MuiToolbar-regular-39 MuiToolbar-gutters-38 css-1pwdmmq e1yrof0d0\\"><div class=\\"MuiToolbar-root-37 MuiToolbar-regular-39 MuiToolbar-gutters-38 css-1vacr9s e1yrof0d3\\"><a style=\\"margin-right:1em\\" href=\\"/\\"><div class=\\"css-12nq0oo e1nk49ti0\\"></div></a></div><div class=\\"MuiToolbar-root-37 MuiToolbar-regular-39 MuiToolbar-gutters-38 css-m61s5i e1yrof0d2\\"><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,3 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<Help /> component should render the component in default state 1`] = `"<div class=\\"MuiPaper-root-2 MuiPaper-elevation1-5 MuiPaper-rounded-3 MuiCard-root-1 css-ryznli e1ail7510\\" id=\\"help-card\\"><div class=\\"MuiCardContent-root-29\\"><h2 class=\\"MuiTypography-root-30 MuiTypography-headline-35 MuiTypography-gutterBottom-57\\" id=\\"help-card__title\\">No Package Published Yet.</h2><p class=\\"MuiTypography-root-30 MuiTypography-body1-39 MuiTypography-colorTextSecondary-63 MuiTypography-gutterBottom-57 css-zg2fwz e1ail7511\\">To publish your first package just:</p><p class=\\"MuiTypography-root-30 MuiTypography-body2-38\\">1. Login</p><div class=\\"css-1mta3t8 e1mfrkg70\\"><span class=\\"css-1m8aenu e1mfrkg71\\">npm adduser --registry http://localhost</span><button class=\\"MuiButtonBase-root-80 MuiIconButton-root-74 css-56v3u0 e1mfrkg72\\" tabindex=\\"0\\" type=\\"button\\" title=\\"Copy to Clipboard\\"><span class=\\"MuiIconButton-label-79\\"><svg class=\\"MuiSvgIcon-root-83\\" focusable=\\"false\\" viewBox=\\"0 0 24 24\\" aria-hidden=\\"true\\" role=\\"presentation\\"><path fill=\\"none\\" d=\\"M0 0h24v24H0z\\"></path><path d=\\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm-1 4l6 6v10c0 1.1-.9 2-2 2H7.99C6.89 23 6 22.1 6 21l.01-14c0-1.1.89-2 1.99-2h7zm-1 7h5.5L14 6.5V12z\\"></path></svg></span></button></div><p class=\\"MuiTypography-root-30 MuiTypography-body2-38\\">2. Publish</p><div class=\\"css-1mta3t8 e1mfrkg70\\"><span class=\\"css-1m8aenu e1mfrkg71\\">npm publish --registry http://localhost</span><button class=\\"MuiButtonBase-root-80 MuiIconButton-root-74 css-56v3u0 e1mfrkg72\\" tabindex=\\"0\\" type=\\"button\\" title=\\"Copy to Clipboard\\"><span class=\\"MuiIconButton-label-79\\"><svg class=\\"MuiSvgIcon-root-83\\" focusable=\\"false\\" viewBox=\\"0 0 24 24\\" aria-hidden=\\"true\\" role=\\"presentation\\"><path fill=\\"none\\" d=\\"M0 0h24v24H0z\\"></path><path d=\\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm-1 4l6 6v10c0 1.1-.9 2-2 2H7.99C6.89 23 6 22.1 6 21l.01-14c0-1.1.89-2 1.99-2h7zm-1 7h5.5L14 6.5V12z\\"></path></svg></span></button></div><p class=\\"MuiTypography-root-30 MuiTypography-body2-38\\">3. Refresh this page.</p></div><div class=\\"MuiCardActions-root-92\\"><a class=\\"MuiButtonBase-root-80 MuiButton-root-95 MuiButton-text-97 MuiButton-textPrimary-98 MuiButton-flat-100 MuiButton-flatPrimary-101 MuiButton-sizeSmall-118 MuiCardActions-action-94\\" tabindex=\\"0\\" role=\\"button\\" href=\\"https://verdaccio.org/docs/en/installation\\" target=\\"_blank\\"><span class=\\"MuiButton-label-96\\">Learn More</span></a></div></div>"`;
|
||||
@@ -1,5 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<LoginModal /> should load the component in default state 1`] = `"<div role=\\"dialog\\" class=\\"mui-fixed MuiModal-root-15 MuiDialog-root-1\\" id=\\"login--form-container\\" style=\\"padding-right: 0px;\\"><div class=\\"MuiBackdrop-root-17\\" aria-hidden=\\"true\\" style=\\"opacity: 1; webkit-transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;\\"></div><div class=\\"MuiDialog-container-4 MuiDialog-scrollPaper-2\\" role=\\"document\\" style=\\"opacity: 1; webkit-transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;\\" tabindex=\\"-1\\"><div class=\\"MuiPaper-root-19 MuiPaper-elevation24-45 MuiPaper-rounded-20 MuiDialog-paper-5 MuiDialog-paperScrollPaper-6 MuiDialog-paperWidthXs-8 MuiDialog-paperFullWidth-13\\"><form novalidate=\\"\\"><div class=\\"MuiDialogTitle-root-46\\"><h2 class=\\"MuiTypography-root-47 MuiTypography-title-53\\">Login</h2></div><div class=\\"MuiDialogContent-root-83\\"><div class=\\"MuiFormControl-root-84 MuiFormControl-fullWidth-87\\"><label class=\\"MuiFormLabel-root-99 MuiFormLabel-required-104 MuiInputLabel-required-92 MuiInputLabel-root-88 MuiInputLabel-formControl-93 MuiInputLabel-animated-96\\" data-shrink=\\"false\\" for=\\"username\\">Username<span class=\\"MuiFormLabel-asterisk-105\\"> *</span></label><div class=\\"MuiInputBase-root-119 MuiInput-root-106 MuiInput-underline-110 MuiInputBase-formControl-120 MuiInput-formControl-107\\"><input aria-invalid=\\"false\\" class=\\"MuiInputBase-input-129 MuiInput-input-114\\" id=\\"login--form-username\\" placeholder=\\"Your username\\" required=\\"\\" type=\\"text\\" value=\\"\\"></div></div><div class=\\"MuiFormControl-root-84 MuiFormControl-fullWidth-87\\" style=\\"margin-top: 8px;\\"><label class=\\"MuiFormLabel-root-99 MuiFormLabel-required-104 MuiInputLabel-required-92 MuiInputLabel-root-88 MuiInputLabel-formControl-93 MuiInputLabel-animated-96\\" data-shrink=\\"false\\" for=\\"password\\">Password<span class=\\"MuiFormLabel-asterisk-105\\"> *</span></label><div class=\\"MuiInputBase-root-119 MuiInput-root-106 MuiInput-underline-110 MuiInputBase-formControl-120 MuiInput-formControl-107\\"><input aria-invalid=\\"false\\" class=\\"MuiInputBase-input-129 MuiInput-input-114 MuiInputBase-inputType-132 MuiInput-inputType-117\\" id=\\"login--form-password\\" placeholder=\\"Your strong password\\" required=\\"\\" type=\\"password\\" value=\\"\\"></div></div></div><div class=\\"MuiDialogActions-root-136 dialog-footer\\"><button class=\\"MuiButtonBase-root-164 MuiButton-root-138 MuiButton-text-140 MuiButton-flat-143 MuiButton-colorInherit-159 MuiDialogActions-action-137\\" tabindex=\\"0\\" type=\\"button\\" id=\\"login--form-cancel\\"><span class=\\"MuiButton-label-139\\">Cancel</span><span class=\\"MuiTouchRipple-root-167\\"></span></button><button class=\\"MuiButtonBase-root-164 MuiButtonBase-disabled-165 MuiButton-root-138 MuiButton-text-140 MuiButton-flat-143 MuiButton-disabled-158 MuiButton-colorInherit-159 MuiDialogActions-action-137\\" tabindex=\\"-1\\" type=\\"submit\\" disabled=\\"\\" id=\\"login--form-submit\\"><span class=\\"MuiButton-label-139\\">Login</span></button></div></form></div></div></div>"`;
|
||||
|
||||
exports[`<LoginModal /> should load the component with props 1`] = `"<div role=\\"dialog\\" class=\\"mui-fixed MuiModal-root-15 MuiDialog-root-1\\" id=\\"login--form-container\\"><div class=\\"MuiBackdrop-root-17\\" aria-hidden=\\"true\\" style=\\"opacity: 1; webkit-transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;\\"></div><div class=\\"MuiDialog-container-4 MuiDialog-scrollPaper-2\\" role=\\"document\\" style=\\"opacity: 1; webkit-transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;\\" tabindex=\\"-1\\"><div class=\\"MuiPaper-root-19 MuiPaper-elevation24-45 MuiPaper-rounded-20 MuiDialog-paper-5 MuiDialog-paperScrollPaper-6 MuiDialog-paperWidthXs-8 MuiDialog-paperFullWidth-13\\"><form novalidate=\\"\\"><div class=\\"MuiDialogTitle-root-46\\"><h2 class=\\"MuiTypography-root-47 MuiTypography-title-53\\">Login</h2></div><div class=\\"MuiDialogContent-root-83\\"><div class=\\"MuiTypography-root-47 MuiTypography-body1-56 MuiPaper-root-19 MuiPaper-elevation6-27 MuiSnackbarContent-root-174 loginError\\" role=\\"alertdialog\\"><div class=\\"MuiSnackbarContent-message-175\\"><div class=\\"loginErrorMsg\\" id=\\"client-snackbar\\"><svg class=\\"MuiSvgIcon-root-177 loginIcon\\" 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-2h2v2zm0-4h-2V7h2v6z\\"></path></svg><span><div><strong>Error Title</strong></div><div>Error Description</div></span></div></div></div><div class=\\"MuiFormControl-root-84 MuiFormControl-fullWidth-87\\"><label class=\\"MuiFormLabel-root-99 MuiFormLabel-required-104 MuiInputLabel-required-92 MuiInputLabel-root-88 MuiInputLabel-formControl-93 MuiInputLabel-animated-96\\" data-shrink=\\"false\\" for=\\"username\\">Username<span class=\\"MuiFormLabel-asterisk-105\\"> *</span></label><div class=\\"MuiInputBase-root-119 MuiInput-root-106 MuiInput-underline-110 MuiInputBase-formControl-120 MuiInput-formControl-107\\"><input aria-invalid=\\"false\\" class=\\"MuiInputBase-input-129 MuiInput-input-114\\" id=\\"login--form-username\\" placeholder=\\"Your username\\" required=\\"\\" type=\\"text\\" value=\\"\\"></div></div><div class=\\"MuiFormControl-root-84 MuiFormControl-fullWidth-87\\" style=\\"margin-top: 8px;\\"><label class=\\"MuiFormLabel-root-99 MuiFormLabel-required-104 MuiInputLabel-required-92 MuiInputLabel-root-88 MuiInputLabel-formControl-93 MuiInputLabel-animated-96\\" data-shrink=\\"false\\" for=\\"password\\">Password<span class=\\"MuiFormLabel-asterisk-105\\"> *</span></label><div class=\\"MuiInputBase-root-119 MuiInput-root-106 MuiInput-underline-110 MuiInputBase-formControl-120 MuiInput-formControl-107\\"><input aria-invalid=\\"false\\" class=\\"MuiInputBase-input-129 MuiInput-input-114 MuiInputBase-inputType-132 MuiInput-inputType-117\\" id=\\"login--form-password\\" placeholder=\\"Your strong password\\" required=\\"\\" type=\\"password\\" value=\\"\\"></div></div></div><div class=\\"MuiDialogActions-root-136 dialog-footer\\"><button class=\\"MuiButtonBase-root-164 MuiButton-root-138 MuiButton-text-140 MuiButton-flat-143 MuiButton-colorInherit-159 MuiDialogActions-action-137\\" tabindex=\\"0\\" type=\\"button\\" id=\\"login--form-cancel\\"><span class=\\"MuiButton-label-139\\">Cancel</span><span class=\\"MuiTouchRipple-root-167\\"></span></button><button class=\\"MuiButtonBase-root-164 MuiButtonBase-disabled-165 MuiButton-root-138 MuiButton-text-140 MuiButton-flat-143 MuiButton-disabled-158 MuiButton-colorInherit-159 MuiDialogActions-action-137\\" tabindex=\\"-1\\" type=\\"submit\\" disabled=\\"\\" id=\\"login--form-submit\\"><span class=\\"MuiButton-label-139\\">Login</span></button></div></form></div></div></div>"`;
|
||||
@@ -1,5 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<NoItem /> component should load the component in default state 1`] = `"<h6 class=\\"MuiTypography-root-1 MuiTypography-subtitle1-19 MuiTypography-gutterBottom-28\\"></h6>"`;
|
||||
|
||||
exports[`<NoItem /> component should set html from props 1`] = `"<h6 class=\\"MuiTypography-root-1 MuiTypography-subtitle1-19 MuiTypography-gutterBottom-28\\">This is a test string</h6>"`;
|
||||
@@ -1,3 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<NotFound /> component should load the component in default state 1`] = `<withRouter(WithTheme(WithWidth(NotFound))) />`;
|
||||
@@ -1,3 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<Package /> component should load the component without author 1`] = `"<a class=\\"package css-scoisj e11fsc2k15\\" href=\\"detail/verdaccio\\"><div class=\\"css-esn5nr e11fsc2k0\\"><span class=\\"css-ilb586 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-1vtxmi9 e11fsc2k3\\"><svg class=\\"e11fsc2k6 css-19sh63r ej4jd2o0\\"><title>License</title><use xlink:href=\\"[object Object]#license\\"></use></svg>MIT</span><span class=\\"css-1vtxmi9 e11fsc2k3\\"><svg class=\\"e11fsc2k6 css-1iep4l8 ej4jd2o0\\"><title>Time</title><use xlink:href=\\"[object Object]#time\\"></use></svg><span class=\\"css-c3js4s e11fsc2k7\\">Published on 09.12.2018, 17:49:30 •</span>about 6 hours ago</span></span></div><div class=\\"css-tywa7u e11fsc2k9\\"><div class=\\"css-r6baau e11fsc2k8\\"><div class=\\"e11fsc2k10 css-1w35jfk e1pneb170\\">Author</div><div class=\\"css-15496ft e11fsc2k12\\"><div class=\\"MuiAvatar-root-1 MuiAvatar-colorDefault-2 css-1to0t9u e11fsc2k13\\">A</div><span class=\\"css-1xj37ub e11fsc2k11\\"><div class=\\"e11fsc2k10 css-1xe0n7g e1pneb170\\">Anonymous</div></span></div></div><div class=\\"css-r6baau e11fsc2k8\\"><div class=\\"e11fsc2k10 css-1w35jfk e1pneb170\\">Description</div><span>Private NPM repository</span></div></div></a>"`;
|
||||
@@ -1,5 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<Readme /> component should dangerously set html 1`] = `"<div class=\\"markdown-body\\"><h1>This is a test string</h1></div>"`;
|
||||
|
||||
exports[`<Readme /> component should load the component in default state 1`] = `"<div class=\\"markdown-body\\">test</div>"`;
|
||||
@@ -1,3 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<Search /> component test should load the component in default state 1`] = `"<div class=\\"css-1crzyyo e18292mt0\\"><div role=\\"combobox\\" aria-haspopup=\\"listbox\\" aria-owns=\\"react-autowhatever-1\\" aria-expanded=\\"false\\" class=\\"react-autosuggest__container\\"><div class=\\"MuiFormControl-root-1 MuiFormControl-fullWidth-4 react-autosuggest__input\\" aria-autocomplete=\\"list\\" aria-controls=\\"react-autowhatever-1\\"><div class=\\"MuiInputBase-root-18 MuiInput-root-5 css-n9ojyg MuiInput-underline-9 MuiInputBase-fullWidth-27 MuiInput-fullWidth-12 MuiInputBase-formControl-19 MuiInput-formControl-6 MuiInputBase-adornedStart-22\\"><div class=\\"MuiInputAdornment-root-35 MuiInputAdornment-positionStart-37\\" style=\\"color: rgb(255, 255, 255);\\"><svg class=\\"MuiSvgIcon-root-40\\" focusable=\\"false\\" viewBox=\\"0 0 24 24\\" aria-hidden=\\"true\\" role=\\"presentation\\"><path d=\\"M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z\\"></path><path fill=\\"none\\" d=\\"M0 0h24v24H0z\\"></path></svg></div><input aria-invalid=\\"false\\" autocomplete=\\"off\\" class=\\"MuiInputBase-input-28 MuiInput-input-13 css-hodoyq MuiInputBase-inputAdornedStart-33\\" placeholder=\\"Search Packages\\" type=\\"text\\" value=\\"\\"></div></div><div class=\\"MuiPaper-root-49 MuiPaper-elevation2-53 react-autosuggest__suggestions-container css-cfo6a e18292mt1\\" id=\\"react-autowhatever-1\\" role=\\"listbox\\"></div></div></div>"`;
|
||||
@@ -1,45 +0,0 @@
|
||||
/**
|
||||
* @prettier
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import CopyToClipBoard from '../../../src/webui/components/CopyToClipBoard/index';
|
||||
import { CopyIcon } from '../../../src/webui/components/CopyToClipBoard/styles';
|
||||
|
||||
describe('<CopyToClipBoard /> component', () => {
|
||||
let wrapper;
|
||||
let props;
|
||||
|
||||
beforeEach(() => {
|
||||
props = {
|
||||
text: 'copy text',
|
||||
};
|
||||
wrapper = shallow(<CopyToClipBoard {...props} />);
|
||||
});
|
||||
|
||||
test('render the component', () => {
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should call the DOM APIs for copy to clipboard utility', () => {
|
||||
const event = {
|
||||
preventDefault: jest.fn(),
|
||||
};
|
||||
|
||||
global.getSelection = jest.fn(() => ({
|
||||
removeAllRanges: () => {},
|
||||
addRange: () => {},
|
||||
}));
|
||||
|
||||
const { document, getSelection } = global;
|
||||
|
||||
wrapper.find(CopyIcon).simulate('click', event);
|
||||
expect(event.preventDefault).toHaveBeenCalled();
|
||||
expect(document.createRange).toHaveBeenCalled();
|
||||
expect(getSelection).toHaveBeenCalled();
|
||||
expect(document.execCommand).toHaveBeenCalledWith('copy');
|
||||
});
|
||||
});
|
||||
@@ -1,22 +0,0 @@
|
||||
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
|
||||
import Footer from '../../../src/webui/components/Footer/index';
|
||||
|
||||
jest.mock('../../../package.json', () => ({
|
||||
version: '4.0.0-alpha.3'
|
||||
}));
|
||||
|
||||
describe('<Footer /> component', () => {
|
||||
let wrapper;
|
||||
beforeEach(() => {
|
||||
window.VERDACCIO_VERSION = 'v.1.0.0';
|
||||
wrapper = mount(<Footer />);
|
||||
delete window.VERDACCIO_VERSION;
|
||||
});
|
||||
|
||||
test('should load the initial state of Footer component', () => {
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -1,116 +0,0 @@
|
||||
/**
|
||||
* @prettier
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { BrowserRouter as Router } from 'react-router-dom';
|
||||
import { shallow } from 'enzyme';
|
||||
import Header from '../../../src/webui/components/Header/index';
|
||||
|
||||
describe('<Header /> component with logged in state', () => {
|
||||
let wrapper;
|
||||
let routerWrapper;
|
||||
let instance;
|
||||
let props;
|
||||
|
||||
beforeEach(() => {
|
||||
props = {
|
||||
username: 'test user',
|
||||
handleLogout: jest.fn(),
|
||||
logo: '',
|
||||
onToggleLoginModal: jest.fn(),
|
||||
scope: 'test scope',
|
||||
withoutSearch: true,
|
||||
};
|
||||
routerWrapper = shallow(
|
||||
<Router>
|
||||
<Header {...props} />
|
||||
</Router>
|
||||
);
|
||||
wrapper = routerWrapper.find(Header).dive();
|
||||
instance = wrapper.instance();
|
||||
});
|
||||
|
||||
test('should load the component in logged in state', () => {
|
||||
const state = {
|
||||
openInfoDialog: false,
|
||||
packages: undefined,
|
||||
registryUrl: 'http://localhost',
|
||||
showMobileNavBar: false,
|
||||
};
|
||||
|
||||
expect(wrapper.state()).toEqual(state);
|
||||
expect(routerWrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('handleLoggedInMenu: set anchorEl to html element value in state', () => {
|
||||
// creates a sample menu
|
||||
const div = document.createElement('div');
|
||||
const text = document.createTextNode('sample menu');
|
||||
div.appendChild(text);
|
||||
|
||||
const event = {
|
||||
currentTarget: div,
|
||||
};
|
||||
|
||||
instance.handleLoggedInMenu(event);
|
||||
expect(wrapper.state('anchorEl')).toEqual(div);
|
||||
});
|
||||
});
|
||||
|
||||
describe('<Header /> component with logged out state', () => {
|
||||
let wrapper;
|
||||
let routerWrapper;
|
||||
let instance;
|
||||
let props;
|
||||
|
||||
beforeEach(() => {
|
||||
props = {
|
||||
handleLogout: jest.fn(),
|
||||
onToggleLoginModal: jest.fn(),
|
||||
scope: 'test scope',
|
||||
logo: '',
|
||||
withoutSearch: true,
|
||||
};
|
||||
routerWrapper = shallow(
|
||||
<Router>
|
||||
<Header {...props} />
|
||||
</Router>
|
||||
);
|
||||
wrapper = routerWrapper.find(Header).dive();
|
||||
instance = wrapper.instance();
|
||||
});
|
||||
|
||||
test('should load the component in logged out state', () => {
|
||||
const state = {
|
||||
openInfoDialog: false,
|
||||
packages: undefined,
|
||||
registryUrl: 'http://localhost',
|
||||
showMobileNavBar: false,
|
||||
};
|
||||
expect(wrapper.state()).toEqual(state);
|
||||
expect(routerWrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('handleLoggedInMenuClose: set anchorEl value to null in state', () => {
|
||||
instance.handleLoggedInMenuClose();
|
||||
expect(wrapper.state('anchorEl')).toBeNull();
|
||||
});
|
||||
|
||||
test('handleOpenRegistryInfoDialog: set openInfoDialog to be truthy in state', () => {
|
||||
instance.handleOpenRegistryInfoDialog();
|
||||
expect(wrapper.state('openInfoDialog')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('handleCloseRegistryInfoDialog: set openInfoDialog to be falsy in state', () => {
|
||||
instance.handleCloseRegistryInfoDialog();
|
||||
expect(wrapper.state('openInfoDialog')).toBeFalsy();
|
||||
});
|
||||
|
||||
test('handleToggleLogin: close/open popover menu', () => {
|
||||
instance.handleToggleLogin();
|
||||
expect(wrapper.state('anchorEl')).toBeNull();
|
||||
expect(props.onToggleLoginModal).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -1,14 +0,0 @@
|
||||
/**
|
||||
* Help component
|
||||
*/
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import Help from '../../../src/webui/components/Help/index';
|
||||
|
||||
describe('<Help /> component', () => {
|
||||
|
||||
test('should render the component in default state', () => {
|
||||
const wrapper = shallow(<Help />);
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -1,129 +0,0 @@
|
||||
/**
|
||||
* @prettier
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
|
||||
import LoginModal from '../../../src/webui/components/Login/index';
|
||||
|
||||
const eventUsername = {
|
||||
target: {
|
||||
value: 'xyz',
|
||||
},
|
||||
};
|
||||
|
||||
const eventPassword = {
|
||||
target: {
|
||||
value: '1234',
|
||||
},
|
||||
};
|
||||
|
||||
const event = {
|
||||
preventDefault: jest.fn(),
|
||||
};
|
||||
|
||||
describe('<LoginModal />', () => {
|
||||
test('should load the component in default state', () => {
|
||||
const wrapper = mount(<LoginModal />);
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should load the component with props', () => {
|
||||
const props = {
|
||||
visibility: true,
|
||||
error: {
|
||||
type: 'error',
|
||||
title: 'Error Title',
|
||||
description: 'Error Description',
|
||||
},
|
||||
onCancel: () => {},
|
||||
onSubmit: () => {},
|
||||
};
|
||||
const wrapper = mount(<LoginModal {...props} />);
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('onCancel: should close the login modal', () => {
|
||||
const props = {
|
||||
visibility: true,
|
||||
error: {
|
||||
type: 'error',
|
||||
title: 'Error Title',
|
||||
description: 'Error Description',
|
||||
},
|
||||
onCancel: jest.fn(),
|
||||
onSubmit: () => {},
|
||||
};
|
||||
const wrapper = mount(<LoginModal {...props} />);
|
||||
wrapper.find('button[id="login--form-cancel"]').simulate('click');
|
||||
expect(props.onCancel).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('setCredentials - should set username and password in state', () => {
|
||||
const props = {
|
||||
visibility: true,
|
||||
error: {},
|
||||
onCancel: () => {},
|
||||
onSubmit: () => {},
|
||||
};
|
||||
const wrapper = mount(<LoginModal {...props} />);
|
||||
const { setCredentials } = wrapper.instance();
|
||||
|
||||
expect(setCredentials('username', eventUsername)).toBeUndefined();
|
||||
expect(wrapper.state('form').username.value).toEqual('xyz');
|
||||
|
||||
expect(setCredentials('password', eventPassword)).toBeUndefined();
|
||||
expect(wrapper.state('form').password.value).toEqual('1234');
|
||||
});
|
||||
|
||||
test('validateCredentials: should validate credentials', async () => {
|
||||
const props = {
|
||||
visibility: true,
|
||||
error: {},
|
||||
onCancel: () => {},
|
||||
onSubmit: jest.fn(),
|
||||
};
|
||||
|
||||
const wrapper = mount(<LoginModal {...props} />);
|
||||
const instance = wrapper.instance();
|
||||
|
||||
instance.submitCredentials = jest.fn();
|
||||
const { validateCredentials, setCredentials, submitCredentials } = instance;
|
||||
|
||||
expect(setCredentials('username', eventUsername)).toBeUndefined();
|
||||
expect(wrapper.state('form').username.value).toEqual('xyz');
|
||||
|
||||
expect(setCredentials('password', eventPassword)).toBeUndefined();
|
||||
expect(wrapper.state('form').password.value).toEqual('1234');
|
||||
|
||||
validateCredentials(event);
|
||||
expect(event.preventDefault).toHaveBeenCalled();
|
||||
expect(wrapper.state('form').username.pristine).toEqual(false);
|
||||
expect(wrapper.state('form').password.pristine).toEqual(false);
|
||||
|
||||
expect(submitCredentials).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('submitCredentials: should submit credentials', async () => {
|
||||
const props = {
|
||||
onSubmit: jest.fn(),
|
||||
};
|
||||
|
||||
const wrapper = mount(<LoginModal {...props} />);
|
||||
const { setCredentials, submitCredentials } = wrapper.instance();
|
||||
expect(setCredentials('username', eventUsername)).toBeUndefined();
|
||||
expect(wrapper.state('form').username.value).toEqual('xyz');
|
||||
|
||||
expect(setCredentials('password', eventPassword)).toBeUndefined();
|
||||
expect(wrapper.state('form').password.value).toEqual('1234');
|
||||
|
||||
await submitCredentials();
|
||||
expect(props.onSubmit).toHaveBeenCalledWith('xyz', '1234');
|
||||
expect(wrapper.state('form').username.value).toEqual('');
|
||||
expect(wrapper.state('form').username.pristine).toEqual(true);
|
||||
expect(wrapper.state('form').password.value).toEqual('');
|
||||
expect(wrapper.state('form').password.pristine).toEqual(true);
|
||||
});
|
||||
});
|
||||
@@ -1,24 +0,0 @@
|
||||
/**
|
||||
* NoItems component
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { shallow, mount } from 'enzyme';
|
||||
import NoItems from '../../../src/webui/components/NoItems/index';
|
||||
|
||||
console.error = jest.fn();
|
||||
|
||||
describe('<NoItem /> component', () => {
|
||||
test('should load the component in default state', () => {
|
||||
const wrapper = shallow(<NoItems />);
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should set html from props', () => {
|
||||
const props = {
|
||||
text: 'This is a test string'
|
||||
};
|
||||
const wrapper = mount(<NoItems {...props} />);
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* NotFound component
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { BrowserRouter as Router } from 'react-router-dom';
|
||||
import { shallow } from 'enzyme';
|
||||
import NotFound from '../../../src/webui/components/NotFound/index';
|
||||
|
||||
console.error = jest.fn();
|
||||
|
||||
describe('<NotFound /> component', () => {
|
||||
let routerWrapper;
|
||||
beforeEach(() => {
|
||||
routerWrapper = shallow(
|
||||
<Router>
|
||||
<NotFound />
|
||||
</Router>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
test('should load the component in default state', () => {
|
||||
expect(routerWrapper.find(NotFound)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,86 +0,0 @@
|
||||
/**
|
||||
* Package component
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import Package from '../../../src/webui/components/Package/index';
|
||||
import Tag from '../../../src/webui/components/Tag/index';
|
||||
import { Version, WrapperLink, Field, OverviewItem } from '../../../src/webui/components/Package/styles';
|
||||
|
||||
|
||||
/**
|
||||
* Generates one month back date from current time
|
||||
* @return {object} date object
|
||||
*/
|
||||
const dateOneMonthAgo = () => new Date(1544377770747)
|
||||
|
||||
describe('<Package /> component', () => {
|
||||
test.skip('should load the component', () => {
|
||||
const props = {
|
||||
name: 'verdaccio',
|
||||
version: '1.0.0',
|
||||
time: dateOneMonthAgo(),
|
||||
license: 'MIT',
|
||||
description: 'Private NPM repository',
|
||||
author: {
|
||||
name: 'Sam'
|
||||
},
|
||||
keywords: [
|
||||
"verdaccio"
|
||||
]
|
||||
};
|
||||
|
||||
const wrapper = shallow(
|
||||
<Package {...props} />
|
||||
);
|
||||
|
||||
|
||||
// integration expectations
|
||||
|
||||
// check link
|
||||
expect(wrapper.find(WrapperLink).prop('to')).toEqual(`detail/${props.name}`);
|
||||
|
||||
// check version
|
||||
expect(wrapper.find(Version).prop('children')).toEqual(`v${props.version}`);
|
||||
|
||||
// TODO - REWRITE THE TEST
|
||||
//expect(wrapper.find(Author).dive())
|
||||
|
||||
// check description
|
||||
expect(wrapper.find(Field).someWhere(n => {
|
||||
return (
|
||||
n.children().first().get(0).props.children[0].props.text === 'Description' &&
|
||||
n.children().childAt(1).containsMatchingElement(<span>{props.description}</span>)
|
||||
)
|
||||
})).toBe(true);
|
||||
|
||||
// check license
|
||||
expect(wrapper.find(OverviewItem).someWhere(n => n.get(0).props.children[1] === props.license)).toBe(true);
|
||||
|
||||
// check keyword
|
||||
expect(wrapper.find(Tag).prop('children')).toEqual(props.keywords[0]);
|
||||
|
||||
});
|
||||
|
||||
test.skip('should load the component without author', () => {
|
||||
const props = {
|
||||
name: 'verdaccio',
|
||||
version: '1.0.0',
|
||||
time: dateOneMonthAgo(),
|
||||
license: 'MIT',
|
||||
author: {
|
||||
name: 'Anonymous',
|
||||
email: '',
|
||||
avatar: ''
|
||||
},
|
||||
description: 'Private NPM repository'
|
||||
};
|
||||
const wrapper = shallow(
|
||||
<Package {...props} />
|
||||
);
|
||||
|
||||
// integration expectations
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -1,61 +0,0 @@
|
||||
/**
|
||||
* PackageList component
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import PackageList from '../../../src/webui/components/PackageList/index';
|
||||
import Help from '../../../src/webui/components/Help/index';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
|
||||
describe('<PackageList /> component', () => {
|
||||
test('should load the component with no packages', () => {
|
||||
const props = {
|
||||
packages: [],
|
||||
help: true
|
||||
};
|
||||
const wrapper = mount(
|
||||
<PackageList help={props.help} packages={props.packages} />
|
||||
);
|
||||
expect(wrapper.find(Help).exists()).toBeTruthy();
|
||||
|
||||
});
|
||||
|
||||
test('should load the component with packages', () => {
|
||||
const props = {
|
||||
packages: [
|
||||
{
|
||||
name: 'verdaccio',
|
||||
version: '1.0.0',
|
||||
time: new Date(1532211072138).getTime(),
|
||||
description: 'Private NPM repository',
|
||||
author: { name: 'Sam', avatar: 'test avatar' }
|
||||
},
|
||||
{
|
||||
name: 'abc',
|
||||
version: '1.0.1',
|
||||
time: new Date(1532211072138).getTime(),
|
||||
description: 'abc description',
|
||||
author: { name: 'Rose', avatar: 'test avatar' }
|
||||
},
|
||||
{
|
||||
name: 'xyz',
|
||||
version: '1.1.0',
|
||||
description: 'xyz description',
|
||||
author: { name: 'Martin', avatar: 'test avatar' }
|
||||
}
|
||||
],
|
||||
help: false
|
||||
};
|
||||
|
||||
const wrapper = mount(
|
||||
<BrowserRouter>
|
||||
<PackageList help={props.help} packages={props.packages} />
|
||||
</BrowserRouter>
|
||||
);
|
||||
|
||||
|
||||
// package count
|
||||
expect(wrapper.find('Package')).toHaveLength(3);
|
||||
});
|
||||
});
|
||||
@@ -1,22 +0,0 @@
|
||||
/**
|
||||
* Readme component
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { shallow, mount } from 'enzyme';
|
||||
import Readme from '../../../src/webui/components/Readme/index';
|
||||
|
||||
describe('<Readme /> component', () => {
|
||||
test('should load the component in default state', () => {
|
||||
const wrapper = mount(<Readme description={"test"} />);
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should dangerously set html', () => {
|
||||
const wrapper = shallow(<Readme description={"<h1>This is a test string</h1>"} />);
|
||||
expect(wrapper.html()).toEqual(
|
||||
'<div class="markdown-body"><h1>This is a test string</h1></div>'
|
||||
);
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -1,193 +0,0 @@
|
||||
/**
|
||||
* @flow
|
||||
* @prettier
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
|
||||
import { Search } from '../../../src/webui/components/Search/index';
|
||||
|
||||
const SEARCH_FILE_PATH = '../../../src/webui/components/Search/index';
|
||||
const API_FILE_PATH = '../../../src/webui/utils/api';
|
||||
const URL_FILE_PATH = '../../../src/webui/utils/url';
|
||||
|
||||
// Global mocks
|
||||
const event = {
|
||||
stopPropagation: jest.fn(),
|
||||
};
|
||||
window.location.assign = jest.fn();
|
||||
|
||||
describe('<Search /> component test', () => {
|
||||
let wrapper;
|
||||
beforeEach(() => {
|
||||
wrapper = mount(<Search />);
|
||||
});
|
||||
|
||||
test('should load the component in default state', () => {
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('onBlur: should cancel all search requests', async () => {
|
||||
const { onBlur, requestList } = wrapper.instance();
|
||||
const spy = jest.spyOn(wrapper.instance(), 'cancelAllSearchRequests');
|
||||
|
||||
const request = {
|
||||
abort: jest.fn(),
|
||||
};
|
||||
// adds a request for AbortController
|
||||
wrapper.instance().requestList = [request];
|
||||
|
||||
onBlur(event);
|
||||
|
||||
expect(request.abort).toHaveBeenCalled();
|
||||
expect(event.stopPropagation).toHaveBeenCalled();
|
||||
expect(wrapper.state('error')).toBeFalsy();
|
||||
expect(wrapper.state('loaded')).toBeFalsy();
|
||||
expect(wrapper.state('loading')).toBeFalsy();
|
||||
expect(spy).toHaveBeenCalled();
|
||||
expect(requestList).toEqual([]);
|
||||
});
|
||||
|
||||
test('handleSearch: when user type package name in search component and set loading to true', () => {
|
||||
const { handleSearch } = wrapper.instance();
|
||||
const newValue = 'verdaccio';
|
||||
|
||||
handleSearch(event, { newValue, method: 'type' });
|
||||
|
||||
expect(event.stopPropagation).toHaveBeenCalled();
|
||||
expect(wrapper.state('error')).toBeFalsy();
|
||||
expect(wrapper.state('loaded')).toBeFalsy();
|
||||
expect(wrapper.state('loading')).toBeTruthy();
|
||||
expect(wrapper.state('search')).toEqual(newValue);
|
||||
});
|
||||
|
||||
test('handleSearch: cancel all search requests when there is no value in search component with type method', () => {
|
||||
const { handleSearch, requestList } = wrapper.instance();
|
||||
const spy = jest.spyOn(wrapper.instance(), 'cancelAllSearchRequests');
|
||||
const newValue = '';
|
||||
|
||||
handleSearch(event, { newValue, method: 'type' });
|
||||
|
||||
expect(event.stopPropagation).toHaveBeenCalled();
|
||||
expect(wrapper.state('error')).toBeFalsy();
|
||||
expect(wrapper.state('loaded')).toBeFalsy();
|
||||
expect(wrapper.state('loading')).toBeTruthy();
|
||||
expect(wrapper.state('search')).toEqual(newValue);
|
||||
expect(spy).toHaveBeenCalled();
|
||||
expect(requestList).toEqual([]);
|
||||
});
|
||||
|
||||
test('handleSearch: when method is not type method', () => {
|
||||
const { handleSearch } = wrapper.instance();
|
||||
const newValue = '';
|
||||
|
||||
handleSearch(event, { newValue, method: 'click' });
|
||||
|
||||
expect(event.stopPropagation).toHaveBeenCalled();
|
||||
expect(wrapper.state('error')).toBeFalsy();
|
||||
expect(wrapper.state('loaded')).toBeFalsy();
|
||||
expect(wrapper.state('loading')).toBeFalsy();
|
||||
expect(wrapper.state('search')).toEqual(newValue);
|
||||
});
|
||||
|
||||
test('handlePackagesClearRequested: should clear suggestions', () => {
|
||||
const { handlePackagesClearRequested } = wrapper.instance();
|
||||
|
||||
handlePackagesClearRequested();
|
||||
|
||||
expect(wrapper.state('suggestions')).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('<Search /> component: mocks specific tests ', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
jest.doMock('lodash/debounce', () => {
|
||||
return function debounceMock(fn, delay) {
|
||||
return fn;
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
test('handleFetchPackages: should load the packages from API', async () => {
|
||||
const apiResponse = [{ name: 'verdaccio' }, { name: 'verdaccio-htpasswd' }];
|
||||
const suggestions = [{ name: 'verdaccio' }, { name: 'verdaccio-htpasswd' }];
|
||||
|
||||
jest.doMock(API_FILE_PATH, () => ({
|
||||
request(url) {
|
||||
expect(url).toEqual('search/verdaccio');
|
||||
return Promise.resolve(apiResponse);
|
||||
},
|
||||
}));
|
||||
|
||||
const Search = require(SEARCH_FILE_PATH).Search;
|
||||
const component = mount(<Search />);
|
||||
component.setState({ search: 'verdaccio' });
|
||||
const { handleFetchPackages } = component.instance();
|
||||
await handleFetchPackages({ value: 'verdaccio' });
|
||||
|
||||
expect(component.state('suggestions')).toEqual(suggestions);
|
||||
expect(component.state('error')).toBeFalsy();
|
||||
expect(component.state('loaded')).toBeTruthy();
|
||||
expect(component.state('loading')).toBeFalsy();
|
||||
});
|
||||
|
||||
test('handleFetchPackages: when browser cancel a request', async () => {
|
||||
const apiResponse = { name: 'AbortError' };
|
||||
|
||||
jest.doMock(API_FILE_PATH, () => ({ request: jest.fn(() => Promise.reject(apiResponse)) }));
|
||||
|
||||
const Search = require(SEARCH_FILE_PATH).Search;
|
||||
const component = mount(<Search />);
|
||||
component.setState({ search: 'verdaccio' });
|
||||
const { handleFetchPackages } = component.instance();
|
||||
await handleFetchPackages({ value: 'verdaccio' });
|
||||
|
||||
expect(component.state('error')).toBeFalsy();
|
||||
expect(component.state('loaded')).toBeFalsy();
|
||||
expect(component.state('loading')).toBeFalsy();
|
||||
});
|
||||
|
||||
test('handleFetchPackages: when API server failed request', async () => {
|
||||
const apiResponse = { name: 'BAD_REQUEST' };
|
||||
|
||||
jest.doMock(API_FILE_PATH, () => ({
|
||||
request(url) {
|
||||
expect(url).toEqual('search/verdaccio');
|
||||
return Promise.reject(apiResponse);
|
||||
},
|
||||
}));
|
||||
|
||||
const Search = require(SEARCH_FILE_PATH).Search;
|
||||
const component = mount(<Search />);
|
||||
component.setState({ search: 'verdaccio' });
|
||||
const { handleFetchPackages } = component.instance();
|
||||
await handleFetchPackages({ value: 'verdaccio' });
|
||||
|
||||
expect(component.state('error')).toBeTruthy();
|
||||
expect(component.state('loaded')).toBeFalsy();
|
||||
expect(component.state('loading')).toBeFalsy();
|
||||
});
|
||||
|
||||
test('handleClickSearch: should change the window location on click or return key', () => {
|
||||
const getDetailPageURL = jest.fn(() => 'detail/page/url');
|
||||
jest.doMock(URL_FILE_PATH, () => ({ getDetailPageURL }));
|
||||
|
||||
const suggestionValue = [];
|
||||
const Search = require(SEARCH_FILE_PATH).Search;
|
||||
const pushHandler = jest.fn();
|
||||
const component = mount(<Search history={{ push: pushHandler }} />);
|
||||
const { handleClickSearch } = component.instance();
|
||||
|
||||
// click
|
||||
handleClickSearch(event, { suggestionValue, method: 'click' });
|
||||
expect(event.stopPropagation).toHaveBeenCalled();
|
||||
expect(pushHandler).toHaveBeenCalledTimes(1);
|
||||
|
||||
// return key
|
||||
handleClickSearch(event, { suggestionValue, method: 'enter' });
|
||||
expect(event.stopPropagation).toHaveBeenCalled();
|
||||
expect(pushHandler).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
@@ -1,21 +0,0 @@
|
||||
import {API_ERROR} from '../../../../src/lib/constants';
|
||||
/**
|
||||
* API mock for login endpoint
|
||||
* @param {object} config configuration of api call
|
||||
* @returns {promise}
|
||||
*/
|
||||
export default function(config) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const body = JSON.parse(config.body);
|
||||
if (body.username === 'sam' && body.password === '1234') {
|
||||
resolve({
|
||||
username: 'sam',
|
||||
token: 'TEST_TOKEN'
|
||||
});
|
||||
} else {
|
||||
reject({
|
||||
error: API_ERROR.BAD_USERNAME_PASSWORD
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
/**
|
||||
* Mock response for logo api
|
||||
* @returns {promise}
|
||||
*/
|
||||
export default function() {
|
||||
return Promise.resolve('http://localhost/-/static/logo.png');
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
export const packageInformation = [
|
||||
{
|
||||
name: 'jquery',
|
||||
title: 'jQuery',
|
||||
description: 'JavaScript library for DOM operations',
|
||||
version: '3.3.2-pre',
|
||||
main: 'dist/jquery.js',
|
||||
homepage: 'https://jquery.com',
|
||||
author: {
|
||||
name: 'JS Foundation and other contributors',
|
||||
url: 'https://github.com/jquery/jquery/blob/master/AUTHORS.txt',
|
||||
avatar: '',
|
||||
},
|
||||
repository: {
|
||||
type: 'git',
|
||||
url: 'https://github.com/jquery/jquery.git'
|
||||
},
|
||||
keywords: ['jquery', 'javascript', 'browser', 'library'],
|
||||
bugs: {
|
||||
url: 'https://github.com/jquery/jquery/issues'
|
||||
},
|
||||
license: 'MIT',
|
||||
dependencies: {},
|
||||
devDependencies: {
|
||||
'babel-core': '7.0.0-beta.0',
|
||||
'babel-plugin-transform-es2015-for-of': '7.0.0-beta.0',
|
||||
commitplease: '3.2.0',
|
||||
'core-js': '2.5.7',
|
||||
'eslint-config-jquery': '1.0.1',
|
||||
grunt: '1.0.3',
|
||||
'grunt-babel': '7.0.0',
|
||||
'grunt-cli': '1.2.0',
|
||||
'grunt-compare-size': '0.4.2',
|
||||
'grunt-contrib-uglify': '3.3.0',
|
||||
'grunt-contrib-watch': '1.1.0',
|
||||
'grunt-eslint': '20.2.0',
|
||||
'grunt-git-authors': '3.2.0',
|
||||
'grunt-jsonlint': '1.1.0',
|
||||
'grunt-karma': '2.0.0',
|
||||
'grunt-newer': '1.3.0',
|
||||
'grunt-npmcopy': '0.1.0',
|
||||
'gzip-js': '0.3.2',
|
||||
husky: '0.14.3',
|
||||
insight: '0.10.1',
|
||||
jsdom: '5.6.1',
|
||||
karma: '2.0.3',
|
||||
'karma-browserstack-launcher': '1.3.0',
|
||||
'karma-chrome-launcher': '2.2.0',
|
||||
'karma-firefox-launcher': '1.1.0',
|
||||
'karma-qunit': '1.2.1',
|
||||
'load-grunt-tasks': '4.0.0',
|
||||
'native-promise-only': '0.8.1',
|
||||
'promises-aplus-tests': '2.1.2',
|
||||
q: '1.5.1',
|
||||
'qunit-assert-step': '1.1.1',
|
||||
qunitjs: '1.23.1',
|
||||
'raw-body': '2.3.3',
|
||||
requirejs: '2.3.5',
|
||||
sinon: '2.3.7',
|
||||
sizzle: '2.3.3',
|
||||
'strip-json-comments': '2.0.1',
|
||||
testswarm: '1.1.0',
|
||||
'uglify-js': '3.4.0'
|
||||
},
|
||||
scripts: {
|
||||
build: 'npm install && grunt',
|
||||
start: 'grunt watch',
|
||||
'test:browserless': 'grunt && grunt test:slow',
|
||||
'test:browser': 'grunt && grunt karma:main',
|
||||
test: 'grunt && grunt test:slow && grunt karma:main',
|
||||
jenkins: 'npm run test:browserless',
|
||||
precommit: 'grunt lint:newer qunit_fixture',
|
||||
commitmsg: 'node node_modules/commitplease'
|
||||
},
|
||||
commitplease: {
|
||||
nohook: true,
|
||||
components: [
|
||||
'Docs',
|
||||
'Tests',
|
||||
'Build',
|
||||
'Support',
|
||||
'Release',
|
||||
'Core',
|
||||
'Ajax',
|
||||
'Attributes',
|
||||
'Callbacks',
|
||||
'CSS',
|
||||
'Data',
|
||||
'Deferred',
|
||||
'Deprecated',
|
||||
'Dimensions',
|
||||
'Effects',
|
||||
'Event',
|
||||
'Manipulation',
|
||||
'Offset',
|
||||
'Queue',
|
||||
'Selector',
|
||||
'Serialize',
|
||||
'Traversing',
|
||||
'Wrap'
|
||||
],
|
||||
markerPattern: '^((clos|fix|resolv)(e[sd]|ing))|^(refs?)',
|
||||
ticketPattern: '^((Closes|Fixes) ([a-zA-Z]{2,}-)[0-9]+)|^(Refs? [^#])'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'lodash',
|
||||
version: '4.17.4',
|
||||
license: 'MIT',
|
||||
private: true,
|
||||
main: 'lodash.js',
|
||||
author: {
|
||||
name: 'John david dalton',
|
||||
url: 'test url',
|
||||
avatar: 'test avatar',
|
||||
},
|
||||
engines: {
|
||||
node: '>=4.0.0'
|
||||
},
|
||||
sideEffects: false,
|
||||
scripts: {
|
||||
build: 'npm run build:main && npm run build:fp',
|
||||
'build:fp': 'node lib/fp/build-dist.js',
|
||||
'build:fp-modules': 'node lib/fp/build-modules.js',
|
||||
'build:main': 'node lib/main/build-dist.js',
|
||||
'build:main-modules': 'node lib/main/build-modules.js',
|
||||
doc: 'node lib/main/build-doc github && npm run test:doc',
|
||||
'doc:fp': 'node lib/fp/build-doc',
|
||||
'doc:site': 'node lib/main/build-doc site',
|
||||
'doc:sitehtml':
|
||||
'optional-dev-dependency marky-markdown@^9.0.1 && npm run doc:site && node lib/main/build-site',
|
||||
pretest: 'npm run build',
|
||||
style: 'eslint *.js .internal/**/*.js',
|
||||
test: 'npm run test:main && npm run test:fp',
|
||||
'test:doc': 'markdown-doctest doc/*.md',
|
||||
'test:fp': 'node test/test-fp',
|
||||
'test:main': 'node test/test',
|
||||
validate: 'npm run style && npm run test'
|
||||
},
|
||||
devDependencies: {
|
||||
async: '^2.1.4',
|
||||
benchmark: '^2.1.3',
|
||||
chalk: '^1.1.3',
|
||||
cheerio: '^0.22.0',
|
||||
'codecov.io': '~0.1.6',
|
||||
coveralls: '^2.11.15',
|
||||
'curl-amd': '~0.8.12',
|
||||
docdown: '~0.7.2',
|
||||
dojo: '^1.12.1',
|
||||
ecstatic: '^2.1.0',
|
||||
eslint: '^3.15.0',
|
||||
'eslint-plugin-import': '^2.2.0',
|
||||
'fs-extra': '~1.0.0',
|
||||
glob: '^7.1.1',
|
||||
istanbul: '0.4.5',
|
||||
jquery: '^3.1.1',
|
||||
lodash: '4.17.3',
|
||||
'lodash-doc-globals': '^0.1.1',
|
||||
'markdown-doctest': '^0.9.1',
|
||||
'optional-dev-dependency': '^2.0.0',
|
||||
platform: '^1.3.3',
|
||||
'qunit-extras': '^3.0.0',
|
||||
qunitjs: '^2.1.0',
|
||||
request: '^2.79.0',
|
||||
requirejs: '^2.3.2',
|
||||
'sauce-tunnel': '^2.5.0',
|
||||
'uglify-js': '2.7.5',
|
||||
webpack: '^1.14.0'
|
||||
},
|
||||
greenkeeper: {
|
||||
ignore: ['lodash']
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -1,668 +0,0 @@
|
||||
export const packageMeta = {
|
||||
name: 'verdaccio',
|
||||
'dist-tags': { latest: '2.7.1', beta: '2.4.1-beta' },
|
||||
time: {
|
||||
modified: '2017-12-14T15:43:27.317Z',
|
||||
created: '2016-07-28T12:48:43.536Z',
|
||||
'1.4.0': '2016-07-28T12:48:43.536Z',
|
||||
'2.0.0': '2016-08-26T22:36:41.762Z',
|
||||
'2.0.1': '2016-08-29T13:26:21.754Z',
|
||||
'2.1.0': '2016-10-12T00:48:03.025Z',
|
||||
'2.1.1': '2017-02-07T06:43:22.801Z',
|
||||
'2.2.0-v20170212': '2017-02-12T14:48:27.322Z',
|
||||
'2.1.2': '2017-03-09T06:25:28.107Z',
|
||||
'2.1.3': '2017-03-29T20:03:36.850Z',
|
||||
'2.1.4': '2017-04-13T20:08:41.131Z',
|
||||
'2.1.5': '2017-04-22T09:07:39.821Z',
|
||||
'2.1.6': '2017-05-12T07:43:36.616Z',
|
||||
'2.1.7': '2017-05-14T13:50:14.016Z',
|
||||
'2.1.10': '2017-06-03T09:53:52.449Z',
|
||||
'2.2.0': '2017-06-08T19:02:53.618Z',
|
||||
'2.2.1': '2017-06-17T16:23:14.158Z',
|
||||
'2.2.2': '2017-07-02T13:13:13.304Z',
|
||||
'2.2.3': '2017-07-04T20:43:59.442Z',
|
||||
'2.2.4': '2017-07-05T17:28:07.187Z',
|
||||
'2.2.5': '2017-07-05T17:34:11.089Z',
|
||||
'2.2.6': '2017-07-13T05:04:54.418Z',
|
||||
'2.2.7': '2017-07-15T23:27:24.523Z',
|
||||
'2.3.0-beta': '2017-07-15T23:31:31.664Z',
|
||||
'2.2.7-r': '2017-07-18T19:44:48.946Z',
|
||||
'2.3.0-beta-1': '2017-07-22T16:27:45.025Z',
|
||||
'2.3.0-beta-2': '2017-07-22T17:12:09.905Z',
|
||||
'2.3.0-beta-3': '2017-07-22T17:35:05.771Z',
|
||||
'2.3.0-beta-4': '2017-07-22T18:22:42.563Z',
|
||||
'2.3.0': '2017-07-22T23:08:37.513Z',
|
||||
'2.3.1-pre': '2017-07-24T05:50:40.852Z',
|
||||
'2.3.1': '2017-07-25T05:24:27.651Z',
|
||||
'2.3.2': '2017-07-28T23:05:36.431Z',
|
||||
'2.3.3': '2017-07-29T10:05:30.120Z',
|
||||
'2.3.4': '2017-07-29T10:18:44.061Z',
|
||||
'2.3.5': '2017-08-14T06:22:57.686Z',
|
||||
'2.3.6': '2017-08-17T04:30:44.872Z',
|
||||
'2.4.0': '2017-09-23T08:01:22.780Z',
|
||||
'2.4.1-beta': '2017-10-01T08:57:14.509Z',
|
||||
'2.5.0': '2017-10-01T12:31:06.333Z',
|
||||
'2.5.1': '2017-10-01T13:32:06.584Z',
|
||||
'2.6.0': '2017-10-18T20:22:32.836Z',
|
||||
'2.6.1': '2017-10-19T17:26:24.083Z',
|
||||
'2.6.2': '2017-10-21T08:37:16.527Z',
|
||||
'2.6.3': '2017-10-21T16:04:05.556Z',
|
||||
'2.6.4': '2017-10-31T17:47:03.647Z',
|
||||
'2.6.5': '2017-11-05T09:09:31.332Z',
|
||||
'2.6.6': '2017-11-08T22:47:16.504Z',
|
||||
'2.7.0': '2017-12-05T23:25:06.372Z',
|
||||
'2.7.1': '2017-12-14T15:43:27.317Z'
|
||||
},
|
||||
_uplinks: {
|
||||
abc: { etag: 'ddfdxjn8m8n6gn70-8m', fetched: 1532297472000},
|
||||
npmjs: { etag: '"5a272ad2-4f6b1"', fetched: 1513266232741 },
|
||||
xyz: { etag: '564748hydydygs-s7ehj', fetched: 1532124672000}
|
||||
},
|
||||
_rev: '16-ba1b806df0298246',
|
||||
_attachments: {},
|
||||
latest: {
|
||||
name: 'verdaccio',
|
||||
version: '2.7.1',
|
||||
description: 'Private npm repository server',
|
||||
author: {
|
||||
name: 'User NPM',
|
||||
email: 'test@author.local',
|
||||
avatar: 'https://www.gravatar.com/avatar/a5a236ba477ee98908600c40cda74f4a'
|
||||
},
|
||||
repository: {
|
||||
type: 'git',
|
||||
url: 'git://github.com/verdaccio/verdaccio.git'
|
||||
},
|
||||
main: 'index.js',
|
||||
bin: { verdaccio: './bin/verdaccio' },
|
||||
dependencies: {
|
||||
'@verdaccio/file-locking': '0.0.3',
|
||||
'@verdaccio/streams': '0.0.2',
|
||||
JSONStream: '^1.1.1',
|
||||
'apache-md5': '^1.1.2',
|
||||
async: '^2.0.1',
|
||||
'body-parser': '^1.15.0',
|
||||
bunyan: '^1.8.0',
|
||||
chalk: '^2.0.1',
|
||||
commander: '^2.11.0',
|
||||
compression: '1.6.2',
|
||||
cookies: '^0.7.0',
|
||||
cors: '^2.8.3',
|
||||
express: '4.15.3',
|
||||
global: '^4.3.2',
|
||||
handlebars: '4.0.5',
|
||||
'http-errors': '^1.4.0',
|
||||
'js-string-escape': '1.0.1',
|
||||
'js-yaml': '^3.6.0',
|
||||
jsonwebtoken: '^7.4.1',
|
||||
lockfile: '^1.0.1',
|
||||
lodash: '4.17.4',
|
||||
lunr: '^0.7.0',
|
||||
marked: '0.3.6',
|
||||
mime: '^1.3.6',
|
||||
minimatch: '^3.0.2',
|
||||
mkdirp: '^0.5.1',
|
||||
pkginfo: '^0.4.0',
|
||||
request: '^2.72.0',
|
||||
semver: '^5.1.0',
|
||||
'unix-crypt-td-js': '^1.0.0'
|
||||
},
|
||||
devDependencies: {
|
||||
axios: '0.16.2',
|
||||
'babel-cli': '6.24.1',
|
||||
'babel-core': '6.25.0',
|
||||
'babel-eslint': '7.2.3',
|
||||
'babel-loader': '7.1.1',
|
||||
'babel-plugin-flow-runtime': '0.11.1',
|
||||
'babel-plugin-transform-decorators-legacy': '1.3.4',
|
||||
'babel-plugin-transform-runtime': '6.23.0',
|
||||
'babel-polyfill': '^6.26.0',
|
||||
'babel-preset-env': '1.5.2',
|
||||
'babel-preset-flow': '6.23.0',
|
||||
'babel-preset-react': '6.24.1',
|
||||
'babel-preset-stage-2': '6.24.1',
|
||||
'babel-preset-stage-3': '6.24.1',
|
||||
'babel-runtime': '6.23.0',
|
||||
'codacy-coverage': '2.0.2',
|
||||
codecov: '2.2.0',
|
||||
coveralls: '2.13.1',
|
||||
'css-loader': '0.28.4',
|
||||
'element-react': '1.0.16',
|
||||
'element-theme-default': '1.3.7',
|
||||
eslint: '4.2.0',
|
||||
'eslint-config-google': '0.8.0',
|
||||
'eslint-loader': '1.8.0',
|
||||
'eslint-plugin-babel': '4.1.1',
|
||||
'eslint-plugin-flowtype': '2.35.0',
|
||||
'eslint-plugin-import': '2.6.1',
|
||||
'eslint-plugin-react': '7.1.0',
|
||||
'extract-text-webpack-plugin': '3.0.0',
|
||||
'file-loader': '0.11.2',
|
||||
'flow-runtime': '0.13.0',
|
||||
'friendly-errors-webpack-plugin': '1.6.1',
|
||||
'fs-extra': '4.0.1',
|
||||
'github-markdown-css': '2.8.0',
|
||||
'html-webpack-plugin': '2.29.0',
|
||||
'in-publish': '2.0.0',
|
||||
'localstorage-memory': '1.0.2',
|
||||
mocha: '3.4.2',
|
||||
'mocha-lcov-reporter': '1.3.0',
|
||||
'node-sass': '4.5.3',
|
||||
'normalize.css': '7.0.0',
|
||||
nyc: '11.0.3',
|
||||
ora: '1.3.0',
|
||||
'prop-types': '15.5.10',
|
||||
react: '15.6.1',
|
||||
'react-dom': '15.6.1',
|
||||
'react-hot-loader': '3.0.0-beta.7',
|
||||
'react-router-dom': '4.1.1',
|
||||
'react-syntax-highlighter': '5.6.2',
|
||||
rimraf: '2.6.1',
|
||||
'sass-loader': '6.0.6',
|
||||
'source-map-loader': '0.2.1',
|
||||
'standard-version': '4.2.0',
|
||||
'style-loader': '0.18.2',
|
||||
stylelint: '7.13.0',
|
||||
'stylelint-config-standard': '16.0.0',
|
||||
'stylelint-webpack-plugin': '0.8.0',
|
||||
'url-loader': '0.5.8',
|
||||
webpack: '3.2.0',
|
||||
'webpack-dev-server': '2.5.0',
|
||||
'webpack-merge': '4.1.0'
|
||||
},
|
||||
keywords: [
|
||||
'private',
|
||||
'package',
|
||||
'repository',
|
||||
'registry',
|
||||
'enterprise',
|
||||
'modules',
|
||||
'proxy',
|
||||
'server'
|
||||
],
|
||||
scripts: {
|
||||
release: 'standard-version -a -s',
|
||||
prepublish: 'in-publish && npm run build:webui || not-in-publish',
|
||||
test: 'mocha ./test/functional ./test/unit --reporter=spec --full-trace',
|
||||
'pre:ci': 'npm run build:webui',
|
||||
'test:ci': 'npm run test:coverage',
|
||||
'test:only': 'mocha ./test/functional ./test/unit',
|
||||
'test:coverage': 'nyc npm t',
|
||||
'coverage:html': 'nyc report --reporter=html',
|
||||
'coverage:publish': 'nyc report --reporter=lcov | codecov',
|
||||
lint: 'eslint .',
|
||||
'lint:css': "stylelint 'src/**/*.scss' --syntax scss",
|
||||
'pre:webpack': 'npm run lint && rimraf static/*',
|
||||
'dev:webui': 'babel-node tools/dev.server.js',
|
||||
'build:webui':
|
||||
'npm run pre:webpack && webpack --config tools/webpack.prod.config.babel.js',
|
||||
'build:docker': 'docker build -t verdaccio . --no-cache',
|
||||
'build:docker:rpi': 'docker build -f Dockerfile.rpi -t verdaccio:rpi .'
|
||||
},
|
||||
jest: { snapshotSerializers: ['jest-serializer-enzyme'] },
|
||||
engines: { node: '>=4.6.1', npm: '>=2.15.9' },
|
||||
preferGlobal: true,
|
||||
publishConfig: { registry: 'http://localhost:4873/' },
|
||||
license: 'WTFPL',
|
||||
contributors: [
|
||||
{
|
||||
name: '030',
|
||||
email: 'test1@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/4ef03c2bf8d8689527903212d96fb45b'
|
||||
},
|
||||
{
|
||||
name: 'User NPM',
|
||||
email: 'test2@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/a5a236ba477ee98908600c40cda74f4a'
|
||||
},
|
||||
{
|
||||
name: 'User NPM',
|
||||
email: 'test3@test.comu',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/41a61049006855759bd6ec82ef0543a0'
|
||||
},
|
||||
{
|
||||
name: 'Alex Vernacchia',
|
||||
email: 'tes4@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/06975001f7f2be7052bcf978700c6112'
|
||||
},
|
||||
{
|
||||
name: 'Alexander Makarenko',
|
||||
email: 'test5@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/d9acfc4ed4e49a436738ff26a722dce4'
|
||||
},
|
||||
{
|
||||
name: 'Alexandre-io',
|
||||
email: 'test6@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/2e095c7cfd278f72825d0fed6e12e3b1'
|
||||
},
|
||||
{
|
||||
name: 'Aram Drevekenin',
|
||||
email: 'test7@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/371edff6d79c39bb9e36bde39d41a4b0'
|
||||
},
|
||||
{
|
||||
name: 'Bart Dubois',
|
||||
email: 'test8@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/4acf72b14fcb459286c988c4523bafc8'
|
||||
},
|
||||
{
|
||||
name: 'Barthélemy Vessemont',
|
||||
email: 'test9@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/322cd2fad528a55c4351ec76d85ef525'
|
||||
},
|
||||
{
|
||||
name: 'Brandon Nicholls',
|
||||
email: 'test10@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/2d3b462f08f214ed459967aa7ef206f7'
|
||||
},
|
||||
{
|
||||
name: 'Bren Norris',
|
||||
email: 'test11@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/465a42204a22efada0f15b46a7cdad3a'
|
||||
},
|
||||
{
|
||||
name: 'Brett Trotter',
|
||||
email: 'test12@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/27a54519dcbe64c6d705f3cc4854595a'
|
||||
},
|
||||
{
|
||||
name: 'Brian Peacock',
|
||||
email: 'test13@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/3dd3d627330e7e048c13a7480f19842e'
|
||||
},
|
||||
{
|
||||
name: 'Cedric Darne',
|
||||
email: 'test14@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/0a617cebc6539940d7956c86e86c72a6'
|
||||
},
|
||||
{
|
||||
name: 'Chad Killingsworth',
|
||||
email: 'test15@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/a5825b2d69311e559e28a535e5f0d483'
|
||||
},
|
||||
{
|
||||
name: 'Chris Breneman',
|
||||
email: 'test16@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/3c5c3edef955c93edac672cbad04d7cd'
|
||||
},
|
||||
{
|
||||
name: 'Cody Droz',
|
||||
email: 'test17@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/b762ce4d14acfece36e783b1592d882b'
|
||||
},
|
||||
{
|
||||
name: 'Daniel Rodríguez Rivero',
|
||||
email: 'test18@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/ac7f548c31e8a002cfa41bd4c71e222d'
|
||||
},
|
||||
{
|
||||
name: 'Denis Babineau',
|
||||
email: 'test19@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/ee5a522e067759ba0403824ecebeab4d'
|
||||
},
|
||||
{
|
||||
name: 'Emmanuel Narh',
|
||||
email: 'test20@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/93a84a6120969fd181785ff9de834f0a'
|
||||
},
|
||||
{
|
||||
name: 'Fabio Poloni',
|
||||
email: 'test21@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/f9a05677360e5f52fcca6e1af9b0f2ee'
|
||||
},
|
||||
{
|
||||
name: 'Facundo Chambó',
|
||||
email: 'test22@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/ec9e7c590ba4081c25fcf197f90a4ea0'
|
||||
},
|
||||
{
|
||||
name: 'Guilherme Bernal',
|
||||
email: 'test23@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/e5d55dcf2495618e8b9f8778f8353ee0'
|
||||
},
|
||||
{
|
||||
name: 'Jakub Jirutka',
|
||||
email: 'test24@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/061bdb74aa4a543108658b277a257b4b'
|
||||
},
|
||||
{
|
||||
name: 'James Newell',
|
||||
email: 'test25@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/825190aaae6ec7fd95085e1fb6f261d2'
|
||||
},
|
||||
{
|
||||
name: 'Jan Vansteenkiste',
|
||||
email: 'test26@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/41835625a324201c796a0a0cffe4796b'
|
||||
},
|
||||
{
|
||||
name: 'Jannis Achstetter',
|
||||
email: 'test27@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/92d1cce007b032f4a63c6df764f18030'
|
||||
},
|
||||
{
|
||||
name: 'Jeremy Moritz',
|
||||
email: 'test28@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/008127e8f10293f43e62de3b7b3520e1'
|
||||
},
|
||||
{
|
||||
name: 'John Gozde',
|
||||
email: 'test29@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/3e8927c60cb043a56fdd6531cfcaddbc'
|
||||
},
|
||||
{
|
||||
name: 'Jon de la Motte',
|
||||
email: 'test30@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/126c1ea4fdb20bbb85c3ff735b7b0964'
|
||||
},
|
||||
{
|
||||
name: 'Joseph Gentle',
|
||||
email: 'test31@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/484f0b8ba8b7cc43db0be8f910a91254'
|
||||
},
|
||||
{
|
||||
name: 'José De Paz',
|
||||
email: 'test32@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/2532122835f5ebf1642b707ae088c895'
|
||||
},
|
||||
{
|
||||
name: 'Juan Carlos Picado',
|
||||
email: 'test33@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/c676605ff39f9c7a43f5518a8ce54e12'
|
||||
},
|
||||
{
|
||||
name: 'Juan Carlos Picado',
|
||||
email: 'test34@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/fba48015a688c38cc84e5b55b07858c0'
|
||||
},
|
||||
{
|
||||
name: 'User NPM',
|
||||
email: 'test35@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/fba48015a688c38cc84e5b55b07858c0'
|
||||
},
|
||||
{
|
||||
name: 'User NPM @nickname',
|
||||
email: 'test36@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/fba48015a688c38cc84e5b55b07858c0'
|
||||
},
|
||||
{
|
||||
name: 'Kalman Speier',
|
||||
email: 'test37@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/272806ba17639e2fbf811e51eb8bfb99'
|
||||
},
|
||||
{
|
||||
name: 'Keyvan Fatehi',
|
||||
email: 'test38@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/22735d1ba5765955914eb2d597dfaab5'
|
||||
},
|
||||
{
|
||||
name: 'Kody J. Peterson',
|
||||
email: 'test39@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/918a15afc52e9b0a67b2651191b23d04'
|
||||
},
|
||||
{
|
||||
name: 'Madison Grubb',
|
||||
email: 'test40@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/73b84fdf661c11d48d3370bfa197162b'
|
||||
},
|
||||
{
|
||||
name: 'Manuel de Brito Fontes',
|
||||
email: 'test41@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/8798ca0a499428e5e8f25d3614ac8b6e'
|
||||
},
|
||||
{
|
||||
name: 'Mark Doeswijk',
|
||||
email: 'test42@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/0d70ebd6c46dc01502bfab5f8c2d2bc5'
|
||||
},
|
||||
{
|
||||
name: 'Meeeeow',
|
||||
email: 'test43@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/baa061890d7b352ba121082272419a8a'
|
||||
},
|
||||
{
|
||||
name: 'Meeeeow',
|
||||
email: 'test44@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/12a36e093451d4c0f75d4240960ce29b'
|
||||
},
|
||||
{
|
||||
name: 'Michael Arnel',
|
||||
email: 'test45@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/5f9a5ed24c63609d52651258f6dd8c12'
|
||||
},
|
||||
{
|
||||
name: 'Michael Crowe',
|
||||
email: 'test46@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/eec9ee62019852da28a3bc91c57907f9'
|
||||
},
|
||||
{
|
||||
name: 'Miguel Mejias',
|
||||
email: 'test47@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/7289a01fedfdb9ddf855ee4dd4d41ae2'
|
||||
},
|
||||
{
|
||||
name: 'Miroslav Bajtoš',
|
||||
email: 'test48@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/b4d8831300713259f74aea79f842ca57'
|
||||
},
|
||||
{
|
||||
name: 'Nate Ziarek',
|
||||
email: 'test49@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/6442023756294fd43aa518bbe5cc6dcc'
|
||||
},
|
||||
{
|
||||
name: 'Nick',
|
||||
email: 'test50@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/8a810f12c9624ea2092852fe7c19f1ee'
|
||||
},
|
||||
{
|
||||
name: 'Piotr Synowiec',
|
||||
email: 'test51@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/87028f33a3e1e5b4201c371abddf93e2'
|
||||
},
|
||||
{
|
||||
name: 'Rafael Cesar',
|
||||
email: 'test52@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/204ed93fa5be7e2f9f299ad8bca6431f'
|
||||
},
|
||||
{
|
||||
name: 'Robert Ewald',
|
||||
email: 'test53@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/ec2166ce419f78fb354f128b01a4a44d'
|
||||
},
|
||||
{
|
||||
name: 'Robert Groh',
|
||||
email: 'test54@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/565ccb5374a3e0e31a75f11da2eb57aa'
|
||||
},
|
||||
{
|
||||
name: 'Robin Persson',
|
||||
email: 'test55@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/99da46e4d59664134b176869340f464b'
|
||||
},
|
||||
{
|
||||
name: 'Romain Lai-King',
|
||||
email: 'test56@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/69d0370c58399d0e0bbd15ccabfe1ec5'
|
||||
},
|
||||
{
|
||||
name: 'Ryan Graham',
|
||||
email: 'test57@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/8bd1dd86bbf8705a5a702b86a2f3a390'
|
||||
},
|
||||
{
|
||||
name: 'Ryan Graham',
|
||||
email: 'test58@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/e272ab422c1c629e9be26cba8b6c0166'
|
||||
},
|
||||
{
|
||||
name: 'Sam Day',
|
||||
email: 'test59@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/1886554b0562a0eeeb78a4d1f27917ea'
|
||||
},
|
||||
{
|
||||
name: 'Tarun Garg',
|
||||
email: 'test60@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/185e200c3451cfbe341f0e758626303a'
|
||||
},
|
||||
{
|
||||
name: 'Thomas Cort',
|
||||
email: 'test61@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/120d2921c33c1bd8dedfce67a28dcc63'
|
||||
},
|
||||
{
|
||||
name: 'Tom Vincent',
|
||||
email: 'test62@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/fb0c7faeda7f5d5632182a3d80381bfa'
|
||||
},
|
||||
{
|
||||
name: 'Trent Earl',
|
||||
email: 'test63@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/1e30abe66d21824b89c28d05e5b57d84'
|
||||
},
|
||||
{
|
||||
name: 'Yannick Croissant',
|
||||
email: 'test64@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/1e619ddb2a180222dd3d9f0348e65b9b'
|
||||
},
|
||||
{
|
||||
name: 'Yannick Galatol',
|
||||
email: 'test65@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/2f624f92326fef845bb2c07b392b7e48'
|
||||
},
|
||||
{
|
||||
name: 'cklein',
|
||||
email: 'test66@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/f8288370380881cf3afc5a92a63d652d'
|
||||
},
|
||||
{
|
||||
name: 'danielo515',
|
||||
email: 'test67@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/ac7f548c31e8a002cfa41bd4c71e222d'
|
||||
},
|
||||
{
|
||||
name: 'jmwilkinson',
|
||||
email: 'test68@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/3b99683f0a4c26a8906ecbe7968a4ade'
|
||||
},
|
||||
{
|
||||
name: 'nickname',
|
||||
email: 'test69@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/fba48015a688c38cc84e5b55b07858c0'
|
||||
},
|
||||
{
|
||||
name: 'nickname',
|
||||
email: 'test70@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/047ba1e853d20459e531619af5493c56'
|
||||
},
|
||||
{
|
||||
name: 'maxlaverse',
|
||||
email: 'test71@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/74324a2900906c45949a8c5cee6d0730'
|
||||
},
|
||||
{
|
||||
name: 'saheba',
|
||||
email: 'test72@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/77644c51856cab149e0f550c5f0c6ed8'
|
||||
},
|
||||
{
|
||||
name: 'steve-p-com',
|
||||
email: 'test73@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/bef1821d3036b8b9242c4999826c1c3c'
|
||||
},
|
||||
{
|
||||
name: 'trent.earl',
|
||||
email: 'test74@test.local',
|
||||
avatar:
|
||||
'https://www.gravatar.com/avatar/f84b8ae496f7c988dce5a71d773e75bb'
|
||||
}
|
||||
],
|
||||
readmeFilename: 'README.md',
|
||||
gitHead: '567dbe327819ed30afb96906f8d43f19740e2e3d',
|
||||
bugs: { url: 'https://github.com/verdaccio/verdaccio/issues' },
|
||||
homepage: 'https://github.com/verdaccio/verdaccio#readme',
|
||||
_id: 'verdaccio@2.7.1',
|
||||
_shasum: '958c919180e7f2ed6775f48d4ec64bd8de2a14df',
|
||||
_from: '.',
|
||||
_npmVersion: '3.10.10',
|
||||
_nodeVersion: '6.9.5',
|
||||
_npmUser: {},
|
||||
dist: {
|
||||
shasum: '958c919180e7f2ed6775f48d4ec64bd8de2a14df',
|
||||
tarball: 'http://localhost:4873/verdaccio/-/verdaccio-2.7.1.tgz'
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export default {};
|
||||
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* @prettier
|
||||
* Setup configuration for Jest
|
||||
* This file includes global settings for the JEST environment.
|
||||
*/
|
||||
import 'raf/polyfill';
|
||||
import { configure } from 'enzyme';
|
||||
import Adapter from 'enzyme-adapter-react-16';
|
||||
|
||||
configure({ adapter: new Adapter() });
|
||||
|
||||
global.__APP_VERSION__ = '1.0.0';
|
||||
global.__VERDACCIO_BASENAME_UI_OPTIONS = {};
|
||||
|
||||
// mocking few DOM methods
|
||||
if (global.document) {
|
||||
document.createRange = jest.fn(() => ({
|
||||
selectNodeContents: () => {},
|
||||
}));
|
||||
document.execCommand = jest.fn();
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
import { isTokenExpire, makeLogin } from '../../../src/webui/utils/login';
|
||||
|
||||
import {
|
||||
generateTokenWithTimeRange,
|
||||
generateTokenWithExpirationAsString,
|
||||
generateTokenWithOutExpiration
|
||||
} from '../components/__mocks__/token';
|
||||
|
||||
console.error = jest.fn();
|
||||
|
||||
jest.mock('.../../../../src/webui/utils/api', () => ({
|
||||
request: require('../components/__mocks__/api').default.request
|
||||
}));
|
||||
|
||||
describe('isTokenExpire', () => {
|
||||
test('isTokenExpire - token is not present', () => {
|
||||
expect(isTokenExpire()).toBeTruthy();
|
||||
});
|
||||
|
||||
test('isTokenExpire - token is not a valid payload', () => {
|
||||
expect(isTokenExpire('not_a_valid_token')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('isTokenExpire - token should not expire in 24 hrs range', () => {
|
||||
const token = generateTokenWithTimeRange(24);
|
||||
expect(isTokenExpire(token)).toBeFalsy();
|
||||
});
|
||||
|
||||
test('isTokenExpire - token should expire for current time', () => {
|
||||
const token = generateTokenWithTimeRange();
|
||||
expect(isTokenExpire(token)).toBeTruthy();
|
||||
});
|
||||
|
||||
test('isTokenExpire - token expiration is not available', () => {
|
||||
const token = generateTokenWithOutExpiration();
|
||||
expect(isTokenExpire(token)).toBeTruthy();
|
||||
});
|
||||
|
||||
test('isTokenExpire - token is not a valid json token', () => {
|
||||
const token = generateTokenWithExpirationAsString();
|
||||
const result = [
|
||||
'Invalid token:',
|
||||
SyntaxError('Unexpected token o in JSON at position 1'),
|
||||
'xxxxxx.W29iamVjdCBPYmplY3Rd.xxxxxx'
|
||||
];
|
||||
expect(isTokenExpire(token)).toBeTruthy();
|
||||
expect(console.error).toHaveBeenCalledWith(...result);
|
||||
});
|
||||
});
|
||||
|
||||
describe('makeLogin', () => {
|
||||
test('makeLogin - should give error for blank username and password', async () => {
|
||||
const result = {
|
||||
error: {
|
||||
description: "Username or password can't be empty!",
|
||||
title: 'Unable to login',
|
||||
type: 'error'
|
||||
}
|
||||
};
|
||||
const login = await makeLogin();
|
||||
expect(login).toEqual(result);
|
||||
});
|
||||
|
||||
test('makeLogin - should login successfully', async () => {
|
||||
const { username, password } = { username: 'sam', password: '1234' };
|
||||
const result = { token: 'TEST_TOKEN', username: 'sam' };
|
||||
const login = await makeLogin(username, password);
|
||||
expect(login).toEqual(result);
|
||||
});
|
||||
|
||||
test('makeLogin - login should failed with 401', async () => {
|
||||
const result = {
|
||||
error: {
|
||||
description: 'bad username/password, access denied',
|
||||
title: 'Unable to login',
|
||||
type: 'error'
|
||||
}
|
||||
};
|
||||
|
||||
const { username, password } = { username: 'sam', password: '123456' };
|
||||
const login = await makeLogin(username, password);
|
||||
expect(login).toEqual(result);
|
||||
});
|
||||
|
||||
test('makeLogin - login should failed with when no data is sent', async () => {
|
||||
const result = {
|
||||
error: {
|
||||
title: 'Unable to login',
|
||||
type: 'error',
|
||||
description: "Username or password can't be empty!"
|
||||
}
|
||||
};
|
||||
|
||||
const { username, password } = { username: '', password: '' };
|
||||
const login = await makeLogin(username, password);
|
||||
expect(login).toEqual(result);
|
||||
});
|
||||
});
|
||||
@@ -1,98 +0,0 @@
|
||||
import {
|
||||
formatLicense,
|
||||
formatRepository,
|
||||
formatDate,
|
||||
formatDateDistance,
|
||||
getLastUpdatedPackageTime,
|
||||
getRecentReleases
|
||||
} from '../../../src/webui/utils/package';
|
||||
|
||||
import { packageMeta } from '../components/store/packageMeta';
|
||||
|
||||
describe('formatLicense', () => {
|
||||
test('should check license field different values', () => {
|
||||
expect(formatLicense('MIT')).toEqual('MIT');
|
||||
});
|
||||
test('should check license field for object value', () => {
|
||||
const license = { type: 'ISC', url: 'https://opensource.org/licenses/ISC' };
|
||||
expect(formatLicense(license)).toEqual('ISC');
|
||||
});
|
||||
test('should check license field for other value', () => {
|
||||
expect(formatLicense(null)).toBeNull();
|
||||
expect(formatLicense({})).toBeNull();
|
||||
expect(formatLicense([])).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('formatRepository', () => {
|
||||
test('should check repository field different values', () => {
|
||||
const repository = 'https://github.com/verdaccio/verdaccio';
|
||||
expect(formatRepository(repository)).toEqual(repository);
|
||||
});
|
||||
test('should check repository field for object value', () => {
|
||||
const license = {
|
||||
type: 'git',
|
||||
url: 'https://github.com/verdaccio/verdaccio'
|
||||
};
|
||||
expect(formatRepository(license)).toEqual(license.url);
|
||||
});
|
||||
test('should check repository field for other value', () => {
|
||||
expect(formatRepository(null)).toBeNull();
|
||||
expect(formatRepository({})).toBeNull();
|
||||
expect(formatRepository([])).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('formatDate', () => {
|
||||
test('should format the date', () => {
|
||||
const date = 1532211072138;
|
||||
expect(formatDate(date)).toEqual('21.07.2018, 22:11:12');
|
||||
});
|
||||
});
|
||||
|
||||
describe('formatDateDistance', () => {
|
||||
test('should calculate the distance', () => {
|
||||
// const dateAboutTwoMonthsAgo = () => {
|
||||
// const date = new Date();
|
||||
// date.setMonth(date.getMonth() - 1);
|
||||
// date.setDate(date.getDay() - 20);
|
||||
// return date;
|
||||
// };
|
||||
const dateTwoMonthsAgo = () => {
|
||||
const date = new Date();
|
||||
date.setMonth(date.getMonth() - 2);
|
||||
return date;
|
||||
};
|
||||
// const date1 = dateAboutTwoMonthsAgo();
|
||||
const date2 = dateTwoMonthsAgo();
|
||||
// FIXME: we need to review this expect, fails every x time.
|
||||
// expect(formatDateDistance(date1)).toEqual('about 2 months');
|
||||
expect(formatDateDistance(date2)).toEqual('2 months');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getLastUpdatedPackageTime', () => {
|
||||
test('should get the last update time', () => {
|
||||
const lastUpdated = packageMeta._uplinks;
|
||||
expect(getLastUpdatedPackageTime(lastUpdated)).toEqual(
|
||||
'22.07.2018, 22:11:12'
|
||||
);
|
||||
});
|
||||
test('should get the last update time for blank uplink', () => {
|
||||
const lastUpdated = {};
|
||||
expect(getLastUpdatedPackageTime(lastUpdated)).toEqual('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getRecentReleases', () => {
|
||||
test('should get the recent releases', () => {
|
||||
const { time } = packageMeta;
|
||||
const result = [
|
||||
{ time: '14.12.2017, 15:43:27', version: '2.7.1' },
|
||||
{ time: '05.12.2017, 23:25:06', version: '2.7.0' },
|
||||
{ time: '08.11.2017, 22:47:16', version: '2.6.6' }
|
||||
];
|
||||
expect(getRecentReleases(time)).toEqual(result);
|
||||
expect(getRecentReleases()).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user