Enable linting on whole src dir, fix linting errors
Update .eslintrc with additional rules, fix linting errors
This commit is contained in:
parent
b05e933bce
commit
415b9b9628
109
.eslintrc
109
.eslintrc
|
@ -1,58 +1,55 @@
|
|||
{
|
||||
"rules": {
|
||||
"indent": [
|
||||
2,
|
||||
2
|
||||
],
|
||||
"quotes": [
|
||||
2,
|
||||
"single"
|
||||
],
|
||||
"linebreak-style": [
|
||||
2,
|
||||
"unix"
|
||||
],
|
||||
"semi": [
|
||||
2,
|
||||
"always"
|
||||
],
|
||||
"strict": 0,
|
||||
"react/display-name": [1, { "acceptTranspilerName": true }],
|
||||
"react/jsx-boolean-value": [1, "never"],
|
||||
"react/jsx-curly-spacing": [1, "never"],
|
||||
"react/jsx-no-duplicate-props": 1,
|
||||
"react/jsx-no-undef": 1,
|
||||
"react/jsx-quotes": 1,
|
||||
"react/jsx-sort-prop-types": 1,
|
||||
"react/jsx-sort-props": 0,
|
||||
"react/jsx-uses-react": 1,
|
||||
"react/jsx-uses-vars": 1,
|
||||
"react/no-danger": 1,
|
||||
"react/no-did-mount-set-state": 1,
|
||||
"react/no-did-update-set-state": 1,
|
||||
"react/no-multi-comp": 0, // reconsider this later
|
||||
"react/no-unknown-property": 1,
|
||||
"react/prop-types": 1,
|
||||
"react/react-in-jsx-scope": 1,
|
||||
"react/require-extension": 1,
|
||||
"react/self-closing-comp": 1,
|
||||
"react/sort-comp": 1,
|
||||
"react/wrap-multilines": 1
|
||||
},
|
||||
"env": {
|
||||
"es6": true,
|
||||
"browser": true,
|
||||
"jasmine": true,
|
||||
'node': true,
|
||||
"jest": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"ecmaFeatures": {
|
||||
"jsx": true,
|
||||
"experimentalObjectRestSpread": true
|
||||
},
|
||||
"plugins": [
|
||||
"react"
|
||||
],
|
||||
"parser": "babel-eslint"
|
||||
"rules": {
|
||||
"default-case": 0,
|
||||
"indent": [ 2, 2 ],
|
||||
"linebreak-style": [ 2, "unix" ],
|
||||
"max-len": [1, 100, 2, { "ignoreComments": true }],
|
||||
"no-cond-assign": [2, "except-parens"],
|
||||
"no-else-return": 0,
|
||||
"no-param-reassign": 0,
|
||||
"no-unused-vars": [1, {"vars": "local", "args": "none"}],
|
||||
"quotes": [ 2, "single" ],
|
||||
"quote-props": [1, "consistent-as-needed"],
|
||||
"radix": 0,
|
||||
"react/display-name": [1, { "acceptTranspilerName": true }],
|
||||
"react/jsx-boolean-value": [1, "never"],
|
||||
"react/jsx-curly-spacing": [1, "never"],
|
||||
"react/jsx-no-duplicate-props": 1,
|
||||
"react/jsx-no-undef": 1,
|
||||
"react/jsx-quotes": 1,
|
||||
"react/jsx-sort-prop-types": 1,
|
||||
"react/jsx-sort-props": 0,
|
||||
"react/jsx-uses-react": 1,
|
||||
"react/jsx-uses-vars": 1,
|
||||
"react/no-danger": 1,
|
||||
"react/no-did-mount-set-state": 1,
|
||||
"react/no-did-update-set-state": 1,
|
||||
"react/no-multi-comp": 0,
|
||||
"react/no-unknown-property": 1,
|
||||
"react/prop-types": 1,
|
||||
"react/react-in-jsx-scope": 1,
|
||||
"react/require-extension": 1,
|
||||
"react/self-closing-comp": 1,
|
||||
"react/sort-comp": 1,
|
||||
"react/wrap-multilines": 1,
|
||||
"space-infix-ops": 0,
|
||||
"semi": [ 2, "always" ],
|
||||
"strict": 0
|
||||
},
|
||||
"env": {
|
||||
"es6": true,
|
||||
"browser": true,
|
||||
"jasmine": true,
|
||||
"node": true,
|
||||
"jest": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"ecmaFeatures": {
|
||||
"jsx": true,
|
||||
"experimentalObjectRestSpread": true
|
||||
},
|
||||
"plugins": [
|
||||
"react"
|
||||
],
|
||||
"parser": "babel-eslint"
|
||||
}
|
||||
|
|
|
@ -30,7 +30,10 @@ In case of errors during ```npm install```, remove node_modules dir and clean np
|
|||
- ```npm run lint``` to run ESLint
|
||||
- ```npm test && npm run lint``` to run Tests and ESLint
|
||||
|
||||
(Info on Linting setup here: https://medium.com/@dan_abramov/lint-like-it-s-2015-6987d44c5b48)
|
||||
(Info on Linting setup here: https://medium.com/@dan_abramov/lint-like-it-s-2015-6987d44c5b48,
|
||||
.eslintrc rules tweaks here: http://blog.javascripting.com/2015/09/07/fine-tuning-airbnbs-eslint-config/)
|
||||
|
||||
Style guide: https://github.com/airbnb/javascript
|
||||
|
||||
#### Tests during development:
|
||||
|
||||
|
|
|
@ -44,10 +44,10 @@ gulp.task('fonts', function() {
|
|||
});
|
||||
|
||||
gulp.task('webpack-token-worker', function() {
|
||||
return gulp.src('./src/js/workers/TokenWorker.js')
|
||||
.pipe(webpack(tokenWorkerConfig))
|
||||
.pipe(gulp.dest('./dist/js'))
|
||||
.pipe(browserSync.stream());
|
||||
return gulp.src('./src/js/workers/TokenWorker.js')
|
||||
.pipe(webpack(tokenWorkerConfig))
|
||||
.pipe(gulp.dest('./dist/js'))
|
||||
.pipe(browserSync.stream());
|
||||
});
|
||||
|
||||
// Start test server, run tests once, then quit.
|
||||
|
|
|
@ -14,7 +14,7 @@ module.exports = function(config) {
|
|||
files: ['webpack.tests.js'],
|
||||
preprocessors: {
|
||||
// Run this through webpack, and enable inline sourcemaps
|
||||
'webpack.tests.js': ['webpack', 'sourcemap'],
|
||||
'webpack.tests.js': ['webpack', 'sourcemap']
|
||||
},
|
||||
|
||||
webpack: webpackConfig,
|
||||
|
@ -32,8 +32,7 @@ module.exports = function(config) {
|
|||
|
||||
// Webpack takes a little while to compile -- this manifests as a really
|
||||
// long load time while webpack blocks on serving the request.
|
||||
browserNoActivityTimeout: 60000, // 60 seconds
|
||||
browserNoActivityTimeout: 60000 // 60 seconds
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
},
|
||||
"scripts": {
|
||||
"test": "karma start --single-run",
|
||||
"lint": "eslint src/js"
|
||||
"lint": "eslint src"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
|
@ -24,20 +24,20 @@ let notLoggedInState = {};
|
|||
describe('Login component', () => {
|
||||
describe('When user is not logged in', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(LoginStore, 'getState').and.returnValue(notLoggedInState);
|
||||
spyOn(LoginStore, 'isLoggedIn').and.returnValue(false);
|
||||
loginInstance = TestUtils.renderIntoDocument(<Login/>);
|
||||
spyOn(LoginStore, 'getState').and.returnValue(notLoggedInState);
|
||||
spyOn(LoginStore, 'isLoggedIn').and.returnValue(false);
|
||||
loginInstance = TestUtils.renderIntoDocument(<Login/>);
|
||||
});
|
||||
|
||||
it('should check for redirection prior to mounting', () => {
|
||||
spyOn(loginInstance, '_shouldRedirect').and.callThrough();
|
||||
loginInstance.componentWillMount();
|
||||
expect(loginInstance._shouldRedirect).toHaveBeenCalled();
|
||||
spyOn(loginInstance, '_shouldRedirect').and.callThrough();
|
||||
loginInstance.componentWillMount();
|
||||
expect(loginInstance._shouldRedirect).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should check if User is logged in when testing for redirection', () => {
|
||||
loginInstance._shouldRedirect();
|
||||
expect(LoginStore.isLoggedIn).toHaveBeenCalled();
|
||||
loginInstance._shouldRedirect();
|
||||
expect(LoginStore.isLoggedIn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should render with expected markup', () => {
|
||||
|
|
|
@ -2,47 +2,40 @@ const AuthTokenStorage = require('../../js/services/AuthTokenStorage.js');
|
|||
const LoginActions = require('../../js/actions/LoginActions');
|
||||
|
||||
describe('AuthTokenStorage.', () => {
|
||||
describe('```AuthTokenStorage.getTokenId```', () => {
|
||||
let cbObj = { cb: (token) => {} };
|
||||
|
||||
describe('```AuthTokenStorage.getTokenId```', () => {
|
||||
|
||||
let cbObj = { cb: (token) => {} };
|
||||
|
||||
beforeEach(() => {
|
||||
spyOn(cbObj, 'cb');
|
||||
});
|
||||
|
||||
it('calls the given callback with the token if one has been set.',
|
||||
(done) => {
|
||||
LoginActions.loginUser({
|
||||
token: 'token-from-login',
|
||||
user: null,
|
||||
serviceCatalog: null,
|
||||
metadata: null
|
||||
});
|
||||
// unset the sessionStorage value to make sure
|
||||
// the value is retreived from the worker.
|
||||
spyOn(sessionStorage, 'getItem').and.returnValue(null);
|
||||
AuthTokenStorage.getTokenId(cbObj.cb);
|
||||
done();
|
||||
expect(cbObj.cb).toHaveBeenCalledWith('token-from-login');
|
||||
});
|
||||
|
||||
it('gives precedence to the token in sessionStorage if one is set', () => {
|
||||
spyOn(sessionStorage, 'getItem').and.returnValue('token-from-session-storage');
|
||||
AuthTokenStorage.getTokenId(cbObj.cb);
|
||||
expect(cbObj.cb).toHaveBeenCalledWith('token-from-session-storage');
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
spyOn(cbObj, 'cb');
|
||||
});
|
||||
|
||||
describe('```AuthTokenStorage.onLogoutUser```', () => {
|
||||
|
||||
it('removes the token from sessionStorage', () => {
|
||||
spyOn(sessionStorage, 'removeItem');
|
||||
AuthTokenStorage.removeTokenId();
|
||||
expect(sessionStorage.removeItem).toHaveBeenCalledWith('keystoneAuthTokenId');
|
||||
});
|
||||
|
||||
it('calls the given callback with the token if one has been set.', (done) => {
|
||||
LoginActions.loginUser({
|
||||
token: 'token-from-login',
|
||||
user: null,
|
||||
serviceCatalog: null,
|
||||
metadata: null
|
||||
});
|
||||
// unset the sessionStorage value to make sure
|
||||
// the value is retreived from the worker.
|
||||
spyOn(sessionStorage, 'getItem').and.returnValue(null);
|
||||
AuthTokenStorage.getTokenId(cbObj.cb);
|
||||
done();
|
||||
expect(cbObj.cb).toHaveBeenCalledWith('token-from-login');
|
||||
});
|
||||
|
||||
|
||||
it('gives precedence to the token in sessionStorage if one is set', () => {
|
||||
spyOn(sessionStorage, 'getItem').and.returnValue('token-from-session-storage');
|
||||
AuthTokenStorage.getTokenId(cbObj.cb);
|
||||
expect(cbObj.cb).toHaveBeenCalledWith('token-from-session-storage');
|
||||
});
|
||||
});
|
||||
|
||||
describe('```AuthTokenStorage.onLogoutUser```', () => {
|
||||
it('removes the token from sessionStorage', () => {
|
||||
spyOn(sessionStorage, 'removeItem');
|
||||
AuthTokenStorage.removeTokenId();
|
||||
expect(sessionStorage.removeItem).toHaveBeenCalledWith('keystoneAuthTokenId');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -27,7 +27,7 @@ describe('KeystoneApiService', () => {
|
|||
// let wrongApiRequest = jest.genMockFunction().mockImplementation(() => {
|
||||
// return when.reject(expectedError);
|
||||
// });
|
||||
KeystoneApiService.handleAuth(when(wrongApiRequest()));
|
||||
// KeystoneApiService.handleAuth(when(wrongApiRequest()));
|
||||
// jest.runAllTicks();
|
||||
expect(console.error).toBeCalledWith('Error in handleAuth', expectedError);
|
||||
});
|
||||
|
|
|
@ -73,7 +73,7 @@ export default class Login extends React.Component {
|
|||
render() {
|
||||
return (
|
||||
<div className="row">
|
||||
<div className="col-md-6 col-xs-8 col-md-offset-3 col-xs-offset-2">
|
||||
<div className="col-md-6 col-sm-8 col-xs-12 col-md-offset-3 col-sm-offset-2">
|
||||
<div className="panel panel-default panel-login">
|
||||
<div className="panel-heading">
|
||||
<h1 className="panel-title">TripleO UI Login</h1>
|
||||
|
|
|
@ -11,9 +11,11 @@ export default class NodePicker extends React.Component {
|
|||
render() {
|
||||
return (
|
||||
<div className="node-picker">
|
||||
<PickerArrow direction="left" increment={this.props.onIncrement.bind(this, -this.props.incrementValue)}/>
|
||||
<PickerArrow direction="left"
|
||||
increment={this.props.onIncrement.bind(this, -this.props.incrementValue)}/>
|
||||
<NodeStack count={this.props.nodeCount}/>
|
||||
<PickerArrow direction="right" increment={this.props.onIncrement.bind(this, this.props.incrementValue)}/>
|
||||
<PickerArrow direction="right"
|
||||
increment={this.props.onIncrement.bind(this, this.props.incrementValue)}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -30,7 +32,8 @@ export class PickerArrow extends React.Component {
|
|||
render() {
|
||||
return (
|
||||
<button className="picker-arrow" onClick={this.props.increment}>
|
||||
<span className={'glyphicon glyphicon-chevron-' + this.props.direction} aria-hidden="true"></span>
|
||||
<span className={'glyphicon glyphicon-chevron-' + this.props.direction}
|
||||
aria-hidden="true"></span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ export class FlavorPanelList extends React.Component {
|
|||
}
|
||||
}
|
||||
FlavorPanelList.propTypes = {
|
||||
'flavors': React.PropTypes.array.isRequired
|
||||
flavors: React.PropTypes.array.isRequired
|
||||
};
|
||||
|
||||
|
||||
|
@ -100,7 +100,7 @@ export class FlavorPanel extends React.Component {
|
|||
}
|
||||
}
|
||||
FlavorPanel.propTypes = {
|
||||
'flavor': React.PropTypes.object.isRequired
|
||||
flavor: React.PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
|
||||
|
@ -121,7 +121,7 @@ export class RoleList extends React.Component {
|
|||
}
|
||||
}
|
||||
RoleList.propTypes = {
|
||||
'roles': React.PropTypes.array.isRequired
|
||||
roles: React.PropTypes.array.isRequired
|
||||
};
|
||||
|
||||
|
||||
|
@ -140,7 +140,7 @@ export class FreeNodesPanel extends React.Component {
|
|||
}
|
||||
}
|
||||
FreeNodesPanel.propTypes = {
|
||||
'nodeCount': React.PropTypes.number.isRequired
|
||||
nodeCount: React.PropTypes.number.isRequired
|
||||
};
|
||||
|
||||
|
||||
|
@ -174,12 +174,13 @@ export class RolePanel extends React.Component {
|
|||
<h3 className="panel-title">{this.props.role.name}</h3>
|
||||
</div>
|
||||
<div className="panel-body clearfix">
|
||||
<NodePicker nodeCount={this.props.role.nodeCount} onIncrement={this.updateCount.bind(this)}/>
|
||||
<NodePicker nodeCount={this.props.role.nodeCount}
|
||||
onIncrement={this.updateCount.bind(this)}/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
RolePanel.propTypes = {
|
||||
'role': React.PropTypes.object.isRequired
|
||||
role: React.PropTypes.object.isRequired
|
||||
};
|
||||
|
|
|
@ -13,7 +13,10 @@ export default class Notification extends React.Component {
|
|||
});
|
||||
return (
|
||||
<div className={classes} role="alert">
|
||||
<button type="button" className="close" aria-label="Close" onClick={this.props.removeNotification}>
|
||||
<button type="button"
|
||||
className="close"
|
||||
aria-label="Close"
|
||||
onClick={this.props.removeNotification}>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<strong>{this.props.title}</strong><br/>
|
||||
|
|
|
@ -43,7 +43,8 @@ export default class NotificationList extends React.Component {
|
|||
return (
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-lg-3 col-lg-offset-9 col-md-4 col-md-offset-8 col-sm-6 col-sm-offset-6">
|
||||
<div className="col-lg-3 col-lg-offset-9 col-md-4
|
||||
col-md-offset-8 col-sm-6 col-sm-offset-6">
|
||||
<div className="notification-list">
|
||||
{notifications}
|
||||
</div>
|
||||
|
|
|
@ -11,5 +11,5 @@ export class PageHeader extends React.Component {
|
|||
}
|
||||
}
|
||||
PageHeader.propTypes = {
|
||||
'children': React.PropTypes.node
|
||||
children: React.PropTypes.node
|
||||
};
|
||||
|
|
|
@ -35,7 +35,7 @@ export default (ComposedComponent) => {
|
|||
|
||||
static willTransitionTo(transition) {
|
||||
if (!LoginStore.isLoggedIn()) {
|
||||
transition.redirect('/login', {}, {'nextPath' : transition.path});
|
||||
transition.redirect('/login', {}, { nextPath: transition.path });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@ export default class BaseHttpRequestErrorHandler{
|
|||
this.xmlHttpRequestError = xmlHttpRequestError;
|
||||
this.formInputFieldNames = formInputFieldNames || [];
|
||||
this._errors = this._generateErrors(this.xmlHttpRequestError);
|
||||
this._formFieldErrors = this._generateFormFieldErrors(this.xmlHttpRequestError, this.formInputFieldNames);
|
||||
this._formFieldErrors = this._generateFormFieldErrors(this.xmlHttpRequestError,
|
||||
this.formInputFieldNames);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -15,7 +16,7 @@ export default class BaseHttpRequestErrorHandler{
|
|||
@param {object} xmlHttpRequestError - The Error object
|
||||
@returns {array} array of error objects with type, title and message properties
|
||||
*/
|
||||
_generateErrors() {
|
||||
_generateErrors(xmlHttpRequestError) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
@ -26,7 +27,7 @@ export default class BaseHttpRequestErrorHandler{
|
|||
@returns {object} object with with form field names as keys and error messages as
|
||||
values. e.g. {'username': 'Username does not exist'}
|
||||
*/
|
||||
_generateFormFieldErrors() {
|
||||
_generateFormFieldErrors(xmlHttpRequestError, formInputFieldNames) {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,9 @@ class FlavorStore extends BaseStore {
|
|||
}
|
||||
|
||||
getState() {
|
||||
this.state.flavors.forEach((flavor) => { flavor.freeNodeCount = this._calculateFreeNodes(flavor); });
|
||||
this.state.flavors.forEach((flavor) => {
|
||||
flavor.freeNodeCount = this._calculateFreeNodes(flavor);
|
||||
});
|
||||
return this.state;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
module.exports = {
|
||||
devtool: 'source-map',
|
||||
output: {
|
||||
filename: 'tripleo_ui_token_worker.js',
|
||||
sourceMapFilename: 'tripleo_ui_token_worker.js.map'
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.js$/, include: /src\/js\/workers/, loader: 'babel-loader' }//,
|
||||
]
|
||||
},
|
||||
node: {
|
||||
fs: 'empty',
|
||||
net: 'empty',
|
||||
tls: 'empty'
|
||||
}
|
||||
devtool: 'source-map',
|
||||
output: {
|
||||
filename: 'tripleo_ui_token_worker.js',
|
||||
sourceMapFilename: 'tripleo_ui_token_worker.js.map'
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.js$/, include: /src\/js\/workers/, loader: 'babel-loader' }//,
|
||||
]
|
||||
},
|
||||
node: {
|
||||
fs: 'empty',
|
||||
net: 'empty',
|
||||
tls: 'empty'
|
||||
}
|
||||
};
|
||||
|
|
|
@ -6,8 +6,8 @@ module.exports = {
|
|||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.js$/, include: /src/, exclude: /(node_modules|src\/js\/workers)/, loader: 'babel-loader' }//,
|
||||
// { test: /disqus-thread.js$/, loader: 'babel-loader' },
|
||||
{ test: /\.js$/, include: /src/,
|
||||
exclude: /src\/js\/workers/, loader: 'babel-loader' }
|
||||
// { test: /\.json$/, loader: 'json-loader' }
|
||||
]
|
||||
},
|
||||
|
@ -15,5 +15,5 @@ module.exports = {
|
|||
fs: 'empty',
|
||||
net: 'empty',
|
||||
tls: 'empty'
|
||||
},
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue