test: added test cases for hover card component
This commit is contained in:
@@ -230,18 +230,14 @@ describe('CommentsView', () => {
|
||||
});
|
||||
|
||||
it('should not allow posting a comment on a closed post', async () => {
|
||||
const componet = renderComponent(closedPostId);
|
||||
renderComponent(closedPostId);
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.mouseOver(await waitFor(() => screen.findByText('comment number 5', { exact: false })));
|
||||
fireEvent.mouseOver(await waitFor(() => screen.findByText('comment number 3', { exact: false })));
|
||||
});
|
||||
// await waitFor(() => screen.findByText('thread-2', { exact: false }));
|
||||
screen.debug(componet, 99999999);
|
||||
expect(screen.queryByRole('button', { name: /add comment/i }, { hidden: false })).toBeDisabled();
|
||||
// await act(async () => {
|
||||
// expect(
|
||||
// screen.queryByRole('button', { name: /add comment/i }, { hidden: false })
|
||||
// ).toBeDisabled();
|
||||
// });
|
||||
|
||||
const addCommentButton = screen.getAllByRole('button', { name: /add comment/i }, { hidden: false })[0];
|
||||
expect(addCommentButton).toBeDisabled();
|
||||
});
|
||||
|
||||
it('should allow editing an existing comment', async () => {
|
||||
@@ -322,7 +318,7 @@ describe('CommentsView', () => {
|
||||
setupCourseConfig();
|
||||
renderComponent(discussionPostId);
|
||||
await act(async () => {
|
||||
fireEvent.mouseOver(await waitFor(() => screen.findByText('Thread-1', { exact: false })));
|
||||
fireEvent.mouseOver(await waitFor(() => screen.findByTestId('post-thread-1')));
|
||||
});
|
||||
await act(async () => {
|
||||
fireEvent.click(
|
||||
@@ -353,7 +349,7 @@ describe('CommentsView', () => {
|
||||
setupCourseConfig(false);
|
||||
renderComponent(discussionPostId);
|
||||
await act(async () => {
|
||||
fireEvent.mouseOver(await waitFor(() => screen.findByText('Thread-1', { exact: false })));
|
||||
fireEvent.mouseOver(await waitFor(() => screen.findByTestId('post-thread-1')));
|
||||
});
|
||||
await act(async () => {
|
||||
fireEvent.click(
|
||||
@@ -396,7 +392,7 @@ describe('CommentsView', () => {
|
||||
setupCourseConfig(false);
|
||||
renderComponent(discussionPostId);
|
||||
await act(async () => {
|
||||
fireEvent.mouseOver(await waitFor(() => screen.findByText('Thread-1', { exact: false })));
|
||||
fireEvent.mouseOver(await waitFor(() => screen.findByTestId('post-thread-1')));
|
||||
});
|
||||
await act(async () => {
|
||||
fireEvent.click(
|
||||
@@ -413,7 +409,7 @@ describe('CommentsView', () => {
|
||||
it('should allow pinning the post', async () => {
|
||||
renderComponent(discussionPostId);
|
||||
await act(async () => {
|
||||
fireEvent.mouseOver(await waitFor(() => screen.findByText('Thread-1', { exact: false })));
|
||||
fireEvent.mouseOver(await waitFor(() => screen.findByTestId('post-thread-1')));
|
||||
});
|
||||
await act(async () => {
|
||||
fireEvent.click(
|
||||
@@ -430,7 +426,7 @@ describe('CommentsView', () => {
|
||||
it('should allow reporting the post', async () => {
|
||||
renderComponent(discussionPostId);
|
||||
await act(async () => {
|
||||
fireEvent.mouseOver(await waitFor(() => screen.findByText('Thread-1', { exact: false })));
|
||||
fireEvent.mouseOver(await waitFor(() => screen.findByTestId('post-thread-1')));
|
||||
});
|
||||
await act(async () => {
|
||||
fireEvent.click(
|
||||
@@ -504,264 +500,257 @@ describe('CommentsView', () => {
|
||||
});
|
||||
});
|
||||
|
||||
// describe('for discussion thread', () => {
|
||||
// const findLoadMoreCommentsButton = () => screen.findByTestId('load-more-comments');
|
||||
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('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('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);
|
||||
it('pressing load more button will load next page of comments', async () => {
|
||||
renderComponent(discussionPostId);
|
||||
|
||||
// const loadMoreButton = await findLoadMoreCommentsButton();
|
||||
// fireEvent.click(loadMoreButton);
|
||||
const loadMoreButton = await findLoadMoreCommentsButton();
|
||||
fireEvent.click(loadMoreButton);
|
||||
|
||||
// await screen.findByText('comment number 1', { exact: false });
|
||||
// await screen.findByText('comment number 2', { exact: false });
|
||||
// });
|
||||
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);
|
||||
it('newly loaded comments are appended to the old ones', async () => {
|
||||
renderComponent(discussionPostId);
|
||||
|
||||
// const loadMoreButton = await findLoadMoreCommentsButton();
|
||||
// fireEvent.click(loadMoreButton);
|
||||
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();
|
||||
// });
|
||||
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);
|
||||
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);
|
||||
// }
|
||||
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();
|
||||
// });
|
||||
// });
|
||||
await screen.findByText('comment number 2', { exact: false });
|
||||
await expect(findLoadMoreCommentsButton())
|
||||
.rejects
|
||||
.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
// describe('for question thread', () => {
|
||||
// const findLoadMoreCommentsButtons = () => screen.findAllByTestId('load-more-comments');
|
||||
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('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);
|
||||
// });
|
||||
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();
|
||||
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();
|
||||
// });
|
||||
// });
|
||||
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');
|
||||
describe('comments responses', () => {
|
||||
const findLoadMoreCommentsResponsesButton = () => screen.findByTestId('load-more-comments-responses');
|
||||
|
||||
// it('initially loads only the first page', async () => {
|
||||
// renderComponent(discussionPostId);
|
||||
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();
|
||||
// });
|
||||
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);
|
||||
it('pressing load more button will load next page of responses', async () => {
|
||||
renderComponent(discussionPostId);
|
||||
|
||||
// const loadMoreButton = await findLoadMoreCommentsResponsesButton();
|
||||
// await act(async () => {
|
||||
// fireEvent.click(loadMoreButton);
|
||||
// });
|
||||
const loadMoreButton = await findLoadMoreCommentsResponsesButton();
|
||||
await act(async () => {
|
||||
fireEvent.click(loadMoreButton);
|
||||
});
|
||||
|
||||
// await screen.findByText('comment number 8', { exact: false });
|
||||
// });
|
||||
await screen.findByText('comment number 8', { exact: false });
|
||||
});
|
||||
|
||||
// it('newly loaded responses are appended to the old ones', async () => {
|
||||
// renderComponent(discussionPostId);
|
||||
it('newly loaded responses are appended to the old ones', async () => {
|
||||
renderComponent(discussionPostId);
|
||||
|
||||
// const loadMoreButton = await findLoadMoreCommentsResponsesButton();
|
||||
// await act(async () => {
|
||||
// fireEvent.click(loadMoreButton);
|
||||
// });
|
||||
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();
|
||||
// });
|
||||
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);
|
||||
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);
|
||||
// });
|
||||
// }
|
||||
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();
|
||||
// });
|
||||
await screen.findByText('comment number 8', { exact: false });
|
||||
await expect(findLoadMoreCommentsResponsesButton())
|
||||
.rejects
|
||||
.toThrow();
|
||||
});
|
||||
|
||||
// it('handles liking a comment', async () => {
|
||||
// renderComponent(discussionPostId);
|
||||
it('handles liking a comment', async () => {
|
||||
renderComponent(discussionPostId);
|
||||
|
||||
// // Wait for the content to load
|
||||
// await act(async () => {
|
||||
// fireEvent.mouseOver(await waitFor(() => screen.findByText('comment number 7', { exact: false })));
|
||||
// });
|
||||
// const view = screen.getByTestId('comment-comment-1');
|
||||
// Wait for the content to load
|
||||
await act(async () => {
|
||||
fireEvent.mouseOver(await waitFor(() => 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 });
|
||||
// });
|
||||
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 act(async () => {
|
||||
// fireEvent.mouseOver(await waitFor(() => screen.findByText('comment number 7', { exact: false })));
|
||||
// });
|
||||
it('handles endorsing comments', async () => {
|
||||
renderComponent(discussionPostId);
|
||||
// Wait for the content to load
|
||||
await act(async () => {
|
||||
fireEvent.mouseOver(await waitFor(() => 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 });
|
||||
});
|
||||
|
||||
// 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 act(async () => {
|
||||
fireEvent.mouseOver(await waitFor(() => screen.findByText('comment number 7', { exact: false })));
|
||||
});
|
||||
|
||||
// it('handles reporting comments', async () => {
|
||||
// renderComponent(discussionPostId);
|
||||
// // Wait for the content to load
|
||||
// await act(async () => {
|
||||
// fireEvent.mouseOver(await waitFor(() => 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]);
|
||||
});
|
||||
|
||||
// // 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 });
|
||||
});
|
||||
});
|
||||
|
||||
// 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);
|
||||
// await act(async () => {
|
||||
// fireEvent.mouseOver(screen.getByTestId('post-thread-1'));
|
||||
// });
|
||||
// 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();
|
||||
// });
|
||||
// });
|
||||
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);
|
||||
await act(async () => {
|
||||
fireEvent.mouseOver(content);
|
||||
});
|
||||
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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -43,6 +43,7 @@ function Comment({
|
||||
const hasMorePages = useSelector(selectCommentHasMorePages(comment.id));
|
||||
const currentPage = useSelector(selectCommentCurrentPage(comment.id));
|
||||
const userCanAddThreadInBlackoutDate = useUserCanAddThreadInBlackoutDate();
|
||||
const [showHoverCard, setShowHoverCard] = useState(false);
|
||||
const {
|
||||
courseId,
|
||||
} = useContext(DiscussionContext);
|
||||
@@ -91,7 +92,13 @@ function Comment({
|
||||
);
|
||||
return (
|
||||
<div className={classNames({ 'mb-3': (showFullThread && !marginBottom) })}>
|
||||
<div className="d-flex flex-column card on-focus" data-testid={`comment-${comment.id}`} role="listitem">
|
||||
{/* eslint-disable jsx-a11y/no-noninteractive-tabindex */}
|
||||
<div
|
||||
tabIndex="0"
|
||||
className="d-flex flex-column card on-focus"
|
||||
data-testid={`comment-${comment.id}`}
|
||||
role="listitem"
|
||||
>
|
||||
<Confirmation
|
||||
isOpen={isDeleting}
|
||||
title={intl.formatMessage(messages.deleteResponseTitle)}
|
||||
@@ -115,16 +122,22 @@ function Comment({
|
||||
<div
|
||||
className="d-flex flex-column post-card-comment px-4 pt-3.5 pb-10px"
|
||||
aria-level={5}
|
||||
onMouseEnter={() => setShowHoverCard(true)}
|
||||
onMouseLeave={() => setShowHoverCard(false)}
|
||||
onFocus={() => setShowHoverCard(true)}
|
||||
onBlur={() => setShowHoverCard(false)}
|
||||
>
|
||||
<HoverCard
|
||||
commentOrPost={comment}
|
||||
actionHandlers={actionHandlers}
|
||||
handleResponseCommentButton={() => setReplying(true)}
|
||||
onLike={() => dispatch(editComment(comment.id, { voted: !comment.voted }))}
|
||||
addResponseCommentButtonMessage={intl.formatMessage(messages.addComment)}
|
||||
isClosedPost={isClosedPost}
|
||||
endorseIcons={endorseIcons}
|
||||
/>
|
||||
{showHoverCard && (
|
||||
<HoverCard
|
||||
commentOrPost={comment}
|
||||
actionHandlers={actionHandlers}
|
||||
handleResponseCommentButton={() => setReplying(true)}
|
||||
onLike={() => dispatch(editComment(comment.id, { voted: !comment.voted }))}
|
||||
addResponseCommentButtonMessage={intl.formatMessage(messages.addComment)}
|
||||
isClosedPost={isClosedPost}
|
||||
endorseIcons={endorseIcons}
|
||||
/>
|
||||
)}
|
||||
<AlertBanner content={comment} />
|
||||
<CommentHeader comment={comment} />
|
||||
{isEditing
|
||||
|
||||
@@ -33,7 +33,7 @@ function HoverCard({
|
||||
|
||||
return (
|
||||
<div
|
||||
className="flex-row flex-fill justify-content-end align-items-center hover-card mr-n4 position-absolute d-none"
|
||||
className="d-flex hover-card mr-n4 position-absolute"
|
||||
data-testid="hover-card"
|
||||
>
|
||||
{userCanAddThreadInBlackoutDate && (
|
||||
|
||||
@@ -1,157 +1,194 @@
|
||||
// import {
|
||||
// act, fireEvent, render, screen, waitFor, within,
|
||||
// } 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 {
|
||||
render, screen, waitFor, within,
|
||||
} from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import { IntlProvider } from 'react-intl';
|
||||
import { MemoryRouter, Route } from 'react-router';
|
||||
import { Factory } from 'rosie';
|
||||
|
||||
// import { camelCaseObject, initializeMockApp } from '@edx/frontend-platform';
|
||||
// import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
// import { AppProvider } from '@edx/frontend-platform/react';
|
||||
import { camelCaseObject, initializeMockApp } from '@edx/frontend-platform';
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
import { AppProvider } from '@edx/frontend-platform/react';
|
||||
|
||||
// import { initializeStore } from '../../store';
|
||||
// import { executeThunk } from '../../test-utils';
|
||||
// import { getCourseConfigApiUrl } from '../data/api';
|
||||
// import { fetchCourseConfig } from '../data/thunks';
|
||||
// import DiscussionContent from '../discussions-home/DiscussionContent';
|
||||
// import { getThreadsApiUrl } from '../posts/data/api';
|
||||
// import { fetchThreads } from '../posts/data/thunks';
|
||||
// import { getCommentsApiUrl } from './data/api';
|
||||
// import { DiscussionContext } from './context';
|
||||
import { initializeStore } from '../../store';
|
||||
import { executeThunk } from '../../test-utils';
|
||||
import { getCommentsApiUrl } from '../comments/data/api';
|
||||
import DiscussionContent from '../discussions-home/DiscussionContent';
|
||||
import { getThreadsApiUrl } from '../posts/data/api';
|
||||
import { fetchThreads } from '../posts/data/thunks';
|
||||
import { DiscussionContext } from './context';
|
||||
|
||||
// import '../posts/data/__factories__';
|
||||
// import './data/__factories__';
|
||||
import '../posts/data/__factories__';
|
||||
import '../comments/data/__factories__';
|
||||
|
||||
// const courseConfigApiUrl = getCourseConfigApiUrl();
|
||||
// const commentsApiUrl = getCommentsApiUrl();
|
||||
// const threadsApiUrl = getThreadsApiUrl();
|
||||
// const discussionPostId = 'thread-1';
|
||||
// const questionPostId = 'thread-2';
|
||||
// const closedPostId = 'thread-2';
|
||||
// const courseId = 'course-v1:edX+TestX+Test_Course';
|
||||
// let store;
|
||||
// let axiosMock;
|
||||
// let testLocation;
|
||||
const commentsApiUrl = getCommentsApiUrl();
|
||||
const threadsApiUrl = getThreadsApiUrl();
|
||||
const discussionPostId = 'thread-1';
|
||||
const questionPostId = 'thread-2';
|
||||
const courseId = 'course-v1:edX+TestX+Test_Course';
|
||||
let store;
|
||||
let axiosMock;
|
||||
let container;
|
||||
|
||||
// function mockAxiosReturnPagedComments() {
|
||||
// [null, false, true].forEach(endorsed => {
|
||||
// const postId = endorsed === null ? discussionPostId : questionPostId;
|
||||
// [1, 2].forEach(page => {
|
||||
// axiosMock
|
||||
// .onGet(commentsApiUrl, {
|
||||
// params: {
|
||||
// thread_id: postId,
|
||||
// page,
|
||||
// page_size: undefined,
|
||||
// requested_fields: 'profile_image',
|
||||
// endorsed,
|
||||
// },
|
||||
// })
|
||||
// .reply(200, Factory.build('commentsResult', { can_delete: true }, {
|
||||
// threadId: postId,
|
||||
// page,
|
||||
// pageSize: 1,
|
||||
// count: 2,
|
||||
// endorsed,
|
||||
// childCount: page === 1 ? 2 : 0,
|
||||
// }));
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
function mockAxiosReturnPagedComments() {
|
||||
[null, false, true].forEach(endorsed => {
|
||||
const postId = endorsed === null ? discussionPostId : questionPostId;
|
||||
[1, 2].forEach(page => {
|
||||
axiosMock
|
||||
.onGet(commentsApiUrl, {
|
||||
params: {
|
||||
thread_id: postId,
|
||||
page,
|
||||
page_size: undefined,
|
||||
requested_fields: 'profile_image',
|
||||
endorsed,
|
||||
},
|
||||
})
|
||||
.reply(200, Factory.build('commentsResult', { can_delete: true }, {
|
||||
threadId: postId,
|
||||
page,
|
||||
pageSize: 1,
|
||||
count: 2,
|
||||
endorsed,
|
||||
childCount: page === 1 ? 2 : 0,
|
||||
}));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// function mockAxiosReturnPagedCommentsResponses() {
|
||||
// const parentId = 'comment-1';
|
||||
// const commentsResponsesApiUrl = `${commentsApiUrl}${parentId}/`;
|
||||
// const paramsTemplate = {
|
||||
// page: undefined,
|
||||
// page_size: undefined,
|
||||
// requested_fields: 'profile_image',
|
||||
// };
|
||||
function mockAxiosReturnPagedCommentsResponses() {
|
||||
const parentId = 'comment-1';
|
||||
const commentsResponsesApiUrl = `${commentsApiUrl}${parentId}/`;
|
||||
const paramsTemplate = {
|
||||
page: undefined,
|
||||
page_size: undefined,
|
||||
requested_fields: 'profile_image',
|
||||
};
|
||||
|
||||
// for (let page = 1; page <= 2; page++) {
|
||||
// axiosMock
|
||||
// .onGet(commentsResponsesApiUrl, { params: { ...paramsTemplate, page } })
|
||||
// .reply(200, Factory.build('commentsResult', null, {
|
||||
// parentId,
|
||||
// page,
|
||||
// pageSize: 1,
|
||||
// count: 2,
|
||||
// }));
|
||||
// }
|
||||
// }
|
||||
for (let page = 1; page <= 2; page++) {
|
||||
axiosMock
|
||||
.onGet(commentsResponsesApiUrl, { params: { ...paramsTemplate, page } })
|
||||
.reply(200, Factory.build('commentsResult', null, {
|
||||
parentId,
|
||||
page,
|
||||
pageSize: 1,
|
||||
count: 2,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// function renderComponent(postId) {
|
||||
// render(
|
||||
// <IntlProvider locale="en">
|
||||
// <AppProvider store={store}>
|
||||
// <DiscussionContext.Provider
|
||||
// value={{ courseId }}
|
||||
// >
|
||||
// <MemoryRouter initialEntries={[`/${courseId}/posts/${postId}`]}>
|
||||
// <DiscussionContent />
|
||||
// <Route
|
||||
// path="*"
|
||||
// render={({ location }) => {
|
||||
// testLocation = location;
|
||||
// return null;
|
||||
// }}
|
||||
// />
|
||||
// </MemoryRouter>
|
||||
// </DiscussionContext.Provider>
|
||||
// </AppProvider>
|
||||
// </IntlProvider>,
|
||||
// );
|
||||
// }
|
||||
function renderComponent(postId) {
|
||||
const wrapper = render(
|
||||
<IntlProvider locale="en">
|
||||
<AppProvider store={store}>
|
||||
<DiscussionContext.Provider
|
||||
value={{ courseId }}
|
||||
>
|
||||
<MemoryRouter initialEntries={[`/${courseId}/posts/${postId}`]}>
|
||||
<DiscussionContent />
|
||||
<Route
|
||||
path="*"
|
||||
/>
|
||||
</MemoryRouter>
|
||||
</DiscussionContext.Provider>
|
||||
</AppProvider>
|
||||
</IntlProvider>,
|
||||
);
|
||||
container = wrapper.container;
|
||||
return container;
|
||||
}
|
||||
|
||||
// describe('HoverCard', () => {
|
||||
// beforeEach(() => {
|
||||
// initializeMockApp({
|
||||
// authenticatedUser: {
|
||||
// userId: 3,
|
||||
// username: 'abc123',
|
||||
// administrator: true,
|
||||
// roles: [],
|
||||
// },
|
||||
// });
|
||||
describe('HoverCard', () => {
|
||||
beforeEach(() => {
|
||||
initializeMockApp({
|
||||
authenticatedUser: {
|
||||
userId: 3,
|
||||
username: 'abc123',
|
||||
administrator: true,
|
||||
roles: [],
|
||||
},
|
||||
});
|
||||
|
||||
// store = initializeStore();
|
||||
// Factory.resetAll();
|
||||
// axiosMock = new MockAdapter(getAuthenticatedHttpClient());
|
||||
// axiosMock.onGet(threadsApiUrl)
|
||||
// .reply(200, Factory.build('threadsResult'));
|
||||
// axiosMock.onPatch(new RegExp(`${commentsApiUrl}*`)).reply(({
|
||||
// url,
|
||||
// data,
|
||||
// }) => {
|
||||
// const commentId = url.match(/comments\/(?<id>[a-z1-9-]+)\//).groups.id;
|
||||
// const {
|
||||
// rawBody,
|
||||
// } = camelCaseObject(JSON.parse(data));
|
||||
// return [200, Factory.build('comment', {
|
||||
// id: commentId,
|
||||
// rendered_body: rawBody,
|
||||
// raw_body: rawBody,
|
||||
// })];
|
||||
// });
|
||||
// axiosMock.onPost(commentsApiUrl)
|
||||
// .reply(({ data }) => {
|
||||
// const {
|
||||
// rawBody,
|
||||
// threadId,
|
||||
// } = camelCaseObject(JSON.parse(data));
|
||||
// return [200, Factory.build(
|
||||
// 'comment',
|
||||
// {
|
||||
// rendered_body: rawBody,
|
||||
// raw_body: rawBody,
|
||||
// thread_id: threadId,
|
||||
// },
|
||||
// )];
|
||||
// });
|
||||
store = initializeStore();
|
||||
Factory.resetAll();
|
||||
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
|
||||
axiosMock.onGet(threadsApiUrl)
|
||||
.reply(200, Factory.build('threadsResult'));
|
||||
axiosMock.onPatch(new RegExp(`${commentsApiUrl}*`)).reply(({
|
||||
url,
|
||||
data,
|
||||
}) => {
|
||||
const commentId = url.match(/comments\/(?<id>[a-z1-9-]+)\//).groups.id;
|
||||
const {
|
||||
rawBody,
|
||||
} = camelCaseObject(JSON.parse(data));
|
||||
return [200, Factory.build('comment', {
|
||||
id: commentId,
|
||||
rendered_body: rawBody,
|
||||
raw_body: rawBody,
|
||||
})];
|
||||
});
|
||||
axiosMock.onPost(commentsApiUrl)
|
||||
.reply(({ data }) => {
|
||||
const {
|
||||
rawBody,
|
||||
threadId,
|
||||
} = camelCaseObject(JSON.parse(data));
|
||||
return [200, Factory.build(
|
||||
'comment',
|
||||
{
|
||||
rendered_body: rawBody,
|
||||
raw_body: rawBody,
|
||||
thread_id: threadId,
|
||||
},
|
||||
)];
|
||||
});
|
||||
|
||||
// executeThunk(fetchThreads(courseId), store.dispatch, store.getState);
|
||||
// mockAxiosReturnPagedComments();
|
||||
// mockAxiosReturnPagedCommentsResponses();
|
||||
// });
|
||||
// });
|
||||
executeThunk(fetchThreads(courseId), store.dispatch, store.getState);
|
||||
mockAxiosReturnPagedComments();
|
||||
mockAxiosReturnPagedCommentsResponses();
|
||||
});
|
||||
|
||||
test('it should show hover card when hovered on post', async () => {
|
||||
renderComponent(discussionPostId);
|
||||
const post = screen.getByTestId('post-thread-1');
|
||||
userEvent.hover(post);
|
||||
expect(screen.getByTestId('hover-card')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('it should show hover card when hovered on comment', async () => {
|
||||
renderComponent(discussionPostId);
|
||||
const comment = await waitFor(() => screen.findByText('comment number 1', { exact: false }));
|
||||
userEvent.hover(comment);
|
||||
expect(screen.getByTestId('hover-card')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('it should not show hover card when post and comment not hovered', async () => {
|
||||
renderComponent(discussionPostId);
|
||||
expect(screen.queryByTestId('hover-card')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('it should show add response, like, follow and actions menu for hovered post', async () => {
|
||||
renderComponent(discussionPostId);
|
||||
const post = screen.getByTestId('post-thread-1');
|
||||
userEvent.hover(post);
|
||||
const view = screen.getByTestId('hover-card');
|
||||
expect(within(view).queryByRole('button', { name: /Add response/i })).toBeInTheDocument();
|
||||
expect(within(view).getByRole('button', { name: /like/i })).toBeInTheDocument();
|
||||
expect(within(view).queryByRole('button', { name: /follow/i })).toBeInTheDocument();
|
||||
expect(within(view).queryByRole('button', { name: /actions menu/i })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('it should show add comment, Endorse, like and actions menu Buttons for hovered comment', async () => {
|
||||
renderComponent(questionPostId);
|
||||
const comment = await waitFor(() => screen.findByText('unendorsed comment number 3', { exact: false }));
|
||||
userEvent.hover(comment);
|
||||
const view = screen.getByTestId('hover-card');
|
||||
expect(screen.getByTestId('hover-card')).toBeInTheDocument();
|
||||
expect(within(view).queryByRole('button', { name: /Add comment/i })).toBeInTheDocument();
|
||||
expect(within(view).getByRole('button', { name: /Endorse/i })).toBeInTheDocument();
|
||||
expect(within(view).queryByRole('button', { name: /like/i })).toBeInTheDocument();
|
||||
expect(within(view).queryByRole('button', { name: /actions menu/i })).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -39,7 +39,6 @@ function LikeButton({
|
||||
alt="Like"
|
||||
iconAs={Icon}
|
||||
iconClassNames="like-icon-dimentions"
|
||||
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
<div className="font-family-inter font-style-normal">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useContext } from 'react';
|
||||
import React, { useContext, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import classNames from 'classnames';
|
||||
@@ -41,7 +41,7 @@ function Post({
|
||||
const [isDeleting, showDeleteConfirmation, hideDeleteConfirmation] = useToggle(false);
|
||||
const [isReporting, showReportConfirmation, hideReportConfirmation] = useToggle(false);
|
||||
const [isClosing, showClosePostModal, hideClosePostModal] = useToggle(false);
|
||||
|
||||
const [showHoverCard, setShowHoverCard] = useState(false);
|
||||
const handleAbusedFlag = () => {
|
||||
if (post.abuseFlagged) {
|
||||
dispatch(updateExistingThread(post.id, { flagged: !post.abuseFlagged }));
|
||||
@@ -92,6 +92,11 @@ function Post({
|
||||
<div
|
||||
className="d-flex flex-column w-100 mw-100 post-card-comment"
|
||||
aria-level={5}
|
||||
data-testid={`post-${post.id}`}
|
||||
onMouseEnter={() => setShowHoverCard(true)}
|
||||
onMouseLeave={() => setShowHoverCard(false)}
|
||||
onFocus={() => setShowHoverCard(true)}
|
||||
onBlur={() => setShowHoverCard(false)}
|
||||
>
|
||||
<Confirmation
|
||||
isOpen={isDeleting}
|
||||
@@ -113,16 +118,17 @@ function Post({
|
||||
/>
|
||||
)}
|
||||
|
||||
<HoverCard
|
||||
commentOrPost={post}
|
||||
actionHandlers={actionHandlers}
|
||||
handleResponseCommentButton={handleAddResponseButton}
|
||||
addResponseCommentButtonMessage={intl.formatMessage(messages.addResponse)}
|
||||
onLike={() => dispatch(updateExistingThread(post.id, { voted: !post.voted }))}
|
||||
onFollow={() => dispatch(updateExistingThread(post.id, { following: !post.following }))}
|
||||
isClosedPost={post.closed}
|
||||
/>
|
||||
|
||||
{showHoverCard && (
|
||||
<HoverCard
|
||||
commentOrPost={post}
|
||||
actionHandlers={actionHandlers}
|
||||
handleResponseCommentButton={handleAddResponseButton}
|
||||
addResponseCommentButtonMessage={intl.formatMessage(messages.addResponse)}
|
||||
onLike={() => dispatch(updateExistingThread(post.id, { voted: !post.voted }))}
|
||||
onFollow={() => dispatch(updateExistingThread(post.id, { following: !post.following }))}
|
||||
isClosedPost={post.closed}
|
||||
/>
|
||||
)}
|
||||
<AlertBanner content={post} />
|
||||
<PostHeader post={post} />
|
||||
<div className="d-flex mt-14px text-break font-style-normal font-family-inter text-primary-500">
|
||||
@@ -171,7 +177,7 @@ Post.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
post: postShape.isRequired,
|
||||
preview: PropTypes.bool,
|
||||
handleAddResponseButton: PropTypes.objectOf(PropTypes.func).isRequired,
|
||||
handleAddResponseButton: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
Post.defaultProps = {
|
||||
|
||||
Reference in New Issue
Block a user