mirror of
https://github.com/verdaccio/verdaccio.git
synced 2025-04-01 02:42:23 -05:00
Merge pull request #1197 from verdaccio/fix-1013
feat: migrate react router from hash to history api #1013
This commit is contained in:
commit
5ed2d54b6a
20 changed files with 131 additions and 82 deletions
|
@ -12,6 +12,7 @@ import express from 'express';
|
|||
import { combineBaseUrl, getWebProtocol } from '../../lib/utils';
|
||||
import Search from '../../lib/search';
|
||||
import { HEADERS, HTTP_STATUS, WEB_TITLE } from '../../lib/constants';
|
||||
import { spliceURL } from '../../utils/string';
|
||||
|
||||
const { securityIframe } = require('../middleware');
|
||||
/* eslint new-cap:off */
|
||||
|
@ -52,9 +53,8 @@ module.exports = function(config, auth, storage) {
|
|||
});
|
||||
});
|
||||
|
||||
router.get('/', function(req, res) {
|
||||
const installPath = _.get(config, 'url_prefix', '');
|
||||
const base = combineBaseUrl(getWebProtocol(req.get(HEADERS.FORWARDED_PROTO), req.protocol), req.get('host'), installPath);
|
||||
function renderHTML(req, res) {
|
||||
const base = combineBaseUrl(getWebProtocol(req.get(HEADERS.FORWARDED_PROTO), req.protocol), req.get('host'), config.url_prefix);
|
||||
const webPage = template
|
||||
.replace(/ToReplaceByVerdaccio/g, base)
|
||||
.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.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;
|
||||
|
|
|
@ -4,16 +4,16 @@ import isNil from 'lodash/isNil';
|
|||
import storage from './utils/storage';
|
||||
import { makeLogin, isTokenExpire } from './utils/login';
|
||||
|
||||
import Footer from './components/Footer';
|
||||
import Loading from './components/Loading';
|
||||
import LoginModal from './components/Login';
|
||||
import Header from './components/Header';
|
||||
import { Container, Content } from './components/Layout';
|
||||
import Route from './router';
|
||||
import RouterApp from './router';
|
||||
import API from './utils/api';
|
||||
import './styles/typeface-roboto.scss';
|
||||
import './styles/main.scss';
|
||||
import 'normalize.css';
|
||||
import Footer from './components/Footer';
|
||||
|
||||
export const AppContext = React.createContext();
|
||||
|
||||
|
@ -67,7 +67,8 @@ export default class App extends Component {
|
|||
isLoading: false,
|
||||
});
|
||||
} catch (error) {
|
||||
this.handleShowAlertDialog({
|
||||
// FIXME: add dialog
|
||||
console.error({
|
||||
title: 'Warning',
|
||||
message: `Unable to load package list: ${error.message}`,
|
||||
});
|
||||
|
@ -140,15 +141,14 @@ export default class App extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { isLoading, isUserLoggedIn, packages } = this.state;
|
||||
const { isLoading, isUserLoggedIn, packages, logoUrl, user, scope } = this.state;
|
||||
return (
|
||||
<Container isLoading={isLoading}>
|
||||
{isLoading ? (
|
||||
<Loading />
|
||||
) : (
|
||||
<Fragment>
|
||||
<AppContextProvider value={{isUserLoggedIn, packages}}>
|
||||
{this.renderHeader()}
|
||||
<AppContextProvider value={{isUserLoggedIn, packages, logoUrl, user, scope}}>
|
||||
{this.renderContent()}
|
||||
</AppContextProvider>
|
||||
</Fragment>
|
||||
|
@ -175,7 +175,11 @@ export default class App extends Component {
|
|||
return (
|
||||
<Fragment>
|
||||
<Content>
|
||||
<Route></Route>
|
||||
<RouterApp
|
||||
onLogout={this.handleLogout}
|
||||
onToggleLoginModal={this.handleToggleLoginModal}>
|
||||
{this.renderHeader()}
|
||||
</RouterApp>
|
||||
</Content>
|
||||
<Footer />
|
||||
</Fragment>
|
||||
|
|
|
@ -34,7 +34,7 @@ class DepDetail extends Component<any, any> {
|
|||
const { onLoading, history } = this.props;
|
||||
|
||||
onLoading();
|
||||
history.push(`/version/${name}`);
|
||||
history.push(`/-/web/version/${name}`);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -22,12 +22,12 @@ class DetailSidebar extends Component<any, any> {
|
|||
|
||||
renderSideBar = ({packageMeta, packageName}) => {
|
||||
return (
|
||||
<Content>
|
||||
<Content className={'sidebar-info'}>
|
||||
<Grid container={true} spacing={24}>
|
||||
<Grid item={true} xs={12}>
|
||||
{this.renderTitle(packageName, packageMeta)}
|
||||
</Grid>
|
||||
<Grid item={true} xs={12}>
|
||||
<Grid className={'detail-info'} item={true} xs={12}>
|
||||
{this.renderCopyCLI()}
|
||||
</Grid>
|
||||
<Grid item={true} xs={12}>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import React, { Component } from 'react';
|
||||
import type { Node } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import Button from '@material-ui/core/Button/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 { getRegistryURL } from '../../utils/url';
|
||||
import Link from '../Link';
|
||||
import ExternalLink from '../Link';
|
||||
import Logo from '../Logo';
|
||||
import RegistryInfoDialog from '../RegistryInfoDialog';
|
||||
import Label from '../Label';
|
||||
|
@ -138,7 +139,7 @@ class Header extends Component<IProps, IState> {
|
|||
switch (type) {
|
||||
case 'help':
|
||||
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 />
|
||||
</IconButton>
|
||||
);
|
||||
|
|
|
@ -80,7 +80,7 @@ const Package = ({ name: label, version, time, author: { name, avatar }, descrip
|
|||
);
|
||||
|
||||
return (
|
||||
<WrapperLink className={'package'} to={`version/${label}`}>
|
||||
<WrapperLink className={'package'} to={`/-/web/version/${label}`}>
|
||||
<Header>
|
||||
{renderMainInfo()}
|
||||
<Overview>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import React, { Component } from 'react';
|
||||
import type { Node } from 'react';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
|
||||
import { default as IconSearch } from '@material-ui/icons/Search';
|
||||
import InputAdornment from '@material-ui/core/InputAdornment';
|
||||
|
@ -13,7 +14,6 @@ import debounce from 'lodash/debounce';
|
|||
import API from '../../utils/api';
|
||||
import AutoComplete from '../AutoComplete';
|
||||
import colors from '../../utils/styles/colors';
|
||||
import { getDetailPageURL } from '../../utils/url';
|
||||
|
||||
import { IProps, IState } from './types';
|
||||
import type { cancelAllSearchRequests, handlePackagesClearRequested, handleSearch, handleClickSearch, handleFetchPackages, onBlur } from './types';
|
||||
|
@ -24,7 +24,7 @@ const CONSTANTS = {
|
|||
ABORT_ERROR: 'AbortError',
|
||||
};
|
||||
|
||||
class Search extends Component<IProps, IState> {
|
||||
export class Search extends Component<IProps, IState> {
|
||||
requestList: Array<any>;
|
||||
|
||||
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.
|
||||
*/
|
||||
handleClickSearch: handleClickSearch = (event, { suggestionValue, method }) => {
|
||||
const { history } = this.props;
|
||||
// stops event bubbling
|
||||
event.stopPropagation();
|
||||
switch (method) {
|
||||
case 'click':
|
||||
case 'enter':
|
||||
this.setState({ search: '' });
|
||||
window.location.assign(getDetailPageURL(suggestionValue));
|
||||
// $FlowFixMe
|
||||
history.push(`/-/web/version/${suggestionValue}`);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
@ -181,4 +183,4 @@ class Search extends Component<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
export default Search;
|
||||
export default withRouter(Search);
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
* @flow
|
||||
*/
|
||||
|
||||
export interface IProps {}
|
||||
export interface IProps {
|
||||
history?: any;
|
||||
}
|
||||
|
||||
export interface IState {
|
||||
search: string;
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
* @prettier
|
||||
*/
|
||||
|
||||
import { createHashHistory } from 'history';
|
||||
import { createBrowserHistory } from 'history';
|
||||
|
||||
const history = createHashHistory();
|
||||
const history = createBrowserHistory();
|
||||
|
||||
// Listen for changes to the current location.
|
||||
history.listen((location, action) => {
|
||||
|
|
|
@ -9,6 +9,7 @@ import Loading from '../../components/Loading';
|
|||
import DetailContainer from '../../components/DetailContainer';
|
||||
import DetailSidebar from '../../components/DetailSidebar';
|
||||
import { callDetailPage } from '../../utils/calls';
|
||||
import { getRouterPackageName } from '../../utils/package';
|
||||
|
||||
export const DetailContext = React.createContext();
|
||||
|
||||
|
@ -21,7 +22,7 @@ class VersionPage extends Component<any, any> {
|
|||
|
||||
this.state = {
|
||||
readMe: '',
|
||||
packageName: this.getPackageName(props),
|
||||
packageName: getRouterPackageName(props.match),
|
||||
packageMeta: null,
|
||||
isLoading: true,
|
||||
notFound: false,
|
||||
|
@ -32,13 +33,6 @@ class VersionPage extends Component<any, any> {
|
|||
await this.loadPackageInfo();
|
||||
}
|
||||
|
||||
getPackageName(props: any = this.props): string {
|
||||
const { match } = props;
|
||||
const packageName = match.params.package;
|
||||
|
||||
return packageName;
|
||||
}
|
||||
|
||||
/* eslint no-unused-vars: 0 */
|
||||
async componentDidUpdate(nextProps: any, prevState: any) {
|
||||
const { packageName } = this.state;
|
||||
|
@ -56,7 +50,7 @@ class VersionPage extends Component<any, any> {
|
|||
|
||||
static getDerivedStateFromProps(nextProps: any, prevState: any) {
|
||||
const { match } = nextProps;
|
||||
const packageName = match.params.package;
|
||||
const packageName = getRouterPackageName(match);
|
||||
|
||||
if (packageName !== prevState.packageName) {
|
||||
try {
|
||||
|
|
|
@ -3,39 +3,50 @@
|
|||
* @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 { AppContextConsumer } from './app';
|
||||
|
||||
import { asyncComponent } from './utils/asyncComponent';
|
||||
import history from './history';
|
||||
import Header from './components/Header';
|
||||
|
||||
const DetailPackage = asyncComponent(() => import('./pages/detail'));
|
||||
const VersionPackage = asyncComponent(() => import('./pages/version'));
|
||||
const HomePage = asyncComponent(() => import('./pages/home'));
|
||||
|
||||
interface IProps {
|
||||
isUserLoggedIn: boolean;
|
||||
packages: Array<Object>;
|
||||
}
|
||||
|
||||
interface IState {}
|
||||
|
||||
class RouterApp extends Component<IProps, IState> {
|
||||
class RouterApp extends Component<any, any> {
|
||||
render() {
|
||||
return (
|
||||
<Router history={history}>
|
||||
<Switch>
|
||||
<Route exact={true} path={'/'} render={this.renderHomePage} />
|
||||
<Route exact={true} path={'/detail/@:scope/:package'} render={this.renderDetailPage} />
|
||||
<Route exact={true} path={'/detail/:package'} render={this.renderDetailPage} />
|
||||
<Route exact={true} path={'/version/@:scope/:package'} render={this.renderVersionPage} />
|
||||
<Route exact={true} path={'/version/:package'} render={this.renderVersionPage} />
|
||||
</Switch>
|
||||
<Fragment>
|
||||
{this.renderHeader()}
|
||||
<Switch>
|
||||
<Route exact={true} path={'/'} render={this.renderHomePage} />
|
||||
<Route exact={true} path={'/-/web/detail/@:scope/:package'} render={this.renderDetailPage} />
|
||||
<Route exact={true} path={'/-/web/detail/:package'} render={this.renderDetailPage} />
|
||||
<Route exact={true} path={'/-/web/version/@:scope/:package'} render={this.renderVersionPage} />
|
||||
<Route exact={true} path={'/-/web/version/:package'} render={this.renderVersionPage} />
|
||||
</Switch>
|
||||
</Fragment>
|
||||
</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 = () => {
|
||||
return (
|
||||
<AppContextConsumer>
|
||||
|
|
|
@ -106,3 +106,13 @@ export function formatDate(lastUpdate) {
|
|||
export function formatDateDistance(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
|
||||
*/
|
||||
export function getDetailPageURL(packageName) {
|
||||
return `${getRegistryURL()}/#/detail/${packageName}`;
|
||||
return `${getRegistryURL()}/-/web/version/${packageName}`;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
const scopedPackageMetadata = require('./partials/pkg-scoped');
|
||||
const protectedPackageMetadata = require('./partials/pkg-protected');
|
||||
|
||||
describe('/ (Verdaccio Page)', () => {
|
||||
describe.skip('/ (Verdaccio Page)', () => {
|
||||
let page;
|
||||
// this might be increased based on the delays included in all test
|
||||
jest.setTimeout(200000);
|
||||
|
@ -139,7 +139,7 @@ describe('/ (Verdaccio Page)', () => {
|
|||
});
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
|
|
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
|
||||
|
||||
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,3 +1,3 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<PackageList /> component should load the component with packages 1`] = `"<div class=\\"package-list-items\\"><div class=\\"pkgContainer\\"><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>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=\\"/-/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>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=\\"/-/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 { mount } from 'enzyme';
|
||||
import { BrowserRouter as Router } from 'react-router-dom';
|
||||
import { shallow } from 'enzyme';
|
||||
import Header from '../../../../src/webui/components/Header';
|
||||
|
||||
describe('<Header /> component with logged in state', () => {
|
||||
let wrapper;
|
||||
let routerWrapper;
|
||||
let instance;
|
||||
let props;
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -20,7 +23,13 @@ describe('<Header /> component with logged in state', () => {
|
|||
scope: 'test scope',
|
||||
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', () => {
|
||||
|
@ -30,13 +39,12 @@ describe('<Header /> component with logged in state', () => {
|
|||
registryUrl: 'http://localhost',
|
||||
showMobileNavBar: false,
|
||||
};
|
||||
|
||||
expect(wrapper.state()).toEqual(state);
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
expect(routerWrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('handleLoggedInMenu: set anchorEl to html element value in state', () => {
|
||||
const { handleLoggedInMenu } = wrapper.instance();
|
||||
|
||||
// creates a sample menu
|
||||
const div = document.createElement('div');
|
||||
const text = document.createTextNode('sample menu');
|
||||
|
@ -46,13 +54,15 @@ describe('<Header /> component with logged in state', () => {
|
|||
currentTarget: div,
|
||||
};
|
||||
|
||||
handleLoggedInMenu(event);
|
||||
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(() => {
|
||||
|
@ -63,7 +73,13 @@ describe('<Header /> component with logged out state', () => {
|
|||
logo: '',
|
||||
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', () => {
|
||||
|
@ -74,30 +90,26 @@ describe('<Header /> component with logged out state', () => {
|
|||
showMobileNavBar: false,
|
||||
};
|
||||
expect(wrapper.state()).toEqual(state);
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
expect(routerWrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('handleLoggedInMenuClose: set anchorEl value to null in state', () => {
|
||||
const { handleLoggedInMenuClose } = wrapper.instance();
|
||||
handleLoggedInMenuClose();
|
||||
instance.handleLoggedInMenuClose();
|
||||
expect(wrapper.state('anchorEl')).toBeNull();
|
||||
});
|
||||
|
||||
test('handleOpenRegistryInfoDialog: set openInfoDialog to be truthy in state', () => {
|
||||
const { handleOpenRegistryInfoDialog } = wrapper.instance();
|
||||
handleOpenRegistryInfoDialog();
|
||||
instance.handleOpenRegistryInfoDialog();
|
||||
expect(wrapper.state('openInfoDialog')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('handleCloseRegistryInfoDialog: set openInfoDialog to be falsy in state', () => {
|
||||
const { handleCloseRegistryInfoDialog } = wrapper.instance();
|
||||
handleCloseRegistryInfoDialog();
|
||||
instance.handleCloseRegistryInfoDialog();
|
||||
expect(wrapper.state('openInfoDialog')).toBeFalsy();
|
||||
});
|
||||
|
||||
test('handleToggleLogin: close/open popover menu', () => {
|
||||
const { handleToggleLogin } = wrapper.instance();
|
||||
handleToggleLogin();
|
||||
instance.handleToggleLogin();
|
||||
expect(wrapper.state('anchorEl')).toBeNull();
|
||||
expect(props.onToggleLoginModal).toHaveBeenCalled();
|
||||
});
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import React from 'react';
|
||||
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 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 />);
|
||||
component.setState({ search: 'verdaccio' });
|
||||
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)) }));
|
||||
|
||||
const Search = require(SEARCH_FILE_PATH).default;
|
||||
const Search = require(SEARCH_FILE_PATH).Search;
|
||||
const component = mount(<Search />);
|
||||
component.setState({ search: 'verdaccio' });
|
||||
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 />);
|
||||
component.setState({ search: 'verdaccio' });
|
||||
const { handleFetchPackages } = component.instance();
|
||||
|
@ -175,20 +175,19 @@ describe('<Search /> component: mocks specific tests ', () => {
|
|||
jest.doMock(URL_FILE_PATH, () => ({ getDetailPageURL }));
|
||||
|
||||
const suggestionValue = [];
|
||||
const Search = require(SEARCH_FILE_PATH).default;
|
||||
const component = mount(<Search />);
|
||||
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(getDetailPageURL).toHaveBeenCalledWith(suggestionValue);
|
||||
expect(window.location.assign).toHaveBeenCalledWith('detail/page/url');
|
||||
expect(pushHandler).toHaveBeenCalledTimes(1);
|
||||
|
||||
// return key
|
||||
handleClickSearch(event, { suggestionValue, method: 'enter' });
|
||||
expect(event.stopPropagation).toHaveBeenCalled();
|
||||
expect(getDetailPageURL).toHaveBeenCalledWith(suggestionValue);
|
||||
expect(window.location.assign).toHaveBeenCalledWith('detail/page/url');
|
||||
expect(pushHandler).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue