fix: [BD-38] [BB-5598][TNL-9626] redirect home page to my posts, fallback to all posts if user has no content (#87)
This alters the behaviour of the base URL. Instead of navigating to the topics page, it now navigates to the user's posts page when the user has posts, and to the all posts page when the user has no posts.
This commit is contained in:
@@ -1,17 +1,34 @@
|
||||
import React from 'react';
|
||||
import React, { useContext, useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import classNames from 'classnames';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import {
|
||||
Redirect, Route, Switch, useLocation,
|
||||
} from 'react-router';
|
||||
|
||||
import { Routes } from '../../data/constants';
|
||||
import { AppContext } from '@edx/frontend-platform/react';
|
||||
|
||||
import { RequestStatus, Routes } from '../../data/constants';
|
||||
import { DiscussionContext } from '../common/context';
|
||||
import { PostsView } from '../posts';
|
||||
import {
|
||||
selectAllThreads, threadsLoadingStatus,
|
||||
} from '../posts/data/selectors';
|
||||
import { fetchThreads } from '../posts/data/thunks';
|
||||
import { TopicsView } from '../topics';
|
||||
|
||||
export default function DiscussionSidebar({ displaySidebar }) {
|
||||
const location = useLocation();
|
||||
const dispatch = useDispatch();
|
||||
const userThreads = useSelector(selectAllThreads);
|
||||
const { courseId } = useContext(DiscussionContext);
|
||||
const { authenticatedUser } = useContext(AppContext);
|
||||
const loadingStatus = useSelector(threadsLoadingStatus());
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetchThreads(courseId, { author: authenticatedUser.username }));
|
||||
}, [authenticatedUser, courseId]);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -31,13 +48,15 @@ export default function DiscussionSidebar({ displaySidebar }) {
|
||||
component={PostsView}
|
||||
/>
|
||||
<Route path={Routes.TOPICS.PATH} component={TopicsView} />
|
||||
{RequestStatus.SUCCESSFUL === loadingStatus && (
|
||||
<Redirect
|
||||
from={Routes.DISCUSSIONS.PATH}
|
||||
to={{
|
||||
...location,
|
||||
pathname: Routes.TOPICS.ALL,
|
||||
pathname: userThreads.length ? Routes.POSTS.MY_POSTS : Routes.POSTS.ALL_POSTS,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Switch>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,22 +1,31 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { IntlProvider } from 'react-intl';
|
||||
import { Context as ResponsiveContext } from 'react-responsive';
|
||||
import { MemoryRouter } from 'react-router';
|
||||
import { Factory } from 'rosie';
|
||||
|
||||
import { initializeMockApp } from '@edx/frontend-platform';
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
import { AppProvider } from '@edx/frontend-platform/react';
|
||||
|
||||
import { initializeStore } from '../../store';
|
||||
import { threadsApiUrl } from '../posts/data/api';
|
||||
import DiscussionSidebar from './DiscussionSidebar';
|
||||
|
||||
let store;
|
||||
import '../posts/data/__factories__';
|
||||
|
||||
function renderComponent(displaySidebar) {
|
||||
let store;
|
||||
const courseId = 'course-v1:edX+DemoX+Demo_Course';
|
||||
let axiosMock;
|
||||
|
||||
function renderComponent(displaySidebar = true, location = `/${courseId}/`) {
|
||||
return render(
|
||||
<IntlProvider locale="en">
|
||||
<ResponsiveContext.Provider value={{ width: 1280 }}>
|
||||
<AppProvider store={store}>
|
||||
<MemoryRouter>
|
||||
<MemoryRouter initialEntries={[location]}>
|
||||
<DiscussionSidebar data-test- displaySidebar={displaySidebar} />
|
||||
</MemoryRouter>
|
||||
</AppProvider>
|
||||
@@ -36,7 +45,14 @@ describe('DiscussionSidebar', () => {
|
||||
},
|
||||
});
|
||||
|
||||
store = initializeStore();
|
||||
store = initializeStore({
|
||||
blocks: { blocks: { 'test-usage-key': { topics: ['some-topic-2', 'some-topic-0'] } } },
|
||||
});
|
||||
Factory.resetAll();
|
||||
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
|
||||
});
|
||||
afterEach(() => {
|
||||
axiosMock.reset();
|
||||
});
|
||||
|
||||
test('component visible if displaySidebar == true', async () => {
|
||||
@@ -50,4 +66,24 @@ describe('DiscussionSidebar', () => {
|
||||
const element = await screen.findByTestId('sidebar');
|
||||
expect(element).toHaveClass('d-none');
|
||||
});
|
||||
|
||||
test('User with some topics should be redirected to "My Posts"', async () => {
|
||||
axiosMock.onGet(threadsApiUrl)
|
||||
.reply(({ params }) => [200, Factory.build('threadsResult', {}, {
|
||||
threadAttrs: { title: `Thread by ${params.author || 'other users'}` },
|
||||
})]);
|
||||
renderComponent();
|
||||
await act(async () => expect(await screen.findAllByText('Thread by abc123')).toBeTruthy());
|
||||
expect(screen.queryByText('Thread by other users')).not.toBeInTheDocument();
|
||||
});
|
||||
test('User with no posts should be redirected to "All Posts"', async () => {
|
||||
axiosMock.onGet(threadsApiUrl)
|
||||
.reply(({ params }) => [200, Factory.build('threadsResult', {}, {
|
||||
count: params.author ? 0 : 3,
|
||||
threadAttrs: { title: `Thread by ${params.author || 'other users'}` },
|
||||
})]);
|
||||
renderComponent();
|
||||
await act(async () => expect(await screen.findAllByText('Thread by other users')).toBeTruthy());
|
||||
expect(screen.queryByText('Thread by abc123')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user