feat: upgrade react router to v6 (#716)

* feat: upgrade react router to v6
* refactor: add hoc to use params
* fix: lint issue
This commit is contained in:
Syed Ali Abbas Zaidi
2023-09-05 23:55:23 +05:00
committed by GitHub
parent e1d4e9b474
commit fe800f2ee9
7 changed files with 83 additions and 304 deletions

View File

@@ -41,6 +41,8 @@ import { profilePageSelector } from './data/selectors';
// i18n
import messages from './ProfilePage.messages';
import withParams from '../utils/hoc';
ensureConfig(['CREDENTIALS_BASE_URL', 'LMS_BASE_URL'], 'ProfilePage');
class ProfilePage extends React.Component {
@@ -63,9 +65,9 @@ class ProfilePage extends React.Component {
}
componentDidMount() {
this.props.fetchProfile(this.props.match.params.username);
this.props.fetchProfile(this.props.params.username);
sendTrackingLogEvent('edx.profile.viewed', {
username: this.props.match.params.username,
username: this.props.params.username,
});
}
@@ -102,7 +104,7 @@ class ProfilePage extends React.Component {
}
isAuthenticatedUserProfile() {
return this.props.match.params.username === this.context.authenticatedUser.username;
return this.props.params.username === this.context.authenticatedUser.username;
}
// Inserted into the DOM in two places (for responsive layout)
@@ -124,7 +126,7 @@ class ProfilePage extends React.Component {
return (
<span data-hj-suppress>
<h1 className="h2 mb-0 font-weight-bold">{this.props.match.params.username}</h1>
<h1 className="h2 mb-0 font-weight-bold">{this.props.params.username}</h1>
<DateJoined date={dateJoined} />
{this.isYOBDisabled() && <UsernameDescription />}
<hr className="d-none d-md-block" />
@@ -370,10 +372,8 @@ ProfilePage.propTypes = {
updateDraft: PropTypes.func.isRequired,
// Router
match: PropTypes.shape({
params: PropTypes.shape({
username: PropTypes.string.isRequired,
}).isRequired,
params: PropTypes.shape({
username: PropTypes.string.isRequired,
}).isRequired,
// i18n
@@ -410,4 +410,4 @@ export default connect(
closeForm,
updateDraft,
},
)(injectIntl(ProfilePage));
)(injectIntl(withParams(ProfilePage)));

View File

@@ -29,7 +29,7 @@ const requiredProfilePageProps = {
deleteProfilePhoto: () => {},
openField: () => {},
closeField: () => {},
match: { params: { username: 'staff' } },
params: { username: 'staff' },
};
// Mock language cookie
@@ -67,29 +67,28 @@ beforeEach(() => {
});
const ProfilePageWrapper = ({
contextValue, store, match, requiresParentalConsent,
contextValue, store, params, requiresParentalConsent,
}) => (
<AppContext.Provider
value={contextValue}
>
<IntlProvider locale="en">
<Provider store={store}>
<ProfilePage {...requiredProfilePageProps} match={match} requiresParentalConsent={requiresParentalConsent} />
<ProfilePage {...requiredProfilePageProps} params={params} requiresParentalConsent={requiresParentalConsent} />
</Provider>
</IntlProvider>
</AppContext.Provider>
);
ProfilePageWrapper.defaultProps = {
match: { params: { username: 'staff' } },
params: { username: 'staff' },
requiresParentalConsent: null,
};
ProfilePageWrapper.propTypes = {
contextValue: PropTypes.shape({}).isRequired,
store: PropTypes.shape({}).isRequired,
match: PropTypes.shape({}),
params: PropTypes.shape({}),
requiresParentalConsent: PropTypes.bool,
};
@@ -124,7 +123,7 @@ describe('<ProfilePage />', () => {
<ProfilePageWrapper
contextValue={contextValue}
store={mockStore(storeMocks.viewOtherProfile)}
match={{ params: { username: 'verified' } }} // Override default match
params={{ username: 'verified' }} // Override default params
/>
);
const tree = renderer.create(component).toJSON();
@@ -279,7 +278,7 @@ describe('<ProfilePage />', () => {
<ProfilePageWrapper
contextValue={contextValue}
store={mockStore(storeMocks.loadingApp)}
match={{ params: { username: 'test-username' } }}
params={{ username: 'test-username' }}
/>
);
const wrapper = mount(component);

View File

@@ -1,17 +1,17 @@
import React from 'react';
import {
AuthenticatedPageRoute,
PageRoute,
PageWrap,
} from '@edx/frontend-platform/react';
import { Switch } from 'react-router-dom';
import { Routes, Route } from 'react-router-dom';
import { ProfilePage, NotFoundPage } from '../profile';
const AppRoutes = () => (
<Switch>
<AuthenticatedPageRoute path="/u/:username" component={ProfilePage} />
<PageRoute path="/notfound" component={NotFoundPage} />
<PageRoute path="*" component={NotFoundPage} />
</Switch>
<Routes>
<Route path="/u/:username" element={<AuthenticatedPageRoute><ProfilePage /></AuthenticatedPageRoute>} />
<Route path="/notfound" element={<PageWrap><NotFoundPage /></PageWrap>} />
<Route path="*" element={<PageWrap><NotFoundPage /></PageWrap>} />
</Routes>
);
export default AppRoutes;

View File

@@ -1,9 +1,8 @@
import React from 'react';
import { AppContext } from '@edx/frontend-platform/react';
import { getConfig } from '@edx/frontend-platform';
import { Router } from 'react-router';
import { MemoryRouter as Router } from 'react-router-dom';
import { render, screen } from '@testing-library/react';
import { createMemoryHistory } from 'history';
import { getLoginRedirectUrl } from '@edx/frontend-platform/auth';
import AppRoutes from './AppRoutes';
@@ -18,9 +17,9 @@ jest.mock('../profile', () => ({
NotFoundPage: () => (<div>Not found page</div>),
}));
const RoutesWithProvider = (context, history) => (
const RoutesWithProvider = (context, path) => (
<AppContext.Provider value={context}>
<Router history={history}>
<Router initialEntries={[`${path}`]}>
<AppRoutes />
</Router>
</AppContext.Provider>
@@ -32,22 +31,14 @@ const unauthenticatedUser = {
};
describe('routes', () => {
let history;
beforeEach(() => {
history = createMemoryHistory();
});
test('Profile page should redirect for unauthenticated users', () => {
history.push('/u/edx');
render(
RoutesWithProvider(unauthenticatedUser, history),
RoutesWithProvider(unauthenticatedUser, '/u/edx'),
);
expect(getLoginRedirectUrl).toHaveBeenCalled();
});
test('Profile page should be accessible for authenticated users', () => {
history.push('/u/edx');
render(
RoutesWithProvider(
{
@@ -57,16 +48,15 @@ describe('routes', () => {
},
config: getConfig(),
},
history,
'/u/edx',
),
);
expect(screen.getByText('Profile page')).toBeTruthy();
});
test('should show NotFound page for a bad route', () => {
history.push('/nonMatchingRoute');
render(
RoutesWithProvider(unauthenticatedUser, history),
RoutesWithProvider(unauthenticatedUser, '/nonMatchingRoute'),
);
expect(screen.getByText('Not found page')).toBeTruthy();
});

10
src/utils/hoc.jsx Normal file
View File

@@ -0,0 +1,10 @@
import React from 'react';
import { useParams } from 'react-router-dom';
const withParams = (WrappedComponent) => {
const WithParamsComponent = (props) => <WrappedComponent params={useParams()} {...props} />;
return WithParamsComponent;
};
export default withParams;