Upgrade react-router-dom

This updates react-router-dom to not quite the latest version, but
a new enough version that it supports hooks.

This also changes how React Refs are handled in such a way that
it breaks some tests which rely on on reaching through the redux
store into child nodes.  To resolve this, some tests are updated
to use the react-test-renderer instead.

The tests in App.test.jsx were not asserting anything past the
initial toEqual assertion in the path, which is why they are only
now being updated to match links added since the test inception.

Change-Id: Ia80fbfe3cf2d2d275fd8422111ec193c467bf606
This commit is contained in:
James E. Blair 2021-11-06 16:05:44 -07:00 committed by Matthieu Huin
parent a7423a4e2b
commit 59af3e2c17
4 changed files with 113 additions and 75 deletions

View File

@ -24,10 +24,11 @@
"react-height": "^3.0.0",
"react-json-view": "^1.21.1",
"react-redux": "<7.1.1",
"react-router": "^4.3.1",
"react-router-dom": "^4.3.1",
"react-router": "5.2.0",
"react-router-dom": "5.2.0",
"react-scripts": "3.4.1",
"react-select": "3.1.0",
"react-test-renderer": "16.13.1",
"redux": "^4.0.5",
"redux-immutable-state-invariant": "^2.1.0",
"redux-thunk": "^2.3.0",

View File

@ -13,7 +13,7 @@
// under the License.
import React from 'react'
import ReactTestUtils from 'react-dom/test-utils'
import { create, act } from 'react-test-renderer'
import ReactDOM from 'react-dom'
import { Link, BrowserRouter as Router } from 'react-router-dom'
import { Provider } from 'react-redux'
@ -31,16 +31,17 @@ api.fetchStatus = jest.fn()
api.fetchConfigErrors = jest.fn()
api.fetchConfigErrors.mockImplementation(() => Promise.resolve({data: []}))
const store = configureStore()
it('renders without crashing', () => {
const store = configureStore()
const div = document.createElement('div')
ReactDOM.render(<Provider store={store}><Router><App /></Router></Provider>,
div)
ReactDOM.unmountComponentAtNode(div)
})
it('renders multi tenant', () => {
it('renders multi tenant', async () => {
const store = configureStore()
api.fetchInfo.mockImplementation(
() => Promise.resolve({data: {
info: {capabilities: {}}
@ -49,28 +50,34 @@ it('renders multi tenant', () => {
api.fetchTenants.mockImplementation(
() => Promise.resolve({data: [{name: 'openstack'}]})
)
const application = ReactTestUtils.renderIntoDocument(
const application = create(
<Provider store={store}><Router><App /></Router></Provider>
)
store.dispatch(fetchInfoIfNeeded()).then(() => {
// Link should be tenant scoped
const topMenuLinks = ReactTestUtils.scryRenderedComponentsWithType(
application, Link)
expect(topMenuLinks[0].props.to).toEqual('/t/openstack/status')
expect(topMenuLinks[1].props.to).toEqual('/t/openstack/projects')
// Location should be /tenants
expect(location.pathname).toEqual('/tenants')
// Info should tell multi tenants
expect(store.getState().info.tenant).toEqual(undefined)
// Tenants list has been rendered
expect(ReactTestUtils.findRenderedComponentWithType(
application, TenantsPage)).not.toEqual(null)
// Fetch tenants has been called
expect(api.fetchTenants).toBeCalled()
await act(async () => {
await store.dispatch(fetchInfoIfNeeded())
})
// Link should be tenant scoped
const topMenuLinks = application.root.findAllByType(Link)
expect(topMenuLinks[0].props.to).toEqual('/')
expect(topMenuLinks[1].props.to).toEqual('/components')
expect(topMenuLinks[2].props.to).toEqual('/openapi')
expect(topMenuLinks[3].props.to).toEqual('/t/openstack/status')
expect(topMenuLinks[4].props.to).toEqual('/t/openstack/projects')
// Location should be /tenants
expect(location.pathname).toEqual('/tenants')
// Info should tell multi tenants
expect(store.getState().info.tenant).toEqual(undefined)
// Tenants list has been rendered
expect(application.root.findAllByType(TenantsPage)).not.toEqual(null)
// Fetch tenants has been called
expect(api.fetchTenants).toBeCalled()
})
it('renders single tenant', () => {
it('renders single tenant', async () => {
const store = configureStore()
api.fetchInfo.mockImplementation(
() => Promise.resolve({data: {
info: {capabilities: {}, tenant: 'openstack'}
@ -79,24 +86,26 @@ it('renders single tenant', () => {
api.fetchStatus.mockImplementation(
() => Promise.resolve({data: {pipelines: []}})
)
const application = ReactTestUtils.renderIntoDocument(
const application = create(
<Provider store={store}><Router><App /></Router></Provider>
)
store.dispatch(fetchInfoIfNeeded()).then(() => {
// Link should be white-label scoped
const topMenuLinks = ReactTestUtils.scryRenderedComponentsWithType(
application, Link)
expect(topMenuLinks[0].props.to).toEqual('/status')
expect(topMenuLinks[1].props.to).toEqual('/projects')
// Location should be /status
expect(location.pathname).toEqual('/status')
// Info should tell white label tenant openstack
expect(store.getState().info.tenant).toEqual('openstack')
// Status page has been rendered
expect(ReactTestUtils.findRenderedComponentWithType(
application, StatusPage)).not.toEqual(null)
// Fetch status has been called
expect(api.fetchStatus).toBeCalled()
await act(async () => {
await store.dispatch(fetchInfoIfNeeded())
})
// Link should be white-label scoped
const topMenuLinks = application.root.findAllByType(Link)
expect(topMenuLinks[0].props.to).toEqual('/status')
expect(topMenuLinks[1].props.to.pathname).toEqual('/status')
expect(topMenuLinks[2].props.to.pathname).toEqual('/projects')
// Location should be /status
expect(location.pathname).toEqual('/status')
// Info should tell white label tenant openstack
expect(store.getState().info.tenant).toEqual('openstack')
// Status page has been rendered
expect(application.root.findAllByType(StatusPage)).not.toEqual(null)
// Fetch status has been called
expect(api.fetchStatus).toBeCalled()
})

View File

@ -13,9 +13,9 @@
// under the License.
import React from 'react'
import ReactTestUtils from 'react-dom/test-utils'
import { Link, BrowserRouter as Router } from 'react-router-dom'
import { Provider } from 'react-redux'
import { create } from 'react-test-renderer'
import { setTenantAction } from '../../actions/tenant'
import configureStore from '../../store'
@ -31,34 +31,33 @@ const fakeChange = {
}]
}
const store = configureStore()
it('change panel render multi tenant links', () => {
const store = configureStore()
store.dispatch(setTenantAction('tenant-one', false))
const application = ReactTestUtils.renderIntoDocument(
<Provider store={store}>
<Router>
<ChangePanel change={fakeChange} globalExpanded={true} />
</Router>
</Provider>
)
const jobLink = ReactTestUtils.findRenderedComponentWithType(
application, Link)
const application = create(
<Provider store={store}>
<Router>
<ChangePanel change={fakeChange} globalExpanded={true} />
</Router>
</Provider>
)
const jobLink = application.root.findByType(Link)
expect(jobLink.props.to).toEqual(
'/t/tenant-one/stream/42')
})
it('change panel render white-label tenant links', () => {
const store = configureStore()
store.dispatch(setTenantAction('tenant-one', true))
const application = ReactTestUtils.renderIntoDocument(
const application = create(
<Provider store={store}>
<Router>
<ChangePanel change={fakeChange} globalExpanded={true} />
</Router>
</Provider>
)
const jobLink = ReactTestUtils.findRenderedComponentWithType(
application, Link)
const jobLink = application.root.findByType(Link)
expect(jobLink.props.to).toEqual(
'/stream/42')
})

View File

@ -1010,6 +1010,13 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.12.1":
version "7.16.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.0.tgz#e27b977f2e2088ba24748bf99b5e1dece64e4f0b"
integrity sha512-Nht8L0O8YCktmsDV6FqFue7vQLRx3Hb0B37lS5y0jDRqRxlBG4wIJHnf9/bgSE2UyipKFA01YtS+npRdTWBUyw==
dependencies:
regenerator-runtime "^0.13.4"
"@babel/template@^7.4.0", "@babel/template@^7.8.3", "@babel/template@^7.8.6":
version "7.8.6"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b"
@ -6922,7 +6929,7 @@ hex-color-regex@^1.1.0:
resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e"
integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==
history@^4.7.2:
history@^4.9.0:
version "4.10.1"
resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3"
integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==
@ -6943,12 +6950,12 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
hoist-non-react-statics@^2.1.1, hoist-non-react-statics@^2.3.1, hoist-non-react-statics@^2.5.0:
hoist-non-react-statics@^2.1.1, hoist-non-react-statics@^2.3.1:
version "2.5.5"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47"
integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==
hoist-non-react-statics@^3.3.0:
hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
@ -9438,6 +9445,14 @@ min-indent@^1.0.0:
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.0.tgz#cfc45c37e9ec0d8f0a0ec3dd4ef7f7c3abe39256"
integrity sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY=
mini-create-react-context@^0.4.0:
version "0.4.1"
resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz#072171561bfdc922da08a60c2197a497cc2d1d5e"
integrity sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==
dependencies:
"@babel/runtime" "^7.12.1"
tiny-warning "^1.0.3"
mini-css-extract-plugin@0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz#47f2cf07aa165ab35733b1fc97d4c46c0564339e"
@ -12150,7 +12165,7 @@ react-inspector@^2.3.0:
is-dom "^1.0.9"
prop-types "^15.6.1"
react-is@^16.3.2, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6:
react-is@^16.3.2, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
@ -12247,30 +12262,34 @@ react-redux@^4.x.x:
loose-envify "^1.4.0"
prop-types "^15.7.2"
react-router-dom@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.3.1.tgz#4c2619fc24c4fa87c9fd18f4fb4a43fe63fbd5c6"
integrity sha512-c/MlywfxDdCp7EnB7YfPMOfMD3tOtIjrQlj/CKfNMBxdmpJP8xcz5P/UAFn3JbnQCNUxsHyVVqllF9LhgVyFCA==
react-router-dom@5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.2.0.tgz#9e65a4d0c45e13289e66c7b17c7e175d0ea15662"
integrity sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==
dependencies:
history "^4.7.2"
invariant "^2.2.4"
"@babel/runtime" "^7.1.2"
history "^4.9.0"
loose-envify "^1.3.1"
prop-types "^15.6.1"
react-router "^4.3.1"
warning "^4.0.1"
prop-types "^15.6.2"
react-router "5.2.0"
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
react-router@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.3.1.tgz#aada4aef14c809cb2e686b05cee4742234506c4e"
integrity sha512-yrvL8AogDh2X42Dt9iknk4wF4V8bWREPirFfS9gLU1huk6qK41sg7Z/1S81jjTrGHxa3B8R3J6xIkDAA6CVarg==
react-router@5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.0.tgz#424e75641ca8747fbf76e5ecca69781aa37ea293"
integrity sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==
dependencies:
history "^4.7.2"
hoist-non-react-statics "^2.5.0"
invariant "^2.2.4"
"@babel/runtime" "^7.1.2"
history "^4.9.0"
hoist-non-react-statics "^3.1.0"
loose-envify "^1.3.1"
mini-create-react-context "^0.4.0"
path-to-regexp "^1.7.0"
prop-types "^15.6.1"
warning "^4.0.1"
prop-types "^15.6.2"
react-is "^16.6.0"
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
react-scripts@3.4.1:
version "3.4.1"
@ -12346,6 +12365,16 @@ react-select@3.1.0:
react-input-autosize "^2.2.2"
react-transition-group "^4.3.0"
react-test-renderer@16.13.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.13.1.tgz#de25ea358d9012606de51e012d9742e7f0deabc1"
integrity sha512-Sn2VRyOK2YJJldOqoh8Tn/lWQ+ZiKhyZTPtaO0Q6yNj+QDbmRkVFap6pZPy3YQk8DScRDfyqm/KxKYP9gCMRiQ==
dependencies:
object-assign "^4.1.1"
prop-types "^15.6.2"
react-is "^16.8.6"
scheduler "^0.19.1"
react-textarea-autosize@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-6.1.0.tgz#df91387f8a8f22020b77e3833c09829d706a09a5"
@ -14321,7 +14350,7 @@ tiny-relative-date@^1.3.0:
resolved "https://registry.yarnpkg.com/tiny-relative-date/-/tiny-relative-date-1.3.0.tgz#fa08aad501ed730f31cc043181d995c39a935e07"
integrity sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A==
tiny-warning@^1.0.0:
tiny-warning@^1.0.0, tiny-warning@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==