mirror of
https://github.com/verdaccio/verdaccio.git
synced 2025-04-08 02:54:13 -05:00
Webui component test with Jest
This commit is contained in:
parent
753281effe
commit
3052e5fb22
12 changed files with 239 additions and 17 deletions
6
.babelrc
6
.babelrc
|
@ -26,10 +26,12 @@
|
|||
]
|
||||
},
|
||||
"test": {
|
||||
"presets": [ "es2015-node4", "flow"],
|
||||
"presets": [ "es2015-node4", "es2015", "flow", "react"],
|
||||
"plugins": [
|
||||
"transform-class-properties",
|
||||
"transform-object-rest-spread"
|
||||
"transform-object-rest-spread",
|
||||
"transform-class-properties",
|
||||
"syntax-async-functions"
|
||||
]
|
||||
},
|
||||
"registry": {
|
||||
|
|
|
@ -17,6 +17,13 @@ module.exports = {
|
|||
'global.js'
|
||||
],
|
||||
'moduleNameMapper': {
|
||||
'\\.(scss)$': '<rootDir>/node_modules/jest-css-modules'
|
||||
}
|
||||
'\\.(scss)$': '<rootDir>/node_modules/identity-obj-proxy',
|
||||
'github-markdown-css': '<rootDir>/node_modules/identity-obj-proxy',
|
||||
'\\.(png)$': '<rootDir>/node_modules/identity-obj-proxy',
|
||||
'api': '<rootDir>/test/webui/components/__mocks__/api.js',
|
||||
'storage': '<rootDir>/test/webui/components/__mocks__/storage.js',
|
||||
},
|
||||
'transformIgnorePatterns': [
|
||||
'<rootDir>/node_modules/(?!react-syntax-highlighter)'
|
||||
]
|
||||
};
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
"babel-jest": "^21.2.0",
|
||||
"babel-loader": "7.1.2",
|
||||
"babel-plugin-flow-runtime": "0.15.0",
|
||||
"babel-plugin-syntax-async-functions": "^6.13.0",
|
||||
"babel-plugin-transform-async-to-generator": "^6.24.1",
|
||||
"babel-plugin-transform-class-properties": "^6.24.1",
|
||||
"babel-plugin-transform-decorators-legacy": "1.3.4",
|
||||
|
@ -72,7 +73,6 @@
|
|||
"babel-register": "^6.26.0",
|
||||
"babel-runtime": "6.26.0",
|
||||
"codecov": "2.2.0",
|
||||
"coveralls": "2.13.1",
|
||||
"cross-env": "5.1.1",
|
||||
"css-loader": "0.28.7",
|
||||
"element-react": "1.4.3",
|
||||
|
@ -95,6 +95,7 @@
|
|||
"fs-extra": "4.0.2",
|
||||
"github-markdown-css": "2.9.0",
|
||||
"html-webpack-plugin": "2.30.1",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"in-publish": "2.0.0",
|
||||
"jest": "^21.2.1",
|
||||
"jest-css-modules": "^1.1.0",
|
||||
|
|
|
@ -26,6 +26,7 @@ export default class Header extends React.Component {
|
|||
super(props);
|
||||
this.toggleLoginModal = this.toggleLoginModal.bind(this);
|
||||
this.handleSubmit = this.handleSubmit.bind(this);
|
||||
this.handleInput = this.handleInput.bind(this);
|
||||
}
|
||||
|
||||
toggleLoginModal() {
|
||||
|
@ -169,9 +170,9 @@ export default class Header extends React.Component {
|
|||
</Alert>
|
||||
}
|
||||
<br/>
|
||||
<Input placeholder="Username" onChange={this.handleInput.bind(this, 'username')} />
|
||||
<Input name="username" placeholder="Username" onChange={this.handleInput('username')} />
|
||||
<br/><br/>
|
||||
<Input type="password" placeholder="Type your password" onChange={this.handleInput.bind(this, 'password')} />
|
||||
<Input name="password" type="password" placeholder="Type your password" onChange={this.handleInput('password')} />
|
||||
</Dialog.Body>
|
||||
<Dialog.Footer className="dialog-footer">
|
||||
<Button onClick={ () => this.toggleLoginModal() }>
|
||||
|
|
|
@ -25,11 +25,11 @@ const Help = () => {
|
|||
<strong>
|
||||
1. Login
|
||||
</strong>
|
||||
<SyntaxHighlighter language='javascript' style={sunburst}>
|
||||
<SyntaxHighlighter language='javascript' style={sunburst} id="adduser">
|
||||
{`npm adduser --registry ${registryURL}`}
|
||||
</SyntaxHighlighter>
|
||||
<strong>2. Publish</strong>
|
||||
<SyntaxHighlighter language='javascript' style={sunburst}>
|
||||
<SyntaxHighlighter language='javascript' style={sunburst} id="publish">
|
||||
{`npm publish --registry ${registryURL}`}
|
||||
</SyntaxHighlighter>
|
||||
<strong>3. Refresh this page!</strong>
|
||||
|
|
33
test/webui/components/__mocks__/api.js
Normal file
33
test/webui/components/__mocks__/api.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* API Mocks for WebUI
|
||||
*/
|
||||
import logo from '../store/logo';
|
||||
import login from '../store/login';
|
||||
|
||||
/**
|
||||
* Register mock api endpoints
|
||||
* @param {string} endpoint
|
||||
* @returns {Promise}
|
||||
*/
|
||||
const register = (method = 'get', endpoint, config = {}) => {
|
||||
|
||||
if (endpoint === 'login' && method === 'post') {
|
||||
return login(config);
|
||||
}
|
||||
|
||||
if (endpoint === 'logo' && method === 'get') {
|
||||
return logo();
|
||||
}
|
||||
|
||||
return Promise.reject({ status: 404, data: 'Not found' });
|
||||
};
|
||||
|
||||
/**
|
||||
* Bind API methods
|
||||
*/
|
||||
const API = ['get', 'post'].reduce((api, method) => {
|
||||
api[method] = register.bind(null, method);
|
||||
return api;
|
||||
}, {});
|
||||
|
||||
export default API;
|
17
test/webui/components/__mocks__/storage.js
Normal file
17
test/webui/components/__mocks__/storage.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* Storage mock
|
||||
*/
|
||||
|
||||
const store = {};
|
||||
|
||||
const storage = {
|
||||
setItem: (key, value) => {
|
||||
store[key] = value;
|
||||
return store;
|
||||
},
|
||||
getItem: key => {
|
||||
return store[key];
|
||||
}
|
||||
};
|
||||
|
||||
export default storage;
|
105
test/webui/components/header.spec.js
Normal file
105
test/webui/components/header.spec.js
Normal file
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* Header component
|
||||
*/
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import Header from '../../../src/webui/src/components/Header';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import storage from '../../../src/webui/utils/storage';
|
||||
|
||||
describe('<Header /> component shallow', () => {
|
||||
let wrapper;
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<BrowserRouter>
|
||||
<Header />
|
||||
</BrowserRouter>
|
||||
);
|
||||
});
|
||||
|
||||
it('should check the initial state', () => {
|
||||
const state = {
|
||||
showLogin: false,
|
||||
username: '',
|
||||
password: '',
|
||||
logo: '',
|
||||
loginError: null
|
||||
};
|
||||
const HeaderWrapper = wrapper.find(Header).dive();
|
||||
expect(HeaderWrapper.state()).toEqual(state);
|
||||
});
|
||||
|
||||
it('should toggleLogin modal', () => {
|
||||
const HeaderWrapper = wrapper.find(Header).dive();
|
||||
const toggleLoginModal = HeaderWrapper.instance().toggleLoginModal;
|
||||
|
||||
expect(toggleLoginModal()).toBeUndefined();
|
||||
expect(HeaderWrapper.state('showLogin')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should handleInput set state', () => {
|
||||
const HeaderWrapper = wrapper.find(Header).dive();
|
||||
const handleInput = HeaderWrapper.instance().handleInput;
|
||||
|
||||
expect(handleInput('username', 'xyz')).toBeUndefined();
|
||||
expect(HeaderWrapper.state('username')).toEqual('xyz');
|
||||
|
||||
expect(handleInput('password', '1234')).toBeUndefined();
|
||||
expect(HeaderWrapper.state('password')).toEqual('1234');
|
||||
});
|
||||
|
||||
it('handleSubmit - should give error for blank username and password', () => {
|
||||
const HeaderWrapper = wrapper.find(Header).dive();
|
||||
const handleSubmit = HeaderWrapper.instance().handleSubmit;
|
||||
const error = {
|
||||
description: "Username or password can't be empty!",
|
||||
title: 'Unable to login',
|
||||
type: 'error'
|
||||
};
|
||||
expect(handleSubmit()).toBeDefined();
|
||||
expect(HeaderWrapper.state('loginError')).toEqual(error);
|
||||
});
|
||||
|
||||
it('handleSubmit - should login successfully', () => {
|
||||
const HeaderWrapper = wrapper.find(Header).dive();
|
||||
const handleSubmit = HeaderWrapper.instance().handleSubmit;
|
||||
|
||||
HeaderWrapper.setState({ username: 'sam', password: '1234' });
|
||||
|
||||
handleSubmit().then(() => {
|
||||
expect(storage.getItem('token')).toEqual('TEST_TOKEN');
|
||||
expect(storage.getItem('username')).toEqual('sam');
|
||||
});
|
||||
});
|
||||
|
||||
it('handleSubmit - login should failed with 401', () => {
|
||||
const HeaderWrapper = wrapper.find(Header).dive();
|
||||
const handleSubmit = HeaderWrapper.instance().handleSubmit;
|
||||
const error = {
|
||||
title: 'Unable to login',
|
||||
type: 'error',
|
||||
description: 'Unauthorized'
|
||||
};
|
||||
HeaderWrapper.setState({ username: 'sam', password: '12345' });
|
||||
|
||||
handleSubmit().then(() => {
|
||||
expect(HeaderWrapper.state('loginError')).toEqual(error);
|
||||
});
|
||||
});
|
||||
|
||||
it('handleSubmit - login should failed with when no data is sent', () => {
|
||||
const HeaderWrapper = wrapper.find(Header).dive();
|
||||
const handleSubmit = HeaderWrapper.instance().handleSubmit;
|
||||
const error = {
|
||||
title: 'Unable to login',
|
||||
type: 'error',
|
||||
description: 'something went wrong'
|
||||
};
|
||||
HeaderWrapper.setState({});
|
||||
|
||||
handleSubmit().then(() => {
|
||||
expect(HeaderWrapper.state('loginError')).toEqual(error);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -4,9 +4,10 @@
|
|||
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import SyntaxHighlighter from 'react-syntax-highlighter/dist/light';
|
||||
import Help from '../../../src/webui/src/components/Help';
|
||||
|
||||
describe('<NoItem /> component', () => {
|
||||
describe('<Help /> component', () => {
|
||||
beforeEach(() => {
|
||||
/**
|
||||
* @see https://github.com/facebook/jest/issues/890
|
||||
|
@ -22,9 +23,13 @@ describe('<NoItem /> component', () => {
|
|||
value: '/'
|
||||
});
|
||||
const wrapper = shallow(<Help />);
|
||||
expect(wrapper.html()).toEqual(
|
||||
'<div><li><h1>No Package Published Yet</h1><div><div>To publish your first package just:</div><br/><strong>1. Login</strong><pre style="display:block;overflow-x:auto;padding:0.5em;background:#000;color:#f8f8f8"><code>npm adduser --registry http:<span style="color:#aeaeae;font-style:italic">//example.com</span></code></pre><strong>2. Publish</strong><pre style="display:block;overflow-x:auto;padding:0.5em;background:#000;color:#f8f8f8"><code>npm publish --registry http:<span style="color:#aeaeae;font-style:italic">//example.com</span></code></pre><strong>3. Refresh this page!</strong></div></li></div>'
|
||||
);
|
||||
expect(
|
||||
wrapper
|
||||
.find('#adduser')
|
||||
.find(SyntaxHighlighter)
|
||||
.dive()
|
||||
.text()
|
||||
).toEqual('npm adduser --registry http://example.com');
|
||||
});
|
||||
|
||||
it('should set html from props with someOtherPath', () => {
|
||||
|
@ -33,6 +38,12 @@ describe('<NoItem /> component', () => {
|
|||
value: '/someOtherPath'
|
||||
});
|
||||
const wrapper = shallow(<Help />);
|
||||
expect(wrapper.html()).toEqual('<div><li><h1>No Package Published Yet</h1><div><div>To publish your first package just:</div><br/><strong>1. Login</strong><pre style="display:block;overflow-x:auto;padding:0.5em;background:#000;color:#f8f8f8"><code>npm adduser --registry http:<span style="color:#aeaeae;font-style:italic">//example.com/someOtherPath</span></code></pre><strong>2. Publish</strong><pre style="display:block;overflow-x:auto;padding:0.5em;background:#000;color:#f8f8f8"><code>npm publish --registry http:<span style="color:#aeaeae;font-style:italic">//example.com/someOtherPath</span></code></pre><strong>3. Refresh this page!</strong></div></li></div>');
|
||||
expect(
|
||||
wrapper
|
||||
.find('#publish')
|
||||
.find(SyntaxHighlighter)
|
||||
.dive()
|
||||
.text()
|
||||
).toEqual('npm publish --registry http://example.com/someOtherPath');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import PackageDetail from '../../../src/webui/src/components/PackageDetail';
|
||||
import Readme from '../../../src/webui/src/components/Readme';
|
||||
|
||||
console.error = jest.fn();
|
||||
|
||||
|
@ -19,9 +20,13 @@ describe('<PackageDetail /> component', () => {
|
|||
package: 'Verdaccio'
|
||||
};
|
||||
const wrapper = shallow(<PackageDetail {...props} />);
|
||||
|
||||
|
||||
expect(wrapper.find('h1').text()).toEqual('Verdaccio');
|
||||
|
||||
// here write a test to match readMe prop
|
||||
expect(
|
||||
wrapper
|
||||
.find(Readme)
|
||||
.dive()
|
||||
.html()
|
||||
).toEqual('<div class="markdown-body">Test readme</div>');
|
||||
});
|
||||
});
|
||||
|
|
30
test/webui/components/store/login.js
Normal file
30
test/webui/components/store/login.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* API mock for login endpoint
|
||||
*/
|
||||
export default function(config) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (config.data.username === 'sam' && config.data.password === '1234') {
|
||||
resolve({
|
||||
status: 200,
|
||||
data: {
|
||||
username: 'sam',
|
||||
token: 'TEST_TOKEN'
|
||||
}
|
||||
});
|
||||
} else if (
|
||||
config.data.username === undefined ||
|
||||
config.data.password === undefined
|
||||
) {
|
||||
reject({
|
||||
message: 'something went wrong'
|
||||
});
|
||||
} else {
|
||||
reject({
|
||||
response: {
|
||||
status: 401,
|
||||
data: { error: 'Unauthorized' }
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
10
test/webui/components/store/logo.js
Normal file
10
test/webui/components/store/logo.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* Mock response for login api
|
||||
* @returns {promise}
|
||||
*/
|
||||
export default function() {
|
||||
const response = {
|
||||
data: 'http://xyz.com/image.jpg'
|
||||
};
|
||||
return Promise.resolve(response);
|
||||
}
|
Loading…
Add table
Reference in a new issue