gnarails 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
-
});
|