test: add tests for TopicsView component

This commit is contained in:
Maxim Beder
2021-10-23 21:40:39 +02:00
committed by Maxim Beder
parent 5564ef7549
commit fc2c528bf7
5 changed files with 199 additions and 2 deletions

View File

@@ -38,7 +38,7 @@ function TopicsView() {
),
);
if (nonCoursewareTopics && category === undefined) {
if (nonCoursewareTopics?.length > 1 && category === undefined) {
topicElements.unshift(<TopicGroup subtopics={nonCoursewareTopics} filter={filter} key="non-courseware" />);
}

View File

@@ -0,0 +1,186 @@
import {
fireEvent, queryByText, render, screen, waitFor,
} from '@testing-library/react';
import MockAdapter from 'axios-mock-adapter';
import { IntlProvider } from 'react-intl';
import { MemoryRouter, Route } 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 { API_BASE_URL } from '../../data/constants';
import { initializeStore } from '../../store';
import TopicsView from './TopicsView';
import './data/__factories__';
const courseId = 'course-v1:edX+TestX+Test_Course';
const topicsApiUrl = `${API_BASE_URL}/api/discussion/v1/course_topics/${courseId}`;
let store;
let axiosMock;
let lastLocation;
function renderComponent() {
render(
<IntlProvider locale="en">
<AppProvider store={store}>
<MemoryRouter initialEntries={[`/discussions/${courseId}/topics/`]}>
<Route path="/discussions/:courseId/topics/">
<TopicsView />
</Route>
<Route path="/discussions/:courseId/category/:category">
<TopicsView />
</Route>
<Route
render={({ location }) => {
lastLocation = location;
return null;
}}
/>
</MemoryRouter>
</AppProvider>
</IntlProvider>,
);
}
describe('TopicsView', () => {
beforeEach(() => {
initializeMockApp({
authenticatedUser: {
userId: 3,
username: 'abc123',
administrator: true,
roles: [],
},
});
store = initializeStore();
Factory.resetAll();
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
lastLocation = undefined;
});
it('displays non-courseware topics', async () => {
axiosMock
.onGet(topicsApiUrl)
.reply(200, {
courseware_topics: [],
non_courseware_topics: Factory.buildList('topic', 3),
});
renderComponent();
await screen.findByText('topic 1');
expect(screen.queryByText('topic 2')).toBeInTheDocument();
expect(screen.queryByText('topic 3')).toBeInTheDocument();
});
it('displays non-courseware in one topic group', async () => {
axiosMock
.onGet(topicsApiUrl)
.reply(200, {
courseware_topics: [],
non_courseware_topics: Factory.buildList('topic', 3),
});
renderComponent();
await screen.findByText('topic 1');
const topicGroups = screen.queryAllByTestId('topic-group');
expect(topicGroups).toHaveLength(1);
});
it('displays courseware topics', async () => {
axiosMock
.onGet(topicsApiUrl)
.reply(200, {
courseware_topics: Factory.buildList('topic', 3),
non_courseware_topics: [],
});
renderComponent();
await screen.findByText('topic 1');
expect(screen.queryByText('topic 2')).toBeInTheDocument();
expect(screen.queryByText('topic 3')).toBeInTheDocument();
});
it('displays courseware topics in individual topic groups', async () => {
axiosMock
.onGet(topicsApiUrl)
.reply(200, {
courseware_topics: Factory.buildList('topic', 3),
non_courseware_topics: [],
});
renderComponent();
await screen.findByText('topic 1');
const topicGroups = screen.queryAllByTestId('topic-group');
expect(topicGroups).toHaveLength(3);
});
it('displays non-courseware topics before courseware topics', async () => {
axiosMock
.onGet(topicsApiUrl)
.reply(200, {
courseware_topics: Factory.buildList('topic', 3),
non_courseware_topics: Factory.buildList('topic', 3),
});
renderComponent();
await screen.findByText('topic 1');
const topicGroups = screen.queryAllByTestId('topic-group');
expect(queryByText(topicGroups[0], 'topic 4')).toBeInTheDocument();
expect(queryByText(topicGroups[0], 'topic 5')).toBeInTheDocument();
expect(queryByText(topicGroups[0], 'topic 6')).toBeInTheDocument();
expect(queryByText(topicGroups[1], 'topic 1')).toBeInTheDocument();
expect(queryByText(topicGroups[2], 'topic 2')).toBeInTheDocument();
expect(queryByText(topicGroups[3], 'topic 3')).toBeInTheDocument();
});
it('clicking on courseware topic (category) takes to category page', async () => {
axiosMock
.onGet(topicsApiUrl)
.reply(200, {
courseware_topics: Factory.buildList('topic', 3),
non_courseware_topics: Factory.buildList('topic', 3),
});
renderComponent();
const topic = await screen.findByText('topic 1');
fireEvent.click(topic);
await waitFor(() => expect(screen.queryByText('topic 2')).not.toBeInTheDocument());
expect(lastLocation.pathname.endsWith('/category/topic 1')).toBeTruthy();
});
it('on category page only selected category and it\'s children are displayed', async () => {
const category = Factory.build('topic');
category.children = Factory.buildList('topic', 3);
axiosMock
.onGet(topicsApiUrl)
.reply(200, {
courseware_topics: [
category,
Factory.build('topic'),
],
non_courseware_topics: Factory.buildList('topic', 3),
});
renderComponent();
const topic = await screen.findByText('topic 1');
fireEvent.click(topic);
await waitFor(() => expect(screen.queryByText('topic 6')).not.toBeInTheDocument());
// children
expect(screen.queryByText('topic 2')).toBeInTheDocument();
expect(screen.queryByText('topic 3')).toBeInTheDocument();
expect(screen.queryByText('topic 4')).toBeInTheDocument();
// other courseware topics (categories) and non-courseware topics
expect(screen.queryByText('topic 5')).not.toBeInTheDocument();
expect(screen.queryByText('topic 6')).not.toBeInTheDocument();
expect(screen.queryByText('topic 7')).not.toBeInTheDocument();
expect(screen.queryByText('topic 8')).not.toBeInTheDocument();
});
});

View File

@@ -0,0 +1 @@
import './topics.factory';

View File

@@ -0,0 +1,6 @@
import { Factory } from 'rosie';
Factory.define('topic')
.sequence('id', (idx) => `topic-${idx}`)
.sequence('name', (idx) => `topic ${idx}`)
.attr('children', []);

View File

@@ -42,7 +42,11 @@ function TopicGroup({
}
return (
<div className="discussion-topic-group d-flex flex-column" data-topic-id={id}>
<div
className="discussion-topic-group d-flex flex-column"
data-topic-id={id}
data-testid="topic-group"
>
{name && (
<Link
className="topic-name list-group-item p-4 text-primary-500"