2015-02-12 18:53:23 +00:00
require 'spec_helper'
2012-08-02 00:26:21 +00:00
2012-08-08 08:52:09 +00:00
describe GitlabMarkdownHelper do
2013-01-16 21:37:39 +00:00
include ApplicationHelper
2015-03-27 11:58:23 +00:00
2014-01-22 19:03:52 +00:00
let! ( :project ) { create ( :project ) }
2012-09-02 06:13:13 +00:00
2012-12-07 03:40:42 +00:00
let ( :user ) { create ( :user , username : 'gfm' ) }
2013-04-01 15:16:08 +00:00
let ( :commit ) { project . repository . commit }
2012-09-02 06:13:13 +00:00
let ( :issue ) { create ( :issue , project : project ) }
2013-04-25 14:15:33 +00:00
let ( :merge_request ) { create ( :merge_request , source_project : project , target_project : project ) }
2013-03-25 07:20:14 +00:00
let ( :snippet ) { create ( :project_snippet , project : project ) }
2012-09-02 06:13:13 +00:00
2015-03-27 11:58:23 +00:00
# Helper expects a current_user method.
let ( :current_user ) { user }
2012-08-02 00:26:21 +00:00
before do
2012-09-02 06:13:13 +00:00
# Helper expects a @project instance variable
@project = project
2012-08-02 00:26:21 +00:00
end
describe " # gfm " do
2012-09-02 06:13:13 +00:00
it " should forward HTML options to links " do
2015-02-12 18:17:35 +00:00
expect ( gfm ( " Fixed in #{ commit . id } " , @project , class : 'foo' ) ) .
2015-04-21 17:12:19 +00:00
to have_selector ( 'a.gfm.foo' )
2012-08-06 00:32:17 +00:00
end
2012-09-02 06:13:13 +00:00
describe " referencing multiple objects " do
2013-08-20 13:56:05 +00:00
let ( :actual ) { " ! #{ merge_request . iid } -> #{ commit . id } -> # #{ issue . iid } " }
2012-09-02 06:13:13 +00:00
it " should link to the merge request " do
2015-01-24 18:02:58 +00:00
expected = namespace_project_merge_request_path ( project . namespace , project , merge_request )
2015-02-12 18:17:35 +00:00
expect ( gfm ( actual ) ) . to match ( expected )
2012-08-02 00:26:21 +00:00
end
2012-09-02 06:13:13 +00:00
it " should link to the commit " do
2015-01-24 18:02:58 +00:00
expected = namespace_project_commit_path ( project . namespace , project , commit )
2015-02-12 18:17:35 +00:00
expect ( gfm ( actual ) ) . to match ( expected )
2012-08-02 00:26:21 +00:00
end
2012-09-02 06:13:13 +00:00
it " should link to the issue " do
2015-01-24 18:02:58 +00:00
expected = namespace_project_issue_path ( project . namespace , project , issue )
2015-02-12 18:17:35 +00:00
expect ( gfm ( actual ) ) . to match ( expected )
2012-08-02 00:26:21 +00:00
end
end
2012-09-05 20:05:20 +00:00
2015-04-13 22:05:42 +00:00
context 'parse_tasks: true' do
before ( :all ) do
@source_text_asterisk = <<-EOT.strip_heredoc
* [ ] valid unchecked task
* [ x ] valid lowercase checked task
* [ X ] valid uppercase checked task
* [ ] valid unchecked nested task
* [ x ] valid checked nested task
[ ] not an unchecked task - no list item
[ x ] not a checked task - no list item
* [ ] not an unchecked task - too many spaces
* [ x ] not a checked task - too many spaces
* [ ] not an unchecked task - no spaces
* Not a task [ ] - not at beginning
EOT
@source_text_dash = <<-EOT.strip_heredoc
- [ ] valid unchecked task
- [ x ] valid lowercase checked task
- [ X ] valid uppercase checked task
- [ ] valid unchecked nested task
- [ x ] valid checked nested task
EOT
end
it 'should render checkboxes at beginning of asterisk list items' do
rendered_text = markdown ( @source_text_asterisk , parse_tasks : true )
expect ( rendered_text ) . to match ( / <input.*checkbox.*valid unchecked task / )
expect ( rendered_text ) . to match (
/ <input.*checkbox.*valid lowercase checked task /
)
expect ( rendered_text ) . to match (
/ <input.*checkbox.*valid uppercase checked task /
)
end
it 'should render checkboxes at beginning of dash list items' do
rendered_text = markdown ( @source_text_dash , parse_tasks : true )
expect ( rendered_text ) . to match ( / <input.*checkbox.*valid unchecked task / )
expect ( rendered_text ) . to match (
/ <input.*checkbox.*valid lowercase checked task /
)
expect ( rendered_text ) . to match (
/ <input.*checkbox.*valid uppercase checked task /
)
end
it 'should render checkboxes for nested tasks' do
rendered_text = markdown ( @source_text_asterisk , parse_tasks : true )
expect ( rendered_text ) . to match (
/ <input.*checkbox.*valid unchecked nested task /
)
expect ( rendered_text ) . to match (
/ <input.*checkbox.*valid checked nested task /
)
end
it 'should not be confused by whitespace before bullets' do
rendered_text_asterisk = markdown ( @source_text_asterisk ,
parse_tasks : true )
rendered_text_dash = markdown ( @source_text_dash , parse_tasks : true )
expect ( rendered_text_asterisk ) . to match (
/ <input.*checkbox.*valid unchecked nested task /
)
expect ( rendered_text_asterisk ) . to match (
/ <input.*checkbox.*valid checked nested task /
)
expect ( rendered_text_dash ) . to match (
/ <input.*checkbox.*valid unchecked nested task /
)
expect ( rendered_text_dash ) . to match (
/ <input.*checkbox.*valid checked nested task /
)
end
it 'should not render checkboxes outside of list items' do
rendered_text = markdown ( @source_text_asterisk , parse_tasks : true )
expect ( rendered_text ) . not_to match (
/ <input.*checkbox.*not an unchecked task - no list item /
)
expect ( rendered_text ) . not_to match (
/ <input.*checkbox.*not a checked task - no list item /
)
end
it 'should not render checkboxes with invalid formatting' do
rendered_text = markdown ( @source_text_asterisk , parse_tasks : true )
expect ( rendered_text ) . not_to match (
/ <input.*checkbox.*not an unchecked task - too many spaces /
)
expect ( rendered_text ) . not_to match (
/ <input.*checkbox.*not a checked task - too many spaces /
)
expect ( rendered_text ) . not_to match (
/ <input.*checkbox.*not an unchecked task - no spaces /
)
expect ( rendered_text ) . not_to match (
/ Not a task.*<input.*checkbox.*not at beginning /
)
end
end
2012-09-02 06:13:13 +00:00
end
2012-08-02 00:26:21 +00:00
2015-04-20 19:43:27 +00:00
describe '#link_to_gfm' do
2015-01-24 18:02:58 +00:00
let ( :commit_path ) { namespace_project_commit_path ( project . namespace , project , commit ) }
2012-09-02 06:13:13 +00:00
let ( :issues ) { create_list ( :issue , 2 , project : project ) }
2012-08-02 00:26:21 +00:00
2015-04-20 19:43:27 +00:00
it 'should handle references nested in links with all the text' do
2013-08-20 13:56:05 +00:00
actual = link_to_gfm ( " This should finally fix # #{ issues [ 0 ] . iid } and # #{ issues [ 1 ] . iid } for real " , commit_path )
2015-04-20 19:43:27 +00:00
doc = Nokogiri :: HTML . parse ( actual )
2012-08-02 00:26:21 +00:00
2015-04-21 17:12:19 +00:00
# Make sure we didn't create invalid markup
expect ( doc . errors ) . to be_empty
2012-09-02 06:13:13 +00:00
# Leading commit link
2015-04-20 19:43:27 +00:00
expect ( doc . css ( 'a' ) [ 0 ] . attr ( 'href' ) ) . to eq commit_path
expect ( doc . css ( 'a' ) [ 0 ] . text ) . to eq 'This should finally fix '
2012-08-02 00:26:21 +00:00
2012-09-02 06:13:13 +00:00
# First issue link
2015-04-20 19:43:27 +00:00
expect ( doc . css ( 'a' ) [ 1 ] . attr ( 'href' ) ) .
to eq namespace_project_issue_path ( project . namespace , project , issues [ 0 ] )
expect ( doc . css ( 'a' ) [ 1 ] . text ) . to eq " # #{ issues [ 0 ] . iid } "
2012-08-02 00:28:50 +00:00
2012-09-02 06:13:13 +00:00
# Internal commit link
2015-04-20 19:43:27 +00:00
expect ( doc . css ( 'a' ) [ 2 ] . attr ( 'href' ) ) . to eq commit_path
expect ( doc . css ( 'a' ) [ 2 ] . text ) . to eq ' and '
2012-08-02 00:28:50 +00:00
2012-09-02 06:13:13 +00:00
# Second issue link
2015-04-20 19:43:27 +00:00
expect ( doc . css ( 'a' ) [ 3 ] . attr ( 'href' ) ) .
to eq namespace_project_issue_path ( project . namespace , project , issues [ 1 ] )
expect ( doc . css ( 'a' ) [ 3 ] . text ) . to eq " # #{ issues [ 1 ] . iid } "
2012-09-02 06:13:13 +00:00
# Trailing commit link
2015-04-20 19:43:27 +00:00
expect ( doc . css ( 'a' ) [ 4 ] . attr ( 'href' ) ) . to eq commit_path
expect ( doc . css ( 'a' ) [ 4 ] . text ) . to eq ' for real'
2012-08-02 00:28:50 +00:00
end
2015-04-20 19:43:27 +00:00
it 'should forward HTML options' do
2012-09-02 06:13:13 +00:00
actual = link_to_gfm ( " Fixed in #{ commit . id } " , commit_path , class : 'foo' )
2015-04-20 19:43:27 +00:00
doc = Nokogiri :: HTML . parse ( actual )
expect ( doc . css ( 'a' ) ) . to satisfy do | v |
# 'foo' gets added to all links
v . all? { | a | a . attr ( 'class' ) . match ( / foo$ / ) }
end
2012-08-02 00:28:50 +00:00
end
2012-09-19 23:42:26 +00:00
it " escapes HTML passed in as the body " do
2013-08-20 13:56:05 +00:00
actual = " This is a <h1>test</h1> - see # #{ issues [ 0 ] . iid } "
2015-02-12 18:53:23 +00:00
expect ( link_to_gfm ( actual , commit_path ) ) .
to match ( '<h1>test</h1>' )
2012-09-19 23:42:26 +00:00
end
2012-08-02 00:28:50 +00:00
end
2012-08-02 00:29:15 +00:00
describe " # markdown " do
2015-04-13 22:00:46 +00:00
# TODO (rspeicher) - This block tests multiple different contexts. Break this up!
2014-02-04 07:48:33 +00:00
it " should add ids and links to headers " do
# Test every rule except nested tags.
text = '..Ab_c-d. e..'
id = 'ab_c-d-e'
2015-02-12 18:53:23 +00:00
expect ( markdown ( " # #{ text } " ) ) .
to match ( %r{ <h1 id=" #{ id } "> #{ text } <a href="[^"]* # #{ id } "></a></h1> } )
expect ( markdown ( " # #{ text } " , { no_header_anchors : true } ) ) .
to eq ( " <h1> #{ text } </h1> " )
2014-02-04 07:48:33 +00:00
id = 'link-text'
2015-02-12 18:17:35 +00:00
expect ( markdown ( " # [link text](url) ![img alt](url) " ) ) . to match (
2014-02-04 07:48:33 +00:00
%r{ <h1 id=" #{ id } "><a href="[^"]*url">link text</a> <img[^>]*><a href="[^"]* # #{ id } "></a></h1> }
)
2012-08-02 00:29:15 +00:00
end
2015-04-21 17:12:19 +00:00
# REFERENCES (PART TWO: THE REVENGE) ---------------------------------------
it " should handle references in headers " do
actual = " \n # Working around # #{ issue . iid } \n # # Apply ! #{ merge_request . iid } "
expect ( markdown ( actual , no_header_anchors : true ) ) .
to match ( %r{ <h1[^<]*>Working around <a.+> # #{ issue . iid } </a></h1> } )
expect ( markdown ( actual , no_header_anchors : true ) ) .
to match ( %r{ <h2[^<]*>Apply <a.+>! #{ merge_request . iid } </a></h2> } )
end
2012-08-02 00:29:15 +00:00
it " should handle references in <em> " do
2013-08-20 13:56:05 +00:00
actual = " Apply _! #{ merge_request . iid } _ ASAP "
2012-09-02 06:13:13 +00:00
2015-02-12 18:53:23 +00:00
expect ( markdown ( actual ) ) .
to match ( %r{ Apply <em><a.+>! #{ merge_request . iid } </a></em> } )
2012-08-02 00:29:15 +00:00
end
2015-04-13 22:00:46 +00:00
# CODE BLOCKS -------------------------------------------------------------
2012-08-02 00:29:15 +00:00
it " should leave code blocks untouched " do
2015-04-13 22:10:49 +00:00
allow ( helper ) . to receive ( :current_user ) . and_return ( user )
2015-02-12 18:17:35 +00:00
allow ( helper ) . to receive ( :user_color_scheme_class ) . and_return ( :white )
2012-08-02 00:29:15 +00:00
2015-02-18 08:40:42 +00:00
target_html = " <pre class= \" code highlight white plaintext \" ><code>some code from $ #{ snippet . id } \n here too \n </code></pre> \n "
2012-11-28 15:05:11 +00:00
2015-04-21 17:12:19 +00:00
expect ( markdown ( " \n some code from $ #{ snippet . id } \n here too \n " ) ) .
2015-02-12 18:53:23 +00:00
to eq ( target_html )
2015-04-21 17:12:19 +00:00
expect ( markdown ( " \n ``` \n some code from $ #{ snippet . id } \n here too \n ``` \n " ) ) .
2015-02-12 18:53:23 +00:00
to eq ( target_html )
2012-08-02 00:29:15 +00:00
end
it " should leave inline code untouched " do
2015-04-21 17:12:19 +00:00
expect ( markdown ( " Don't use `$ #{ snippet . id } ` here. " ) ) .
to eq " <p>Don't use <code>$ #{ snippet . id } </code> here.</p> \n "
2012-08-02 00:29:15 +00:00
end
2013-01-16 21:08:01 +00:00
2015-04-13 22:00:46 +00:00
# REF-LIKE AUTOLINKS? -----------------------------------------------------
# Basically: Don't parse references inside `<a>` tags.
2013-01-16 21:37:39 +00:00
it " should leave ref-like autolinks untouched " do
2015-02-12 18:17:35 +00:00
expect ( markdown ( " look at http://example.tld/ # ! #{ merge_request . iid } " ) ) . to eq ( " <p>look at <a href= \" http://example.tld/ # ! #{ merge_request . iid } \" >http://example.tld/ # ! #{ merge_request . iid } </a></p> \n " )
2013-01-16 21:37:39 +00:00
end
it " should leave ref-like href of 'manual' links untouched " do
2015-04-06 15:18:47 +00:00
expect ( markdown ( " why not [inspect ! #{ merge_request . iid } ](http://example.tld/ # ! #{ merge_request . iid } ) " ) ) . to eq ( " <p>why not <a href= \" http://example.tld/ # ! #{ merge_request . iid } \" >inspect </a><a href= \" #{ namespace_project_merge_request_path ( project . namespace , project , merge_request ) } \" title= \" Merge Request: #{ merge_request . title } \" class= \" gfm gfm-merge_request \" >! #{ merge_request . iid } </a><a href= \" http://example.tld/ # ! #{ merge_request . iid } \" ></a></p> \n " )
2013-01-16 21:37:39 +00:00
end
it " should leave ref-like src of images untouched " do
2015-02-12 18:17:35 +00:00
expect ( markdown ( " screen shot: ![some image](http://example.tld/ # ! #{ merge_request . iid } ) " ) ) . to eq ( " <p>screen shot: <img src= \" http://example.tld/ # ! #{ merge_request . iid } \" alt= \" some image \" ></p> \n " )
2013-01-16 21:37:39 +00:00
end
2015-04-13 22:00:46 +00:00
# RELATIVE URLS -----------------------------------------------------------
# TODO (rspeicher): These belong in a relative link filter spec
2014-10-10 15:31:47 +00:00
2015-04-21 17:12:19 +00:00
context 'relative links' do
context 'with a valid repository' do
before do
@repository = project . repository
@ref = 'markdown'
end
it " should handle relative urls for a file in master " do
actual = " [GitLab API doc](doc/api/README.md) \n "
expected = " <p><a href= \" / #{ project . path_with_namespace } /blob/ #{ @ref } /doc/api/README.md \" >GitLab API doc</a></p> \n "
expect ( markdown ( actual ) ) . to match ( expected )
end
it " should handle relative urls for a file in master with an anchor " do
actual = " [GitLab API doc](doc/api/README.md # section) \n "
expected = " <p><a href= \" / #{ project . path_with_namespace } /blob/ #{ @ref } /doc/api/README.md # section \" >GitLab API doc</a></p> \n "
expect ( markdown ( actual ) ) . to match ( expected )
end
it " should not handle relative urls for the current file with an anchor " do
actual = " [GitLab API doc]( # section) \n "
expected = " <p><a href= \" # section \" >GitLab API doc</a></p> \n "
expect ( markdown ( actual ) ) . to match ( expected )
end
it " should handle relative urls for a directory in master " do
actual = " [GitLab API doc](doc/api) \n "
expected = " <p><a href= \" / #{ project . path_with_namespace } /tree/ #{ @ref } /doc/api \" >GitLab API doc</a></p> \n "
expect ( markdown ( actual ) ) . to match ( expected )
end
it " should handle absolute urls " do
actual = " [GitLab](https://www.gitlab.com) \n "
expected = " <p><a href= \" https://www.gitlab.com \" >GitLab</a></p> \n "
expect ( markdown ( actual ) ) . to match ( expected )
end
it " should handle relative urls in reference links for a file in master " do
actual = " [GitLab API doc][GitLab readme] \n [GitLab readme]: doc/api/README.md \n "
expected = " <p><a href= \" / #{ project . path_with_namespace } /blob/ #{ @ref } /doc/api/README.md \" >GitLab API doc</a></p> \n "
expect ( markdown ( actual ) ) . to match ( expected )
end
it " should handle relative urls in reference links for a directory in master " do
actual = " [GitLab API doc directory][GitLab readmes] \n [GitLab readmes]: doc/api/ \n "
expected = " <p><a href= \" / #{ project . path_with_namespace } /tree/ #{ @ref } /doc/api \" >GitLab API doc directory</a></p> \n "
expect ( markdown ( actual ) ) . to match ( expected )
end
it " should not handle malformed relative urls in reference links for a file in master " do
actual = " [GitLab readme]: doc/api/README.md \n "
expected = " "
expect ( markdown ( actual ) ) . to match ( expected )
end
it 'should allow whitelisted HTML tags from the user' do
actual = '<dl><dt>Term</dt><dd>Definition</dd></dl>'
expect ( markdown ( actual ) ) . to match ( actual )
end
end
2014-10-10 19:34:43 +00:00
2015-04-21 17:12:19 +00:00
context 'with an empty repository' do
before do
@project = create ( :empty_project )
@repository = @project . repository
end
it " should not touch relative urls " do
actual = " [GitLab API doc][GitLab readme] \n [GitLab readme]: doc/api/README.md \n "
expected = " <p><a href= \" doc/api/README.md \" >GitLab API doc</a></p> \n "
expect ( markdown ( actual ) ) . to match ( expected )
end
end
2014-10-10 19:34:43 +00:00
end
2015-04-13 22:00:46 +00:00
# SANITIZATION ------------------------------------------------------------
2015-04-21 17:12:19 +00:00
# TODO (rspeicher): These are testing SanitizationFilter, not `markdown`
2015-04-13 22:00:46 +00:00
2014-10-10 19:34:43 +00:00
it 'should sanitize tags that are not whitelisted' do
actual = '<textarea>no inputs allowed</textarea> <blink>no blinks</blink>'
expected = 'no inputs allowed no blinks'
expect ( markdown ( actual ) ) . to match ( expected )
expect ( markdown ( actual ) ) . not_to match ( '<.textarea>' )
expect ( markdown ( actual ) ) . not_to match ( '<.blink>' )
end
it 'should allow whitelisted tag attributes from the user' do
actual = '<a class="custom">link text</a>'
expect ( markdown ( actual ) ) . to match ( actual )
end
it 'should sanitize tag attributes that are not whitelisted' do
actual = '<a href="http://example.com/bar.html" foo="bar">link text</a>'
expected = '<a href="http://example.com/bar.html">link text</a>'
expect ( markdown ( actual ) ) . to match ( expected )
end
it 'should sanitize javascript in attributes' do
actual = %q( <a href="javascript:alert ( 'foo' ) ">link text</a> )
expected = '<a>link text</a>'
expect ( markdown ( actual ) ) . to match ( expected )
end
2012-08-02 00:29:15 +00:00
end
2013-03-14 06:31:08 +00:00
2015-04-13 22:05:42 +00:00
describe '#render_wiki_content' do
2013-03-14 06:31:08 +00:00
before do
2013-12-14 13:43:48 +00:00
@wiki = double ( 'WikiPage' )
2015-02-12 18:17:35 +00:00
allow ( @wiki ) . to receive ( :content ) . and_return ( 'wiki content' )
2013-03-14 06:31:08 +00:00
end
2013-05-19 09:13:39 +00:00
it " should use GitLab Flavored Markdown for markdown files " do
2015-02-12 18:17:35 +00:00
allow ( @wiki ) . to receive ( :format ) . and_return ( :markdown )
2013-03-14 06:31:08 +00:00
2015-02-12 18:17:35 +00:00
expect ( helper ) . to receive ( :markdown ) . with ( 'wiki content' )
2013-03-14 06:31:08 +00:00
helper . render_wiki_content ( @wiki )
end
it " should use the Gollum renderer for all other file types " do
2015-02-12 18:17:35 +00:00
allow ( @wiki ) . to receive ( :format ) . and_return ( :rdoc )
2013-12-14 13:43:48 +00:00
formatted_content_stub = double ( 'formatted_content' )
2015-02-12 18:17:35 +00:00
expect ( formatted_content_stub ) . to receive ( :html_safe )
allow ( @wiki ) . to receive ( :formatted_content ) . and_return ( formatted_content_stub )
2013-03-14 06:31:08 +00:00
helper . render_wiki_content ( @wiki )
end
end
2012-08-02 00:26:21 +00:00
end