From 7b88e3eea7a66e2ffe5529c0a47ae9d77570d1e1 Mon Sep 17 00:00:00 2001 From: Harshit Bansal Date: Fri, 6 Oct 2017 21:16:29 +0000 Subject: [PATCH] tests: Add a test suite for verifying the mobile push notifs content. This test suite works by using the expected_output and new text_output fields in the bugdown test cases to verify that each syntax is correctly translated by this new function. Some of these translations, like strikethrough, are kinda poor; but this framework should make it easy to iterate on the formatting. Fixes: #6720. --- zerver/fixtures/markdown_test_cases.json | 183 +++++++++++++++-------- zerver/tests/test_push_notifications.py | 42 +++++- 2 files changed, 163 insertions(+), 62 deletions(-) diff --git a/zerver/fixtures/markdown_test_cases.json b/zerver/fixtures/markdown_test_cases.json index e6b155d38e..b7b7e652ed 100644 --- a/zerver/fixtures/markdown_test_cases.json +++ b/zerver/fixtures/markdown_test_cases.json @@ -4,151 +4,176 @@ "name": "codeblock_hilite", "input": "Hamlet said:\n~~~~.python \ndef speak(self):\n x = 1\n~~~~", "expected_output": "

Hamlet said:

\n
def speak(self):\n    x = 1\n
", - "marked_expected_output": "

Hamlet said:

\n
def speak(self):\n    x = 1\n
" + "marked_expected_output": "

Hamlet said:

\n
def speak(self):\n    x = 1\n
", + "text_content": "Hamlet said:\ndef speak(self):\n x = 1\n" }, { "name": "basic_paragraph", "input": "test_input", "expected_output": "

test_input

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "test_input" }, { "name": "codeblock_multiline", "input": "Hamlet once said\n~~~~\ndef func():\n x = 1\n\n y = 2\n\n z = 3\n~~~~\nAnd all was good.", "expected_output": "

Hamlet once said

\n
def func():\n    x = 1\n\n    y = 2\n\n    z = 3\n
\n\n\n

And all was good.

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "Hamlet once said\ndef func():\n x = 1\n\n y = 2\n\n z = 3\n\n\n\nAnd all was good." }, { "name": "codeblock_trailing_whitespace", "input": "Hamlet once said\n~~~~\ndef func():\n x = 1\n\n y = 2\t\t\n\n z = 3 \n~~~~\nAnd all was good.", "expected_output": "

Hamlet once said

\n
def func():\n    x = 1\n\n    y = 2\n\n    z = 3\n
\n\n\n

And all was good.

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "Hamlet once said\ndef func():\n x = 1\n\n y = 2\n\n z = 3\n\n\n\nAnd all was good." }, { "name": "codeblock_backticks", "input": "\n```\nfenced code\n```\n\n```inline code```\n", "expected_output": "
fenced code\n
\n\n\n

inline code

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "test_content": "fenced code\n\n\n\ninline code" }, { "name": "hanging_multi_codeblock", "input": "Hamlet said:\n~~~~\ndef speak(self):\n x = 1\n# Comment to make this code block longer to test Trac #1162\n~~~~\n\nThen he mentioned ````y = 4 + x**2```` and\n~~~~\ndef foobar(self):\n return self.baz()", "expected_output": "

Hamlet said:

\n
def speak(self):\n    x = 1\n# Comment to make this code block longer to test Trac #1162\n
\n\n\n

Then he mentioned y = 4 + x**2 and

\n
def foobar(self):\n    return self.baz()\n
", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "test_content": "Hamlet said:\ndef speak(self):\n x = 1\n# Comment to make this code block longer to test Trac #1162\n\n\n\nThen he mentioned y = 4 + x**2 and\ndef foobar(self):\n return self.baz()\n" }, { "name": "fenced_quote", "input": "Hamlet said:\n~~~ quote\nTo be or **not** to be.\n\nThat is the question\n~~~", "expected_output": "

Hamlet said:

\n
\n

To be or not to be.

\n

That is the question

\n
", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "Hamlet said:\n\nTo be or not to be.\nThat is the question\n" }, { "name": "fenced_nested_quote", "input": "Hamlet said:\n~~~ quote\nPolonius said:\n> This above all: to thine ownself be true,\nAnd it must follow, as the night the day,\nThou canst not then be false to any man.\n\nWhat good advice!\n~~~", "expected_output": "

Hamlet said:

\n
\n

Polonius said:

\n
\n

This above all: to thine ownself be true,
\nAnd it must follow, as the night the day,
\nThou canst not then be false to any man.

\n
\n

What good advice!

\n
", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "Hamlet said:\n\nPolonius said:\n\nThis above all: to thine ownself be true,\nAnd it must follow, as the night the day,\nThou canst not then be false to any man.\n\nWhat good advice!\n" }, { "name": "complexly_nested_quote", "input": "I heard about this second hand...\n~~~ quote\n\nHe said:\n~~~ quote\nThe customer is complaining.\n\nThey looked at this code:\n``` \ndef hello(): print 'hello\n```\nThey would prefer:\n~~~\ndef hello()\n puts 'hello'\nend\n~~~\n\nPlease advise.\n~~~\n\nShe said:\n~~~ quote\nJust send them this:\n```\necho \"hello\n\"\n```\n~~~", "expected_output": "

I heard about this second hand...

\n
\n

He said:

\n
\n

The customer is complaining.

\n

They looked at this code:

\n
def hello(): print 'hello\n
\n\n\n

They would prefer:

\n
\n

def hello()
\n puts 'hello'
\nend

\n
\n

Please advise.

\n
She said:\n~~~ quote\nJust send them this:\n```\necho "hello\n"\n```\n
", - "bugdown_matches_marked": false + "bugdown_matches_marked": false, + "text_content": "I heard about this second hand...\n\nHe said:\n\nThe customer is complaining.\nThey looked at this code:\ndef hello(): print 'hello\n\n\n\nThey would prefer:\n\ndef hello()\n puts 'hello'\nend\n\nPlease advise.\nShe said:\n~~~ quote\nJust send them this:\n```\necho \"hello\n\"\n```\n" }, { "name": "fenced_quote_with_hashtag", "input": "```quote\n# line 1\n# line 2\n```", "expected_output": "
\n

# line 1
\n# line 2

\n
", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "\n# line 1\n# line 2\n" }, { "name": "dangerous_block", "input": "xxxxxx xxxxx xxxxxxxx xxxx. x xxxx xxxxxxxxxx:\n\n```\"xxxx xxxx\\xxxxx\\xxxxxx\"```\n\nxxx xxxx xxxxx:```xx.xxxxxxx(x'^xxxx$', xx.xxxxxxxxx)```\n\nxxxxxxx'x xxxx xxxxxxxxxx ```'xxxx'```, xxxxx xxxxxxxxx xxxxx ^ xxx $ xxxxxx xxxxx xxxxxxxxxxxx xxx xxxx xx x xxxx xx xxxx xx xxx xxxxx xxxxxx?", "expected_output": "

xxxxxx xxxxx xxxxxxxx xxxx. x xxxx xxxxxxxxxx:

\n

\"xxxx xxxx\\xxxxx\\xxxxxx\"

\n

xxx xxxx xxxxx:xx.xxxxxxx(x'^xxxx$', xx.xxxxxxxxx)

\n

xxxxxxx'x xxxx xxxxxxxxxx 'xxxx', xxxxx xxxxxxxxx xxxxx ^ xxx $ xxxxxx xxxxx xxxxxxxxxxxx xxx xxxx xx x xxxx xx xxxx xx xxx xxxxx xxxxxx?

", - "bugdown_matches_marked": false + "bugdown_matches_marked": false, + "text_content": "xxxxxx xxxxx xxxxxxxx xxxx. x xxxx xxxxxxxxxx:\n\"xxxx xxxx\\xxxxx\\xxxxxx\"\nxxx xxxx xxxxx:xx.xxxxxxx(x'^xxxx$', xx.xxxxxxxxx)\nxxxxxxx'x xxxx xxxxxxxxxx 'xxxx', xxxxx xxxxxxxxx xxxxx ^ xxx $ xxxxxx xxxxx xxxxxxxxxxxx xxx xxxx xx x xxxx xx xxxx xx xxx xxxxx xxxxxx?" }, { "name": "dangerous_block", "input": "``` one ```\n\n``` two ```\n\n~~~~\nx = 1", "expected_output": "

one

\n

two

\n
x = 1\n
", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "one\ntwo\nx = 1\n" }, { "name": "four_space_code_block", "input": " def foo(): pass", "expected_output": "
def foo(): pass\n
", - "marked_expected_output": "
def foo(): pass\n
" + "marked_expected_output": "
def foo(): pass\n
", + "text_content": "def foo(): pass\n" }, { "name": "two_space_not_code_block", "input": " notcode", "expected_output": "

notcode

", - "marked_expected_output": "

notcode

" + "marked_expected_output": "

notcode

", + "text_content": "notcode" }, { "name": "ulist_standard", "input": "Some text with a list:\n\n* One item\n* Two items\n* Three items", "expected_output": "

Some text with a list:

\n", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "Some text with a list:\n\nOne item\nTwo items\nThree items\n" }, { "name": "ulist_hanging", "input": "Some text with a hanging list:\n* One item\n* Two items\n* Three items", "expected_output": "

Some text with a hanging list:

\n", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "Some text with a hanging list:\n\nOne item\nTwo items\nThree items\n" }, { "name": "ulist_hanging_mixed", "input": "Plain list\n\n* Alpha\n\n* Beta\n\nThen hang it off:\n* Ypsilon\n* Zeta", "expected_output": "

Plain list

\n\n

Then hang it off:

\n", - "bugdown_matches_marked": false + "bugdown_matches_marked": false, + "text_content": "Plain list\n\n\nAlpha\n\n\nBeta\n\n\nThen hang it off:\n\nYpsilon\nZeta\n" }, { "name": "ulist_hanging_multi", "input": "Plain list\n* Alpha\n* Beta\n\nAnd Again:\n* A\n* B\n* C\n\nOnce more for feeling:\n* Q\n* E\n* D", "expected_output": "

Plain list

\n\n

And Again:

\n\n

Once more for feeling:

\n", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "Plain list\n\nAlpha\nBeta\n\nAnd Again:\n\nA\nB\nC\n\nOnce more for feeling:\n\nQ\nE\nD\n" }, { "name": "ulist_nested_ulist_two_space_indent", "input": "Nested list\n* I am outer list\n * I am inner nested list first item\n * I am inner nested list second item", "expected_output": "

Nested list

\n", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "Nested list\n\nI am outer list\nI am inner nested list first item\nI am inner nested list second item\n\n\n" }, { "name": "ulist_list_two_space_indent", "input": "* I am outer list\n I am something inside", "expected_output": "", - "marked_expected_output": "" + "marked_expected_output": "", + "text_content": "\nI am outer list\n I am something inside\n" }, { "name": "ulist_codeblock", "input": "~~~\nint x = 3\n* 4;\n~~~", "expected_output": "
int x = 3\n* 4;\n
", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "int x = 3\n* 4;\n" }, { "name": "malformed_fence", "input": "~~~~~~~~xxxxxxxxx: xxxxxxxxxxxx xxxxx x xxxxxxxx~~~~~~", "expected_output": "

~~~~~~~~xxxxxxxxx: xxxxxxxxxxxx xxxxx x xxxxxxxx~~~~~~

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "~~~~~~~~xxxxxxxxx: xxxxxxxxxxxx xxxxx x xxxxxxxx~~~~~~" }, { "name": "strikthrough_basic", "input": "I like ~~software~~ hardware", "expected_output": "

I like software hardware

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "I like software hardware" }, { "name": "strikthrough_multiword", "input": "I ~~like software~~ love hardware", "expected_output": "

I like software love hardware

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "I like software love hardware" }, { "name": "strikthrough_multiword", "input": "I ~~ like software ~~ love hardware", "expected_output": "

I like software love hardware

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "I like software love hardware" }, { "name": "underscore_disabled", @@ -160,7 +185,8 @@ "name": "emphasis_text", "input": "*foo*", "expected_output": "

foo

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "foo" }, { "name": "emphasis_code", @@ -172,7 +198,8 @@ "name": "emphasis_with_space", "input": "A *foo bar* is a *baz quux*", "expected_output": "

A foo bar is a baz quux

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "A foo bar is a baz quux" }, { "name": "underscore_strong_disabled", @@ -184,31 +211,36 @@ "name": "star_strong", "input": "**foo**", "expected_output": "

foo

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "foo" }, { "name": "numbered_list", "input": "1. A\n 2. B", "expected_output": "

1. A
\n 2. B

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "1. A\n 2. B" }, { "name": "linkify_interference", "input": "link: xx, x xxxxx xx xxxx xx\n\n[xxxxx #xx](http://xxxxxxxxx:xxxx/xxx/xxxxxx%xxxxxx/xx/):**xxxxxxx**\n\nxxxxxxx xxxxx xxxx xxxxx:\n`xxxxxx`: xxxxxxx\n`xxxxxx`: xxxxx\n`xxxxxx`: xxxxx xxxxx", "expected_output": "

link: xx, x xxxxx xx xxxx xx

\n

xxxxx #xx:xxxxxxx

\n

xxxxxxx xxxxx xxxx xxxxx:
\nxxxxxx: xxxxxxx
\nxxxxxx: xxxxx
\nxxxxxx: xxxxx xxxxx

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "link: xx, x xxxxx xx xxxx xx\nxxxxx #xx:xxxxxxx\nxxxxxxx xxxxx xxxx xxxxx:\nxxxxxx: xxxxxxx\nxxxxxx: xxxxx\nxxxxxx: xxxxx xxxxx" }, { "name": "inline_image", "input": "Google logo today: https://www.google.com/images/srpr/logo4w.png\nKinda boring", "expected_output": "

Google logo today: https://www.google.com/images/srpr/logo4w.png
\nKinda boring

\n
", - "backend_only_rendering": true + "backend_only_rendering": true, + "text_content": "Google logo today: https:\/\/www.google.com\/images\/srpr\/logo4w.png\nKinda boring\n" }, { "name": "two_inline_images", "input": "Google logo today: https://www.google.com/images/srpr/logo4w.png\nKinda boringGoogle logo today: https://www.google.com/images/srpr/logo4w.png\nKinda boring", "expected_output": "

Google logo today: https://www.google.com/images/srpr/logo4w.png
\nKinda boringGoogle logo today: https://www.google.com/images/srpr/logo4w.png
\nKinda boring

\n
", - "backend_only_rendering": true + "backend_only_rendering": true, + "text_content": "Google logo today: https:\/\/www.google.com\/images\/srpr\/logo4w.png\nKinda boringGoogle logo today: https:\/\/www.google.com\/images\/srpr\/logo4w.png\nKinda boring\n" }, { "name": "camo", @@ -220,31 +252,36 @@ "name": "nl2br", "input": "test\nbar", "expected_output": "

test
\nbar

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "test\nbar" }, { "name": "nl2br_trailing_space", "input": "test ", "expected_output": "

test

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "test " }, { "name": "tables", "input": "This is a table:\n\nFirst Header | Second Header\n------------- | -------------\nContent Cell | Content Cell\nContent Cell | Content Cell\n", "expected_output": "

This is a table:

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
First HeaderSecond Header
Content CellContent Cell
Content CellContent Cell
", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "This is a table:\n\n\n\nFirst Header\nSecond Header\n\n\n\n\nContent Cell\nContent Cell\n\n\nContent Cell\nContent Cell\n\n\n" }, { "name": "multiline_strong", "input": "You can check out **any time you'd like\nBut you can never leave**", "expected_output": "

You can check out **any time you'd like
\nBut you can never leave**

", - "bugdown_matches_marked": false + "bugdown_matches_marked": false, + "text_content": "You can check out **any time you'd like\nBut you can never leave**" }, { "name": "many_emoji", "input": "test :smile: again :poop:\n:) foo:)bar x::y::z :wasted waste: :fakeemojithisshouldnotrender:", "expected_output": "

test :smile: again :poop:
\n:) foo:)bar x::y::z :wasted waste: :fakeemojithisshouldnotrender:

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "test \ud83d\ude04 again \ud83d\udca9\n:) foo:)bar x::y::z :wasted waste: :fakeemojithisshouldnotrender:" }, { "name": "random_emoji_1", @@ -256,7 +293,8 @@ "name": "zulip_emoji", "input": ":zulip:", "expected_output": "

\":zulip:\"

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": ":zulip:" }, { "name": "random_emoji_2", @@ -268,43 +306,50 @@ "name": "emojis_without_space", "input": ":cat:hello:dog::rabbit:", "expected_output": "

:cat:hello:dog::rabbit:

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "\ud83d\udc31hello\ud83d\udc36\ud83d\udc30" }, { "name": "emojis_newline", "input": ":cat:\n:dog:", "expected_output": "

:cat:
\n:dog:

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "\ud83d\udc31\n\ud83d\udc36" }, { "name": "not_emoji", "input": ":not_an_emoji:", "expected_output": "

:not_an_emoji:

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": ":not_an_emoji:" }, { "name": "unicode_emoji", "input": "\ud83d\udca9", "expected_output":"

:poop:

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "\ud83d\udca9" }, { "name": "two_unicode_emoji", "input": "\ud83d\udca9\ud83d\udca9", "expected_output":"

:poop::poop:<\/p>", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "\ud83d\udca9\ud83d\udca9" }, { "name": "two_unicode_emoji_separated_by_text", "input": "\ud83d\udca9 word \ud83d\udca9", "expected_output":"

:poop: word :poop:<\/p>", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "\ud83d\udca9 word \ud83d\udca9" }, { "name": "miscellaneous_symbols_and_pictographs", "input": "Merry Christmas!!\ud83c\udf84", "expected_output":"

Merry Christmas!!:christmas_tree:<\/p>", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "Merry Christmas!!\ud83c\udf84" }, { "name": "miscellaneous_and_dingbats_emoji", @@ -334,7 +379,8 @@ "name": "unicode_emojis_new_line", "input": "\ud83d\udc7d\n\ud83d\udc7d", "expected_output":"

:alien:
\n:alien:

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "\ud83d\udc7d\n\ud83d\udc7d" }, { "name": "emoji_alongside_punctuation", @@ -364,31 +410,36 @@ "name": "emojis_with_zwj_are_banned", "input": "Emojis like :man-girl-girl: which have ZWJ are banned for now.", "expected_output": "

Emojis like :man-girl-girl: which have ZWJ are banned for now.

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "Emojis like :man-girl-girl: which have ZWJ are banned for now." }, { "name": "safe_html", "input": "

stay normal

thanks", "expected_output": "

<h1>stay normal</h1> thanks

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "

stay normal<\/h1> thanks" }, { "name": "safe_html_with_simple_script_tag", "input": "", "expected_output": "

<script>alert(1)</script>

", - "bugdown_matches_marked": false + "bugdown_matches_marked": false, + "text_content": "/script>", "expected_output": "

<<script>script>evil()<</script>/script>

", - "bugdown_matches_marked": true + "bugdown_matches_marked": true, + "text_content": "<