diff --git a/src/data/constants.js b/src/data/constants.js index d0c7960cb..dc786b439 100644 --- a/src/data/constants.js +++ b/src/data/constants.js @@ -1,6 +1,9 @@ import { getConfig } from '@edx/frontend-platform'; export const getApiBaseUrl = () => getConfig().LMS_BASE_URL; +export const getFullUrl = (path) => ( + new URL(`${getConfig().PUBLIC_PATH.replace(/\/$/, '')}/${path}`, window.location.origin).href +); /** * Enum for thread types. @@ -137,7 +140,7 @@ export const DiscussionProvider = { OPEN_EDX: 'openedx', }; -const BASE_PATH = `${getConfig().PUBLIC_PATH}:courseId`; +const BASE_PATH = '/:courseId'; export const Routes = { DISCUSSIONS: { diff --git a/src/discussions/post-comments/PostCommentsView.test.jsx b/src/discussions/post-comments/PostCommentsView.test.jsx index 984d3683b..7bd371307 100644 --- a/src/discussions/post-comments/PostCommentsView.test.jsx +++ b/src/discussions/post-comments/PostCommentsView.test.jsx @@ -465,6 +465,20 @@ describe('ThreadView', () => { assertLastUpdateData({ pinned: false }); }); + it('should allow copying a link to the post', async () => { + await waitFor(() => renderComponent(discussionPostId)); + const post = await screen.findByTestId('post-thread-1'); + const hoverCard = within(post).getByTestId('hover-card-thread-1'); + Object.assign(navigator, { clipboard: { writeText: jest.fn() } }); + await act(async () => { + fireEvent.click(within(hoverCard).getByRole('button', { name: /actions menu/i })); + }); + await act(async () => { + fireEvent.click(within(hoverCard).getByRole('button', { name: /copy link/i })); + }); + expect(navigator.clipboard.writeText).toHaveBeenCalledWith(`http://localhost/${courseId}/posts/${discussionPostId}`); + }); + it('should allow reporting the post', async () => { await waitFor(() => renderComponent(discussionPostId)); const post = await screen.findByTestId('post-thread-1'); diff --git a/src/discussions/posts/data/__factories__/threads.factory.js b/src/discussions/posts/data/__factories__/threads.factory.js index fbd9aab30..b072860c8 100644 --- a/src/discussions/posts/data/__factories__/threads.factory.js +++ b/src/discussions/posts/data/__factories__/threads.factory.js @@ -26,6 +26,7 @@ Factory.define('thread') 'type', 'voted', 'pinned', + 'copy_link', ], author: 'test_user', author_label: 'Staff', diff --git a/src/discussions/posts/post/Post.jsx b/src/discussions/posts/post/Post.jsx index 0911dc762..d9a166dba 100644 --- a/src/discussions/posts/post/Post.jsx +++ b/src/discussions/posts/post/Post.jsx @@ -11,7 +11,7 @@ import { useIntl } from '@edx/frontend-platform/i18n'; import { Hyperlink, useToggle } from '@edx/paragon'; import HTMLLoader from '../../../components/HTMLLoader'; -import { ContentActions } from '../../../data/constants'; +import { ContentActions, getFullUrl } from '../../../data/constants'; import { selectorForUnitSubsection, selectTopicContext } from '../../../data/selectors'; import { AlertBanner, Confirmation } from '../../common'; import { DiscussionContext } from '../../common/context'; @@ -37,7 +37,7 @@ const Post = ({ handleAddResponseButton }) => { const location = useLocation(); const history = useHistory(); const dispatch = useDispatch(); - const courseId = useSelector((state) => state.config.id); + const { courseId } = useContext(DiscussionContext); const topic = useSelector(selectTopic(topicId)); const getTopicSubsection = useSelector(selectorForUnitSubsection); const topicContext = useSelector(selectTopicContext(topicId)); @@ -78,8 +78,7 @@ const Post = ({ handleAddResponseButton }) => { }, [closed, postId, reasonCodesEnabled, showClosePostModal]); const handlePostCopyLink = useCallback(() => { - const postURL = new URL(`${getConfig().PUBLIC_PATH}${courseId}/posts/${postId}`, window.location.origin); - navigator.clipboard.writeText(postURL.href); + navigator.clipboard.writeText(getFullUrl(`${courseId}/posts/${postId}`)); }, [window.location.origin, postId, courseId]); const handlePostPin = useCallback(() => dispatch(