diff --git a/public/index.html b/public/index.html
index 7ef8a8a4..fbb12a47 100644
--- a/public/index.html
+++ b/public/index.html
@@ -9,9 +9,10 @@
href="<%=htmlWebpackPlugin.options.FAVICON_URL%>"
type="image/x-icon"
/>
-
+
+
-
-
-
+
+ {/* eslint-disable-next-line react/no-danger */}
+
-
);
}
diff --git a/src/discussions/comments/CommentsView.test.jsx b/src/discussions/comments/CommentsView.test.jsx
index 90874cef..9f8b7910 100644
--- a/src/discussions/comments/CommentsView.test.jsx
+++ b/src/discussions/comments/CommentsView.test.jsx
@@ -1,5 +1,5 @@
import {
- act, fireEvent, render, screen, waitFor, /* within, */
+ act, fireEvent, render, screen, waitFor, within,
} from '@testing-library/react';
import MockAdapter from 'axios-mock-adapter';
import { IntlProvider } from 'react-intl';
@@ -32,7 +32,7 @@ const closedPostId = 'thread-2';
const courseId = 'course-v1:edX+TestX+Test_Course';
let store;
let axiosMock;
-// let testLocation;
+let testLocation;
function mockAxiosReturnPagedComments() {
[null, false, true].forEach(endorsed => {
@@ -92,7 +92,10 @@ function renderComponent(postId) {
null}
+ render={({ location }) => {
+ testLocation = location;
+ return null;
+ }}
/>
@@ -157,43 +160,43 @@ describe('CommentsView', () => {
expect(JSON.parse(axiosMock.history.patch[axiosMock.history.patch.length - 1].data)).toMatchObject(data);
}
- // it('should show and hide the editor', async () => {
- // renderComponent(discussionPostId);
- // await waitFor(() => screen.findByText('comment number 1', { exact: false }));
- // const addResponseButtons = screen.getAllByRole('button', { name: /add a response/i });
- // await act(async () => {
- // fireEvent.click(
- // addResponseButtons[0],
- // );
- // });
- // expect(screen.queryByTestId('tinymce-editor')).toBeInTheDocument();
- // await act(async () => {
- // fireEvent.click(screen.getByRole('button', { name: /cancel/i }));
- // });
- // expect(screen.queryByTestId('tinymce-editor')).not.toBeInTheDocument();
- // });
+ it('should show and hide the editor', async () => {
+ renderComponent(discussionPostId);
+ await waitFor(() => screen.findByText('comment number 1', { exact: false }));
+ const addResponseButtons = screen.getAllByRole('button', { name: /add a response/i });
+ await act(async () => {
+ fireEvent.click(
+ addResponseButtons[0],
+ );
+ });
+ expect(screen.queryByTestId('tinymce-editor')).toBeInTheDocument();
+ await act(async () => {
+ fireEvent.click(screen.getByRole('button', { name: /cancel/i }));
+ });
+ expect(screen.queryByTestId('tinymce-editor')).not.toBeInTheDocument();
+ });
- // it('should allow posting a response', async () => {
- // renderComponent(discussionPostId);
- // await waitFor(() => screen.findByText('comment number 1', { exact: false }));
- // const responseButtons = screen.getAllByRole('button', { name: /add a response/i });
- // await act(async () => {
- // fireEvent.click(
- // responseButtons[0],
- // );
- // });
- // await act(() => {
- // fireEvent.change(screen.getByTestId('tinymce-editor'), { target: { value: 'testing123' } });
- // });
- //
- // await act(async () => {
- // fireEvent.click(
- // screen.getByText(/submit/i),
- // );
- // });
- // expect(screen.queryByTestId('tinymce-editor')).not.toBeInTheDocument();
- // await waitFor(async () => expect(await screen.findByText('testing123', { exact: false })).toBeInTheDocument());
- // });
+ it('should allow posting a response', async () => {
+ renderComponent(discussionPostId);
+ await waitFor(() => screen.findByText('comment number 1', { exact: false }));
+ const responseButtons = screen.getAllByRole('button', { name: /add a response/i });
+ await act(async () => {
+ fireEvent.click(
+ responseButtons[0],
+ );
+ });
+ await act(() => {
+ fireEvent.change(screen.getByTestId('tinymce-editor'), { target: { value: 'testing123' } });
+ });
+
+ await act(async () => {
+ fireEvent.click(
+ screen.getByText(/submit/i),
+ );
+ });
+ expect(screen.queryByTestId('tinymce-editor')).not.toBeInTheDocument();
+ await waitFor(async () => expect(await screen.findByText('testing123', { exact: false })).toBeInTheDocument());
+ });
it('should not allow posting a response on a closed post', async () => {
renderComponent(closedPostId);
@@ -201,26 +204,26 @@ describe('CommentsView', () => {
expect(screen.queryByRole('button', { name: /add a response/i })).not.toBeInTheDocument();
});
- // it('should allow posting a comment', async () => {
- // renderComponent(discussionPostId);
- // await waitFor(() => screen.findByText('comment number 1', { exact: false }));
- // await act(async () => {
- // fireEvent.click(
- // screen.getAllByRole('button', { name: /add a comment/i })[0],
- // );
- // });
- // act(() => {
- // fireEvent.change(screen.getByTestId('tinymce-editor'), { target: { value: 'testing123' } });
- // });
- //
- // await act(async () => {
- // fireEvent.click(
- // screen.getByText(/submit/i),
- // );
- // });
- // expect(screen.queryByTestId('tinymce-editor')).not.toBeInTheDocument();
- // await waitFor(async () => expect(await screen.findByText('testing123', { exact: false })).toBeInTheDocument());
- // });
+ it('should allow posting a comment', async () => {
+ renderComponent(discussionPostId);
+ await waitFor(() => screen.findByText('comment number 1', { exact: false }));
+ await act(async () => {
+ fireEvent.click(
+ screen.getAllByRole('button', { name: /add a comment/i })[0],
+ );
+ });
+ act(() => {
+ fireEvent.change(screen.getByTestId('tinymce-editor'), { target: { value: 'testing123' } });
+ });
+
+ await act(async () => {
+ fireEvent.click(
+ screen.getByText(/submit/i),
+ );
+ });
+ expect(screen.queryByTestId('tinymce-editor')).not.toBeInTheDocument();
+ await waitFor(async () => expect(await screen.findByText('testing123', { exact: false })).toBeInTheDocument());
+ });
it('should not allow posting a comment on a closed post', async () => {
renderComponent(closedPostId);
@@ -232,29 +235,29 @@ describe('CommentsView', () => {
});
});
- // it('should allow editing an existing comment', async () => {
- // renderComponent(discussionPostId);
- // await waitFor(() => screen.findByText('comment number 1', { exact: false }));
- // await act(async () => {
- // fireEvent.click(
- // // The first edit menu is for the post, the second will be for the first comment.
- // screen.getAllByRole('button', { name: /actions menu/i })[1],
- // );
- // });
- // await act(async () => {
- // fireEvent.click(screen.getByRole('button', { name: /edit/i }));
- // });
- // act(() => {
- // fireEvent.change(screen.getByTestId('tinymce-editor'), { target: { value: 'testing123' } });
- // });
- // await act(async () => {
- // fireEvent.click(screen.getByRole('button', { name: /submit/i }));
- // });
- // await waitFor(async () => {
- // expect(await screen.findByText('testing123', { exact: false })).toBeInTheDocument();
- // });
- // });
- //
+ it('should allow editing an existing comment', async () => {
+ renderComponent(discussionPostId);
+ await waitFor(() => screen.findByText('comment number 1', { exact: false }));
+ await act(async () => {
+ fireEvent.click(
+ // The first edit menu is for the post, the second will be for the first comment.
+ screen.getAllByRole('button', { name: /actions menu/i })[1],
+ );
+ });
+ await act(async () => {
+ fireEvent.click(screen.getByRole('button', { name: /edit/i }));
+ });
+ act(() => {
+ fireEvent.change(screen.getByTestId('tinymce-editor'), { target: { value: 'testing123' } });
+ });
+ await act(async () => {
+ fireEvent.click(screen.getByRole('button', { name: /submit/i }));
+ });
+ await waitFor(async () => {
+ expect(await screen.findByText('testing123', { exact: false })).toBeInTheDocument();
+ });
+ });
+
async function setupCourseConfig(reasonCodesEnabled = true) {
axiosMock.onGet(`${courseConfigApiUrl}${courseId}/`).reply(200, {
has_moderation_privileges: true,
@@ -271,83 +274,81 @@ describe('CommentsView', () => {
axiosMock.onGet(`${courseConfigApiUrl}${courseId}/settings`).reply(200, {});
await executeThunk(fetchCourseConfig(courseId), store.dispatch, store.getState);
}
- //
- // it('should show reason codes when editing an existing comment', async () => {
- // setupCourseConfig();
- // renderComponent(discussionPostId);
- // await waitFor(() => screen.findByText('comment number 1', { exact: false }));
- // await act(async () => {
- // fireEvent.click(
- // // The first edit menu is for the post, the second will be for the first comment.
- // screen.getAllByRole('button', { name: /actions menu/i })[1],
- // );
- // });
- // await act(async () => {
- // fireEvent.click(screen.getByRole('button', { name: /edit/i }));
- // });
- // expect(screen.queryByRole('combobox', { name: /reason for editing/i })).toBeInTheDocument();
- // expect(screen.getAllByRole('option', { name: /reason \d/i })).toHaveLength(2);
- // await act(async () => {
- // fireEvent.change(screen.queryByRole('combobox', { name: /reason for editing/i }),
- // { target: { value: null } });
- // });
- // await act(async () => {
- // fireEvent.change(screen.queryByRole('combobox',
- // { name: /reason for editing/i }), { target: { value: 'reason-1' } });
- // });
- // await act(async () => {
- // fireEvent.change(screen.getByTestId('tinymce-editor'), { target: { value: 'testing123' } });
- // });
- // await act(async () => {
- // fireEvent.click(screen.getByRole('button', { name: /submit/i }));
- // });
- // assertLastUpdateData({ edit_reason_code: 'reason-1' });
- // });
- //
- // it('should show reason codes when closing a post', async () => {
- // setupCourseConfig();
- // renderComponent(discussionPostId);
- // await act(async () => {
- // fireEvent.click(
- // // The first edit menu is for the post
- // screen.getAllByRole('button', {
- // name: /actions menu/i,
- // })[0],
- // );
- // });
- // expect(screen.queryByRole('dialog', { name: /close post/i })).not.toBeInTheDocument();
- // await act(async () => {
- // fireEvent.click(screen.getByRole('button', { name: /close/i }));
- // });
- // expect(screen.queryByRole('dialog', { name: /close post/i })).toBeInTheDocument();
- // expect(screen.queryByRole('combobox', { name: /reason/i })).toBeInTheDocument();
- // expect(screen.getAllByRole('option', { name: /reason \d/i })).toHaveLength(2);
- // await act(async () => {
- // fireEvent.change(screen.queryByRole('combobox', { name: /reason/i }), { target: { value: 'reason-1' } });
- // });
- // await act(async () => {
- // fireEvent.click(screen.getByRole('button', { name: /close post/i }));
- // });
- // expect(screen.queryByRole('dialog', { name: /close post/i })).not.toBeInTheDocument();
- // assertLastUpdateData({ closed: true, close_reason_code: 'reason-1' });
- // });
- // it('should close the post directly if reason codes are not enabled', async () => {
- // setupCourseConfig(false);
- // renderComponent(discussionPostId);
- // await act(async () => {
- // fireEvent.click(
- // // The first edit menu is for the post
- // screen.getAllByRole('button', { name: /actions menu/i })[0],
- // );
- // });
- // expect(screen.queryByRole('dialog', { name: /close post/i })).not.toBeInTheDocument();
- // await act(async () => {
- // fireEvent.click(screen.getByRole('button', { name: /close/i }));
- // });
- // expect(screen.queryByRole('dialog', { name: /close post/i })).not.toBeInTheDocument();
- // assertLastUpdateData({ closed: true });
- // });
+ it('should show reason codes when editing an existing comment', async () => {
+ setupCourseConfig();
+ renderComponent(discussionPostId);
+ await waitFor(() => screen.findByText('comment number 1', { exact: false }));
+ await act(async () => {
+ fireEvent.click(
+ // The first edit menu is for the post, the second will be for the first comment.
+ screen.getAllByRole('button', { name: /actions menu/i })[1],
+ );
+ });
+ await act(async () => {
+ fireEvent.click(screen.getByRole('button', { name: /edit/i }));
+ });
+ expect(screen.queryByRole('combobox', { name: /reason for editing/i })).toBeInTheDocument();
+ expect(screen.getAllByRole('option', { name: /reason \d/i })).toHaveLength(2);
+ await act(async () => {
+ fireEvent.change(screen.queryByRole('combobox', { name: /reason for editing/i }), { target: { value: null } });
+ });
+ await act(async () => {
+ fireEvent.change(screen.queryByRole('combobox', { name: /reason for editing/i }), { target: { value: 'reason-1' } });
+ });
+ await act(async () => {
+ fireEvent.change(screen.getByTestId('tinymce-editor'), { target: { value: 'testing123' } });
+ });
+ await act(async () => {
+ fireEvent.click(screen.getByRole('button', { name: /submit/i }));
+ });
+ assertLastUpdateData({ edit_reason_code: 'reason-1' });
+ });
+
+ it('should show reason codes when closing a post', async () => {
+ setupCourseConfig();
+ renderComponent(discussionPostId);
+ await act(async () => {
+ fireEvent.click(
+ // The first edit menu is for the post
+ screen.getAllByRole('button', {
+ name: /actions menu/i,
+ })[0],
+ );
+ });
+ expect(screen.queryByRole('dialog', { name: /close post/i })).not.toBeInTheDocument();
+ await act(async () => {
+ fireEvent.click(screen.getByRole('button', { name: /close/i }));
+ });
+ expect(screen.queryByRole('dialog', { name: /close post/i })).toBeInTheDocument();
+ expect(screen.queryByRole('combobox', { name: /reason/i })).toBeInTheDocument();
+ expect(screen.getAllByRole('option', { name: /reason \d/i })).toHaveLength(2);
+ await act(async () => {
+ fireEvent.change(screen.queryByRole('combobox', { name: /reason/i }), { target: { value: 'reason-1' } });
+ });
+ await act(async () => {
+ fireEvent.click(screen.getByRole('button', { name: /close post/i }));
+ });
+ expect(screen.queryByRole('dialog', { name: /close post/i })).not.toBeInTheDocument();
+ assertLastUpdateData({ closed: true, close_reason_code: 'reason-1' });
+ });
+
+ it('should close the post directly if reason codes are not enabled', async () => {
+ setupCourseConfig(false);
+ renderComponent(discussionPostId);
+ await act(async () => {
+ fireEvent.click(
+ // The first edit menu is for the post
+ screen.getAllByRole('button', { name: /actions menu/i })[0],
+ );
+ });
+ expect(screen.queryByRole('dialog', { name: /close post/i })).not.toBeInTheDocument();
+ await act(async () => {
+ fireEvent.click(screen.getByRole('button', { name: /close/i }));
+ });
+ expect(screen.queryByRole('dialog', { name: /close post/i })).not.toBeInTheDocument();
+ assertLastUpdateData({ closed: true });
+ });
it.each([true, false])(
'should reopen the post directly when reason codes enabled=%s',
@@ -369,20 +370,20 @@ describe('CommentsView', () => {
},
);
- // it('should show the editor if the post is edited', async () => {
- // setupCourseConfig(false);
- // renderComponent(discussionPostId);
- // await act(async () => {
- // fireEvent.click(
- // // The first edit menu is for the post
- // screen.getAllByRole('button', { name: /actions menu/i })[0],
- // );
- // });
- // await act(async () => {
- // fireEvent.click(screen.getByRole('button', { name: /edit/i }));
- // });
- // expect(testLocation.pathname).toBe(`/${courseId}/posts/${discussionPostId}/edit`);
- // });
+ it('should show the editor if the post is edited', async () => {
+ setupCourseConfig(false);
+ renderComponent(discussionPostId);
+ await act(async () => {
+ fireEvent.click(
+ // The first edit menu is for the post
+ screen.getAllByRole('button', { name: /actions menu/i })[0],
+ );
+ });
+ await act(async () => {
+ fireEvent.click(screen.getByRole('button', { name: /edit/i }));
+ });
+ expect(testLocation.pathname).toBe(`/${courseId}/posts/${discussionPostId}/edit`);
+ });
it('should allow pinning the post', async () => {
renderComponent(discussionPostId);
@@ -417,314 +418,314 @@ describe('CommentsView', () => {
assertLastUpdateData({ abuse_flagged: true });
});
- // it('handles liking a comment', async () => {
- // renderComponent(discussionPostId);
- //
- // // Wait for the content to load
- // await screen.findByText('comment number 7', { exact: false });
- // const view = screen.getByTestId('comment-comment-1');
- //
- // const likeButton = within(view).getByRole('button', { name: /like/i });
- // await act(async () => {
- // fireEvent.click(likeButton);
- // });
- // expect(axiosMock.history.patch).toHaveLength(2);
- // expect(JSON.parse(axiosMock.history.patch[1].data)).toMatchObject({ voted: true });
- // });
- //
- // it('handles endorsing comments', async () => {
- // renderComponent(discussionPostId);
- // // Wait for the content to load
- // await screen.findByText('comment number 7', { exact: false });
- //
- // // There should be three buttons, one for the post, the second for the
- // // comment and the third for a response to that comment
- // const actionButtons = screen.queryAllByRole('button', { name: /actions menu/i });
- // await act(async () => {
- // fireEvent.click(actionButtons[1]);
- // });
- //
- // await act(async () => {
- // fireEvent.click(screen.getByRole('button', { name: /Endorse/i }));
- // });
- // expect(axiosMock.history.patch).toHaveLength(2);
- // expect(JSON.parse(axiosMock.history.patch[1].data)).toMatchObject({ endorsed: true });
- // });
- //
- // it('handles reporting comments', async () => {
- // renderComponent(discussionPostId);
- // // Wait for the content to load
- // await screen.findByText('comment number 7', { exact: false });
- //
- // // There should be three buttons, one for the post, the second for the
- // // comment and the third for a response to that comment
- // const actionButtons = screen.queryAllByRole('button', { name: /actions menu/i });
- // await act(async () => {
- // fireEvent.click(actionButtons[1]);
- // });
- //
- // await act(async () => {
- // fireEvent.click(screen.getByRole('button', { name: /Report/i }));
- // });
- // expect(screen.queryByRole('dialog', { name: /Report \w+/i, exact: false })).toBeInTheDocument();
- // await act(async () => {
- // fireEvent.click(screen.queryByRole('button', { name: /Confirm/i }));
- // });
- // expect(screen.queryByRole('dialog', { name: /Report \w+/i, exact: false })).not.toBeInTheDocument();
- // expect(axiosMock.history.patch).toHaveLength(2);
- // expect(JSON.parse(axiosMock.history.patch[1].data)).toMatchObject({ abuse_flagged: true });
- // });
- // });
- //
- // describe('for discussion thread', () => {
- // const findLoadMoreCommentsButton = () => screen.findByTestId('load-more-comments');
- //
- // it('shown post not found when post id does not belong to course', async () => {
- // renderComponent('unloaded-id');
- // expect(await screen.findByText('Thread not found', { exact: true }))
- // .toBeInTheDocument();
- // });
- //
- // it('initially loads only the first page', async () => {
- // renderComponent(discussionPostId);
- // expect(await screen.findByText('comment number 1', { exact: false }))
- // .toBeInTheDocument();
- // expect(screen.queryByText('comment number 2', { exact: false }))
- // .not
- // .toBeInTheDocument();
- // });
- //
- // it('pressing load more button will load next page of comments', async () => {
- // renderComponent(discussionPostId);
- //
- // const loadMoreButton = await findLoadMoreCommentsButton();
- // fireEvent.click(loadMoreButton);
- //
- // await screen.findByText('comment number 1', { exact: false });
- // await screen.findByText('comment number 2', { exact: false });
- // });
- //
- // it('newly loaded comments are appended to the old ones', async () => {
- // renderComponent(discussionPostId);
- //
- // const loadMoreButton = await findLoadMoreCommentsButton();
- // fireEvent.click(loadMoreButton);
- //
- // await screen.findByText('comment number 1', { exact: false });
- // // check that comments from the first page are also displayed
- // expect(screen.queryByText('comment number 2', { exact: false }))
- // .toBeInTheDocument();
- // });
- //
- // it('load more button is hidden when no more comments pages to load', async () => {
- // const totalPages = 2;
- // renderComponent(discussionPostId);
- //
- // const loadMoreButton = await findLoadMoreCommentsButton();
- // for (let page = 1; page < totalPages; page++) {
- // fireEvent.click(loadMoreButton);
- // }
- //
- // await screen.findByText('comment number 2', { exact: false });
- // await expect(findLoadMoreCommentsButton())
- // .rejects
- // .toThrow();
- // });
- // });
- //
- // describe('for question thread', () => {
- // const findLoadMoreCommentsButtons = () => screen.findAllByTestId('load-more-comments');
- //
- // it('initially loads only the first page', async () => {
- // act(() => renderComponent(questionPostId));
- // expect(await screen.findByText('comment number 3', { exact: false }))
- // .toBeInTheDocument();
- // expect(await screen.findByText('endorsed comment number 5', { exact: false }))
- // .toBeInTheDocument();
- // expect(screen.queryByText('comment number 4', { exact: false }))
- // .not
- // .toBeInTheDocument();
- // });
- //
- // it('pressing load more button will load next page of comments', async () => {
- // act(() => {
- // renderComponent(questionPostId);
- // });
- //
- // const [loadMoreButtonEndorsed, loadMoreButtonUnendorsed] = await findLoadMoreCommentsButtons();
- // // Both load more buttons should show
- // expect(await findLoadMoreCommentsButtons()).toHaveLength(2);
- // expect(await screen.findByText('unendorsed comment number 3', { exact: false }))
- // .toBeInTheDocument();
- // expect(await screen.findByText('endorsed comment number 5', { exact: false }))
- // .toBeInTheDocument();
- // // Comments from next page should not be loaded yet.
- // expect(await screen.queryByText('endorsed comment number 6', { exact: false }))
- // .not
- // .toBeInTheDocument();
- // expect(await screen.queryByText('unendorsed comment number 4', { exact: false }))
- // .not
- // .toBeInTheDocument();
- //
- // await act(async () => {
- // fireEvent.click(loadMoreButtonEndorsed);
- // });
- // // Endorsed comment from next page should be loaded now.
- // await waitFor(() => expect(screen.queryByText('endorsed comment number 6', { exact: false }))
- // .toBeInTheDocument());
- // // Unendorsed comment from next page should not be loaded yet.
- // expect(await screen.queryByText('unendorsed comment number 4', { exact: false }))
- // .not
- // .toBeInTheDocument();
- // // Now only one load more buttons should show, for unendorsed comments
- // expect(await findLoadMoreCommentsButtons()).toHaveLength(1);
- // await act(async () => {
- // fireEvent.click(loadMoreButtonUnendorsed);
- // });
- // // Unendorsed comment from next page should be loaded now.
- // await waitFor(() => expect(screen.queryByText('unendorsed comment number 4', { exact: false }))
- // .toBeInTheDocument());
- // await expect(findLoadMoreCommentsButtons()).rejects.toThrow();
- // });
- // });
- //
- // describe('comments responses', () => {
- // const findLoadMoreCommentsResponsesButton = () => screen.findByTestId('load-more-comments-responses');
- //
- // it('initially loads only the first page', async () => {
- // renderComponent(discussionPostId);
- //
- // await waitFor(() => screen.findByText('comment number 7', { exact: false }));
- // expect(screen.queryByText('comment number 8', { exact: false })).not.toBeInTheDocument();
- // });
- //
- // it('pressing load more button will load next page of responses', async () => {
- // renderComponent(discussionPostId);
- //
- // const loadMoreButton = await findLoadMoreCommentsResponsesButton();
- // await act(async () => {
- // fireEvent.click(loadMoreButton);
- // });
- //
- // await screen.findByText('comment number 8', { exact: false });
- // });
- //
- // it('newly loaded responses are appended to the old ones', async () => {
- // renderComponent(discussionPostId);
- //
- // const loadMoreButton = await findLoadMoreCommentsResponsesButton();
- // await act(async () => {
- // fireEvent.click(loadMoreButton);
- // });
- //
- // await screen.findByText('comment number 8', { exact: false });
- // // check that comments from the first page are also displayed
- // expect(screen.queryByText('comment number 7', { exact: false })).toBeInTheDocument();
- // });
- //
- // it('load more button is hidden when no more responses pages to load', async () => {
- // const totalPages = 2;
- // renderComponent(discussionPostId);
- //
- // const loadMoreButton = await findLoadMoreCommentsResponsesButton();
- // for (let page = 1; page < totalPages; page++) {
- // act(() => {
- // fireEvent.click(loadMoreButton);
- // });
- // }
- //
- // await screen.findByText('comment number 8', { exact: false });
- // await expect(findLoadMoreCommentsResponsesButton())
- // .rejects
- // .toThrow();
- // });
- //
- // it('handles liking a comment', async () => {
- // renderComponent(discussionPostId);
- //
- // // Wait for the content to load
- // await screen.findByText('comment number 7', { exact: false });
- // const view = screen.getByTestId('comment-comment-1');
- //
- // const likeButton = within(view).getByRole('button', { name: /like/i });
- // await act(async () => {
- // fireEvent.click(likeButton);
- // });
- // expect(axiosMock.history.patch).toHaveLength(2);
- // expect(JSON.parse(axiosMock.history.patch[1].data)).toMatchObject({ voted: true });
- // });
- //
- // it('handles endorsing comments', async () => {
- // renderComponent(discussionPostId);
- // // Wait for the content to load
- // await screen.findByText('comment number 7', { exact: false });
- //
- // // There should be three buttons, one for the post, the second for the
- // // comment and the third for a response to that comment
- // const actionButtons = screen.queryAllByRole('button', { name: /actions menu/i });
- // await act(async () => {
- // fireEvent.click(actionButtons[1]);
- // });
- //
- // await act(async () => {
- // fireEvent.click(screen.getByRole('button', { name: /Endorse/i }));
- // });
- // expect(axiosMock.history.patch).toHaveLength(2);
- // expect(JSON.parse(axiosMock.history.patch[1].data)).toMatchObject({ endorsed: true });
- // });
- //
- // it('handles reporting comments', async () => {
- // renderComponent(discussionPostId);
- // // Wait for the content to load
- // await screen.findByText('comment number 7', { exact: false });
- //
- // // There should be three buttons, one for the post, the second for the
- // // comment and the third for a response to that comment
- // const actionButtons = screen.queryAllByRole('button', { name: /actions menu/i });
- // await act(async () => {
- // fireEvent.click(actionButtons[1]);
- // });
- //
- // await act(async () => {
- // fireEvent.click(screen.getByRole('button', { name: /Report/i }));
- // });
- // expect(screen.queryByRole('dialog', { name: /Report \w+/i, exact: false })).toBeInTheDocument();
- // await act(async () => {
- // fireEvent.click(screen.queryByRole('button', { name: /Confirm/i }));
- // });
- // expect(screen.queryByRole('dialog', { name: /Report \w+/i, exact: false })).not.toBeInTheDocument();
- // expect(axiosMock.history.patch).toHaveLength(2);
- // expect(JSON.parse(axiosMock.history.patch[1].data)).toMatchObject({ abuse_flagged: true });
- // });
- // });
- //
- // describe.each([
- // { component: 'post', testId: 'post-thread-1' },
- // { component: 'comment', testId: 'comment-comment-1' },
- // { component: 'reply', testId: 'reply-comment-7' },
- // ])('delete confirmation modal', ({
- // component,
- // testId,
- // }) => {
- // test(`for ${component}`, async () => {
- // renderComponent(discussionPostId);
- // // Wait for the content to load
- // await waitFor(() => expect(screen.queryByText('comment number 7', { exact: false })).toBeInTheDocument());
- // const content = screen.getByTestId(testId);
- // const actionsButton = within(content).getAllByRole('button', { name: /actions menu/i })[0];
- // await act(async () => {
- // fireEvent.click(actionsButton);
- // });
- // expect(screen.queryByRole('dialog', { name: /delete \w+/i, exact: false })).not.toBeInTheDocument();
- // const deleteButton = within(content).queryByRole('button', { name: /delete/i });
- // await act(async () => {
- // fireEvent.click(deleteButton);
- // });
- // expect(screen.queryByRole('dialog', { name: /delete \w+/i, exact: false })).toBeInTheDocument();
- // await act(async () => {
- // fireEvent.click(screen.queryByRole('button', { name: /delete/i }));
- // });
- // expect(screen.queryByRole('dialog', { name: /delete \w+/i, exact: false })).not.toBeInTheDocument();
- // });
+ it('handles liking a comment', async () => {
+ renderComponent(discussionPostId);
+
+ // Wait for the content to load
+ await screen.findByText('comment number 7', { exact: false });
+ const view = screen.getByTestId('comment-comment-1');
+
+ const likeButton = within(view).getByRole('button', { name: /like/i });
+ await act(async () => {
+ fireEvent.click(likeButton);
+ });
+ expect(axiosMock.history.patch).toHaveLength(2);
+ expect(JSON.parse(axiosMock.history.patch[1].data)).toMatchObject({ voted: true });
+ });
+
+ it('handles endorsing comments', async () => {
+ renderComponent(discussionPostId);
+ // Wait for the content to load
+ await screen.findByText('comment number 7', { exact: false });
+
+ // There should be three buttons, one for the post, the second for the
+ // comment and the third for a response to that comment
+ const actionButtons = screen.queryAllByRole('button', { name: /actions menu/i });
+ await act(async () => {
+ fireEvent.click(actionButtons[1]);
+ });
+
+ await act(async () => {
+ fireEvent.click(screen.getByRole('button', { name: /Endorse/i }));
+ });
+ expect(axiosMock.history.patch).toHaveLength(2);
+ expect(JSON.parse(axiosMock.history.patch[1].data)).toMatchObject({ endorsed: true });
+ });
+
+ it('handles reporting comments', async () => {
+ renderComponent(discussionPostId);
+ // Wait for the content to load
+ await screen.findByText('comment number 7', { exact: false });
+
+ // There should be three buttons, one for the post, the second for the
+ // comment and the third for a response to that comment
+ const actionButtons = screen.queryAllByRole('button', { name: /actions menu/i });
+ await act(async () => {
+ fireEvent.click(actionButtons[1]);
+ });
+
+ await act(async () => {
+ fireEvent.click(screen.getByRole('button', { name: /Report/i }));
+ });
+ expect(screen.queryByRole('dialog', { name: /Report \w+/i, exact: false })).toBeInTheDocument();
+ await act(async () => {
+ fireEvent.click(screen.queryByRole('button', { name: /Confirm/i }));
+ });
+ expect(screen.queryByRole('dialog', { name: /Report \w+/i, exact: false })).not.toBeInTheDocument();
+ expect(axiosMock.history.patch).toHaveLength(2);
+ expect(JSON.parse(axiosMock.history.patch[1].data)).toMatchObject({ abuse_flagged: true });
+ });
+ });
+
+ describe('for discussion thread', () => {
+ const findLoadMoreCommentsButton = () => screen.findByTestId('load-more-comments');
+
+ it('shown post not found when post id does not belong to course', async () => {
+ renderComponent('unloaded-id');
+ expect(await screen.findByText('Thread not found', { exact: true }))
+ .toBeInTheDocument();
+ });
+
+ it('initially loads only the first page', async () => {
+ renderComponent(discussionPostId);
+ expect(await screen.findByText('comment number 1', { exact: false }))
+ .toBeInTheDocument();
+ expect(screen.queryByText('comment number 2', { exact: false }))
+ .not
+ .toBeInTheDocument();
+ });
+
+ it('pressing load more button will load next page of comments', async () => {
+ renderComponent(discussionPostId);
+
+ const loadMoreButton = await findLoadMoreCommentsButton();
+ fireEvent.click(loadMoreButton);
+
+ await screen.findByText('comment number 1', { exact: false });
+ await screen.findByText('comment number 2', { exact: false });
+ });
+
+ it('newly loaded comments are appended to the old ones', async () => {
+ renderComponent(discussionPostId);
+
+ const loadMoreButton = await findLoadMoreCommentsButton();
+ fireEvent.click(loadMoreButton);
+
+ await screen.findByText('comment number 1', { exact: false });
+ // check that comments from the first page are also displayed
+ expect(screen.queryByText('comment number 2', { exact: false }))
+ .toBeInTheDocument();
+ });
+
+ it('load more button is hidden when no more comments pages to load', async () => {
+ const totalPages = 2;
+ renderComponent(discussionPostId);
+
+ const loadMoreButton = await findLoadMoreCommentsButton();
+ for (let page = 1; page < totalPages; page++) {
+ fireEvent.click(loadMoreButton);
+ }
+
+ await screen.findByText('comment number 2', { exact: false });
+ await expect(findLoadMoreCommentsButton())
+ .rejects
+ .toThrow();
+ });
+ });
+
+ describe('for question thread', () => {
+ const findLoadMoreCommentsButtons = () => screen.findAllByTestId('load-more-comments');
+
+ it('initially loads only the first page', async () => {
+ act(() => renderComponent(questionPostId));
+ expect(await screen.findByText('comment number 3', { exact: false }))
+ .toBeInTheDocument();
+ expect(await screen.findByText('endorsed comment number 5', { exact: false }))
+ .toBeInTheDocument();
+ expect(screen.queryByText('comment number 4', { exact: false }))
+ .not
+ .toBeInTheDocument();
+ });
+
+ it('pressing load more button will load next page of comments', async () => {
+ act(() => {
+ renderComponent(questionPostId);
+ });
+
+ const [loadMoreButtonEndorsed, loadMoreButtonUnendorsed] = await findLoadMoreCommentsButtons();
+ // Both load more buttons should show
+ expect(await findLoadMoreCommentsButtons()).toHaveLength(2);
+ expect(await screen.findByText('unendorsed comment number 3', { exact: false }))
+ .toBeInTheDocument();
+ expect(await screen.findByText('endorsed comment number 5', { exact: false }))
+ .toBeInTheDocument();
+ // Comments from next page should not be loaded yet.
+ expect(await screen.queryByText('endorsed comment number 6', { exact: false }))
+ .not
+ .toBeInTheDocument();
+ expect(await screen.queryByText('unendorsed comment number 4', { exact: false }))
+ .not
+ .toBeInTheDocument();
+
+ await act(async () => {
+ fireEvent.click(loadMoreButtonEndorsed);
+ });
+ // Endorsed comment from next page should be loaded now.
+ await waitFor(() => expect(screen.queryByText('endorsed comment number 6', { exact: false }))
+ .toBeInTheDocument());
+ // Unendorsed comment from next page should not be loaded yet.
+ expect(await screen.queryByText('unendorsed comment number 4', { exact: false }))
+ .not
+ .toBeInTheDocument();
+ // Now only one load more buttons should show, for unendorsed comments
+ expect(await findLoadMoreCommentsButtons()).toHaveLength(1);
+ await act(async () => {
+ fireEvent.click(loadMoreButtonUnendorsed);
+ });
+ // Unendorsed comment from next page should be loaded now.
+ await waitFor(() => expect(screen.queryByText('unendorsed comment number 4', { exact: false }))
+ .toBeInTheDocument());
+ await expect(findLoadMoreCommentsButtons()).rejects.toThrow();
+ });
+ });
+
+ describe('comments responses', () => {
+ const findLoadMoreCommentsResponsesButton = () => screen.findByTestId('load-more-comments-responses');
+
+ it('initially loads only the first page', async () => {
+ renderComponent(discussionPostId);
+
+ await waitFor(() => screen.findByText('comment number 7', { exact: false }));
+ expect(screen.queryByText('comment number 8', { exact: false })).not.toBeInTheDocument();
+ });
+
+ it('pressing load more button will load next page of responses', async () => {
+ renderComponent(discussionPostId);
+
+ const loadMoreButton = await findLoadMoreCommentsResponsesButton();
+ await act(async () => {
+ fireEvent.click(loadMoreButton);
+ });
+
+ await screen.findByText('comment number 8', { exact: false });
+ });
+
+ it('newly loaded responses are appended to the old ones', async () => {
+ renderComponent(discussionPostId);
+
+ const loadMoreButton = await findLoadMoreCommentsResponsesButton();
+ await act(async () => {
+ fireEvent.click(loadMoreButton);
+ });
+
+ await screen.findByText('comment number 8', { exact: false });
+ // check that comments from the first page are also displayed
+ expect(screen.queryByText('comment number 7', { exact: false })).toBeInTheDocument();
+ });
+
+ it('load more button is hidden when no more responses pages to load', async () => {
+ const totalPages = 2;
+ renderComponent(discussionPostId);
+
+ const loadMoreButton = await findLoadMoreCommentsResponsesButton();
+ for (let page = 1; page < totalPages; page++) {
+ act(() => {
+ fireEvent.click(loadMoreButton);
+ });
+ }
+
+ await screen.findByText('comment number 8', { exact: false });
+ await expect(findLoadMoreCommentsResponsesButton())
+ .rejects
+ .toThrow();
+ });
+
+ it('handles liking a comment', async () => {
+ renderComponent(discussionPostId);
+
+ // Wait for the content to load
+ await screen.findByText('comment number 7', { exact: false });
+ const view = screen.getByTestId('comment-comment-1');
+
+ const likeButton = within(view).getByRole('button', { name: /like/i });
+ await act(async () => {
+ fireEvent.click(likeButton);
+ });
+ expect(axiosMock.history.patch).toHaveLength(2);
+ expect(JSON.parse(axiosMock.history.patch[1].data)).toMatchObject({ voted: true });
+ });
+
+ it('handles endorsing comments', async () => {
+ renderComponent(discussionPostId);
+ // Wait for the content to load
+ await screen.findByText('comment number 7', { exact: false });
+
+ // There should be three buttons, one for the post, the second for the
+ // comment and the third for a response to that comment
+ const actionButtons = screen.queryAllByRole('button', { name: /actions menu/i });
+ await act(async () => {
+ fireEvent.click(actionButtons[1]);
+ });
+
+ await act(async () => {
+ fireEvent.click(screen.getByRole('button', { name: /Endorse/i }));
+ });
+ expect(axiosMock.history.patch).toHaveLength(2);
+ expect(JSON.parse(axiosMock.history.patch[1].data)).toMatchObject({ endorsed: true });
+ });
+
+ it('handles reporting comments', async () => {
+ renderComponent(discussionPostId);
+ // Wait for the content to load
+ await screen.findByText('comment number 7', { exact: false });
+
+ // There should be three buttons, one for the post, the second for the
+ // comment and the third for a response to that comment
+ const actionButtons = screen.queryAllByRole('button', { name: /actions menu/i });
+ await act(async () => {
+ fireEvent.click(actionButtons[1]);
+ });
+
+ await act(async () => {
+ fireEvent.click(screen.getByRole('button', { name: /Report/i }));
+ });
+ expect(screen.queryByRole('dialog', { name: /Report \w+/i, exact: false })).toBeInTheDocument();
+ await act(async () => {
+ fireEvent.click(screen.queryByRole('button', { name: /Confirm/i }));
+ });
+ expect(screen.queryByRole('dialog', { name: /Report \w+/i, exact: false })).not.toBeInTheDocument();
+ expect(axiosMock.history.patch).toHaveLength(2);
+ expect(JSON.parse(axiosMock.history.patch[1].data)).toMatchObject({ abuse_flagged: true });
+ });
+ });
+
+ describe.each([
+ { component: 'post', testId: 'post-thread-1' },
+ { component: 'comment', testId: 'comment-comment-1' },
+ { component: 'reply', testId: 'reply-comment-7' },
+ ])('delete confirmation modal', ({
+ component,
+ testId,
+ }) => {
+ test(`for ${component}`, async () => {
+ renderComponent(discussionPostId);
+ // Wait for the content to load
+ await waitFor(() => expect(screen.queryByText('comment number 7', { exact: false })).toBeInTheDocument());
+ const content = screen.getByTestId(testId);
+ const actionsButton = within(content).getAllByRole('button', { name: /actions menu/i })[0];
+ await act(async () => {
+ fireEvent.click(actionsButton);
+ });
+ expect(screen.queryByRole('dialog', { name: /delete \w+/i, exact: false })).not.toBeInTheDocument();
+ const deleteButton = within(content).queryByRole('button', { name: /delete/i });
+ await act(async () => {
+ fireEvent.click(deleteButton);
+ });
+ expect(screen.queryByRole('dialog', { name: /delete \w+/i, exact: false })).toBeInTheDocument();
+ await act(async () => {
+ fireEvent.click(screen.queryByRole('button', { name: /delete/i }));
+ });
+ expect(screen.queryByRole('dialog', { name: /delete \w+/i, exact: false })).not.toBeInTheDocument();
+ });
});
});