mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-23 15:47:53 -05:00
add tests for feedback form, clean-up form
This commit is contained in:
parent
f2a3dfda1b
commit
9df36b0fcf
4 changed files with 154 additions and 88 deletions
|
@ -32,18 +32,15 @@ class MuteModal extends React.Component {
|
|||
'handleNext',
|
||||
'handlePrevious',
|
||||
'handleGoToFeedback',
|
||||
'handleFeedbackInput',
|
||||
'handleFeedbackSubmit',
|
||||
'handleSetFeedbackRef',
|
||||
'handleValidSubmit',
|
||||
'validateFeedback'
|
||||
]);
|
||||
this.numSteps = 2;
|
||||
if (this.props.showWarning) {
|
||||
this.numSteps++;
|
||||
}
|
||||
|
||||
this.numSteps = this.props.showWarning ? steps.BAN_WARNING : steps.MUTE_INFO;
|
||||
|
||||
this.state = {
|
||||
step: 0,
|
||||
feedback: ''
|
||||
step: 0
|
||||
};
|
||||
}
|
||||
handleNext () {
|
||||
|
@ -64,22 +61,16 @@ class MuteModal extends React.Component {
|
|||
});
|
||||
}
|
||||
|
||||
handleFeedbackSubmit () {
|
||||
const noError = !this.validateFeedback(this.state.feedback);
|
||||
// called after feedback validation passes with no errors
|
||||
handleValidSubmit (formData, formikBag) {
|
||||
formikBag.setSubmitting(false); // formik makes us do this ourselves
|
||||
|
||||
if (noError) {
|
||||
/* eslint-disable no-console */
|
||||
console.log(this.state.feedback);
|
||||
/* eslint-enable no-console */
|
||||
this.setState({
|
||||
step: steps.FEEDBACK_SENT
|
||||
});
|
||||
}
|
||||
}
|
||||
/* eslint-disable no-console */
|
||||
console.log(formData.feedback);
|
||||
/* eslint-enable no-console */
|
||||
|
||||
handleFeedbackInput (feedback) {
|
||||
this.setState({
|
||||
feedback: feedback
|
||||
step: steps.FEEDBACK_SENT
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -89,14 +80,24 @@ class MuteModal extends React.Component {
|
|||
|
||||
validateFeedback (feedback) {
|
||||
if (feedback.length === 0) {
|
||||
return 'Can\'t be empty';
|
||||
return this.props.intl.formatMessage({id: 'comments.muted.feedbackEmpty'});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
render () {
|
||||
const finalStep = this.showWarning ? steps.BAN_WARNING : steps.MUTE_INFO;
|
||||
const feedbackPrompt = (
|
||||
<p className="feedback-prompt">
|
||||
<FormattedMessage
|
||||
id="comments.muted.mistake"
|
||||
values={{feedbackLink: (
|
||||
<a onClick={this.handleGoToFeedback}>
|
||||
<FormattedMessage id="comments.muted.feedbackLinkText" />
|
||||
</a>
|
||||
)}}
|
||||
/>
|
||||
</p>
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
|
@ -142,16 +143,7 @@ class MuteModal extends React.Component {
|
|||
)}}
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="comments.muted.mistake"
|
||||
values={{feedbackLink: (
|
||||
<a onClick={this.handleGoToFeedback}>
|
||||
<FormattedMessage id="comments.muted.feedbackLinkText" />
|
||||
</a>
|
||||
)}}
|
||||
/>
|
||||
</p>
|
||||
{this.state.step === this.numSteps ? feedbackPrompt : null}
|
||||
</MuteStep>
|
||||
<MuteStep
|
||||
bottomImg="/svgs/commenting/warning.svg"
|
||||
|
@ -168,6 +160,7 @@ class MuteModal extends React.Component {
|
|||
)}}
|
||||
/>
|
||||
</p>
|
||||
{this.state.step === this.numSteps ? feedbackPrompt : null}
|
||||
</MuteStep>
|
||||
<MuteStep
|
||||
header={this.props.intl.formatMessage({id: 'comments.muted.mistakeHeader'})}
|
||||
|
@ -182,43 +175,49 @@ class MuteModal extends React.Component {
|
|||
validate={this.validateFeedback}
|
||||
validateOnBlur={false}
|
||||
validateOnChange={false}
|
||||
onSubmit={this.handleValidSubmit}
|
||||
>
|
||||
{props => {
|
||||
const {
|
||||
errors,
|
||||
handleSubmit,
|
||||
setFieldError,
|
||||
setFieldTouched,
|
||||
setFieldValue,
|
||||
validateField
|
||||
} = props;
|
||||
return (
|
||||
<FormikInput
|
||||
autoCapitalize="off"
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
className={classNames(
|
||||
'compose-feedback',
|
||||
)}
|
||||
component="textarea"
|
||||
error={errors.feedback}
|
||||
id="feedback"
|
||||
maxLength={MAX_FEEDBACK_LENGTH}
|
||||
name="feedback"
|
||||
rows={5}
|
||||
type="text"
|
||||
validate={this.validateFeedback}
|
||||
validationClassName="validation-full-width-input"
|
||||
/* eslint-disable react/jsx-no-bind */
|
||||
onBlur={() => validateField('feedback')}
|
||||
onChange={e => {
|
||||
setFieldValue('feedback', e.target.value);
|
||||
setFieldTouched('feedback');
|
||||
setFieldError('feedback', null);
|
||||
this.handleFeedbackInput(e.target.value);
|
||||
}}
|
||||
/* eslint-enable react/jsx-no-bind */
|
||||
onSetRef={this.handleSetFeedbackRef}
|
||||
/>
|
||||
<form
|
||||
id="feedback-form"
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
<FormikInput
|
||||
autoCapitalize="off"
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
className={classNames(
|
||||
'compose-feedback',
|
||||
)}
|
||||
component="textarea"
|
||||
error={errors.feedback}
|
||||
id="feedback"
|
||||
maxLength={MAX_FEEDBACK_LENGTH}
|
||||
name="feedback"
|
||||
rows={5}
|
||||
type="text"
|
||||
validate={this.validateFeedback}
|
||||
validationClassName="validation-full-width-input"
|
||||
/* eslint-disable react/jsx-no-bind */
|
||||
onBlur={() => validateField('feedback')}
|
||||
onChange={e => {
|
||||
setFieldValue('feedback', e.target.value);
|
||||
setFieldTouched('feedback');
|
||||
setFieldError('feedback', null);
|
||||
}}
|
||||
/* eslint-enable react/jsx-no-bind */
|
||||
onSetRef={this.handleSetFeedbackRef}
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
}}
|
||||
</Formik>
|
||||
|
@ -242,7 +241,7 @@ class MuteModal extends React.Component {
|
|||
this.state.step === steps.USER_FEEDBACK ? 'feedback-nav' : 'mute-nav'
|
||||
)}
|
||||
>
|
||||
{this.state.step >= finalStep ? (
|
||||
{this.state.step >= this.numSteps ? (
|
||||
<Button
|
||||
className={classNames('close-button')}
|
||||
onClick={this.props.onRequestClose}
|
||||
|
@ -281,7 +280,8 @@ class MuteModal extends React.Component {
|
|||
className={classNames(
|
||||
'send-button',
|
||||
)}
|
||||
onClick={this.handleFeedbackSubmit}
|
||||
form="feedback-form"
|
||||
type="submit"
|
||||
>
|
||||
<div className="action-button-text">
|
||||
<FormattedMessage id="general.send" />
|
||||
|
|
|
@ -60,16 +60,9 @@
|
|||
padding: 24px;
|
||||
|
||||
button {
|
||||
// min-width: 100px;
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
// .action-button-text {
|
||||
// span {
|
||||
// text-align: center;
|
||||
// }
|
||||
// }
|
||||
|
||||
.close-button {
|
||||
background-color: $ui-dark-gray;
|
||||
}
|
||||
|
@ -87,16 +80,15 @@
|
|||
|
||||
.feedback-text {
|
||||
text-align: center;
|
||||
max-width: 360px;
|
||||
}
|
||||
|
||||
textarea, .row-with-tooltip {
|
||||
#feedback-form, textarea {
|
||||
height: 180px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
textarea {
|
||||
padding: 16px;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.character-limit {
|
||||
|
@ -104,7 +96,7 @@
|
|||
}
|
||||
|
||||
.validation-message {
|
||||
top: 30%;
|
||||
margin-left: 4rem;
|
||||
top: 52px;
|
||||
left: 36px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -365,6 +365,7 @@
|
|||
"comments.muted.thanksFeedback": "Thanks for letting us know!",
|
||||
"comments.muted.thanksInfo": "Your feedback will help us make Scratch better.",
|
||||
"comments.muted.characterLimit": "500 characters max",
|
||||
"comments.muted.feedbackEmpty": "Can't be empty",
|
||||
|
||||
"social.embedLabel": "Embed",
|
||||
"social.copyEmbedLinkText": "Copy embed",
|
||||
|
|
|
@ -33,19 +33,22 @@ describe('MuteModalTest', () => {
|
|||
expect(component.find('button.back-button').exists()).toEqual(false);
|
||||
});
|
||||
|
||||
// test('Mute Modal shows extra showWarning step', () => {
|
||||
// const component = mountWithIntl(
|
||||
// <MuteModal
|
||||
// showWarning
|
||||
// muteModalMessages={defaultMessages}
|
||||
// />
|
||||
// );
|
||||
// component.find('MuteModal').instance()
|
||||
// .setState({step: 2});
|
||||
// component.update();
|
||||
// expect(component.find('MuteStep').prop('bottomImg')).toEqual('/svgs/commenting/warning.svg');
|
||||
// expect(component.find('MuteStep').prop('totalSteps')).toEqual(3);
|
||||
// });
|
||||
test('Mute Modal shows extra showWarning step', () => {
|
||||
const component = mountWithIntl(
|
||||
<MuteModal
|
||||
showWarning
|
||||
muteModalMessages={defaultMessages}
|
||||
/>
|
||||
);
|
||||
component.find('MuteModal').instance()
|
||||
.setState({step: 1});
|
||||
expect(component.find('button.next-button').exists()).toEqual(true);
|
||||
expect(component.find('button.next-button').getElements()[0].props.onClick)
|
||||
.toEqual(component.find('MuteModal').instance().handleNext);
|
||||
component.find('MuteModal').instance()
|
||||
.handleNext();
|
||||
expect(component.find('MuteModal').instance().state.step).toEqual(2);
|
||||
});
|
||||
|
||||
test('Mute Modal shows back & close button on last step', () => {
|
||||
const component = mountWithIntl(
|
||||
|
@ -113,4 +116,74 @@ describe('MuteModalTest', () => {
|
|||
component.instance().handlePrevious();
|
||||
expect(component.instance().state.step).toBe(0);
|
||||
});
|
||||
|
||||
test('Mute modal asks for feedback', () => {
|
||||
const component = mountWithIntl(
|
||||
<MuteModal muteModalMessages={defaultMessages} />
|
||||
);
|
||||
component.find('MuteModal').instance()
|
||||
.setState({step: 1});
|
||||
component.update();
|
||||
expect(component.find('p.feedback-prompt').exists()).toEqual(true);
|
||||
});
|
||||
|
||||
test('Mute modal asks for feedback on extra showWarning step', () => {
|
||||
const component = mountWithIntl(
|
||||
<MuteModal
|
||||
showWarning
|
||||
muteModalMessages={defaultMessages}
|
||||
/>
|
||||
);
|
||||
component.find('MuteModal').instance()
|
||||
.setState({step: 1});
|
||||
component.update();
|
||||
expect(component.find('p.feedback-prompt').exists()).toEqual(false);
|
||||
component.find('MuteModal').instance()
|
||||
.setState({step: 2});
|
||||
component.update();
|
||||
expect(component.find('p.feedback-prompt').exists()).toEqual(true);
|
||||
});
|
||||
|
||||
test('Mute modal handle go to feedback', () => {
|
||||
const component = shallowWithIntl(
|
||||
<MuteModal
|
||||
muteModalMessages={defaultMessages}
|
||||
/>
|
||||
).dive();
|
||||
component.instance().handleGoToFeedback();
|
||||
expect(component.instance().state.step).toBe(3);
|
||||
});
|
||||
|
||||
test('Mute modal empty feedback invalid', () => {
|
||||
const component = shallowWithIntl(
|
||||
<MuteModal
|
||||
muteModalMessages={defaultMessages}
|
||||
/>
|
||||
).dive();
|
||||
|
||||
const emptyError = 'comments.muted.feedbackEmpty';
|
||||
expect(component.instance().validateFeedback('')).toBe(emptyError);
|
||||
});
|
||||
|
||||
test('Mute modal non-empty feedback valid', () => {
|
||||
const component = shallowWithIntl(
|
||||
<MuteModal
|
||||
muteModalMessages={defaultMessages}
|
||||
/>
|
||||
).dive();
|
||||
|
||||
expect(component.instance().validateFeedback('some feedback here')).toBeNull();
|
||||
});
|
||||
|
||||
test('Mute modal submit feedback gives thank you step', () => {
|
||||
const component = shallowWithIntl(
|
||||
<MuteModal
|
||||
muteModalMessages={defaultMessages}
|
||||
/>
|
||||
).dive();
|
||||
const mockFormikBag = {};
|
||||
mockFormikBag.setSubmitting = jest.fn();
|
||||
component.instance().handleValidSubmit({feedback: 'something'}, mockFormikBag);
|
||||
expect(component.instance().state.step).toBe(4);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue