Repository: zulip/zulip

Issue:
Message displays weird behaviour when using /me, newline, and quote mark after editing
When I send a message and edit it with text that contains `/me`, `newline`, and quote mark, the message displays weird behaviour.

See https://chat.zulip.org/#narrow/stream/issues/topic/end.20of.20message.20feed for further information.

![meedit](https://user-images.githubusercontent.com/20320125/30358231-77b9ad3c-986d-11e7-99f0-cbeecb659557.gif)

How to reproduce:
1. Create a message, the content is up to you. For example:
```
up to you
```
2. Send the message.
3. Edit the message, now change the content into something that contains `/me`, `newline`, and quotemark. For example:
![screenshot_20170913_101940](https://user-images.githubusercontent.com/20320125/30358173-15c97c4c-986d-11e7-8ba5-61ed40f1d5ad.png)
4. Save the message

Then you will see the message displays weird behaviour, like this:
![screenshot_20170913_132552](https://user-images.githubusercontent.com/20320125/30362633-232c0188-9887-11e7-88de-ffcea7928727.png)

This weird behaviour becomes normal when the user reloads the page.

Expected behaviour:
The message shouldn't display as `/me` message, it should be displayed as a normal message.


Discussion:
@zulipbot claim
Welcome to Zulip, @msdinit! We just sent you an invite to collaborate on this repository at https://github.com/zulip/zulip/invitations. Please accept this invite in order to claim this issue and begin a fun, rewarding experience contributing to Zulip!

Here's some tips to get you off to a good start:
* Join me on the [Zulip developers' server](https://chat.zulip.org), to get help, chat about this issue, and meet the other developers.
* Sign the [Dropbox Contributor License Agreement](https://opensource.dropbox.com/cla/), so that Zulip can use your code.
* [Unwatch this repository](https://help.github.com/articles/unwatching-repositories/), so that you don't get 100 emails a day.

As you work on this issue, you'll also want to refer to the [Zulip code contribution guide](http://zulip.readthedocs.io/en/latest/index.html#code-contribution-guide), as well as the rest of the developer documentation on that site.


See you on the other side (that is, the pull request side)!
Hello @msdinit, you have been unassigned from this issue because you have not updated this issue or any referenced pull requests for over 10 days.

You can reclaim this issue or claim any other issue by commenting `@zulipbot claim` on that issue.

Thanks for your contributions, and hope to see you again soon!
@zulipbot claim
Hello @wjkg, you claimed this issue to work on it, but this issue and any referenced pull requests haven't been updated for 10 days. Are you still working on this issue?

If so, please update this issue by leaving a comment on this issue to let me know that you're still working on it. Otherwise, I'll automatically remove you from this issue in 4 days.

If you've decided to work on something else, simply comment `@zulipbot abandon` so that someone else can claim it and continue from where you left off.

Thank you for your valuable contributions to Zulip!

<!-- inactiveWarning -->

Resolving patch:
diff --git a/zerver/lib/actions.py b/zerver/lib/actions.py
--- a/zerver/lib/actions.py
+++ b/zerver/lib/actions.py
@@ -3558,6 +3558,7 @@ def do_update_message(user_profile: UserProfile, message: Message, topic_name: O
         event["content"] = content
         event["rendered_content"] = rendered_content
         event['prev_rendered_content_version'] = message.rendered_content_version
+        event['is_me_message'] = Message.is_status_message(content, rendered_content)
 
         prev_content = edit_history_event['prev_content']
         if Message.content_has_attachment(prev_content) or Message.content_has_attachment(message.content):


Test patch:
diff --git a/frontend_tests/node_tests/compose.js b/frontend_tests/node_tests/compose.js
--- a/frontend_tests/node_tests/compose.js
+++ b/frontend_tests/node_tests/compose.js
@@ -1281,6 +1281,14 @@ function test_with_mock_socket(test_params) {
             };
         }
 
+        function setup_mock_markdown_is_status_message(msg_content, msg_rendered, return_val) {
+            markdown.is_status_message = function (content, rendered) {
+                assert.equal(content, msg_content);
+                assert.equal(rendered, msg_rendered);
+                return return_val;
+            };
+        }
+
         function test_post_success(success_callback) {
             var resp = {
                 rendered: 'Server: foobarfoobar',
@@ -1338,6 +1346,7 @@ function test_with_mock_socket(test_params) {
         $("#compose-textarea").val('```foobarfoobar```');
         setup_visibilities();
         setup_mock_markdown_contains_backend_only_syntax('```foobarfoobar```', true);
+        setup_mock_markdown_is_status_message('```foobarfoobar```', 'Server: foobarfoobar', false);
         loading.make_indicator = function (spinner) {
             assert.equal(spinner, $("#markdown_preview_spinner"));
             make_indicator_called = true;
@@ -1353,6 +1362,7 @@ function test_with_mock_socket(test_params) {
         $("#compose-textarea").val('foobarfoobar');
         setup_visibilities();
         setup_mock_markdown_contains_backend_only_syntax('foobarfoobar', false);
+        setup_mock_markdown_is_status_message('foobarfoobar', 'Server: foobarfoobar', false);
         mock_channel_post('foobarfoobar');
         markdown.apply_markdown = function (msg) {
             assert.equal(msg.raw_content, 'foobarfoobar');
diff --git a/frontend_tests/node_tests/markdown.js b/frontend_tests/node_tests/markdown.js
--- a/frontend_tests/node_tests/markdown.js
+++ b/frontend_tests/node_tests/markdown.js
@@ -351,6 +351,12 @@ var bugdown_data = JSON.parse(fs.readFileSync(path.join(__dirname, '../../zerver
     assert.equal(message.is_me_message, true);
     assert(!message.unread);
 
+    input = "/me is testing\nthis";
+    message = {subject: "No links here", raw_content: input};
+    markdown.apply_markdown(message);
+
+    assert.equal(message.is_me_message, false);
+
     input = "testing this @**all** @**Cordelia Lear**";
     message = {subject: "No links here", raw_content: input};
     markdown.apply_markdown(message);
diff --git a/zerver/tests/test_bugdown.py b/zerver/tests/test_bugdown.py
--- a/zerver/tests/test_bugdown.py
+++ b/zerver/tests/test_bugdown.py
@@ -738,6 +738,14 @@ def test_is_status_message(self) -> None:
         )
         self.assertTrue(Message.is_status_message(content, rendered_content))
 
+        content = '/me writes a second line\nline'
+        rendered_content = render_markdown(msg, content)
+        self.assertEqual(
+            rendered_content,
+            '<p>/me writes a second line<br>\nline</p>'
+        )
+        self.assertFalse(Message.is_status_message(content, rendered_content))
+
     def test_alert_words(self) -> None:
         user_profile = self.example_user('othello')
         do_set_alert_words(user_profile, ["ALERTWORD", "scaryword"])
diff --git a/zerver/tests/test_events.py b/zerver/tests/test_events.py
--- a/zerver/tests/test_events.py
+++ b/zerver/tests/test_events.py
@@ -679,6 +679,7 @@ def get_checker(check_gravatar: Validator) -> Validator:
             ('subject', check_string),
             ('subject_links', check_list(None)),
             ('user_id', check_int),
+            ('is_me_message', check_bool),
         ])
 
         message = Message.objects.order_by('-id')[0]