diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 0000000..02dba80
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,37 @@
+module.exports = {
+ env: {
+ browser: true,
+ commonjs: true,
+ es6: true,
+ node: true,
+ },
+ 'plugins': [
+ 'react',
+ 'json'
+ ],
+ 'extends': ['eslint:recommended', 'plugin:react/recommended'],
+ parserOptions: {
+ sourceType: 'module',
+ ecmaFeatures: {
+ 'jsx': true
+ }
+ },
+ rules: {
+ 'comma-dangle': ['error', 'always-multiline'],
+ indent: ['error', 2],
+ 'linebreak-style': ['error', 'unix'],
+ quotes: ['error', 'single'],
+ semi: ['error', 'always'],
+ 'no-unused-vars': ['warn'],
+ 'no-console': 0,
+ 'eol-last':["error", "always"],
+ 'no-trailing-spaces':'error',
+ 'react/jsx-uses-react': 'error',
+ 'react/jsx-uses-vars': 'error',
+ 'comma-spacing': ["error", { "before": false, "after": true }],
+ 'object-curly-spacing': ["error", "always"],
+ 'key-spacing': ["error", { "beforeColon": false, "afterColon": true }],
+ 'arrow-body-style': ["error", "as-needed"],
+ 'linebreak-style': 0,
+ },
+};
diff --git a/.stylelintrc b/.stylelintrc
new file mode 100644
index 0000000..62c21d0
--- /dev/null
+++ b/.stylelintrc
@@ -0,0 +1,3 @@
+{
+ "extends": "stylelint-config-standard",
+}
diff --git a/nightwatch.conf.js b/nightwatch.conf.js
index e40aab8..b2be81d 100644
--- a/nightwatch.conf.js
+++ b/nightwatch.conf.js
@@ -1,64 +1,64 @@
-const seleniumServer = require("selenium-server");
-const chromedriver = require("chromedriver");
-const path = require("path");
-require("nightwatch-cucumber")({
+const seleniumServer = require('selenium-server');
+const chromedriver = require('chromedriver');
+const path = require('path');
+require('nightwatch-cucumber')({
cucumberArgs: [
- "--require-module",
- "@babel/register",
- "--require",
- path.join(__dirname, "test/features/step_definitions"),
- "--format",
- path.join(__dirname, "node_modules/cucumber-pretty"),
- "--format",
- "json:" + path.join(__dirname, "reports/cucumber.json"),
- path.join(__dirname, "test/features/")
- ]
+ '--require-module',
+ '@babel/register',
+ '--require',
+ path.join(__dirname, 'test/features/step_definitions'),
+ '--format',
+ path.join(__dirname, 'node_modules/cucumber-pretty'),
+ '--format',
+ 'json:' + path.join(__dirname, 'reports/cucumber.json'),
+ path.join(__dirname, 'test/features/'),
+ ],
});
module.exports = {
- output_folder: path.join(__dirname, "reports"),
- custom_assertions_path: "",
- page_objects_path: path.join(__dirname, "test/features/page_objects"),
+ output_folder: path.join(__dirname, 'reports'),
+ custom_assertions_path: '',
+ page_objects_path: path.join(__dirname, 'test/features/page_objects'),
live_output: false,
disable_colors: false,
test_workers: {
enabled: true,
- workers: "auto"
+ workers: 'auto',
},
selenium: {
start_process: true,
server_path: seleniumServer.path,
- log_path: "",
- host: "127.0.0.1",
- port: 4444
+ log_path: '',
+ host: '127.0.0.1',
+ port: 4444,
},
test_settings: {
default: {
- launch_url: "http://localhost:3200",
+ launch_url: 'http://localhost:3200',
selenium_port: 4444,
- selenium_host: "127.0.0.1",
+ selenium_host: '127.0.0.1',
silent: true,
detailed_output: true,
screenshots: {
enabled: true,
- path: path.join(__dirname, "reports/screenshots"),
+ path: path.join(__dirname, 'reports/screenshots'),
on_failure: true,
- on_error: true
+ on_error: true,
},
desiredCapabilities: {
- unexpectedAlertBehaviour: "accept",
- browserName: "chrome",
+ unexpectedAlertBehaviour: 'accept',
+ browserName: 'chrome',
javascriptEnabled: true,
acceptSslCerts: true,
chromeOptions: {
- args: ["headless", "verbose", "window-size=1280,1480"]
- }
+ args: ['headless', 'verbose', 'window-size=1280,1480'],
+ },
},
selenium: {
cli_args: {
- "webdriver.chrome.driver": chromedriver.path
- }
- }
- }
- }
+ 'webdriver.chrome.driver': chromedriver.path,
+ },
+ },
+ },
+ },
};
diff --git a/package.json b/package.json
index cf9b65b..547f4b9 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,10 @@
"build:dll:prod": "webpack -p --config webpack.library.config.js",
"test": "nyc mocha",
"feature": "./node_modules/.bin/nightwatch",
- "feature:debug": "node --inspect-brk node_modules/.bin/nightwatch"
+ "feature:debug": "node --inspect-brk node_modules/.bin/nightwatch",
+ "lint": "eslint ./src/client ./src/server ./test/unit ./test/features --fix",
+ "jsonlint": "eslint ./ --ext .json",
+ "stylelint": "stylelint ./src/client/**/*.scss --syntax scss --fix"
},
"author": "",
"license": "ISC",
@@ -23,6 +26,7 @@
"@babel/preset-env": "^7.0.0-rc.2",
"@babel/preset-react": "^7.0.0-rc.2",
"@babel/register": "^7.0.0-rc.2",
+ "babel-eslint": "^8.2.6",
"babel-loader": "^8.0.0-beta.4",
"babel-polyfill": "^6.26.0",
"chromedriver": "^2.41.0",
@@ -31,6 +35,9 @@
"cucumber-pretty": "^1.4.4",
"enzyme": "^3.4.4",
"enzyme-adapter-react-16": "^1.2.0",
+ "eslint": "^5.4.0",
+ "eslint-plugin-json": "^1.2.1",
+ "eslint-plugin-react": "^7.11.1",
"expect": "^23.5.0",
"express": "^4.16.3",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
@@ -44,6 +51,8 @@
"sass-loader": "^7.1.0",
"selenium-server": "^3.14.0",
"style-loader": "^0.22.1",
+ "stylelint": "^9.5.0",
+ "stylelint-config-standard": "^18.2.0",
"uglifyjs-webpack-plugin": "^1.3.0",
"webpack": "^4.17.0",
"webpack-cli": "^3.1.0"
diff --git a/src/client/actions/index.js b/src/client/actions/index.js
index 33b3610..b89ccf6 100644
--- a/src/client/actions/index.js
+++ b/src/client/actions/index.js
@@ -1,4 +1,4 @@
-import { action } from "../helpers/actionCreator";
+import { action } from '../helpers/actionCreator';
import * as actions from '../constants/index';
-export const add = (text) => action(actions.ADD, { text });
+export const add = text => action(actions.ADD, { text });
diff --git a/src/client/components/App.jsx b/src/client/components/App.jsx
index 654eaa3..941e7e1 100644
--- a/src/client/components/App.jsx
+++ b/src/client/components/App.jsx
@@ -1,17 +1,30 @@
import React from 'react';
import PropTypes from 'prop-types';
-import ReactPlayer from 'react-player'
-import '../styles/App.scss'
+import ReactPlayer from 'react-player';
+import '../styles/App.scss';
export default class App extends React.Component {
constructor(props) {
super(props);
}
render() {
- return this.props.number == 1 ?(
+ return this.props.number == 1 ? (
-
+
- ): Welcome this.props.add(1)}/>
;
+ ) : (
+
+ {' '}
+ Welcome{' '}
+ this.props.add(1)}
+ />{' '}
+
+ );
}
}
diff --git a/src/client/constants/index.js b/src/client/constants/index.js
index ec8ba83..d319394 100644
--- a/src/client/constants/index.js
+++ b/src/client/constants/index.js
@@ -1,4 +1,4 @@
export const ADD = 'ADD';
export const SAVE = 'SAVE';
export const START_APPLICATION = 'START_APPLICATION';
-export const ADD_RECIPES = 'ADD_RECIPES';
\ No newline at end of file
+export const ADD_RECIPES = 'ADD_RECIPES';
diff --git a/src/client/containers/App.js b/src/client/containers/App.js
index 1904aab..dac1c0e 100644
--- a/src/client/containers/App.js
+++ b/src/client/containers/App.js
@@ -1,17 +1,24 @@
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import App from '../components/App';
-import { add } from '../actions'
+import { add } from '../actions';
-const mapStateToProps = (state) => ({
+const mapStateToProps = state => ({
number: state.add.number,
recipes: state.recipe.recipes,
});
-const mapDispatchToProps = (dispatch) => bindActionCreators({
- add,
-}, dispatch);
+const mapDispatchToProps = dispatch =>
+ bindActionCreators(
+ {
+ add,
+ },
+ dispatch
+ );
-const AppContainer = connect(mapStateToProps, mapDispatchToProps)(App);
+const AppContainer = connect(
+ mapStateToProps,
+ mapDispatchToProps
+)(App);
export default AppContainer;
diff --git a/src/client/helpers/actionCreator.js b/src/client/helpers/actionCreator.js
index 14527ac..ccc6d2e 100644
--- a/src/client/helpers/actionCreator.js
+++ b/src/client/helpers/actionCreator.js
@@ -1 +1 @@
-export const action = (type, payload = {}) => ({ type, payload });
\ No newline at end of file
+export const action = (type, payload = {}) => ({ type, payload });
diff --git a/src/client/index.js b/src/client/index.js
index f68e78d..02be6ce 100644
--- a/src/client/index.js
+++ b/src/client/index.js
@@ -1,16 +1,16 @@
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
-import { createStore, applyMiddleware } from 'redux'
-import createSagaMiddleware from 'redux-saga'
+import { createStore, applyMiddleware } from 'redux';
+import createSagaMiddleware from 'redux-saga';
import cr from './reducers/combined';
import AppContainer from './containers/App';
-import rootSaga from './sagas/combined'
+import rootSaga from './sagas/combined';
const sagaMiddleware = createSagaMiddleware();
-import * as actions from "./constants"
+import * as actions from './constants';
// then run the saga
-const store = createStore(cr, applyMiddleware(sagaMiddleware))
-sagaMiddleware.run(rootSaga)
+const store = createStore(cr, applyMiddleware(sagaMiddleware));
+sagaMiddleware.run(rootSaga);
export const action = type => store.dispatch({ type });
action(actions.START_APPLICATION);
@@ -19,4 +19,4 @@ render(
,
document.getElementById('app')
-);
\ No newline at end of file
+);
diff --git a/src/client/reducers/add.js b/src/client/reducers/add.js
index 6ca0ecd..ab38ca9 100644
--- a/src/client/reducers/add.js
+++ b/src/client/reducers/add.js
@@ -8,6 +8,7 @@ const add = (state = {}, action) => {
});
default:
return state;
-}};
+ }
+};
export default add;
diff --git a/src/client/reducers/combined.js b/src/client/reducers/combined.js
index 469b186..9e41f0f 100644
--- a/src/client/reducers/combined.js
+++ b/src/client/reducers/combined.js
@@ -1,10 +1,10 @@
import { combineReducers } from 'redux';
-import add from "./add";
+import add from './add';
import recipe from './recipe';
const combined = combineReducers({
add,
- recipe
+ recipe,
});
export default combined;
diff --git a/src/client/reducers/recipe.js b/src/client/reducers/recipe.js
index 83d8fff..0b04ee1 100644
--- a/src/client/reducers/recipe.js
+++ b/src/client/reducers/recipe.js
@@ -8,6 +8,7 @@ const recipe = (state = {}, action) => {
});
default:
return state;
-}};
+ }
+};
export default recipe;
diff --git a/src/client/sagas/add.js b/src/client/sagas/add.js
index bec0ab8..2be08e1 100644
--- a/src/client/sagas/add.js
+++ b/src/client/sagas/add.js
@@ -1,16 +1,16 @@
-import { call, put, takeEvery, takeLatest } from 'redux-saga/effects'
-import * as actions from "../constants"
+import { call, put, takeEvery, takeLatest } from 'redux-saga/effects';
+import * as actions from '../constants';
import { action } from '../helpers/actionCreator';
function* addnumber(action) {
- try {
- yield put({type: actions.SAVE, number: "1"});
- } catch (e) {
- yield put({type: "ADD_FAILED", message: e.message});
- }
+ try {
+ yield put({ type: actions.SAVE, number: '1' });
+ } catch (e) {
+ yield put({ type: 'ADD_FAILED', message: e.message });
+ }
}
function* addWatcher() {
yield takeEvery(actions.ADD, addnumber);
}
-export default addWatcher;
\ No newline at end of file
+export default addWatcher;
diff --git a/src/client/sagas/combined.js b/src/client/sagas/combined.js
index 500a784..1e7a30d 100644
--- a/src/client/sagas/combined.js
+++ b/src/client/sagas/combined.js
@@ -1,9 +1,6 @@
import { all } from 'redux-saga/effects';
import addWatcher from './add';
-import startWatcher from './start'
+import startWatcher from './start';
export default function* rootSaga() {
- yield all([
- addWatcher(),
- startWatcher()
- ]);
+ yield all([addWatcher(), startWatcher()]);
}
diff --git a/src/client/sagas/start.js b/src/client/sagas/start.js
index 20cc3c5..279c396 100644
--- a/src/client/sagas/start.js
+++ b/src/client/sagas/start.js
@@ -1,17 +1,19 @@
-import { call, put, takeEvery, takeLatest } from 'redux-saga/effects'
-import * as actions from "../constants"
-import { action } from '../helpers/actionCreator';
-import { callFetch } from '../services/api'
-function* initalize(action) {
- try {
- const recipes = yield call(callFetch, "/recipes")
- yield put({type: actions.ADD_RECIPES, recipes: JSON.parse(recipes.response)});
- } catch (e) {
- yield put({type: "START_APPLICATION_FAILED", recipes: []});
- }
+import { call, put, takeEvery, takeLatest } from 'redux-saga/effects';
+import * as actions from '../constants';
+import { callFetch } from '../services/api';
+function* initalize() {
+ try {
+ const recipes = yield call(callFetch, '/recipes');
+ yield put({
+ type: actions.ADD_RECIPES,
+ recipes: JSON.parse(recipes.response),
+ });
+ } catch (e) {
+ yield put({ type: 'START_APPLICATION_FAILED', recipes: [] });
+ }
}
function* startWatcher() {
yield takeEvery(actions.START_APPLICATION, initalize);
}
-export default startWatcher;
\ No newline at end of file
+export default startWatcher;
diff --git a/src/client/services/api.js b/src/client/services/api.js
index d237120..cc3619f 100644
--- a/src/client/services/api.js
+++ b/src/client/services/api.js
@@ -7,7 +7,8 @@ export function callFetch(endpoint, params = {}) {
}
return fetch(endpoint, requestOptions)
.then(
- response => _.get(response, 'ok') ? response.json() : Promise.reject(response)
+ response =>
+ _.get(response, 'ok') ? response.json() : Promise.reject(response)
)
.then(
response => ({ response }),
@@ -20,14 +21,13 @@ export function callPost(endpoint, body = {}) {
credentials: 'same-origin',
method: 'POST',
headers: {
- 'Accept': 'application/json',
+ Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
};
- return fetch(endpoint, requestOptions)
- .then(
- response => ({ response }),
- error => ({ error: error.message || 'Something bad happened' })
- );
+ return fetch(endpoint, requestOptions).then(
+ response => ({ response }),
+ error => ({ error: error.message || 'Something bad happened' })
+ );
}
diff --git a/src/dist/index.html b/src/dist/index.html
index 3c913f4..dc89d6b 100644
--- a/src/dist/index.html
+++ b/src/dist/index.html
@@ -1,14 +1,17 @@
-
-
-
- Redux
-
-
-
-
-
-
-
-
+
+
+
+
+ Redux
+
+
+
+
+
+
+
+
+
+