fix: fixed email confirmation params issue (#791)
* fix: fixed email confirmation params issue
This commit is contained in:
@@ -5,7 +5,7 @@ import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { RequestStatus } from '../../data/constants';
|
||||
import { selectConfirmEmailStatus, selectOnlyVerifiedUsersCanPost } from '../data/selectors';
|
||||
import { selectConfirmEmailStatus, selectShouldShowEmailConfirmation } from '../data/selectors';
|
||||
import { sendAccountActivationEmail } from '../posts/data/thunks';
|
||||
import postMessages from '../posts/post-actions-bar/messages';
|
||||
import { Confirmation } from '.';
|
||||
@@ -15,7 +15,7 @@ const withEmailConfirmation = (WrappedComponent) => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useDispatch();
|
||||
const [isConfirming, setIsConfirming] = useState(false);
|
||||
const onlyVerifiedUsersCanPost = useSelector(selectOnlyVerifiedUsersCanPost);
|
||||
const shouldShowEmailConfirmation = useSelector(selectShouldShowEmailConfirmation);
|
||||
const confirmEmailStatus = useSelector(selectConfirmEmailStatus);
|
||||
|
||||
const openConfirmation = useCallback(() => {
|
||||
@@ -42,7 +42,7 @@ const withEmailConfirmation = (WrappedComponent) => {
|
||||
{...props}
|
||||
openEmailConfirmation={openConfirmation}
|
||||
/>
|
||||
{!onlyVerifiedUsersCanPost
|
||||
{shouldShowEmailConfirmation
|
||||
&& (
|
||||
<Confirmation
|
||||
isOpen={isConfirming}
|
||||
|
||||
@@ -44,7 +44,9 @@ describe('EmptyPage', () => {
|
||||
},
|
||||
});
|
||||
|
||||
store = initializeStore();
|
||||
store = initializeStore({
|
||||
config: { provider: 'openedx', onlyVerifiedUsersCanPost: true },
|
||||
});
|
||||
});
|
||||
|
||||
it('should open the confirmation link dialogue box.', async () => {
|
||||
|
||||
@@ -43,6 +43,11 @@ export const selectOnlyVerifiedUsersCanPost = state => state.config.onlyVerified
|
||||
|
||||
export const selectConfirmEmailStatus = state => state.threads.confirmEmailStatus;
|
||||
|
||||
export const selectShouldShowEmailConfirmation = createSelector(
|
||||
[selectIsEmailVerified, selectOnlyVerifiedUsersCanPost],
|
||||
(isEmailVerified, onlyVerifiedUsersCanPost) => !isEmailVerified && onlyVerifiedUsersCanPost,
|
||||
);
|
||||
|
||||
export const selectModerationSettings = state => ({
|
||||
postCloseReasons: state.config.postCloseReasons,
|
||||
editReasons: state.config.editReasons,
|
||||
|
||||
@@ -9,8 +9,8 @@ import withEmailConfirmation from '../common/withEmailConfirmation';
|
||||
import { useIsOnTablet } from '../data/hooks';
|
||||
import {
|
||||
selectAreThreadsFiltered,
|
||||
selectIsEmailVerified,
|
||||
selectPostThreadCount,
|
||||
selectShouldShowEmailConfirmation,
|
||||
} from '../data/selectors';
|
||||
import messages from '../messages';
|
||||
import { showPostEditor } from '../posts/data';
|
||||
@@ -23,11 +23,11 @@ const EmptyPosts = ({ subTitleMessage, openEmailConfirmation }) => {
|
||||
const isOnTabletorDesktop = useIsOnTablet();
|
||||
const isFiltered = useSelector(selectAreThreadsFiltered);
|
||||
const totalThreads = useSelector(selectPostThreadCount);
|
||||
const isEmailVerified = useSelector(selectIsEmailVerified);
|
||||
const shouldShowEmailConfirmation = useSelector(selectShouldShowEmailConfirmation);
|
||||
|
||||
const addPost = useCallback(() => {
|
||||
if (isEmailVerified) { dispatch(showPostEditor()); } else { openEmailConfirmation(); }
|
||||
}, [isEmailVerified, openEmailConfirmation]);
|
||||
if (shouldShowEmailConfirmation) { openEmailConfirmation(); } else { dispatch(showPostEditor()); }
|
||||
}, [shouldShowEmailConfirmation, openEmailConfirmation]);
|
||||
|
||||
let title = messages.noPostSelected;
|
||||
let subTitle = null;
|
||||
|
||||
@@ -8,9 +8,7 @@ import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import withEmailConfirmation from '../common/withEmailConfirmation';
|
||||
import { useIsOnTablet, useTotalTopicThreadCount } from '../data/hooks';
|
||||
import {
|
||||
selectIsEmailVerified, selectTopicThreadCount,
|
||||
} from '../data/selectors';
|
||||
import { selectShouldShowEmailConfirmation, selectTopicThreadCount } from '../data/selectors';
|
||||
import messages from '../messages';
|
||||
import { showPostEditor } from '../posts/data';
|
||||
import postMessages from '../posts/post-actions-bar/messages';
|
||||
@@ -23,11 +21,11 @@ const EmptyTopics = ({ openEmailConfirmation }) => {
|
||||
const isOnTabletorDesktop = useIsOnTablet();
|
||||
const hasGlobalThreads = useTotalTopicThreadCount() > 0;
|
||||
const topicThreadCount = useSelector(selectTopicThreadCount(topicId));
|
||||
const isEmailVerified = useSelector(selectIsEmailVerified);
|
||||
const shouldShowEmailConfirmation = useSelector(selectShouldShowEmailConfirmation);
|
||||
|
||||
const addPost = useCallback(() => {
|
||||
if (isEmailVerified) { dispatch(showPostEditor()); } else { openEmailConfirmation(); }
|
||||
}, [isEmailVerified, openEmailConfirmation]);
|
||||
if (shouldShowEmailConfirmation) { openEmailConfirmation(); } else { dispatch(showPostEditor()); }
|
||||
}, [shouldShowEmailConfirmation, openEmailConfirmation]);
|
||||
|
||||
let title = messages.emptyTitle;
|
||||
let fullWidth = false;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import { IntlProvider } from 'react-intl';
|
||||
import { Context as ResponsiveContext } from 'react-responsive';
|
||||
@@ -61,7 +62,7 @@ describe('EmptyTopics', () => {
|
||||
},
|
||||
});
|
||||
|
||||
store = initializeStore({ config: { provider: 'legacy' } });
|
||||
store = initializeStore({ config: { provider: 'legacy', onlyVerifiedUsersCanPost: true } });
|
||||
});
|
||||
|
||||
test('"no topic selected" text shown when viewing topics page', async () => {
|
||||
@@ -75,4 +76,13 @@ describe('EmptyTopics', () => {
|
||||
|
||||
await screen.findByText(messages.noPostSelected.defaultMessage);
|
||||
});
|
||||
|
||||
it('should open the confirmation link dialogue box.', async () => {
|
||||
renderComponent(`/${courseId}/topics/ncwtopic-3/`);
|
||||
|
||||
const addPostButton = screen.getByRole('button', { name: 'Add a post' });
|
||||
await userEvent.click(addPostButton);
|
||||
|
||||
expect(screen.queryByText('Send confirmation link')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ResponsiveContext } from '@openedx/paragon';
|
||||
import {
|
||||
fireEvent, render, screen, waitFor,
|
||||
within,
|
||||
@@ -18,6 +19,7 @@ import { AppProvider } from '@edx/frontend-platform/react';
|
||||
import { initializeStore } from '../../store';
|
||||
import executeThunk from '../../test-utils';
|
||||
import DiscussionContext from '../common/context';
|
||||
import EmptyTopics from './components/EmptyTopics';
|
||||
import { getCourseTopicsApiUrl } from './data/api';
|
||||
import { selectCoursewareTopics, selectNonCoursewareTopics } from './data/selectors';
|
||||
import fetchCourseTopicsV3 from './data/thunks';
|
||||
@@ -40,6 +42,24 @@ const LocationComponent = () => {
|
||||
return null;
|
||||
};
|
||||
|
||||
function renderEmptyTopicComponent(topicId = 'sample-topic-id') {
|
||||
return render(
|
||||
<IntlProvider locale="en">
|
||||
<ResponsiveContext.Provider value={{ width: 1280 }}>
|
||||
<AppProvider store={store} wrapWithRouter={false}>
|
||||
<DiscussionContext.Provider value={{ courseId, category }}>
|
||||
<MemoryRouter initialEntries={[`/discussion/${category}/${topicId}`]}>
|
||||
<Routes>
|
||||
<Route path="/discussion/:category/:topicId" element={<EmptyTopics />} />
|
||||
</Routes>
|
||||
</MemoryRouter>
|
||||
</DiscussionContext.Provider>
|
||||
</AppProvider>
|
||||
</ResponsiveContext.Provider>
|
||||
</IntlProvider>,
|
||||
);
|
||||
}
|
||||
|
||||
function renderComponent() {
|
||||
const wrapper = render(
|
||||
<IntlProvider locale="en">
|
||||
@@ -72,7 +92,9 @@ describe('InContext Topics View', () => {
|
||||
});
|
||||
|
||||
store = initializeStore({
|
||||
config: { enableInContext: true, provider: 'openedx', hasModerationPrivileges: true },
|
||||
config: {
|
||||
enableInContext: true, provider: 'openedx', hasModerationPrivileges: true, onlyVerifiedUsersCanPost: true,
|
||||
},
|
||||
});
|
||||
Factory.resetAll();
|
||||
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
|
||||
@@ -238,4 +260,14 @@ describe('InContext Topics View', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should open the confirmation link dialogue box.', async () => {
|
||||
renderEmptyTopicComponent();
|
||||
|
||||
const addPostButton = screen.getByRole('button', { name: /Add a post/i });
|
||||
await userEvent.click(addPostButton);
|
||||
|
||||
const confirmationText = await screen.findByText(/send confirmation link/i);
|
||||
expect(confirmationText).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import DiscussionContext from '../../common/context';
|
||||
import withEmailConfirmation from '../../common/withEmailConfirmation';
|
||||
import { useIsOnTablet } from '../../data/hooks';
|
||||
import { selectIsEmailVerified, selectPostThreadCount } from '../../data/selectors';
|
||||
import { selectPostThreadCount, selectShouldShowEmailConfirmation } from '../../data/selectors';
|
||||
import EmptyPage from '../../empty-posts/EmptyPage';
|
||||
import messages from '../../messages';
|
||||
import { messages as postMessages, showPostEditor } from '../../posts';
|
||||
@@ -25,11 +25,11 @@ const EmptyTopics = ({ openEmailConfirmation }) => {
|
||||
const topicThreadsCount = useSelector(selectPostThreadCount);
|
||||
// hasGlobalThreads is used to determine if there are any post available in courseware and non-courseware topics
|
||||
const hasGlobalThreads = useSelector(selectTotalTopicsThreadsCount) > 0;
|
||||
const isEmailVerified = useSelector(selectIsEmailVerified);
|
||||
const shouldShowEmailConfirmation = useSelector(selectShouldShowEmailConfirmation);
|
||||
|
||||
const addPost = useCallback(() => {
|
||||
if (isEmailVerified) { dispatch(showPostEditor()); } else { openEmailConfirmation(); }
|
||||
}, [isEmailVerified, openEmailConfirmation]);
|
||||
if (shouldShowEmailConfirmation) { openEmailConfirmation(); } else { dispatch(showPostEditor()); }
|
||||
}, [shouldShowEmailConfirmation, openEmailConfirmation]);
|
||||
|
||||
let title = messages.emptyTitle;
|
||||
let fullWidth = false;
|
||||
|
||||
@@ -103,7 +103,7 @@ async function getThreadAPIResponse(attr = null) {
|
||||
await executeThunk(fetchThread(discussionPostId), store.dispatch, store.getState);
|
||||
}
|
||||
|
||||
async function setupCourseConfig() {
|
||||
async function setupCourseConfig(isEmailVerified = true, onlyVerifiedUsersCanPost = false) {
|
||||
axiosMock.onGet(`${courseConfigApiUrl}${courseId}/`).reply(200, {
|
||||
has_moderation_privileges: true,
|
||||
isPostingEnabled: true,
|
||||
@@ -115,7 +115,8 @@ async function setupCourseConfig() {
|
||||
{ code: 'reason-1', label: 'reason 1' },
|
||||
{ code: 'reason-2', label: 'reason 2' },
|
||||
],
|
||||
isEmailVerified: true,
|
||||
isEmailVerified,
|
||||
onlyVerifiedUsersCanPost,
|
||||
});
|
||||
axiosMock.onGet(`${courseSettingsApiUrl}${courseId}/settings`).reply(200, {});
|
||||
await executeThunk(fetchCourseConfig(courseId), store.dispatch, store.getState);
|
||||
@@ -310,6 +311,29 @@ describe('ThreadView', () => {
|
||||
expect(screen.queryByTestId('tinymce-editor')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should open the confirmation link dialogue box by clicking on add comment button.', async () => {
|
||||
await setupCourseConfig(false, true);
|
||||
await waitFor(() => renderComponent(discussionPostId));
|
||||
|
||||
const comment = await waitFor(() => screen.findByTestId('comment-comment-1'));
|
||||
const hoverCard = within(comment).getByTestId('hover-card-comment-1');
|
||||
await act(async () => { fireEvent.click(within(hoverCard).getByRole('button', { name: /Add comment/i })); });
|
||||
|
||||
expect(screen.queryByText('Send confirmation link')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should open the confirmation link dialogue box by clicking on add response.', async () => {
|
||||
await setupCourseConfig(false, true);
|
||||
await waitFor(() => renderComponent(discussionPostId));
|
||||
|
||||
const post = await screen.findByTestId('post-thread-1');
|
||||
const hoverCard = within(post).getByTestId('hover-card-thread-1');
|
||||
const addResponseButton = within(hoverCard).getByRole('button', { name: /Add response/i });
|
||||
await act(async () => { fireEvent.click(addResponseButton); });
|
||||
|
||||
expect(screen.queryByText('Send confirmation link')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should allow posting a comment with CAPTCHA', async () => {
|
||||
await setupCourseConfig();
|
||||
await waitFor(() => renderComponent(discussionPostId));
|
||||
@@ -1061,6 +1085,17 @@ describe('ThreadView', () => {
|
||||
expect(responseSortTour().enabled).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
it('should open the confirmation link dialogue box on add response button.', async () => {
|
||||
await setupCourseConfig(false, true);
|
||||
await waitFor(() => renderComponent(discussionPostId));
|
||||
|
||||
const addResponseButton = screen.getByTestId('add-response');
|
||||
|
||||
await act(async () => { fireEvent.click(addResponseButton); });
|
||||
|
||||
expect(screen.queryByText('Send confirmation link')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('MockReCAPTCHA', () => {
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { ThreadType } from '../../../data/constants';
|
||||
import withEmailConfirmation from '../../common/withEmailConfirmation';
|
||||
import { useUserPostingEnabled } from '../../data/hooks';
|
||||
import { selectIsEmailVerified } from '../../data/selectors';
|
||||
import { selectShouldShowEmailConfirmation } from '../../data/selectors';
|
||||
import { isLastElementOfList } from '../../utils';
|
||||
import { usePostComments } from '../data/hooks';
|
||||
import messages from '../messages';
|
||||
@@ -20,8 +20,8 @@ const CommentsView = ({ threadType, openEmailConfirmation }) => {
|
||||
const intl = useIntl();
|
||||
const [addingResponse, setAddingResponse] = useState(false);
|
||||
const { isClosed } = useContext(PostCommentsContext);
|
||||
const isEmailVerified = useSelector(selectIsEmailVerified);
|
||||
const isUserPrivilegedInPostingRestriction = useUserPostingEnabled();
|
||||
const shouldShowEmailConfirmation = useSelector(selectShouldShowEmailConfirmation);
|
||||
|
||||
const {
|
||||
endorsedCommentsIds,
|
||||
@@ -32,8 +32,8 @@ const CommentsView = ({ threadType, openEmailConfirmation }) => {
|
||||
} = usePostComments(threadType);
|
||||
|
||||
const handleAddResponse = useCallback(() => {
|
||||
if (isEmailVerified) { setAddingResponse(true); } else { openEmailConfirmation(); }
|
||||
}, [isEmailVerified, openEmailConfirmation]);
|
||||
if (shouldShowEmailConfirmation) { openEmailConfirmation(); } else { setAddingResponse(true); }
|
||||
}, [shouldShowEmailConfirmation, openEmailConfirmation]);
|
||||
|
||||
const handleCloseResponseEditor = useCallback(() => {
|
||||
setAddingResponse(false);
|
||||
|
||||
@@ -17,7 +17,7 @@ import HoverCard from '../../../common/HoverCard';
|
||||
import withEmailConfirmation from '../../../common/withEmailConfirmation';
|
||||
import { ContentTypes } from '../../../data/constants';
|
||||
import { useUserPostingEnabled } from '../../../data/hooks';
|
||||
import { selectIsEmailVerified } from '../../../data/selectors';
|
||||
import { selectShouldShowEmailConfirmation } from '../../../data/selectors';
|
||||
import { fetchThread } from '../../../posts/data/thunks';
|
||||
import LikeButton from '../../../posts/post/LikeButton';
|
||||
import { useActions } from '../../../utils';
|
||||
@@ -63,9 +63,9 @@ const Comment = ({
|
||||
const hasMorePages = useSelector(selectCommentHasMorePages(id));
|
||||
const currentPage = useSelector(selectCommentCurrentPage(id));
|
||||
const sortedOrder = useSelector(selectCommentSortOrder);
|
||||
const isEmailVerified = useSelector(selectIsEmailVerified);
|
||||
const actions = useActions(ContentTypes.COMMENT, id);
|
||||
const isUserPrivilegedInPostingRestriction = useUserPostingEnabled();
|
||||
const shouldShowEmailConfirmation = useSelector(selectShouldShowEmailConfirmation);
|
||||
|
||||
useEffect(() => {
|
||||
// If the comment has a parent comment, it won't have any children, so don't fetch them.
|
||||
@@ -183,7 +183,7 @@ const Comment = ({
|
||||
id={id}
|
||||
contentType={ContentTypes.COMMENT}
|
||||
actionHandlers={actionHandlers}
|
||||
handleResponseCommentButton={isEmailVerified ? handleAddCommentButton : openEmailConfirmation}
|
||||
handleResponseCommentButton={shouldShowEmailConfirmation ? openEmailConfirmation : handleAddCommentButton}
|
||||
addResponseCommentButtonMessage={intl.formatMessage(messages.addComment)}
|
||||
onLike={handleCommentLike}
|
||||
voted={voted}
|
||||
@@ -274,7 +274,7 @@ const Comment = ({
|
||||
className="d-flex flex-grow mt-2 font-style font-weight-500 text-primary-500 add-comment-btn rounded-0"
|
||||
variant="plain"
|
||||
style={{ height: '36px' }}
|
||||
onClick={isEmailVerified ? handleAddCommentReply : openEmailConfirmation}
|
||||
onClick={shouldShowEmailConfirmation ? openEmailConfirmation : handleAddCommentReply}
|
||||
>
|
||||
{intl.formatMessage(messages.addComment)}
|
||||
</Button>
|
||||
|
||||
@@ -18,7 +18,7 @@ import { useUserPostingEnabled } from '../../data/hooks';
|
||||
import {
|
||||
selectConfigLoadingStatus,
|
||||
selectEnableInContext,
|
||||
selectIsEmailVerified,
|
||||
selectShouldShowEmailConfirmation,
|
||||
} from '../../data/selectors';
|
||||
import { TopicSearchBar as IncontextSearch } from '../../in-context-topics/topic-search';
|
||||
import { postMessageToParent } from '../../utils';
|
||||
@@ -32,7 +32,7 @@ const PostActionsBar = ({ openEmailConfirmation }) => {
|
||||
const dispatch = useDispatch();
|
||||
const loadingStatus = useSelector(selectConfigLoadingStatus);
|
||||
const enableInContext = useSelector(selectEnableInContext);
|
||||
const isEmailVerified = useSelector(selectIsEmailVerified);
|
||||
const shouldShowEmailConfirmation = useSelector(selectShouldShowEmailConfirmation);
|
||||
const isUserPrivilegedInPostingRestriction = useUserPostingEnabled();
|
||||
const { enableInContextSidebar, page } = useContext(DiscussionContext);
|
||||
|
||||
@@ -41,8 +41,8 @@ const PostActionsBar = ({ openEmailConfirmation }) => {
|
||||
}, []);
|
||||
|
||||
const handleAddPost = useCallback(() => {
|
||||
if (isEmailVerified) { dispatch(showPostEditor()); } else { openEmailConfirmation(); }
|
||||
}, [isEmailVerified, openEmailConfirmation]);
|
||||
if (shouldShowEmailConfirmation) { openEmailConfirmation(); } else { dispatch(showPostEditor()); }
|
||||
}, [shouldShowEmailConfirmation, openEmailConfirmation]);
|
||||
|
||||
return (
|
||||
<div className={classNames('d-flex justify-content-end flex-grow-1', { 'py-1': !enableInContextSidebar })}>
|
||||
|
||||
@@ -18,9 +18,7 @@ import DiscussionContext from '../../common/context';
|
||||
import HoverCard from '../../common/HoverCard';
|
||||
import withEmailConfirmation from '../../common/withEmailConfirmation';
|
||||
import { ContentTypes } from '../../data/constants';
|
||||
import {
|
||||
selectIsEmailVerified, selectUserHasModerationPrivileges,
|
||||
} from '../../data/selectors';
|
||||
import { selectShouldShowEmailConfirmation, selectUserHasModerationPrivileges } from '../../data/selectors';
|
||||
import { selectTopic } from '../../topics/data/selectors';
|
||||
import { truncatePath } from '../../utils';
|
||||
import { selectThread } from '../data/selectors';
|
||||
@@ -49,7 +47,7 @@ const Post = ({ handleAddResponseButton, openEmailConfirmation }) => {
|
||||
const [isReporting, showReportConfirmation, hideReportConfirmation] = useToggle(false);
|
||||
const [isClosing, showClosePostModal, hideClosePostModal] = useToggle(false);
|
||||
const userHasModerationPrivileges = useSelector(selectUserHasModerationPrivileges);
|
||||
const isEmailVerified = useSelector(selectIsEmailVerified);
|
||||
const shouldShowEmailConfirmation = useSelector(selectShouldShowEmailConfirmation);
|
||||
|
||||
const displayPostFooter = following || voteCount || closed || (groupId && userHasModerationPrivileges);
|
||||
|
||||
@@ -160,7 +158,7 @@ const Post = ({ handleAddResponseButton, openEmailConfirmation }) => {
|
||||
id={postId}
|
||||
contentType={ContentTypes.POST}
|
||||
actionHandlers={actionHandlers}
|
||||
handleResponseCommentButton={isEmailVerified ? handleAddResponseButton : () => openEmailConfirmation()}
|
||||
handleResponseCommentButton={shouldShowEmailConfirmation ? openEmailConfirmation : handleAddResponseButton}
|
||||
addResponseCommentButtonMessage={intl.formatMessage(messages.addResponse)}
|
||||
onLike={handlePostLike}
|
||||
onFollow={handlePostFollow}
|
||||
|
||||
Reference in New Issue
Block a user