Skip to content

Commit 57ad02f

Browse files
committed
Fix test failure from depdency loop of store>dataProvider>api>store
1 parent 40e92e0 commit 57ad02f

9 files changed

+68
-51
lines changed

src/ProvisionedApp.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Provider } from 'react-redux';
44
import { MuiThemeProvider } from '@material-ui/core/styles';
55

66
import App from './App';
7-
import store from './storeContainer';
7+
import { store } from './reduxGlobals';
88
import ErrorBoundary from './components/ErrorBoundary';
99
import { UserActions } from './modules/user';
1010
import humanTheme from './themes/humanTheme';

src/components/HumanAdmin/HumanAdmin.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import React from 'react';
33
import { Admin, Resource } from 'react-admin';
44
import { useTheme } from '@material-ui/core/styles';
55

6-
import { history } from 'storeContainer';
6+
import { history } from 'reduxGlobals';
77
import AdminLayout from './AdminLayout';
88
import dataProvider from './dataProvider';
99
import { ChallengesList, ChallengesEdit } from './challenges';

src/createStore.js

+12-10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import createSagaMiddleware from 'redux-saga';
66
import { all, fork } from 'redux-saga/effects';
77
import { adminReducer, adminSaga } from 'react-admin';
88

9+
import dataProvider from 'components/HumanAdmin/dataProvider';
910
import { reducer as challenges } from 'modules/challenges/slice';
1011
import { reducer as responses } from 'modules/responses/slice';
1112
import { reducer as user } from 'modules/user/slice';
@@ -14,7 +15,7 @@ import { reducer as user } from 'modules/user/slice';
1415
// routerMiddleware for the react-router, but the main app uses reach router.
1516
// TODO: Decide how to integrate the app with react-admin better.
1617

17-
export default ({ dataProvider, history, preloadedState = {} }) => {
18+
export default (history, preloadedState = {}) => {
1819
const reducer = combineReducers({
1920
challenges,
2021
responses,
@@ -23,15 +24,6 @@ export default ({ dataProvider, history, preloadedState = {} }) => {
2324
router: connectRouter(history),
2425
});
2526

26-
const saga = function* rootSaga() {
27-
yield all(
28-
[
29-
adminSaga(dataProvider),
30-
// add your own sagas here
31-
].map(fork)
32-
);
33-
};
34-
3527
const sagaMiddleware = createSagaMiddleware();
3628

3729
const store = configureStore({
@@ -44,6 +36,16 @@ export default ({ dataProvider, history, preloadedState = {} }) => {
4436
preloadedState,
4537
});
4638

39+
const saga = function* rootSaga() {
40+
yield all(
41+
[
42+
adminSaga(dataProvider),
43+
// add your own sagas here
44+
].map(fork)
45+
);
46+
};
47+
4748
sagaMiddleware.run(saga);
49+
4850
return store;
4951
};

src/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Sentry.init({
1414
});
1515

1616
if (process.env.NODE_ENV !== 'production') {
17-
window.store = require('storeContainer').default;
17+
window.store = require('reduxGlobals').store;
1818
window.api = require('modules/api');
1919
window.challenges = require('modules/challenges');
2020
window.theme = require('./themes/humanTheme');

src/modules/api.js

+25-19
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import RequestDispatcher, { AUTH_API } from './requestDispatcher';
1+
import requestDispatcher, { AUTH_API } from './requestDispatcher';
22

33
// TODO: Keep all the api endpoints in the same place
44
const CHALLENGE_API = '/challenges';
@@ -7,8 +7,6 @@ const AUTH_PASSWORD_API = `${AUTH_API}/password`;
77

88
class HumanApi {
99
constructor() {
10-
this.dispatcher = new RequestDispatcher();
11-
1210
this.login = this.login.bind(this);
1311
this.register = this.register.bind(this);
1412
this.logout = this.logout.bind(this);
@@ -20,7 +18,7 @@ class HumanApi {
2018
}
2119

2220
login(credentials) {
23-
return this.dispatcher
21+
return requestDispatcher
2422
.loginRegister(credentials)
2523
.then(res => res.data)
2624
.catch(error => {
@@ -31,7 +29,7 @@ class HumanApi {
3129
}
3230

3331
register(credentials) {
34-
return this.dispatcher
32+
return requestDispatcher
3533
.loginRegister(credentials, { isRegister: true })
3634
.then(res => res.data)
3735
.catch(error => {
@@ -42,64 +40,72 @@ class HumanApi {
4240
}
4341

4442
logout() {
45-
return this.dispatcher.logout().then(res => res.data);
43+
return requestDispatcher.logout().then(res => res.data);
4644
}
4745

4846
refresh() {
49-
return this.dispatcher.refresh().then(res => res.data);
47+
return requestDispatcher.refresh().then(res => res.data);
5048
}
5149

5250
changePassword(values) {
53-
return this.dispatcher.putWithAuth(AUTH_PASSWORD_API, values).then(res => {
54-
const { user, access_token, refresh_token } = res.data;
55-
this.dispatcher.updateUserAndTokens(user, access_token, refresh_token);
56-
});
51+
return requestDispatcher
52+
.putWithAuth(AUTH_PASSWORD_API, values)
53+
.then(res => {
54+
const { user, access_token, refresh_token } = res.data;
55+
requestDispatcher.updateUserAndTokens(
56+
user,
57+
access_token,
58+
refresh_token
59+
);
60+
});
5761
}
5862

5963
createChallenge(challenge) {
6064
let formData = this.convertToForm(challenge);
61-
return this.dispatcher
65+
return requestDispatcher
6266
.postWithAuth(`${CHALLENGE_API}/create`, formData)
6367
.then(res => res.data);
6468
}
6569

6670
createResponse(response) {
6771
let formData = this.convertToForm(response);
68-
return this.dispatcher
72+
return requestDispatcher
6973
.postWithAuth(`${RESPONSE_API}/create`, formData)
7074
.then(res => res.data);
7175
}
7276

7377
fetchChallenges() {
74-
return this.dispatcher
78+
return requestDispatcher
7579
.getWithAuth(`${CHALLENGE_API}`)
7680
.then(res => res.data);
7781
}
7882

7983
fetchChallenge(id) {
80-
return this.dispatcher
84+
return requestDispatcher
8185
.getWithAuth(`${CHALLENGE_API}/${id}`)
8286
.then(res => res.data);
8387
}
8488

8589
updateChallenge(id, patches) {
86-
return this.dispatcher
90+
return requestDispatcher
8791
.putWithAuth(`${CHALLENGE_API}/${id}`, patches)
8892
.then(res => res.data);
8993
}
9094

9195
deleteChallenge(id) {
92-
return this.dispatcher
96+
return requestDispatcher
9397
.deleteWithAuth(`${CHALLENGE_API}/${id}`)
9498
.then(res => undefined);
9599
}
96100

97101
fetchResponses() {
98-
return this.dispatcher.getWithAuth(`${RESPONSE_API}`).then(res => res.data);
102+
return requestDispatcher
103+
.getWithAuth(`${RESPONSE_API}`)
104+
.then(res => res.data);
99105
}
100106

101107
fetchResponse(id) {
102-
return this.dispatcher
108+
return requestDispatcher
103109
.getWithAuth(`${RESPONSE_API}/${id}`)
104110
.then(res => res.data);
105111
}

src/modules/requestDispatcher.js

+14-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import axios from 'axios';
22
import config from 'config';
33

44
import { actions } from './user/slice';
5-
import store from 'storeContainer';
65

76
const API = config['API'];
87
const AUTH_API = '/auth';
@@ -108,6 +107,12 @@ class RequestDispatcher {
108107
this.pendingRequests = [];
109108
this.pendingAuthCancel = undefined;
110109

110+
this.store = {
111+
dispatch: () => {
112+
throw new Error('redux store not initialized');
113+
},
114+
};
115+
111116
this.state = DISPATCHER_STATE.UNAUTHENTICATED;
112117

113118
this.tokenStorage = new TokenStorage();
@@ -131,8 +136,12 @@ class RequestDispatcher {
131136
});
132137
}
133138

139+
setStore(reduxStore) {
140+
this.store = reduxStore;
141+
}
142+
134143
unauthenticated() {
135-
store.dispatch(actions.unauthenticated());
144+
this.store.dispatch(actions.unauthenticated());
136145
}
137146

138147
updateUserAndTokens(user, access_token, refresh_token) {
@@ -142,7 +151,7 @@ class RequestDispatcher {
142151

143152
updateUser(user, access_token) {
144153
const token = this.tokenStorage.readToken(access_token);
145-
store.dispatch(actions.authenticated({ user: user, token: token }));
154+
this.store.dispatch(actions.authenticated({ user: user, token: token }));
146155
}
147156

148157
cancelInFlightRequiringAuth() {
@@ -415,5 +424,5 @@ class RequestDispatcher {
415424
}
416425
}
417426

418-
export { AUTH_API };
419-
export default RequestDispatcher;
427+
export default new RequestDispatcher();
428+
export { AUTH_API, RequestDispatcher };

src/modules/requestDispatcher.test.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
import RequestDispatcher, { AUTH_REFRESH_API } from './requestDispatcher';
1+
import { AUTH_REFRESH_API, RequestDispatcher } from './requestDispatcher';
22
import mockAxios from 'axios';
3+
import createStore from 'createStore';
4+
import { createMemoryHistory } from 'history';
35

46
const accessTokenA =
57
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZGVudGl0eSI6IjEiLCJ0eXBlIjoiYWNjZXNzIiwibmJmIjoxNTY2NDU4MDAwLCJleHAiOjE1NjY0NTkwMDAsInVzZXJfY2xhaW1zIjp7InJvbGVzIjpbeyJhZG1pbiI6ImFkbWluIn1dfSwiaWF0IjoxNTY2NDU4MDAwLCJqdGkiOiIxMTUxZjBlNi03NDBkLTQ3MmQtOTRmNS02YTI5MGJmNGFiZjAifQ.ZEw2CdhuBJc_QzN0YrOQ63t1JMI3KJfCJpcV-Hz9M5U';
@@ -89,6 +91,7 @@ let rd;
8991
describe('Testing Unauthenticated requests', () => {
9092
beforeAll(() => {
9193
rd = new RequestDispatcher();
94+
rd.setStore(createStore(createMemoryHistory()));
9295
mockAxios.__clearMockResponses();
9396
mockResponses.forEach(mr => mockAxios.__setMockResponse(mr));
9497
});
@@ -110,6 +113,7 @@ describe('Testing Unauthenticated requests', () => {
110113
describe('Testing Authenticated Requests', () => {
111114
beforeEach(() => {
112115
rd = new RequestDispatcher();
116+
rd.setStore(createStore(createMemoryHistory()));
113117
mockAxios.__clearMockResponses();
114118
mockResponses.forEach(mr => mockAxios.__setMockResponse(mr));
115119
});

src/reduxGlobals.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import createStore from 'createStore';
2+
import { createBrowserHistory } from 'history';
3+
import requestDispatcher from 'modules/requestDispatcher';
4+
5+
export const history = createBrowserHistory();
6+
7+
export const store = createStore(history);
8+
9+
requestDispatcher.setStore(store);

src/storeContainer.js

-13
This file was deleted.

0 commit comments

Comments
 (0)