2019-10-12 21:52:04 +05:30
# frozen_string_literal: true
2019-12-04 20:38:33 +05:30
require 'spec_helper'
2017-08-17 22:00:37 +05:30
2023-03-17 16:20:25 +05:30
RSpec . describe Banzai :: Pipeline :: FullPipeline , feature_category : :team_planning do
2023-04-23 21:23:45 +05:30
using RSpec :: Parameterized :: TableSyntax
2017-08-17 22:00:37 +05:30
describe 'References' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project , :public ) }
2017-08-17 22:00:37 +05:30
let ( :issue ) { create ( :issue , project : project ) }
it 'handles markdown inside a reference' do
markdown = " [some `code` inside]( #{ issue . to_reference } ) "
result = described_class . call ( markdown , project : project )
link_content = result [ :output ] . css ( 'a' ) . inner_html
expect ( link_content ) . to eq ( 'some <code>code</code> inside' )
end
it 'sanitizes reference HTML' do
link_label = '<script>bad things</script>'
markdown = " [ #{ link_label } ]( #{ issue . to_reference } ) "
result = described_class . to_html ( markdown , project : project )
expect ( result ) . not_to include ( link_label )
end
it 'escapes the data-original attribute on a reference' do
markdown = %Q{ [">bad things]( #{ issue . to_reference } ) }
result = described_class . to_html ( markdown , project : project )
2020-07-02 01:45:43 +05:30
expect ( result ) . to include ( %{ data-original=' \" &gt;bad things' } )
2017-08-17 22:00:37 +05:30
end
end
2019-02-02 18:00:53 +05:30
2019-03-02 22:35:43 +05:30
describe 'footnotes' do
let ( :project ) { create ( :project , :public ) }
let ( :html ) { described_class . to_html ( footnote_markdown , project : project ) }
2021-12-11 22:18:48 +05:30
let ( :identifier ) { html [ / .*fnref-1-( \ d+).* / , 1 ] }
2019-03-02 22:35:43 +05:30
let ( :footnote_markdown ) do
<< ~ EOF
2021-12-11 22:18:48 +05:30
first [ ^ 1 ] and second [ ^ 😄 second ] and twenty [ ^ _twenty ]
2019-03-02 22:35:43 +05:30
[ ^ 1 ] : one
2021-12-11 22:18:48 +05:30
[ ^ 😄 second ] : two
[ ^ _twenty ] : twenty
2019-03-02 22:35:43 +05:30
EOF
end
let ( :filtered_footnote ) do
2021-12-11 22:18:48 +05:30
<< ~ EOF . strip_heredoc
2022-01-26 12:08:38 +05:30
< p dir = " auto " > first < sup class = " footnote-ref " > < a href = " # fn-1- #{ identifier } " id = " fnref-1- #{ identifier } " data - footnote - ref > 1 < / a>< /su p > and second < sup class = " footnote-ref " > < a href = " # fn-%F0%9F%98%84second- #{ identifier } " id = " fnref-%F0%9F%98%84second- #{ identifier } " data - footnote - ref > 2 < / a>< /su p > and twenty < sup class = " footnote-ref " > < a href = " # fn-_twenty- #{ identifier } " id = " fnref-_twenty- #{ identifier } " data - footnote - ref > 3 < / a>< /su p > < / p>
< section data - footnotes class = " footnotes " >
< ol >
2021-12-11 22:18:48 +05:30
< li id = " fn-1- #{ identifier } " >
2022-01-26 12:08:38 +05:30
< p > one < a href = " # fnref-1- #{ identifier } " data - footnote - backref aria - label = " Back to content " class = " footnote-backref " > < gl - emoji title = " leftwards arrow with hook " data - name = " leftwards_arrow_with_hook " data - unicode - version = " 1.1 " > ↩ < / gl-emoji>< / a > < / p>
2019-03-02 22:35:43 +05:30
< / li>
2021-12-11 22:18:48 +05:30
< li id = " fn-%F0%9F%98%84second- #{ identifier } " >
2022-01-26 12:08:38 +05:30
< p > two < a href = " # fnref-%F0%9F%98%84second- #{ identifier } " data - footnote - backref aria - label = " Back to content " class = " footnote-backref " > < gl - emoji title = " leftwards arrow with hook " data - name = " leftwards_arrow_with_hook " data - unicode - version = " 1.1 " > ↩ < / gl-emoji>< / a > < / p>
2019-03-02 22:35:43 +05:30
< / li>
2021-12-11 22:18:48 +05:30
< li id = " fn-_twenty- #{ identifier } " >
2022-01-26 12:08:38 +05:30
< p > twenty < a href = " # fnref-_twenty- #{ identifier } " data - footnote - backref aria - label = " Back to content " class = " footnote-backref " > < gl - emoji title = " leftwards arrow with hook " data - name = " leftwards_arrow_with_hook " data - unicode - version = " 1.1 " > ↩ < / gl-emoji>< / a > < / p>
2021-11-18 22:05:49 +05:30
< / li>
2022-01-26 12:08:38 +05:30
< / ol>
< / section>
2019-03-02 22:35:43 +05:30
EOF
end
it 'properly adds the necessary ids and classes' do
stub_commonmark_sourcepos_disabled
2022-01-26 12:08:38 +05:30
expect ( html . lines . map ( & :strip ) . join ( " \n " ) ) . to eq filtered_footnote . strip
2019-03-02 22:35:43 +05:30
end
end
2019-02-02 18:00:53 +05:30
describe 'links are detected as malicious' do
it 'has tooltips for malicious links' do
examples = %W[
http : / /ex ample . com / evil \ u202E3pm . exe
[ evilexe . mp3 ] ( http : / /ex ample . com / evil \ u202E3pm . exe )
rdar : / / localhost . com / \ u202E3pm . exe
http : / /one 😄 two . com
[ Evil - Test ] ( http : / /one 😄 two . com )
http : / / \ u0261itlab . com
[ Evil - GitLab - link ] ( http : / / \ u0261itlab . com )
! [ Evil - GitLab - link ] ( http : / / \ u0261itlab . com . png )
]
examples . each do | markdown |
result = described_class . call ( markdown , project : nil ) [ :output ]
link = result . css ( 'a' ) . first
expect ( link [ :class ] ) . to include ( 'has-tooltip' )
end
end
it 'has no tooltips for safe links' do
examples = %w[
http : / /ex ample . com
[ Safe - Test ] ( http : / /ex ample . com )
https : / / commons . wikimedia . org / wiki / File : ا س ك ر ا م _2_ - _تمنرا ست . jpg
[ Wikipedia - link ] ( https : / / commons . wikimedia . org / wiki / File : ا س ك ر ا م _2_ - _تمنرا ست . jpg )
]
examples . each do | markdown |
result = described_class . call ( markdown , project : nil ) [ :output ]
link = result . css ( 'a' ) . first
expect ( link [ :class ] ) . to be_nil
end
end
end
2020-03-13 15:44:24 +05:30
describe 'table of contents' do
let ( :project ) { create ( :project , :public ) }
2021-10-27 15:23:28 +05:30
shared_examples 'table of contents tag' do | tag , tag_html |
let ( :markdown ) do
<<-MARKDOWN.strip_heredoc
#{tag}
2020-03-13 15:44:24 +05:30
# Header
2021-10-27 15:23:28 +05:30
MARKDOWN
end
2020-10-24 23:57:45 +05:30
2021-10-27 15:23:28 +05:30
let ( :invalid_markdown ) do
<<-MARKDOWN.strip_heredoc
test #{tag}
2020-03-13 15:44:24 +05:30
# Header
2021-10-27 15:23:28 +05:30
MARKDOWN
end
2020-03-13 15:44:24 +05:30
2021-10-27 15:23:28 +05:30
it 'inserts a table of contents' do
output = described_class . to_html ( markdown , project : project )
2020-03-13 15:44:24 +05:30
2021-10-27 15:23:28 +05:30
expect ( output ) . to include ( " <ul class= \" section-nav \" > " )
expect ( output ) . to include ( " <li><a href= \" # header \" >Header</a></li> " )
end
it 'does not insert a table of contents' do
output = described_class . to_html ( invalid_markdown , project : project )
expect ( output ) . to include ( " test #{ tag_html } " )
end
2020-03-13 15:44:24 +05:30
end
2021-10-27 15:23:28 +05:30
context 'with [[_TOC_]] as tag' do
it_behaves_like 'table of contents tag' , '[[_TOC_]]' , '[[<em>TOC</em>]]'
end
2020-03-13 15:44:24 +05:30
2021-10-27 15:23:28 +05:30
context 'with [toc] as tag' do
it_behaves_like 'table of contents tag' , '[toc]' , '[toc]'
it_behaves_like 'table of contents tag' , '[TOC]' , '[TOC]'
2020-03-13 15:44:24 +05:30
end
end
2021-03-11 19:13:27 +05:30
describe 'backslash escapes' do
let_it_be ( :project ) { create ( :project , :public ) }
let_it_be ( :issue ) { create ( :issue , project : project ) }
it 'does not convert an escaped reference' do
markdown = " \\ #{ issue . to_reference } "
output = described_class . to_html ( markdown , project : project )
2023-04-23 21:23:45 +05:30
expect ( output ) . to include ( " <span data-escaped-char> # </span> #{ issue . iid } " )
2021-03-11 19:13:27 +05:30
end
2021-04-17 20:07:23 +05:30
it 'converts user reference with escaped underscore because of italics' do
markdown = '_@test\__'
output = described_class . to_html ( markdown , project : project )
2023-04-23 21:23:45 +05:30
expect ( output ) . to include ( '<em>@test_</em>' )
end
context 'when a reference (such as a label name) is autocompleted with characters that require escaping' do
# Labels are fairly representative of the type of characters that can be in a reference
# and aligns with the testing in spec/frontend/gfm_auto_complete_spec.js
where ( :valid , :label_name , :markdown ) do
# These are currently not supported
# true | 'a~bug' | '~"a\~bug"'
# true | 'b~~bug~~' | '~"b\~\~bug\~\~"'
true | 'c_bug_' | '~c_bug\_'
true | 'c_bug_' | 'Label ~c_bug\_ and _more_ text'
true | 'd _bug_' | '~"d \_bug\_"'
true | 'e*bug*' | '~"e\*bug\*"'
true | 'f *bug*' | '~"f \*bug\*"'
true | 'f *bug*' | 'Label ~"f \*bug\*" **with** more text'
true | 'g`bug`' | '~"g\`bug\`" '
true | 'h `bug`' | '~"h \`bug\`"'
end
with_them do
it 'detects valid escaped reference' do
create ( :label , name : label_name , project : project )
result = Banzai :: Pipeline :: FullPipeline . call ( markdown , project : project )
expect ( result [ :output ] . css ( 'a' ) . first . attr ( 'class' ) ) . to eq 'gfm gfm-label has-tooltip gl-link gl-label-link'
expect ( result [ :output ] . css ( 'a' ) . first . content ) . to eq label_name
end
end
2021-04-17 20:07:23 +05:30
end
2021-03-11 19:13:27 +05:30
end
2022-09-01 20:07:04 +05:30
2022-11-25 23:54:43 +05:30
describe 'cmark-gfm and autlolinks' do
it 'does not hang with significant number of unclosed image links' do
markdown = '![a ' * 300000
expect do
Timeout . timeout ( 2 . seconds ) { described_class . to_html ( markdown , project : nil ) }
end . not_to raise_error
2022-09-01 20:07:04 +05:30
end
end
2017-08-17 22:00:37 +05:30
end