Configure redux for development

This enables the redux developer tools for the browser. To make use of
this, one must also install the Redux DevTools extension which is
available for various browsers. The extension visualize all state
transitions in the redux store and also allows changing them manually to
see the effects.

Additionally, this change makes use of the third-party library called
"redux-immutable-state-invariant", which throws exception in development
mode whenever a state is mutated directly within an action or reducer.

Change-Id: I8a8588cd7f5f1b17b247d9700a492e5c1e27f040
This commit is contained in:
Felix Edel 2020-09-28 08:15:03 +02:00
parent fb57e35626
commit 7abe44ef73
No known key found for this signature in database
GPG Key ID: E95717A102DD3030
11 changed files with 85 additions and 14 deletions

View File

@ -23,3 +23,4 @@ env:
jest/globals: true
browser: true
es6: true
node: true

View File

@ -28,6 +28,7 @@
"react-scripts": "3.4.1",
"react-select": "3.1.0",
"redux": "^4.0.5",
"redux-immutable-state-invariant": "^2.1.0",
"redux-thunk": "^2.3.0",
"sockette": "^2.0.0",
"swagger-ui": "^3.20.1",

View File

@ -19,7 +19,7 @@ import { Link, BrowserRouter as Router } from 'react-router-dom'
import { Provider } from 'react-redux'
import { fetchInfoIfNeeded } from './actions/info'
import store from './store'
import configureStore from './store'
import App from './App'
import TenantsPage from './pages/Tenants'
import StatusPage from './pages/Status'
@ -31,6 +31,7 @@ api.fetchStatus = jest.fn()
api.fetchConfigErrors = jest.fn()
api.fetchConfigErrors.mockImplementation(() => Promise.resolve({data: []}))
const store = configureStore()
it('renders without crashing', () => {
const div = document.createElement('div')

View File

@ -1,4 +1,3 @@
/* global process */
// Copyright 2018 Red Hat, Inc
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may

View File

@ -18,7 +18,7 @@ import { Link, BrowserRouter as Router } from 'react-router-dom'
import { Provider } from 'react-redux'
import { setTenantAction } from '../../actions/tenant'
import store from '../../store'
import configureStore from '../../store'
import ChangePanel from './ChangePanel'
@ -31,6 +31,8 @@ const fakeChange = {
}]
}
const store = configureStore()
it('change panel render multi tenant links', () => {
store.dispatch(setTenantAction('tenant-one', false))
const application = ReactTestUtils.renderIntoDocument(

View File

@ -37,7 +37,7 @@ import './pf4-migration.css'
import { getHomepageUrl } from './api'
import registerServiceWorker from './registerServiceWorker'
import { fetchInfoIfNeeded } from './actions/info'
import store from './store'
import configureStore from './store'
import App from './App'
// Importing our custom css file after the App allows us to also overwrite the
@ -45,6 +45,8 @@ import App from './App'
// is imported within the App).
import './index.css'
const store = configureStore()
// Load info endpoint
store.dispatch(fetchInfoIfNeeded())

View File

@ -1,4 +1,3 @@
/* global process */
// In production, we register a service worker to serve assets from local cache.
// This lets the app load faster on subsequent visits in production, and gives

39
web/src/store.dev.js Normal file
View File

@ -0,0 +1,39 @@
// Copyright 2020 BMW Group
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
import { applyMiddleware, compose, createStore } from 'redux'
import appReducer from './reducers'
import reduxImmutableStateInvariant from 'redux-immutable-state-invariant'
import thunk from 'redux-thunk'
export default function configureStore(initialState) {
// Add support for Redux devtools
const composeEnhancers =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose
return createStore(
appReducer,
initialState,
// Warn us if we accidentially mutate state directly in the Redux store
// (only during development).
composeEnhancers(
applyMiddleware(
thunk,
// TODO (felix): Re-enable the status.status path once we know how to
// solve the weird state mutations that are done somewhere deep within
// the logic of the status page (or its child components).
reduxImmutableStateInvariant({ ignore: ['status.status'] })
)
)
)
}

View File

@ -12,11 +12,9 @@
// License for the specific language governing permissions and limitations
// under the License.
import { applyMiddleware, createStore } from 'redux'
import thunk from 'redux-thunk'
import appReducers from './reducers'
const store = createStore(appReducers, applyMiddleware(thunk))
export default store
// Use CommonJS require so we can dynamically import during build-time.
if (process.env.NODE_ENV === 'production') {
module.exports = require('./store.prod')
} else {
module.exports = require('./store.dev')
}

21
web/src/store.prod.js Normal file
View File

@ -0,0 +1,21 @@
// Copyright 2020 BMW Group
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
import { applyMiddleware, createStore } from 'redux'
import appReducer from './reducers'
import thunk from 'redux-thunk'
export default function configureStore(initialState) {
return createStore(appReducer, initialState, applyMiddleware(thunk))
}

View File

@ -7305,7 +7305,7 @@ into-stream@^5.0.0:
from2 "^2.3.0"
p-is-promise "^3.0.0"
invariant@^2.0.0, invariant@^2.2.0, invariant@^2.2.1, invariant@^2.2.2, invariant@^2.2.4:
invariant@^2.0.0, invariant@^2.1.0, invariant@^2.2.0, invariant@^2.2.1, invariant@^2.2.2, invariant@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
@ -12450,6 +12450,14 @@ redeyed@~2.1.0:
dependencies:
esprima "~4.0.0"
redux-immutable-state-invariant@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/redux-immutable-state-invariant/-/redux-immutable-state-invariant-2.1.0.tgz#308fd3cc7415a0e7f11f51ec997b6379c7055ce1"
integrity sha512-3czbDKs35FwiBRsx/3KabUk5zSOoTXC+cgVofGkpBNv3jQcqIe5JrHcF5AmVt7B/4hyJ8MijBIpCJ8cife6yJg==
dependencies:
invariant "^2.1.0"
json-stringify-safe "^5.0.1"
redux-immutable@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/redux-immutable/-/redux-immutable-3.1.0.tgz#cafbd686e0711261119b9c28960935dc47a49d0a"