Skip to content

Commit fa77205

Browse files
fix: fixed email confirmation params issue (#791)
* fix: fixed email confirmation params issue
1 parent 76da74a commit fa77205

File tree

13 files changed

+119
-39
lines changed

13 files changed

+119
-39
lines changed

src/discussions/common/withEmailConfirmation.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { useDispatch, useSelector } from 'react-redux';
55
import { useIntl } from '@edx/frontend-platform/i18n';
66

77
import { RequestStatus } from '../../data/constants';
8-
import { selectConfirmEmailStatus, selectOnlyVerifiedUsersCanPost } from '../data/selectors';
8+
import { selectConfirmEmailStatus, selectShouldShowEmailConfirmation } from '../data/selectors';
99
import { sendAccountActivationEmail } from '../posts/data/thunks';
1010
import postMessages from '../posts/post-actions-bar/messages';
1111
import { Confirmation } from '.';
@@ -15,7 +15,7 @@ const withEmailConfirmation = (WrappedComponent) => {
1515
const intl = useIntl();
1616
const dispatch = useDispatch();
1717
const [isConfirming, setIsConfirming] = useState(false);
18-
const onlyVerifiedUsersCanPost = useSelector(selectOnlyVerifiedUsersCanPost);
18+
const shouldShowEmailConfirmation = useSelector(selectShouldShowEmailConfirmation);
1919
const confirmEmailStatus = useSelector(selectConfirmEmailStatus);
2020

2121
const openConfirmation = useCallback(() => {
@@ -42,7 +42,7 @@ const withEmailConfirmation = (WrappedComponent) => {
4242
{...props}
4343
openEmailConfirmation={openConfirmation}
4444
/>
45-
{!onlyVerifiedUsersCanPost
45+
{shouldShowEmailConfirmation
4646
&& (
4747
<Confirmation
4848
isOpen={isConfirming}

src/discussions/common/withEmailConfirmation.test.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ describe('EmptyPage', () => {
4444
},
4545
});
4646

47-
store = initializeStore();
47+
store = initializeStore({
48+
config: { provider: 'openedx', onlyVerifiedUsersCanPost: true },
49+
});
4850
});
4951

5052
it('should open the confirmation link dialogue box.', async () => {

src/discussions/data/selectors.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ export const selectOnlyVerifiedUsersCanPost = state => state.config.onlyVerified
4343

4444
export const selectConfirmEmailStatus = state => state.threads.confirmEmailStatus;
4545

46+
export const selectShouldShowEmailConfirmation = createSelector(
47+
[selectIsEmailVerified, selectOnlyVerifiedUsersCanPost],
48+
(isEmailVerified, onlyVerifiedUsersCanPost) => !isEmailVerified && onlyVerifiedUsersCanPost,
49+
);
50+
4651
export const selectModerationSettings = state => ({
4752
postCloseReasons: state.config.postCloseReasons,
4853
editReasons: state.config.editReasons,

src/discussions/empty-posts/EmptyPosts.jsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import withEmailConfirmation from '../common/withEmailConfirmation';
99
import { useIsOnTablet } from '../data/hooks';
1010
import {
1111
selectAreThreadsFiltered,
12-
selectIsEmailVerified,
1312
selectPostThreadCount,
13+
selectShouldShowEmailConfirmation,
1414
} from '../data/selectors';
1515
import messages from '../messages';
1616
import { showPostEditor } from '../posts/data';
@@ -23,11 +23,11 @@ const EmptyPosts = ({ subTitleMessage, openEmailConfirmation }) => {
2323
const isOnTabletorDesktop = useIsOnTablet();
2424
const isFiltered = useSelector(selectAreThreadsFiltered);
2525
const totalThreads = useSelector(selectPostThreadCount);
26-
const isEmailVerified = useSelector(selectIsEmailVerified);
26+
const shouldShowEmailConfirmation = useSelector(selectShouldShowEmailConfirmation);
2727

2828
const addPost = useCallback(() => {
29-
if (isEmailVerified) { dispatch(showPostEditor()); } else { openEmailConfirmation(); }
30-
}, [isEmailVerified, openEmailConfirmation]);
29+
if (shouldShowEmailConfirmation) { openEmailConfirmation(); } else { dispatch(showPostEditor()); }
30+
}, [shouldShowEmailConfirmation, openEmailConfirmation]);
3131

3232
let title = messages.noPostSelected;
3333
let subTitle = null;

src/discussions/empty-posts/EmptyTopics.jsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ import { useIntl } from '@edx/frontend-platform/i18n';
88

99
import withEmailConfirmation from '../common/withEmailConfirmation';
1010
import { useIsOnTablet, useTotalTopicThreadCount } from '../data/hooks';
11-
import {
12-
selectIsEmailVerified, selectTopicThreadCount,
13-
} from '../data/selectors';
11+
import { selectShouldShowEmailConfirmation, selectTopicThreadCount } from '../data/selectors';
1412
import messages from '../messages';
1513
import { showPostEditor } from '../posts/data';
1614
import postMessages from '../posts/post-actions-bar/messages';
@@ -23,11 +21,11 @@ const EmptyTopics = ({ openEmailConfirmation }) => {
2321
const isOnTabletorDesktop = useIsOnTablet();
2422
const hasGlobalThreads = useTotalTopicThreadCount() > 0;
2523
const topicThreadCount = useSelector(selectTopicThreadCount(topicId));
26-
const isEmailVerified = useSelector(selectIsEmailVerified);
24+
const shouldShowEmailConfirmation = useSelector(selectShouldShowEmailConfirmation);
2725

2826
const addPost = useCallback(() => {
29-
if (isEmailVerified) { dispatch(showPostEditor()); } else { openEmailConfirmation(); }
30-
}, [isEmailVerified, openEmailConfirmation]);
27+
if (shouldShowEmailConfirmation) { openEmailConfirmation(); } else { dispatch(showPostEditor()); }
28+
}, [shouldShowEmailConfirmation, openEmailConfirmation]);
3129

3230
let title = messages.emptyTitle;
3331
let fullWidth = false;

src/discussions/empty-posts/EmptyTopics.test.jsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { render, screen } from '@testing-library/react';
2+
import userEvent from '@testing-library/user-event';
23
import MockAdapter from 'axios-mock-adapter';
34
import { IntlProvider } from 'react-intl';
45
import { Context as ResponsiveContext } from 'react-responsive';
@@ -61,7 +62,7 @@ describe('EmptyTopics', () => {
6162
},
6263
});
6364

64-
store = initializeStore({ config: { provider: 'legacy' } });
65+
store = initializeStore({ config: { provider: 'legacy', onlyVerifiedUsersCanPost: true } });
6566
});
6667

6768
test('"no topic selected" text shown when viewing topics page', async () => {
@@ -75,4 +76,13 @@ describe('EmptyTopics', () => {
7576

7677
await screen.findByText(messages.noPostSelected.defaultMessage);
7778
});
79+
80+
it('should open the confirmation link dialogue box.', async () => {
81+
renderComponent(`/${courseId}/topics/ncwtopic-3/`);
82+
83+
const addPostButton = screen.getByRole('button', { name: 'Add a post' });
84+
await userEvent.click(addPostButton);
85+
86+
expect(screen.queryByText('Send confirmation link')).toBeInTheDocument();
87+
});
7888
});

src/discussions/in-context-topics/TopicsView.test.jsx

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { ResponsiveContext } from '@openedx/paragon';
12
import {
23
fireEvent, render, screen, waitFor,
34
within,
@@ -18,6 +19,7 @@ import { AppProvider } from '@edx/frontend-platform/react';
1819
import { initializeStore } from '../../store';
1920
import executeThunk from '../../test-utils';
2021
import DiscussionContext from '../common/context';
22+
import EmptyTopics from './components/EmptyTopics';
2123
import { getCourseTopicsApiUrl } from './data/api';
2224
import { selectCoursewareTopics, selectNonCoursewareTopics } from './data/selectors';
2325
import fetchCourseTopicsV3 from './data/thunks';
@@ -40,6 +42,24 @@ const LocationComponent = () => {
4042
return null;
4143
};
4244

45+
function renderEmptyTopicComponent(topicId = 'sample-topic-id') {
46+
return render(
47+
<IntlProvider locale="en">
48+
<ResponsiveContext.Provider value={{ width: 1280 }}>
49+
<AppProvider store={store} wrapWithRouter={false}>
50+
<DiscussionContext.Provider value={{ courseId, category }}>
51+
<MemoryRouter initialEntries={[`/discussion/${category}/${topicId}`]}>
52+
<Routes>
53+
<Route path="/discussion/:category/:topicId" element={<EmptyTopics />} />
54+
</Routes>
55+
</MemoryRouter>
56+
</DiscussionContext.Provider>
57+
</AppProvider>
58+
</ResponsiveContext.Provider>
59+
</IntlProvider>,
60+
);
61+
}
62+
4363
function renderComponent() {
4464
const wrapper = render(
4565
<IntlProvider locale="en">
@@ -72,7 +92,9 @@ describe('InContext Topics View', () => {
7292
});
7393

7494
store = initializeStore({
75-
config: { enableInContext: true, provider: 'openedx', hasModerationPrivileges: true },
95+
config: {
96+
enableInContext: true, provider: 'openedx', hasModerationPrivileges: true, onlyVerifiedUsersCanPost: true,
97+
},
7698
});
7799
Factory.resetAll();
78100
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
@@ -238,4 +260,14 @@ describe('InContext Topics View', () => {
238260
});
239261
});
240262
});
263+
264+
it('should open the confirmation link dialogue box.', async () => {
265+
renderEmptyTopicComponent();
266+
267+
const addPostButton = screen.getByRole('button', { name: /Add a post/i });
268+
await userEvent.click(addPostButton);
269+
270+
const confirmationText = await screen.findByText(/send confirmation link/i);
271+
expect(confirmationText).toBeInTheDocument();
272+
});
241273
});

src/discussions/in-context-topics/components/EmptyTopics.jsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { useIntl } from '@edx/frontend-platform/i18n';
99
import DiscussionContext from '../../common/context';
1010
import withEmailConfirmation from '../../common/withEmailConfirmation';
1111
import { useIsOnTablet } from '../../data/hooks';
12-
import { selectIsEmailVerified, selectPostThreadCount } from '../../data/selectors';
12+
import { selectPostThreadCount, selectShouldShowEmailConfirmation } from '../../data/selectors';
1313
import EmptyPage from '../../empty-posts/EmptyPage';
1414
import messages from '../../messages';
1515
import { messages as postMessages, showPostEditor } from '../../posts';
@@ -25,11 +25,11 @@ const EmptyTopics = ({ openEmailConfirmation }) => {
2525
const topicThreadsCount = useSelector(selectPostThreadCount);
2626
// hasGlobalThreads is used to determine if there are any post available in courseware and non-courseware topics
2727
const hasGlobalThreads = useSelector(selectTotalTopicsThreadsCount) > 0;
28-
const isEmailVerified = useSelector(selectIsEmailVerified);
28+
const shouldShowEmailConfirmation = useSelector(selectShouldShowEmailConfirmation);
2929

3030
const addPost = useCallback(() => {
31-
if (isEmailVerified) { dispatch(showPostEditor()); } else { openEmailConfirmation(); }
32-
}, [isEmailVerified, openEmailConfirmation]);
31+
if (shouldShowEmailConfirmation) { openEmailConfirmation(); } else { dispatch(showPostEditor()); }
32+
}, [shouldShowEmailConfirmation, openEmailConfirmation]);
3333

3434
let title = messages.emptyTitle;
3535
let fullWidth = false;

src/discussions/post-comments/PostCommentsView.test.jsx

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ async function getThreadAPIResponse(attr = null) {
103103
await executeThunk(fetchThread(discussionPostId), store.dispatch, store.getState);
104104
}
105105

106-
async function setupCourseConfig() {
106+
async function setupCourseConfig(isEmailVerified = true, onlyVerifiedUsersCanPost = false) {
107107
axiosMock.onGet(`${courseConfigApiUrl}${courseId}/`).reply(200, {
108108
has_moderation_privileges: true,
109109
isPostingEnabled: true,
@@ -115,7 +115,8 @@ async function setupCourseConfig() {
115115
{ code: 'reason-1', label: 'reason 1' },
116116
{ code: 'reason-2', label: 'reason 2' },
117117
],
118-
isEmailVerified: true,
118+
isEmailVerified,
119+
onlyVerifiedUsersCanPost,
119120
});
120121
axiosMock.onGet(`${courseSettingsApiUrl}${courseId}/settings`).reply(200, {});
121122
await executeThunk(fetchCourseConfig(courseId), store.dispatch, store.getState);
@@ -310,6 +311,29 @@ describe('ThreadView', () => {
310311
expect(screen.queryByTestId('tinymce-editor')).not.toBeInTheDocument();
311312
});
312313

314+
it('should open the confirmation link dialogue box by clicking on add comment button.', async () => {
315+
await setupCourseConfig(false, true);
316+
await waitFor(() => renderComponent(discussionPostId));
317+
318+
const comment = await waitFor(() => screen.findByTestId('comment-comment-1'));
319+
const hoverCard = within(comment).getByTestId('hover-card-comment-1');
320+
await act(async () => { fireEvent.click(within(hoverCard).getByRole('button', { name: /Add comment/i })); });
321+
322+
expect(screen.queryByText('Send confirmation link')).toBeInTheDocument();
323+
});
324+
325+
it('should open the confirmation link dialogue box by clicking on add response.', async () => {
326+
await setupCourseConfig(false, true);
327+
await waitFor(() => renderComponent(discussionPostId));
328+
329+
const post = await screen.findByTestId('post-thread-1');
330+
const hoverCard = within(post).getByTestId('hover-card-thread-1');
331+
const addResponseButton = within(hoverCard).getByRole('button', { name: /Add response/i });
332+
await act(async () => { fireEvent.click(addResponseButton); });
333+
334+
expect(screen.queryByText('Send confirmation link')).toBeInTheDocument();
335+
});
336+
313337
it('should allow posting a comment with CAPTCHA', async () => {
314338
await setupCourseConfig();
315339
await waitFor(() => renderComponent(discussionPostId));
@@ -1061,6 +1085,17 @@ describe('ThreadView', () => {
10611085
expect(responseSortTour().enabled).toBeFalsy();
10621086
});
10631087
});
1088+
1089+
it('should open the confirmation link dialogue box on add response button.', async () => {
1090+
await setupCourseConfig(false, true);
1091+
await waitFor(() => renderComponent(discussionPostId));
1092+
1093+
const addResponseButton = screen.getByTestId('add-response');
1094+
1095+
await act(async () => { fireEvent.click(addResponseButton); });
1096+
1097+
expect(screen.queryByText('Send confirmation link')).toBeInTheDocument();
1098+
});
10641099
});
10651100

10661101
describe('MockReCAPTCHA', () => {

src/discussions/post-comments/comments/CommentsView.jsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { useIntl } from '@edx/frontend-platform/i18n';
99
import { ThreadType } from '../../../data/constants';
1010
import withEmailConfirmation from '../../common/withEmailConfirmation';
1111
import { useUserPostingEnabled } from '../../data/hooks';
12-
import { selectIsEmailVerified } from '../../data/selectors';
12+
import { selectShouldShowEmailConfirmation } from '../../data/selectors';
1313
import { isLastElementOfList } from '../../utils';
1414
import { usePostComments } from '../data/hooks';
1515
import messages from '../messages';
@@ -20,8 +20,8 @@ const CommentsView = ({ threadType, openEmailConfirmation }) => {
2020
const intl = useIntl();
2121
const [addingResponse, setAddingResponse] = useState(false);
2222
const { isClosed } = useContext(PostCommentsContext);
23-
const isEmailVerified = useSelector(selectIsEmailVerified);
2423
const isUserPrivilegedInPostingRestriction = useUserPostingEnabled();
24+
const shouldShowEmailConfirmation = useSelector(selectShouldShowEmailConfirmation);
2525

2626
const {
2727
endorsedCommentsIds,
@@ -32,8 +32,8 @@ const CommentsView = ({ threadType, openEmailConfirmation }) => {
3232
} = usePostComments(threadType);
3333

3434
const handleAddResponse = useCallback(() => {
35-
if (isEmailVerified) { setAddingResponse(true); } else { openEmailConfirmation(); }
36-
}, [isEmailVerified, openEmailConfirmation]);
35+
if (shouldShowEmailConfirmation) { openEmailConfirmation(); } else { setAddingResponse(true); }
36+
}, [shouldShowEmailConfirmation, openEmailConfirmation]);
3737

3838
const handleCloseResponseEditor = useCallback(() => {
3939
setAddingResponse(false);

0 commit comments

Comments
 (0)