0
Fork 0
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:
Ayush Sharma 2017-12-02 00:34:01 +05:30 committed by juanpicado
parent 753281effe
commit 3052e5fb22
12 changed files with 239 additions and 17 deletions

View file

@ -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": {

View file

@ -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)'
]
};

View file

@ -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",

View file

@ -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() }>

View file

@ -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>

View 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;

View 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;

View 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);
});
});
});

View file

@ -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');
});
});

View file

@ -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>');
});
});

View 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' }
}
});
}
});
}

View 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);
}