Skip to content

Commit cced750

Browse files
author
Ahtesham Quraish
committed
refactor: Replace connect with useSelector() and useDispatch() 2/5 #231
1 parent 2bb2b76 commit cced750

File tree

10 files changed

+255
-365
lines changed

10 files changed

+255
-365
lines changed
Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import React from 'react';
2-
import PropTypes from 'prop-types';
3-
import { connect } from 'react-redux';
2+
import { useSelector } from 'react-redux';
43
import { useIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
54
import { getConfig } from '@edx/frontend-platform';
65

@@ -9,27 +8,31 @@ import messages from './messages';
98
import TinyMceWidget from '../../../../../sharedComponents/TinyMceWidget';
109
import { prepareEditorRef, replaceStaticWithAsset } from '../../../../../sharedComponents/TinyMceWidget/hooks';
1110

12-
const ExplanationWidget = ({
13-
// redux
14-
settings,
15-
learningContextId,
16-
images,
17-
isLibrary,
18-
blockId,
19-
}) => {
11+
const ExplanationWidget = () => {
2012
const intl = useIntl();
2113
const { editorRef, refReady, setEditorRef } = prepareEditorRef();
14+
15+
// Select state values using useSelector
16+
const settings = useSelector(selectors.problem.settings);
17+
const learningContextId = useSelector(selectors.app.learningContextId);
18+
const images = useSelector(selectors.app.images);
19+
const isLibrary = useSelector(selectors.app.isLibrary);
20+
const blockId = useSelector(selectors.app.blockId);
21+
2222
const initialContent = settings?.solutionExplanation || '';
2323
const newContent = replaceStaticWithAsset({
2424
initialContent,
2525
learningContextId,
2626
});
2727
const solutionContent = newContent || initialContent;
28+
2829
let staticRootUrl;
2930
if (isLibrary) {
30-
staticRootUrl = `${getConfig().STUDIO_BASE_URL }/library_assets/blocks/${ blockId }/`;
31+
staticRootUrl = `${getConfig().STUDIO_BASE_URL}/library_assets/blocks/${blockId}/`;
3132
}
33+
3234
if (!refReady) { return null; }
35+
3336
return (
3437
<div className="tinyMceWidget mt-4 text-primary-500">
3538
<div className="h4 mb-3">
@@ -57,22 +60,4 @@ const ExplanationWidget = ({
5760
);
5861
};
5962

60-
ExplanationWidget.propTypes = {
61-
// redux
62-
// eslint-disable-next-line
63-
settings: PropTypes.any.isRequired,
64-
learningContextId: PropTypes.string.isRequired,
65-
images: PropTypes.shape({}).isRequired,
66-
isLibrary: PropTypes.bool.isRequired,
67-
blockId: PropTypes.string.isRequired,
68-
};
69-
export const mapStateToProps = (state) => ({
70-
settings: selectors.problem.settings(state),
71-
learningContextId: selectors.app.learningContextId(state),
72-
images: selectors.app.images(state),
73-
isLibrary: selectors.app.isLibrary(state),
74-
blockId: selectors.app.blockId(state),
75-
});
76-
77-
export const ExplanationWidgetInternal = ExplanationWidget; // For testing only
78-
export default connect(mapStateToProps)(ExplanationWidget);
63+
export default ExplanationWidget;

src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.test.tsx

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,8 @@
11
import React from 'react';
2-
import { render, screen, initializeMocks } from '@src/testUtils';
3-
import ExplanationWidget from '.';
4-
5-
jest.mock('../../../../../data/redux', () => ({
6-
__esModule: true,
7-
default: jest.fn(),
8-
selectors: {
9-
problem: {
10-
settings: jest.fn(state => ({ question: state })),
11-
},
12-
app: {
13-
learningContextId: jest.fn(state => ({ learningContextId: state })),
14-
images: jest.fn(state => ({ images: state })),
15-
isLibrary: jest.fn(state => ({ isLibrary: state })),
16-
blockId: jest.fn(state => ({ blockId: state })),
17-
},
18-
},
19-
thunkActions: {
20-
video: {
21-
importTranscript: jest.fn(),
22-
},
23-
},
24-
}));
2+
import { screen, initializeMocks } from '@src/testUtils';
3+
import editorRender from '../../../../../modifiedEditorTestRender';
4+
import ExplanationWidget from './index';
5+
import { initializeStore } from '../../../../../data/redux';
256

267
jest.mock('../../../../../sharedComponents/TinyMceWidget/hooks', () => ({
278
...jest.requireActual('../../../../../sharedComponents/TinyMceWidget/hooks'),
@@ -36,19 +17,27 @@ jest.mock('../../../../../sharedComponents/TinyMceWidget', () => ({
3617
default: () => <div>TinyMceWidget</div>,
3718
}));
3819

39-
describe('SolutionWidget', () => {
40-
const props = {
20+
const initialState = {
21+
problem: {
4122
settings: { solutionExplanation: 'This is my solution' },
23+
},
24+
app: {
4225
learningContextId: 'course+org+run',
4326
images: {},
4427
isLibrary: false,
4528
blockId: 'block-v1:Org+TS100+24+type@html+block@12345',
46-
};
29+
},
30+
};
31+
32+
describe('SolutionWidget', () => {
4733
beforeEach(() => {
48-
initializeMocks();
34+
initializeMocks({
35+
initializeStore,
36+
initialState,
37+
});
4938
});
5039
test('renders correct default', () => {
51-
render(<ExplanationWidget {...props} />);
40+
editorRender(<ExplanationWidget />, { initialState });
5241
expect(screen.getByText('Explanation')).toBeInTheDocument();
5342
expect(screen.getByText('Provide an explanation for the correct answer')).toBeInTheDocument();
5443
expect(screen.getByText('TinyMceWidget')).toBeInTheDocument();
Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,40 @@
11
import React from 'react';
2-
import PropTypes from 'prop-types';
3-
import { connect } from 'react-redux';
4-
import { injectIntl, FormattedMessage, intlShape } from '@edx/frontend-platform/i18n';
2+
import { useSelector } from 'react-redux';
3+
import { useIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
54
import { getConfig } from '@edx/frontend-platform';
65

76
import { selectors } from '../../../../../data/redux';
87
import messages from './messages';
98
import TinyMceWidget from '../../../../../sharedComponents/TinyMceWidget';
10-
import { prepareEditorRef, replaceStaticWithAsset } from '../../../../../sharedComponents/TinyMceWidget/hooks';
9+
import {
10+
prepareEditorRef,
11+
replaceStaticWithAsset,
12+
} from '../../../../../sharedComponents/TinyMceWidget/hooks';
13+
14+
const QuestionWidget = () => {
15+
const intl = useIntl();
16+
const question = useSelector(selectors.problem.question);
17+
const learningContextId = useSelector(selectors.app.learningContextId);
18+
const images = useSelector(selectors.app.images);
19+
const isLibrary = useSelector(selectors.app.isLibrary);
20+
const blockId = useSelector(selectors.app.blockId);
1121

12-
const QuestionWidget = ({
13-
// redux
14-
question,
15-
learningContextId,
16-
images,
17-
isLibrary,
18-
blockId,
19-
// injected
20-
intl,
21-
}) => {
2222
const { editorRef, refReady, setEditorRef } = prepareEditorRef();
23+
2324
const initialContent = question;
2425
const newContent = replaceStaticWithAsset({
2526
initialContent,
2627
learningContextId,
2728
});
2829
const questionContent = newContent || initialContent;
30+
2931
let staticRootUrl;
3032
if (isLibrary) {
31-
staticRootUrl = `${getConfig().STUDIO_BASE_URL }/library_assets/blocks/${ blockId }/`;
33+
staticRootUrl = `${getConfig().STUDIO_BASE_URL}/library_assets/blocks/${blockId}/`;
3234
}
35+
3336
if (!refReady) { return null; }
37+
3438
return (
3539
<div className="tinyMceWidget">
3640
<div className="h4 mb-3">
@@ -55,23 +59,4 @@ const QuestionWidget = ({
5559
);
5660
};
5761

58-
QuestionWidget.propTypes = {
59-
// redux
60-
question: PropTypes.string.isRequired,
61-
learningContextId: PropTypes.string.isRequired,
62-
images: PropTypes.shape({}).isRequired,
63-
isLibrary: PropTypes.bool.isRequired,
64-
blockId: PropTypes.string.isRequired,
65-
// injected
66-
intl: intlShape.isRequired,
67-
};
68-
export const mapStateToProps = (state) => ({
69-
question: selectors.problem.question(state),
70-
learningContextId: selectors.app.learningContextId(state),
71-
images: selectors.app.images(state),
72-
isLibrary: selectors.app.isLibrary(state),
73-
blockId: selectors.app.blockId(state),
74-
});
75-
76-
export const QuestionWidgetInternal = QuestionWidget; // For testing only
77-
export default injectIntl(connect(mapStateToProps)(QuestionWidget));
62+
export default QuestionWidget;

src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.test.tsx

Lines changed: 16 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,8 @@
11
import React from 'react';
2-
import { render, screen, initializeMocks } from '@src/testUtils';
3-
import { formatMessage } from '@src/editors/testUtils';
4-
import { QuestionWidgetInternal as QuestionWidget } from '.';
5-
6-
jest.mock('@src/editors/data/redux', () => ({
7-
__esModule: true,
8-
default: jest.fn(),
9-
actions: {
10-
problem: {
11-
updateQuestion: jest.fn().mockName('actions.problem.updateQuestion'),
12-
},
13-
},
14-
selectors: {
15-
app: {
16-
learningContextId: jest.fn(state => ({ learningContextId: state })),
17-
images: jest.fn(state => ({ images: state })),
18-
isLibrary: jest.fn(state => ({ isLibrary: state })),
19-
blockId: jest.fn(state => ({ blockId: state })),
20-
},
21-
problem: {
22-
question: jest.fn(state => ({ question: state })),
23-
},
24-
},
25-
thunkActions: {
26-
video: {
27-
importTranscript: jest.fn(),
28-
},
29-
},
30-
}));
2+
import { screen, initializeMocks } from '@src/testUtils';
3+
import editorRender from '../../../../../modifiedEditorTestRender';
4+
import { initializeStore } from '../../../../../data/redux';
5+
import QuestionWidget from '.';
316

327
jest.mock('@src/editors/sharedComponents/TinyMceWidget/hooks', () => ({
338
...jest.requireActual('../../../../../sharedComponents/TinyMceWidget/hooks'),
@@ -39,23 +14,28 @@ jest.mock('@src/editors/sharedComponents/TinyMceWidget/hooks', () => ({
3914

4015
jest.mock('@src/editors/sharedComponents/TinyMceWidget', () => ('TinyMceWidget'));
4116

42-
describe('QuestionWidget', () => {
43-
const props = {
17+
const initialState = {
18+
problem: {
4419
question: 'This is my question',
45-
updateQuestion: jest.fn(),
20+
},
21+
app: {
4622
learningContextId: 'course+org+run',
4723
images: {},
4824
isLibrary: false,
4925
blockId: '',
50-
// injected
51-
intl: { formatMessage },
52-
};
26+
},
27+
};
28+
29+
describe('QuestionWidget', () => {
30+
beforeEach(() => {
31+
initializeMocks({ initialState, initializeStore });
32+
});
5333
describe('render', () => {
5434
beforeEach(() => {
5535
initializeMocks();
5636
});
5737
test('renders correct default', () => {
58-
render(<QuestionWidget {...props} />);
38+
editorRender(<QuestionWidget />, { initialState });
5939
expect(screen.getByText('Question')).toBeInTheDocument();
6040
});
6141
});

0 commit comments

Comments
 (0)