fix: post summaries are being repeated in the list (#105)
* fix: post summaries are being repeated in the list
This commit is contained in:
@@ -1,35 +1,18 @@
|
||||
import React, { useContext, useEffect } from 'react';
|
||||
import React 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 { AppContext } from '@edx/frontend-platform/react';
|
||||
|
||||
import { RequestStatus, Routes } from '../../data/constants';
|
||||
import { DiscussionContext } from '../common/context';
|
||||
import { Routes } from '../../data/constants';
|
||||
import { LearnersView } from '../learners';
|
||||
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
|
||||
@@ -50,15 +33,13 @@ export default function DiscussionSidebar({ displaySidebar }) {
|
||||
/>
|
||||
<Route path={Routes.TOPICS.PATH} component={TopicsView} />
|
||||
<Route path={Routes.LEARNERS.PATH} component={LearnersView} />
|
||||
{RequestStatus.SUCCESSFUL === loadingStatus && (
|
||||
<Redirect
|
||||
from={Routes.DISCUSSIONS.PATH}
|
||||
to={{
|
||||
...location,
|
||||
pathname: userThreads.length ? Routes.POSTS.MY_POSTS : Routes.POSTS.ALL_POSTS,
|
||||
pathname: Routes.POSTS.ALL_POSTS,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Switch>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -17,21 +17,24 @@ import DiscussionSidebar from './DiscussionSidebar';
|
||||
import '../posts/data/__factories__';
|
||||
|
||||
let store;
|
||||
let container;
|
||||
const courseId = 'course-v1:edX+DemoX+Demo_Course';
|
||||
let axiosMock;
|
||||
|
||||
function renderComponent(displaySidebar = true, location = `/${courseId}/`) {
|
||||
return render(
|
||||
const wrapper = render(
|
||||
<IntlProvider locale="en">
|
||||
<ResponsiveContext.Provider value={{ width: 1280 }}>
|
||||
<AppProvider store={store}>
|
||||
<MemoryRouter initialEntries={[location]}>
|
||||
<DiscussionSidebar data-test- displaySidebar={displaySidebar} />
|
||||
<DiscussionSidebar displaySidebar={displaySidebar} />
|
||||
</MemoryRouter>
|
||||
</AppProvider>
|
||||
</ResponsiveContext.Provider>
|
||||
</IntlProvider>,
|
||||
);
|
||||
container = wrapper.container;
|
||||
return container;
|
||||
}
|
||||
|
||||
describe('DiscussionSidebar', () => {
|
||||
@@ -67,23 +70,26 @@ describe('DiscussionSidebar', () => {
|
||||
expect(element).toHaveClass('d-none');
|
||||
});
|
||||
|
||||
test('User with some topics should be redirected to "My Posts"', async () => {
|
||||
test('User will be redirected to "All Posts" by default', 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();
|
||||
});
|
||||
|
||||
test('Display discussion posts should equal to post count in "All Posts"', async () => {
|
||||
const postCount = 5;
|
||||
axiosMock.onGet(threadsApiUrl)
|
||||
.reply(({ params }) => [200, Factory.build('threadsResult', {}, {
|
||||
count: postCount,
|
||||
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();
|
||||
expect(container.querySelectorAll('.discussion-post')).toHaveLength(postCount);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -102,7 +102,7 @@ function PostsView({ showOwnPosts }) {
|
||||
filters,
|
||||
page: nextPage,
|
||||
author: showOwnPosts ? authenticatedUser.username : null,
|
||||
}, posts));
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ export function fetchThreads(courseId, {
|
||||
author = null,
|
||||
filters = {},
|
||||
page = 1,
|
||||
} = {}, posts = []) {
|
||||
} = {}) {
|
||||
const options = {
|
||||
orderBy,
|
||||
topicIds,
|
||||
@@ -122,7 +122,6 @@ export function fetchThreads(courseId, {
|
||||
try {
|
||||
dispatch(fetchThreadsRequest({ courseId }));
|
||||
const data = await getThreads(courseId, options);
|
||||
data.results = [...posts, ...data.results];
|
||||
const normalisedData = normaliseThreads(camelCaseObject(data));
|
||||
dispatch(fetchThreadsSuccess({ ...normalisedData, page, author }));
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user