gnarails 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +21 -90
- data/.ruby-version +1 -1
- data/CHANGELOG.md +50 -0
- data/README.md +1 -34
- data/bin/ci_pronto +1 -1
- data/gnarails.gemspec +2 -3
- data/gnarly.rb +44 -137
- data/lib/gnarails/version.rb +1 -1
- data/templates/.circleci/config.yml +7 -2
- data/templates/Procfile +1 -0
- data/templates/{script → bin}/brakeman +1 -1
- data/templates/{script → bin}/ci_pronto +1 -1
- data/test-app/app/views/layouts/application.html.erb +4 -2
- data/test-app/spec/factories/job_postings.rb +1 -1
- metadata +9 -64
- data/bin/generate-react-test-app.sh +0 -2
- data/templates/.ruby-version +0 -1
- data/templates/Dockerfile-assets +0 -24
- data/templates/docker-compose.yml/docker-compose-webpack.yml +0 -26
- data/templates/react/.babelrc +0 -18
- data/templates/react/.eslintrc.js +0 -45
- data/templates/react/controllers/home_controller.rb +0 -4
- data/templates/react/js/Router/Router.jsx +0 -22
- data/templates/react/js/Router/index.js +0 -3
- data/templates/react/js/api/index.js +0 -17
- data/templates/react/js/api/sessions.js +0 -8
- data/templates/react/js/app_constants/index.js +0 -6
- data/templates/react/js/components/App/App.jsx +0 -15
- data/templates/react/js/components/App/App.tests.jsx +0 -15
- data/templates/react/js/components/App/_styles.scss +0 -3
- data/templates/react/js/components/App/index.js +0 -3
- data/templates/react/js/index.scss +0 -2
- data/templates/react/js/packs/main.jsx +0 -13
- data/templates/react/js/redux/entity_getter.js +0 -7
- data/templates/react/js/redux/history.js +0 -5
- data/templates/react/js/redux/initial_state.js +0 -5
- data/templates/react/js/redux/middlewares/authentication_middleware/authentication_middleware.tests.js +0 -109
- data/templates/react/js/redux/middlewares/authentication_middleware/helpers.js +0 -21
- data/templates/react/js/redux/middlewares/authentication_middleware/helpers.tests.js +0 -84
- data/templates/react/js/redux/middlewares/authentication_middleware/index.js +0 -20
- data/templates/react/js/redux/middlewares/index.js +0 -11
- data/templates/react/js/redux/nodes/app/actions.js +0 -36
- data/templates/react/js/redux/nodes/app/config.js +0 -12
- data/templates/react/js/redux/nodes/app/reducer.js +0 -35
- data/templates/react/js/redux/nodes/app/reducer.tests.js +0 -78
- data/templates/react/js/redux/reducers.js +0 -11
- data/templates/react/js/redux/store.js +0 -14
- data/templates/react/js/storage.js +0 -15
- data/templates/react/js/styles/_variables.scss +0 -1
- data/templates/react/js/test/.setup.js +0 -51
- data/templates/react/js/test/connect_wrapper.jsx +0 -28
- data/templates/react/js/test/create_request_mock.js +0 -29
- data/templates/react/js/test/mock_store.js +0 -12
- data/templates/react/layout.html.erb +0 -16
- data/templates/react/rails_routes.rb +0 -5
- data/templates/react/views/home/default.html.erb +0 -1
@@ -1,13 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import ReactDOM from 'react-dom';
|
3
|
-
|
4
|
-
import Router from 'Router';
|
5
|
-
import 'index.scss';
|
6
|
-
|
7
|
-
if (typeof window !== 'undefined') {
|
8
|
-
global.document.addEventListener('DOMContentLoaded', () => {
|
9
|
-
const mountNode = global.document.getElementById('react');
|
10
|
-
|
11
|
-
ReactDOM.render(<Router />, mountNode);
|
12
|
-
});
|
13
|
-
};
|
@@ -1,109 +0,0 @@
|
|
1
|
-
import expect from 'expect';
|
2
|
-
|
3
|
-
import appConfig from 'redux/nodes/app/config';
|
4
|
-
import mockStore from 'test/mock_store';
|
5
|
-
import storage from 'storage';
|
6
|
-
|
7
|
-
const authToken = 'abc123';
|
8
|
-
|
9
|
-
describe('Authentication middleware', () => {
|
10
|
-
beforeEach(() => storage.setItem('auth_token', authToken));
|
11
|
-
afterEach(() => storage.removeItem('auth_token'));
|
12
|
-
|
13
|
-
context('when the action type is for the login success action', () => {
|
14
|
-
const action = {
|
15
|
-
type: appConfig.actionTypes.LOGIN_SUCCESS,
|
16
|
-
payload: { jwt: 'jwt' },
|
17
|
-
};
|
18
|
-
const store = mockStore({});
|
19
|
-
|
20
|
-
it('adds the auth_token to local storage', () => {
|
21
|
-
storage.removeItem('auth_token');
|
22
|
-
store.dispatch(action);
|
23
|
-
|
24
|
-
expect(storage.getItem('auth_token')).toEqual('jwt');
|
25
|
-
});
|
26
|
-
});
|
27
|
-
|
28
|
-
context('when the action type is for the logout success action', () => {
|
29
|
-
const action = {
|
30
|
-
type: appConfig.actionTypes.LOGOUT_SUCCESS,
|
31
|
-
payload: {},
|
32
|
-
};
|
33
|
-
const store = mockStore({});
|
34
|
-
|
35
|
-
it('removes the auth_token from local storage', () => {
|
36
|
-
store.dispatch(action);
|
37
|
-
|
38
|
-
expect(storage.getItem('auth_token')).toEqual(undefined);
|
39
|
-
});
|
40
|
-
});
|
41
|
-
|
42
|
-
context('when the action type is not for the logout success action', () => {
|
43
|
-
const action = {
|
44
|
-
type: 'FOO',
|
45
|
-
payload: {},
|
46
|
-
};
|
47
|
-
const store = mockStore({});
|
48
|
-
|
49
|
-
it('does not remove the auth_token from local storage', () => {
|
50
|
-
store.dispatch(action);
|
51
|
-
|
52
|
-
expect(storage.getItem('auth_token')).toEqual(authToken);
|
53
|
-
});
|
54
|
-
});
|
55
|
-
|
56
|
-
context('when the action is for an entity that fails to load', () => {
|
57
|
-
context('when the payload error is an unauthorized error', () => {
|
58
|
-
const action = {
|
59
|
-
type: 'entity_name_SOMETHING_FAILURE',
|
60
|
-
payload: {
|
61
|
-
errors: {
|
62
|
-
http_status: 401,
|
63
|
-
},
|
64
|
-
},
|
65
|
-
};
|
66
|
-
const store = mockStore({});
|
67
|
-
|
68
|
-
it('removes the auth_token from local storage', () => {
|
69
|
-
store.dispatch(action);
|
70
|
-
|
71
|
-
expect(storage.getItem('auth_token')).toEqual(undefined);
|
72
|
-
});
|
73
|
-
});
|
74
|
-
|
75
|
-
context('when the payload error is not an unauthorized error', () => {
|
76
|
-
const action = {
|
77
|
-
type: 'entity_name_SOMETHING_FAILURE',
|
78
|
-
payload: {
|
79
|
-
errors: {},
|
80
|
-
},
|
81
|
-
};
|
82
|
-
const store = mockStore({});
|
83
|
-
|
84
|
-
it('does not remove the auth_token from local storage', () => {
|
85
|
-
store.dispatch(action);
|
86
|
-
|
87
|
-
expect(storage.getItem('auth_token')).toEqual(authToken);
|
88
|
-
});
|
89
|
-
});
|
90
|
-
});
|
91
|
-
|
92
|
-
context('when the action type is not a failure action', () => {
|
93
|
-
const action = {
|
94
|
-
type: 'entity_name_SOMETHING_SUCCESS',
|
95
|
-
payload: {
|
96
|
-
errors: {
|
97
|
-
http_status: 401,
|
98
|
-
},
|
99
|
-
},
|
100
|
-
};
|
101
|
-
const store = mockStore({});
|
102
|
-
|
103
|
-
it('does not remove the auth_token from local storage', () => {
|
104
|
-
store.dispatch(action);
|
105
|
-
|
106
|
-
expect(storage.getItem('auth_token')).toEqual(authToken);
|
107
|
-
});
|
108
|
-
});
|
109
|
-
});
|
@@ -1,21 +0,0 @@
|
|
1
|
-
import { endsWith, get } from 'lodash';
|
2
|
-
import appConfig from 'redux/nodes/app/config';
|
3
|
-
|
4
|
-
const { LOGIN_SUCCESS, LOGOUT_SUCCESS } = appConfig.actionTypes;
|
5
|
-
const UNAUTHORIZED_ERROR = 401;
|
6
|
-
|
7
|
-
const isFailureAction = (action) => {
|
8
|
-
return endsWith(action.type, '_FAILURE');
|
9
|
-
};
|
10
|
-
|
11
|
-
const isLoginAction = action => action.type === LOGIN_SUCCESS;
|
12
|
-
const isLogoutAction = action => action.type === LOGOUT_SUCCESS;
|
13
|
-
|
14
|
-
const isUnauthorizedError = action => get(action, 'payload.errors.http_status') === UNAUTHORIZED_ERROR;
|
15
|
-
|
16
|
-
export default {
|
17
|
-
isFailureAction,
|
18
|
-
isLoginAction,
|
19
|
-
isLogoutAction,
|
20
|
-
isUnauthorizedError,
|
21
|
-
};
|
@@ -1,84 +0,0 @@
|
|
1
|
-
import expect from 'expect';
|
2
|
-
|
3
|
-
import helpers from 'redux/middlewares/authentication_middleware/helpers';
|
4
|
-
|
5
|
-
describe('Authentication middleware - helpers', () => {
|
6
|
-
describe('#isFailureAction', () => {
|
7
|
-
it('returns true when the action type ends in _FAILURE', () => {
|
8
|
-
const action = { type: 'SOMETHING_FAILURE' };
|
9
|
-
|
10
|
-
expect(helpers.isFailureAction(action)).toEqual(true);
|
11
|
-
});
|
12
|
-
|
13
|
-
it('returns false when the action type does not end in _FAILURE', () => {
|
14
|
-
const action = { type: 'SOMETHING_FAILUR' };
|
15
|
-
|
16
|
-
expect(helpers.isFailureAction(action)).toEqual(false);
|
17
|
-
});
|
18
|
-
});
|
19
|
-
|
20
|
-
describe('#isLoginAction', () => {
|
21
|
-
it('returns true when the action type is the login success action type', () => {
|
22
|
-
const action = { type: 'LOGIN_SUCCESS' };
|
23
|
-
|
24
|
-
expect(helpers.isLoginAction(action)).toEqual(true);
|
25
|
-
});
|
26
|
-
|
27
|
-
it('returns false when the action type is not the login success action type', () => {
|
28
|
-
const action = { type: 'LOGIN_FAILURE' };
|
29
|
-
|
30
|
-
expect(helpers.isLoginAction(action)).toEqual(false);
|
31
|
-
});
|
32
|
-
});
|
33
|
-
|
34
|
-
describe('#isLogoutAction', () => {
|
35
|
-
it('returns true when the action type is the logout success action type', () => {
|
36
|
-
const action = { type: 'LOGOUT_SUCCESS' };
|
37
|
-
|
38
|
-
expect(helpers.isLogoutAction(action)).toEqual(true);
|
39
|
-
});
|
40
|
-
|
41
|
-
it('returns false when the action type is not the logout success action type', () => {
|
42
|
-
const action = { type: 'LOGOUT_FAILURE' };
|
43
|
-
|
44
|
-
expect(helpers.isLogoutAction(action)).toEqual(false);
|
45
|
-
});
|
46
|
-
});
|
47
|
-
|
48
|
-
describe('#isUnauthorizedError', () => {
|
49
|
-
it('returns true when the action payload has an unauthorized http status', () => {
|
50
|
-
const action = {
|
51
|
-
type: 'FOOBAR',
|
52
|
-
payload: {
|
53
|
-
errors: {
|
54
|
-
http_status: 401,
|
55
|
-
},
|
56
|
-
},
|
57
|
-
};
|
58
|
-
|
59
|
-
expect(helpers.isUnauthorizedError(action)).toEqual(true);
|
60
|
-
});
|
61
|
-
|
62
|
-
it('returns false when the action payload does not have an unauthorized http status', () => {
|
63
|
-
const action = {
|
64
|
-
type: 'FOOBAR',
|
65
|
-
payload: {
|
66
|
-
errors: {
|
67
|
-
http_status: 500,
|
68
|
-
},
|
69
|
-
},
|
70
|
-
};
|
71
|
-
|
72
|
-
expect(helpers.isUnauthorizedError(action)).toEqual(false);
|
73
|
-
});
|
74
|
-
|
75
|
-
it('returns false when there is no action payload http status', () => {
|
76
|
-
const action = {
|
77
|
-
type: 'FOOBAR',
|
78
|
-
payload: {},
|
79
|
-
};
|
80
|
-
|
81
|
-
expect(helpers.isUnauthorizedError(action)).toEqual(false);
|
82
|
-
});
|
83
|
-
});
|
84
|
-
});
|
@@ -1,20 +0,0 @@
|
|
1
|
-
import helpers from 'redux/middlewares/authentication_middleware/helpers';
|
2
|
-
import storage from 'storage';
|
3
|
-
|
4
|
-
const authMiddleware = () => next => (action) => {
|
5
|
-
if (helpers.isLoginAction(action)) {
|
6
|
-
storage.setItem('auth_token', action.payload.jwt);
|
7
|
-
}
|
8
|
-
|
9
|
-
if (helpers.isLogoutAction(action)) {
|
10
|
-
storage.removeItem('auth_token');
|
11
|
-
}
|
12
|
-
|
13
|
-
if (helpers.isFailureAction(action) && helpers.isUnauthorizedError(action)) {
|
14
|
-
storage.removeItem('auth_token');
|
15
|
-
}
|
16
|
-
|
17
|
-
return next(action);
|
18
|
-
};
|
19
|
-
|
20
|
-
export default authMiddleware;
|
@@ -1,11 +0,0 @@
|
|
1
|
-
import { routerMiddleware } from 'react-router-redux';
|
2
|
-
import thunkMiddleware from 'redux-thunk';
|
3
|
-
|
4
|
-
import authenticationMiddleware from 'redux/middlewares/authentication_middleware';
|
5
|
-
import history from 'redux/history';
|
6
|
-
|
7
|
-
export default [
|
8
|
-
thunkMiddleware,
|
9
|
-
routerMiddleware(history),
|
10
|
-
authenticationMiddleware,
|
11
|
-
];
|
@@ -1,36 +0,0 @@
|
|
1
|
-
import API from 'api';
|
2
|
-
import config from 'redux/nodes/app/config';
|
3
|
-
|
4
|
-
const { actionTypes } = config;
|
5
|
-
|
6
|
-
const loginRequest = { type: actionTypes.LOGIN_REQUEST };
|
7
|
-
const loginFailure = { type: actionTypes.LOGIN_FAILURE };
|
8
|
-
const loginSuccess = (jwt) => {
|
9
|
-
return { type: actionTypes.LOGIN_SUCCESS, payload: { jwt } };
|
10
|
-
};
|
11
|
-
|
12
|
-
const logoutRequest = { type: actionTypes.LOGOUT_REQUEST };
|
13
|
-
const logoutFailure = { type: actionTypes.LOGOUT_FAILURE };
|
14
|
-
const logoutSuccess = { type: actionTypes.LOGOUT_FAILURE };
|
15
|
-
|
16
|
-
const login = ({ email, password }) => {
|
17
|
-
return (dispatch) => {
|
18
|
-
dispatch(loginRequest);
|
19
|
-
|
20
|
-
return API.sessions.create({ email, password })
|
21
|
-
.then(({ jwt }) => dispatch(loginSuccess(jwt)))
|
22
|
-
.catch(() => dispatch(loginFailure));
|
23
|
-
};
|
24
|
-
};
|
25
|
-
|
26
|
-
const logout = () => {
|
27
|
-
return (dispatch) => {
|
28
|
-
dispatch(logoutRequest);
|
29
|
-
|
30
|
-
return API.sessions.destroy()
|
31
|
-
.then(() => dispatch(logoutSuccess))
|
32
|
-
.catch(() => dispatch(logoutFailure));
|
33
|
-
};
|
34
|
-
};
|
35
|
-
|
36
|
-
export default { login, logout };
|
@@ -1,12 +0,0 @@
|
|
1
|
-
const actionTypes = {
|
2
|
-
LOGIN_REQUEST: 'LOGIN_REQUEST',
|
3
|
-
LOGIN_SUCCESS: 'LOGIN_SUCCESS',
|
4
|
-
LOGIN_FAILURE: 'LOGIN_FAILURE',
|
5
|
-
LOGOUT_REQUEST: 'LOGOUT_REQUEST',
|
6
|
-
LOGOUT_SUCCESS: 'LOGOUT_SUCCESS',
|
7
|
-
LOGOUT_FAILURE: 'LOGOUT_FAILURE',
|
8
|
-
};
|
9
|
-
|
10
|
-
export default {
|
11
|
-
actionTypes,
|
12
|
-
};
|
@@ -1,35 +0,0 @@
|
|
1
|
-
import config from 'redux/nodes/app/config';
|
2
|
-
import initialState from 'redux/initial_state';
|
3
|
-
|
4
|
-
const { actionTypes } = config;
|
5
|
-
|
6
|
-
export default (state = initialState.app, action) => {
|
7
|
-
switch (action.type) {
|
8
|
-
case actionTypes.LOGIN_REQUEST:
|
9
|
-
case actionTypes.LOGOUT_REQUEST:
|
10
|
-
return {
|
11
|
-
...state,
|
12
|
-
loading: true,
|
13
|
-
};
|
14
|
-
case actionTypes.LOGIN_SUCCESS:
|
15
|
-
return {
|
16
|
-
...state,
|
17
|
-
loading: false,
|
18
|
-
session: { jwt: action.payload.jwt },
|
19
|
-
};
|
20
|
-
case actionTypes.LOGIN_FAILURE:
|
21
|
-
case actionTypes.LOGOUT_SUCCESS:
|
22
|
-
return {
|
23
|
-
...state,
|
24
|
-
session: {},
|
25
|
-
loading: false,
|
26
|
-
};
|
27
|
-
case actionTypes.LOGOUT_FAILURE:
|
28
|
-
return {
|
29
|
-
...state,
|
30
|
-
loading: false,
|
31
|
-
};
|
32
|
-
default:
|
33
|
-
return state;
|
34
|
-
}
|
35
|
-
};
|
@@ -1,78 +0,0 @@
|
|
1
|
-
import expect from 'expect';
|
2
|
-
|
3
|
-
import reducer from 'redux/nodes/app/reducer';
|
4
|
-
import { app as appState } from 'redux/initial_state';
|
5
|
-
|
6
|
-
describe('App - reducer', () => {
|
7
|
-
describe('dispatching the login actions', () => {
|
8
|
-
describe('LOGIN_REQUEST', () => {
|
9
|
-
it('sets the loading boolean to true', () => {
|
10
|
-
const action = { type: 'LOGIN_REQUEST' };
|
11
|
-
|
12
|
-
expect(reducer(appState, action)).toEqual({
|
13
|
-
...appState,
|
14
|
-
loading: true,
|
15
|
-
});
|
16
|
-
});
|
17
|
-
});
|
18
|
-
|
19
|
-
describe('LOGIN_SUCCESS', () => {
|
20
|
-
it('saves the JWT to state', () => {
|
21
|
-
const action = { type: 'LOGIN_SUCCESS', payload: { jwt: 'jwt' } };
|
22
|
-
expect(reducer(appState, action)).toEqual({
|
23
|
-
...appState,
|
24
|
-
session: { jwt: 'jwt' },
|
25
|
-
});
|
26
|
-
});
|
27
|
-
});
|
28
|
-
|
29
|
-
describe('LOGIN_FAILURE', () => {
|
30
|
-
it('removes the JWT from state', () => {
|
31
|
-
const action = { type: 'LOGIN_FAILURE' };
|
32
|
-
const state = { ...appState, session: { jwt: 'jwt' } };
|
33
|
-
|
34
|
-
expect(reducer(state, action)).toEqual({
|
35
|
-
...appState,
|
36
|
-
session: {},
|
37
|
-
});
|
38
|
-
});
|
39
|
-
});
|
40
|
-
});
|
41
|
-
|
42
|
-
describe('dispatching the logout actions', () => {
|
43
|
-
describe('LOGOUT_REQUEST', () => {
|
44
|
-
it('sets the loading boolean to true', () => {
|
45
|
-
const action = { type: 'LOGOUT_REQUEST' };
|
46
|
-
|
47
|
-
expect(reducer(appState, action)).toEqual({
|
48
|
-
...appState,
|
49
|
-
loading: true,
|
50
|
-
});
|
51
|
-
});
|
52
|
-
});
|
53
|
-
|
54
|
-
describe('LOGOUT_SUCCESS', () => {
|
55
|
-
it('removes the JWT from state', () => {
|
56
|
-
const action = { type: 'LOGOUT_SUCCESS' };
|
57
|
-
const state = { ...appState, session: { jwt: 'jwt' } };
|
58
|
-
|
59
|
-
expect(reducer(state, action)).toEqual({
|
60
|
-
...appState,
|
61
|
-
session: {},
|
62
|
-
});
|
63
|
-
});
|
64
|
-
});
|
65
|
-
|
66
|
-
describe('LOGOUT_FAILURE', () => {
|
67
|
-
it('sets the loading boolean to false', () => {
|
68
|
-
const action = { type: 'LOGOUT_FAILURE' };
|
69
|
-
const state = { ...appState, loading: true };
|
70
|
-
|
71
|
-
expect(reducer(state, action)).toEqual({
|
72
|
-
...appState,
|
73
|
-
loading: false,
|
74
|
-
});
|
75
|
-
});
|
76
|
-
});
|
77
|
-
});
|
78
|
-
});
|