diff --git a/src/views/preview/comment/comment.scss b/src/views/preview/comment/comment.scss index b3b9fab3d..060d1e9a8 100644 --- a/src/views/preview/comment/comment.scss +++ b/src/views/preview/comment/comment.scss @@ -275,6 +275,10 @@ } } +.compose-disabled { + opacity: .5; +} + .comments-root-reply { margin-bottom: 1.5rem; } diff --git a/src/views/preview/comment/compose-comment.jsx b/src/views/preview/comment/compose-comment.jsx index f05a5eb24..3fecfe53e 100644 --- a/src/views/preview/comment/compose-comment.jsx +++ b/src/views/preview/comment/compose-comment.jsx @@ -38,8 +38,8 @@ class ComposeComment extends React.Component { 'handleCancel', 'handleInput', 'handleMuteClose', - 'handleMuteOpen' - + 'handleMuteOpen', + 'isMuted' ]); this.state = { message: '', @@ -115,6 +115,10 @@ class ComposeComment extends React.Component { return Math.ceil(((timeStampInSec * 1000) - Date.now()) / (60 * 1000)); } + isMuted () { + return this.state.muteExpiresAt * 1000 > Date.now(); + } + handleMuteClose () { this.setState({ muteOpen: false @@ -163,10 +167,10 @@ class ComposeComment extends React.Component { render () { return ( - {this.state.status === ComposeStatus.REJECTED_MUTE ? ( + {this.isMuted() ? ( -

Scratch thinks your comment was disrespectful.

+

Scratch thinks your most recent comment was disrespectful.

For the next {this.convertToMinutesFromNow(this.state.muteExpiresAt)} minutes you won't be able to post comments. @@ -182,7 +186,10 @@ class ComposeComment extends React.Component { ) : null }

@@ -205,6 +212,7 @@ class ComposeComment extends React.Component { className={classNames('compose-input', MAX_COMMENT_LENGTH - this.state.message.length >= 0 ? 'compose-valid' : 'compose-invalid')} + disabled={this.state.status === ComposeStatus.REJECTED_MUTE} handleUpdate={onUpdate} name="compose-comment" type="textarea" diff --git a/test/unit/components/compose-comment.test.jsx b/test/unit/components/compose-comment.test.jsx index 0d35d191d..804c44ba3 100644 --- a/test/unit/components/compose-comment.test.jsx +++ b/test/unit/components/compose-comment.test.jsx @@ -66,23 +66,73 @@ describe('Compose Comment test', () => { expect(component.find('FlexRow.compose-error-row').exists()).toEqual(false); }); - test('Comment Status shows when state is REJECTED_MUTE ', () => { + test('Comment Status shows when mute expiration in the future ', () => { + const realDateNow = Date.now.bind(global.Date); + global.Date.now = () => 0; const component = getComposeCommentWrapper({}); const commentInstance = component.instance(); - commentInstance.setState({status: 'REJECTED_MUTE'}); + commentInstance.setState({muteExpiresAt: 100}); component.update(); expect(component.find('FlexRow.compose-comment').exists()).toEqual(true); expect(component.find('MuteModal').exists()).toEqual(false); expect(component.find('CommentingStatus').exists()).toEqual(true); + global.Date.now = realDateNow; + }); + test('Comment Status shows when user just submitted a comment that got them muted', () => { + const realDateNow = Date.now.bind(global.Date); + global.Date.now = () => 0; + const component = getComposeCommentWrapper({}); + const commentInstance = component.instance(); + commentInstance.setState({ + status: 'REJECTED_MUTE', + muteExpiresAt: 100 + }); + component.update(); + expect(component.find('FlexRow.compose-comment').exists()).toEqual(true); + expect(component.find('MuteModal').exists()).toEqual(false); + expect(component.find('CommentingStatus').exists()).toEqual(true); + // Compose box is disabled + expect(component.find('InplaceInput.compose-input').exists()).toEqual(true); + expect(component.find('InplaceInput.compose-input').props().disabled).toBe(true); + global.Date.now = realDateNow; + }); + test('Comment Error does not show for mutes', () => { + const realDateNow = Date.now.bind(global.Date); + global.Date.now = () => 0; + const component = getComposeCommentWrapper({}); + const commentInstance = component.instance(); + commentInstance.setState({ + status: 'REJECTED_MUTE', + error: 'a mute error' + }); + component.update(); + expect(component.find('FlexRow.compose-error-row').exists()).toEqual(false); + expect(component.find('FlexRow.compose-comment').exists()).toEqual(true); + global.Date.now = realDateNow; + }); + test('Comment Error does show for non-mute errors', () => { + const component = getComposeCommentWrapper({}); + const commentInstance = component.instance(); + commentInstance.setState({ + error: 'some error', + status: 'FLOOD' + }); + component.update(); + expect(component.find('FlexRow.compose-error-row').exists()).toEqual(true); + expect(component.find('FlexRow.compose-comment').exists()).toEqual(true); + expect(component.find('InplaceInput.compose-input').exists()).toEqual(true); + expect(component.find('InplaceInput.compose-input').props().disabled).toBe(false); }); test('Mute Modal shows when muteOpen is true ', () => { + const realDateNow = Date.now.bind(global.Date); + global.Date.now = () => 0; const component = getComposeCommentWrapper({}); const commentInstance = component.instance(); commentInstance.setState({muteOpen: true}); component.update(); - expect(component.find('FlexRow.compose-comment').exists()).toEqual(true); expect(component.find('MuteModal').exists()).toEqual(true); + global.Date.now = realDateNow; }); test('shouldShowMuteModal is false when list is undefined ', () => { @@ -130,4 +180,32 @@ describe('Compose Comment test', () => { global.Date.now = realDateNow; }); + test('isMuted: expiration is in the future ', () => { + const realDateNow = Date.now.bind(global.Date); + global.Date.now = () => 0; // Set "now" to 0 for easier testing. + + const commentInstance = getComposeCommentWrapper({}).instance(); + commentInstance.setState({muteExpiresAt: 100}); + expect(commentInstance.isMuted()).toBe(true); + global.Date.now = realDateNow; + }); + + test('isMuted: expiration is in the past ', () => { + const realDateNow = Date.now.bind(global.Date); + global.Date.now = () => 0; + + const commentInstance = getComposeCommentWrapper({}).instance(); + commentInstance.setState({muteExpiresAt: -100}); + expect(commentInstance.isMuted()).toBe(false); + global.Date.now = realDateNow; + }); + + test('isMuted: expiration is not set ', () => { + const realDateNow = Date.now.bind(global.Date); + global.Date.now = () => 0; + + const commentInstance = getComposeCommentWrapper({}).instance(); + expect(commentInstance.isMuted()).toBe(false); + global.Date.now = realDateNow; + }); });