summaryrefslogtreecommitdiff
path: root/spec/lib/banzai
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/banzai')
-rw-r--r--spec/lib/banzai/filter/design_reference_filter_spec.rb307
-rw-r--r--spec/lib/banzai/filter/external_issue_reference_filter_spec.rb30
-rw-r--r--spec/lib/banzai/filter/gollum_tags_filter_spec.rb34
-rw-r--r--spec/lib/banzai/filter/issue_reference_filter_spec.rb44
-rw-r--r--spec/lib/banzai/filter/label_reference_filter_spec.rb22
-rw-r--r--spec/lib/banzai/filter/repository_link_filter_spec.rb8
-rw-r--r--spec/lib/banzai/filter/wiki_link_filter_spec.rb16
-rw-r--r--spec/lib/banzai/pipeline/description_pipeline_spec.rb4
-rw-r--r--spec/lib/banzai/pipeline/wiki_pipeline_spec.rb67
9 files changed, 441 insertions, 91 deletions
diff --git a/spec/lib/banzai/filter/design_reference_filter_spec.rb b/spec/lib/banzai/filter/design_reference_filter_spec.rb
new file mode 100644
index 00000000000..8a6c2e3b3f9
--- /dev/null
+++ b/spec/lib/banzai/filter/design_reference_filter_spec.rb
@@ -0,0 +1,307 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Banzai::Filter::DesignReferenceFilter do
+ include FilterSpecHelper
+ include DesignManagementTestHelpers
+
+ let_it_be(:issue) { create(:issue, iid: 10) }
+ let_it_be(:issue_proj_2) { create(:issue, iid: 20) }
+ let_it_be(:issue_b) { create(:issue, project: issue.project) }
+ let_it_be(:developer) { create(:user, developer_projects: [issue.project, issue_proj_2.project]) }
+ let_it_be(:design_a) { create(:design, :with_versions, issue: issue) }
+ let_it_be(:design_b) { create(:design, :with_versions, issue: issue_b) }
+ let_it_be(:design_proj_2) { create(:design, :with_versions, issue: issue_proj_2) }
+ let_it_be(:project_with_no_lfs) { create(:project, :public, lfs_enabled: false) }
+
+ let(:design) { design_a }
+ let(:project) { issue.project }
+ let(:project_2) { issue_proj_2.project }
+ let(:reference) { design.to_reference }
+ let(:design_url) { url_for_design(design) }
+ let(:input_text) { "Added #{design_url}" }
+ let(:doc) { process_doc(input_text) }
+ let(:current_user) { developer }
+
+ before do
+ enable_design_management
+ end
+
+ shared_examples 'a no-op filter' do
+ it 'does nothing' do
+ expect(process(input_text)).to eq(baseline(input_text).to_html)
+ end
+ end
+
+ shared_examples 'a good link reference' do
+ let(:link) { doc.css('a').first }
+ let(:href) { url_for_design(design) }
+ let(:title) { design.filename }
+
+ it 'produces a good link', :aggregate_failures do
+ expect(link.attr('href')).to eq(href)
+ expect(link.attr('title')).to eq(title)
+ expect(link.attr('class')).to eq('gfm gfm-design has-tooltip')
+ expect(link.attr('data-project')).to eq(design.project.id.to_s)
+ expect(link.attr('data-issue')).to eq(design.issue.id.to_s)
+ expect(link.attr('data-original')).to eq(href)
+ expect(link.attr('data-reference-type')).to eq('design')
+ expect(link.text).to eq(design.to_reference(project))
+ end
+ end
+
+ describe '.call' do
+ it 'requires project context' do
+ expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
+ end
+ end
+
+ it 'does not error when we add redaction to the pipeline' do
+ enable_design_management
+
+ res = reference_pipeline(redact: true).to_document(input_text)
+
+ expect(res.css('a').first).to be_present
+ end
+
+ describe '#call' do
+ describe 'feature flags' do
+ context 'design management is not enabled' do
+ before do
+ enable_design_management(false)
+ end
+
+ it_behaves_like 'a no-op filter'
+ end
+
+ context 'design reference filter is not enabled' do
+ before do
+ stub_feature_flags(described_class::FEATURE_FLAG => false)
+ end
+
+ it_behaves_like 'a no-op filter'
+
+ it 'issues no queries' do
+ expect { process(input_text) }.not_to exceed_query_limit(0)
+ end
+ end
+
+ context 'the filter is enabled for the context project' do
+ before do
+ stub_feature_flags(described_class::FEATURE_FLAG => project)
+ end
+
+ it_behaves_like 'a good link reference'
+ end
+ end
+ end
+
+ %w(pre code a style).each do |elem|
+ context "wrapped in a <#{elem}/>" do
+ let(:input_text) { "<#{elem}>Design #{url_for_design(design)}</#{elem}>" }
+
+ it_behaves_like 'a no-op filter'
+ end
+ end
+
+ describe '.identifier' do
+ where(:filename) do
+ [
+ ['simple.png'],
+ ['SIMPLE.PNG'],
+ ['has spaces.png'],
+ ['has-hyphen.jpg'],
+ ['snake_case.svg'],
+ ['has "quotes".svg'],
+ ['has <special> characters [o].svg']
+ ]
+ end
+
+ with_them do
+ let(:design) { build(:design, issue: issue, filename: filename) }
+ let(:url) { url_for_design(design) }
+ let(:pattern) { described_class.object_class.link_reference_pattern }
+ let(:parsed) do
+ m = pattern.match(url)
+ described_class.identifier(m) if m
+ end
+
+ it 'can parse the reference' do
+ expect(parsed).to have_attributes(
+ filename: filename,
+ issue_iid: issue.iid
+ )
+ end
+ end
+ end
+
+ describe 'static properties' do
+ specify do
+ expect(described_class).to have_attributes(
+ object_sym: :design,
+ object_class: ::DesignManagement::Design
+ )
+ end
+ end
+
+ describe '#data_attributes_for' do
+ let(:subject) { filter_instance.data_attributes_for(input_text, project, design) }
+
+ specify do
+ is_expected.to include(issue: design.issue_id,
+ original: input_text,
+ project: project.id,
+ design: design.id)
+ end
+ end
+
+ context 'a design with a quoted filename' do
+ let(:filename) { %q{A "very" good file.png} }
+ let(:design) { create(:design, :with_versions, issue: issue, filename: filename) }
+
+ it 'links to the design' do
+ expect(doc.css('a').first.attr('href'))
+ .to eq url_for_design(design)
+ end
+ end
+
+ context 'internal reference' do
+ it_behaves_like 'a reference containing an element node'
+
+ context 'the reference is valid' do
+ it_behaves_like 'a good link reference'
+
+ context 'the filename needs to be escaped' do
+ where(:filename) do
+ [
+ ['with some spaces.png'],
+ ['with <script>console.log("pwded")<%2Fscript>.png']
+ ]
+ end
+
+ with_them do
+ let(:design) { create(:design, :with_versions, filename: filename, issue: issue) }
+ let(:link) { doc.css('a').first }
+
+ it 'replaces the content with the reference, but keeps the link', :aggregate_failures do
+ expect(doc.text).to eq(CGI.unescapeHTML("Added #{design.to_reference}"))
+ expect(link.attr('title')).to eq(design.filename)
+ expect(link.attr('href')).to eq(design_url)
+ end
+ end
+ end
+ end
+
+ context 'the reference is to a non-existant design' do
+ let(:design_url) { url_for_design(build(:design, issue: issue)) }
+
+ it_behaves_like 'a no-op filter'
+ end
+
+ context 'design management is disabled for the referenced project' do
+ let(:public_issue) { create(:issue, project: project_with_no_lfs) }
+ let(:design) { create(:design, :with_versions, issue: public_issue) }
+
+ it_behaves_like 'a no-op filter'
+ end
+ end
+
+ describe 'link pattern' do
+ let(:reference) { url_for_design(design) }
+
+ it 'matches' do
+ expect(reference).to match(DesignManagement::Design.link_reference_pattern)
+ end
+ end
+
+ context 'cross-project / cross-namespace complete reference' do
+ let(:design) { design_proj_2 }
+
+ it_behaves_like 'a reference containing an element node'
+
+ it_behaves_like 'a good link reference'
+
+ it 'links to a valid reference' do
+ expect(doc.css('a').first.attr('href')).to eq(design_url)
+ end
+
+ context 'design management is disabled for that project' do
+ let(:design) { create(:design, project: project_with_no_lfs) }
+
+ it_behaves_like 'a no-op filter'
+ end
+
+ it 'link has valid text' do
+ ref = "#{design.project.full_path}##{design.issue.iid}[#{design.filename}]"
+
+ expect(doc.css('a').first.text).to eql(ref)
+ end
+
+ it 'includes default classes' do
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-design has-tooltip'
+ end
+
+ context 'the reference is invalid' do
+ let(:design_url) { url_for_design(design).gsub(/jpg/, 'gif') }
+
+ it_behaves_like 'a no-op filter'
+ end
+ end
+
+ describe 'performance' do
+ it 'is linear in the number of projects with design management enabled each design refers to' do
+ design_c = build(:design, :with_versions, issue: issue)
+ design_d = build(:design, :with_versions, issue: issue_b)
+ design_e = build(:design, :with_versions, issue: build_stubbed(:issue, project: project_2))
+
+ one_ref_per_project = <<~MD
+ Design #{url_for_design(design_a)}, #{url_for_design(design_proj_2)}
+ MD
+
+ multiple_references = <<~MD
+ Designs that affect the count:
+ * #{url_for_design(design_a)}
+ * #{url_for_design(design_b)}
+ * #{url_for_design(design_c)}
+ * #{url_for_design(design_d)}
+ * #{url_for_design(design_proj_2)}
+ * #{url_for_design(design_e)}
+
+ Things that do not affect the count:
+ * #{url_for_design(build_stubbed(:design, project: project_with_no_lfs))}
+ * #{url_for_designs(issue)}
+ * #1[not a valid reference.gif]
+ MD
+
+ baseline = ActiveRecord::QueryRecorder.new { process(one_ref_per_project) }
+
+ # each project mentioned requires 2 queries:
+ #
+ # * SELECT "issues".* FROM "issues" WHERE "issues"."project_id" = 1 AND ...
+ # :in `parent_records'*/
+ # * SELECT "_designs".* FROM "_designs"
+ # WHERE (issue_id = ? AND filename = ?) OR ...
+ # :in `parent_records'*/
+ #
+ # In addition there is a 1 query overhead for all the projects at the
+ # start. Currently, the baseline for 2 projects is `2 * 2 + 1 = 5` queries
+ #
+ expect { process(multiple_references) }.not_to exceed_query_limit(baseline.count)
+ end
+ end
+
+ private
+
+ def process_doc(text)
+ reference_filter(text, project: project)
+ end
+
+ def baseline(text)
+ null_filter(text, project: project)
+ end
+
+ def process(text)
+ process_doc(text).to_html
+ end
+end
diff --git a/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb b/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
index 78795a157f8..a70c820f97a 100644
--- a/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
@@ -5,10 +5,6 @@ require 'spec_helper'
describe Banzai::Filter::ExternalIssueReferenceFilter do
include FilterSpecHelper
- def helper
- IssuesHelper
- end
-
shared_examples_for "external issue tracker" do
it_behaves_like 'a reference containing an element node'
@@ -36,7 +32,7 @@ describe Banzai::Filter::ExternalIssueReferenceFilter do
issue_id = doc.css('a').first.attr("data-external-issue")
expect(doc.css('a').first.attr('href'))
- .to eq helper.url_for_issue(issue_id, project)
+ .to eq project.external_issue_tracker.issue_url(issue_id)
end
it 'links to the external tracker' do
@@ -45,7 +41,7 @@ describe Banzai::Filter::ExternalIssueReferenceFilter do
link = doc.css('a').first.attr('href')
issue_id = doc.css('a').first.attr("data-external-issue")
- expect(link).to eq(helper.url_for_issue(issue_id, project))
+ expect(link).to eq(project.external_issue_tracker.issue_url(issue_id))
end
it 'links with adjacent text' do
@@ -56,7 +52,7 @@ describe Banzai::Filter::ExternalIssueReferenceFilter do
it 'includes a title attribute' do
doc = filter("Issue #{reference}")
- expect(doc.css('a').first.attr('title')).to include("Issue in #{project.issues_tracker.title}")
+ expect(doc.css('a').first.attr('title')).to include("Issue in #{project.external_issue_tracker.title}")
end
it 'escapes the title attribute' do
@@ -78,7 +74,25 @@ describe Banzai::Filter::ExternalIssueReferenceFilter do
link = doc.css('a').first.attr('href')
issue_id = doc.css('a').first["data-external-issue"]
- expect(link).to eq helper.url_for_issue(issue_id, project, only_path: true)
+ expect(link).to eq project.external_issue_tracker.issue_path(issue_id)
+ end
+
+ it 'has an empty link if issue_url is invalid' do
+ expect_any_instance_of(project.external_issue_tracker.class).to receive(:issue_url) { 'javascript:alert("foo");' }
+
+ doc = filter("Issue #{reference}")
+ link = doc.css('a').first.attr('href')
+
+ expect(link).to eq ''
+ end
+
+ it 'has an empty link if issue_path is invalid' do
+ expect_any_instance_of(project.external_issue_tracker.class).to receive(:issue_path) { 'javascript:alert("foo");' }
+
+ doc = filter("Issue #{reference}", only_path: true)
+ link = doc.css('a').first.attr('href')
+
+ expect(link).to eq ''
end
context 'with RequestStore enabled', :request_store do
diff --git a/spec/lib/banzai/filter/gollum_tags_filter_spec.rb b/spec/lib/banzai/filter/gollum_tags_filter_spec.rb
index 1580177eaad..00d8b871224 100644
--- a/spec/lib/banzai/filter/gollum_tags_filter_spec.rb
+++ b/spec/lib/banzai/filter/gollum_tags_filter_spec.rb
@@ -7,11 +7,11 @@ describe Banzai::Filter::GollumTagsFilter do
let(:project) { create(:project) }
let(:user) { double }
- let(:project_wiki) { ProjectWiki.new(project, user) }
+ let(:wiki) { ProjectWiki.new(project, user) }
describe 'validation' do
- it 'ensure that a :project_wiki key exists in context' do
- expect { filter("See [[images/image.jpg]]", {}) }.to raise_error ArgumentError, "Missing context keys for Banzai::Filter::GollumTagsFilter: :project_wiki"
+ it 'ensure that a :wiki key exists in context' do
+ expect { filter("See [[images/image.jpg]]", {}) }.to raise_error ArgumentError, "Missing context keys for Banzai::Filter::GollumTagsFilter: :wiki"
end
end
@@ -23,19 +23,19 @@ describe Banzai::Filter::GollumTagsFilter do
path: 'images/image.jpg',
raw_data: '')
wiki_file = Gitlab::Git::WikiFile.new(gollum_file_double)
- expect(project_wiki).to receive(:find_file).with('images/image.jpg').and_return(wiki_file)
+ expect(wiki).to receive(:find_file).with('images/image.jpg').and_return(wiki_file)
tag = '[[images/image.jpg]]'
- doc = filter("See #{tag}", project_wiki: project_wiki)
+ doc = filter("See #{tag}", wiki: wiki)
- expect(doc.at_css('img')['data-src']).to eq "#{project_wiki.wiki_base_path}/images/image.jpg"
+ expect(doc.at_css('img')['data-src']).to eq "#{wiki.wiki_base_path}/images/image.jpg"
end
it 'does not creates img tag if image does not exist' do
- expect(project_wiki).to receive(:find_file).with('images/image.jpg').and_return(nil)
+ expect(wiki).to receive(:find_file).with('images/image.jpg').and_return(nil)
tag = '[[images/image.jpg]]'
- doc = filter("See #{tag}", project_wiki: project_wiki)
+ doc = filter("See #{tag}", wiki: wiki)
expect(doc.css('img').size).to eq 0
end
@@ -44,14 +44,14 @@ describe Banzai::Filter::GollumTagsFilter do
context 'linking external images' do
it 'creates img tag for valid URL' do
tag = '[[http://example.com/image.jpg]]'
- doc = filter("See #{tag}", project_wiki: project_wiki)
+ doc = filter("See #{tag}", wiki: wiki)
expect(doc.at_css('img')['data-src']).to eq "http://example.com/image.jpg"
end
it 'does not creates img tag for invalid URL' do
tag = '[[http://example.com/image.pdf]]'
- doc = filter("See #{tag}", project_wiki: project_wiki)
+ doc = filter("See #{tag}", wiki: wiki)
expect(doc.css('img').size).to eq 0
end
@@ -60,7 +60,7 @@ describe Banzai::Filter::GollumTagsFilter do
context 'linking external resources' do
it "the created link's text will be equal to the resource's text" do
tag = '[[http://example.com]]'
- doc = filter("See #{tag}", project_wiki: project_wiki)
+ doc = filter("See #{tag}", wiki: wiki)
expect(doc.at_css('a').text).to eq 'http://example.com'
expect(doc.at_css('a')['href']).to eq 'http://example.com'
@@ -68,7 +68,7 @@ describe Banzai::Filter::GollumTagsFilter do
it "the created link's text will be link-text" do
tag = '[[link-text|http://example.com/pdfs/gollum.pdf]]'
- doc = filter("See #{tag}", project_wiki: project_wiki)
+ doc = filter("See #{tag}", wiki: wiki)
expect(doc.at_css('a').text).to eq 'link-text'
expect(doc.at_css('a')['href']).to eq 'http://example.com/pdfs/gollum.pdf'
@@ -78,8 +78,8 @@ describe Banzai::Filter::GollumTagsFilter do
context 'linking internal resources' do
it "the created link's text includes the resource's text and wiki base path" do
tag = '[[wiki-slug]]'
- doc = filter("See #{tag}", project_wiki: project_wiki)
- expected_path = ::File.join(project_wiki.wiki_base_path, 'wiki-slug')
+ doc = filter("See #{tag}", wiki: wiki)
+ expected_path = ::File.join(wiki.wiki_base_path, 'wiki-slug')
expect(doc.at_css('a').text).to eq 'wiki-slug'
expect(doc.at_css('a')['href']).to eq expected_path
@@ -87,15 +87,15 @@ describe Banzai::Filter::GollumTagsFilter do
it "the created link's text will be link-text" do
tag = '[[link-text|wiki-slug]]'
- doc = filter("See #{tag}", project_wiki: project_wiki)
- expected_path = ::File.join(project_wiki.wiki_base_path, 'wiki-slug')
+ doc = filter("See #{tag}", wiki: wiki)
+ expected_path = ::File.join(wiki.wiki_base_path, 'wiki-slug')
expect(doc.at_css('a').text).to eq 'link-text'
expect(doc.at_css('a')['href']).to eq expected_path
end
it "inside back ticks will be exempt from linkification" do
- doc = filter('<code>[[link-in-backticks]]</code>', project_wiki: project_wiki)
+ doc = filter('<code>[[link-in-backticks]]</code>', wiki: wiki)
expect(doc.at_css('code').text).to eq '[[link-in-backticks]]'
end
diff --git a/spec/lib/banzai/filter/issue_reference_filter_spec.rb b/spec/lib/banzai/filter/issue_reference_filter_spec.rb
index 61c59162a30..603da2b4421 100644
--- a/spec/lib/banzai/filter/issue_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/issue_reference_filter_spec.rb
@@ -11,7 +11,9 @@ describe Banzai::Filter::IssueReferenceFilter do
end
let(:project) { create(:project, :public) }
- let(:issue) { create(:issue, project: project) }
+ let(:issue) { create(:issue, project: project) }
+ let(:issue_path) { "/#{issue.project.namespace.path}/#{issue.project.path}/-/issues/#{issue.iid}" }
+ let(:issue_url) { "http://#{Gitlab.config.gitlab.host}#{issue_path}" }
it 'requires project context' do
expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
@@ -46,7 +48,7 @@ describe Banzai::Filter::IssueReferenceFilter do
doc = reference_filter("Fixed #{reference}")
expect(doc.css('a').first.attr('href'))
- .to eq helper.url_for_issue(issue.iid, project)
+ .to eq issue_url
end
it 'links with adjacent text' do
@@ -113,7 +115,7 @@ describe Banzai::Filter::IssueReferenceFilter do
link = doc.css('a').first.attr('href')
expect(link).not_to match %r(https?://)
- expect(link).to eq helper.url_for_issue(issue.iid, project, only_path: true)
+ expect(link).to eq issue_path
end
it 'does not process links containing issue numbers followed by text' do
@@ -145,7 +147,7 @@ describe Banzai::Filter::IssueReferenceFilter do
doc = reference_filter("See #{reference}")
expect(doc.css('a').first.attr('href'))
- .to eq helper.url_for_issue(issue.iid, project2)
+ .to eq issue_url
end
it 'link has valid text' do
@@ -195,7 +197,7 @@ describe Banzai::Filter::IssueReferenceFilter do
doc = reference_filter("See #{reference}")
expect(doc.css('a').first.attr('href'))
- .to eq helper.url_for_issue(issue.iid, project2)
+ .to eq issue_url
end
it 'link has valid text' do
@@ -245,7 +247,7 @@ describe Banzai::Filter::IssueReferenceFilter do
doc = reference_filter("See #{reference}")
expect(doc.css('a').first.attr('href'))
- .to eq helper.url_for_issue(issue.iid, project2)
+ .to eq issue_url
end
it 'link has valid text' do
@@ -279,7 +281,7 @@ describe Banzai::Filter::IssueReferenceFilter do
let(:namespace) { create(:namespace, name: 'cross-reference') }
let(:project2) { create(:project, :public, namespace: namespace) }
let(:issue) { create(:issue, project: project2) }
- let(:reference) { helper.url_for_issue(issue.iid, project2) + "#note_123" }
+ let(:reference) { issue_url + "#note_123" }
it 'links to a valid reference' do
doc = reference_filter("See #{reference}")
@@ -314,7 +316,7 @@ describe Banzai::Filter::IssueReferenceFilter do
doc = reference_filter("See #{reference_link}")
expect(doc.css('a').first.attr('href'))
- .to eq helper.url_for_issue(issue.iid, project2)
+ .to eq issue_url
end
it 'links with adjacent text' do
@@ -336,14 +338,14 @@ describe Banzai::Filter::IssueReferenceFilter do
let(:namespace) { create(:namespace, name: 'cross-reference') }
let(:project2) { create(:project, :public, namespace: namespace) }
let(:issue) { create(:issue, project: project2) }
- let(:reference) { "#{helper.url_for_issue(issue.iid, project2) + "#note_123"}" }
+ let(:reference) { "#{issue_url + "#note_123"}" }
let(:reference_link) { %{<a href="#{reference}">Reference</a>} }
it 'links to a valid reference' do
doc = reference_filter("See #{reference_link}")
expect(doc.css('a').first.attr('href'))
- .to eq helper.url_for_issue(issue.iid, project2) + "#note_123"
+ .to eq issue_url + "#note_123"
end
it 'links with adjacent text' do
@@ -374,6 +376,16 @@ describe Banzai::Filter::IssueReferenceFilter do
expect(link.attr('href')).to eq(designs_tab_url)
expect(link.text).to eq("#{issue.to_reference} (designs)")
end
+
+ context 'design management is not available' do
+ before do
+ enable_design_management(false)
+ end
+
+ it 'links to the issue, but not to the designs tab' do
+ expect(link.text).to eq(issue.to_reference)
+ end
+ end
end
context 'group context' do
@@ -403,7 +415,7 @@ describe Banzai::Filter::IssueReferenceFilter do
doc = reference_filter("See #{reference}", context)
link = doc.css('a').first
- expect(link.attr('href')).to eq(helper.url_for_issue(issue.iid, project))
+ expect(link.attr('href')).to eq(issue_url)
expect(link.text).to include("#{project.full_path}##{issue.iid}")
end
@@ -415,23 +427,23 @@ describe Banzai::Filter::IssueReferenceFilter do
end
it 'links to a valid reference for url cross-reference' do
- reference = helper.url_for_issue(issue.iid, project) + "#note_123"
+ reference = issue_url + "#note_123"
doc = reference_filter("See #{reference}", context)
link = doc.css('a').first
- expect(link.attr('href')).to eq(helper.url_for_issue(issue.iid, project) + "#note_123")
+ expect(link.attr('href')).to eq(issue_url + "#note_123")
expect(link.text).to include("#{project.full_path}##{issue.iid}")
end
it 'links to a valid reference for cross-reference in link href' do
- reference = "#{helper.url_for_issue(issue.iid, project) + "#note_123"}"
+ reference = "#{issue_url + "#note_123"}"
reference_link = %{<a href="#{reference}">Reference</a>}
doc = reference_filter("See #{reference_link}", context)
link = doc.css('a').first
- expect(link.attr('href')).to eq(helper.url_for_issue(issue.iid, project) + "#note_123")
+ expect(link.attr('href')).to eq(issue_url + "#note_123")
expect(link.text).to include('Reference')
end
@@ -441,7 +453,7 @@ describe Banzai::Filter::IssueReferenceFilter do
doc = reference_filter("See #{reference_link}", context)
link = doc.css('a').first
- expect(link.attr('href')).to eq(helper.url_for_issue(issue.iid, project))
+ expect(link.attr('href')).to eq(issue_url)
expect(link.text).to include('Reference')
end
end
diff --git a/spec/lib/banzai/filter/label_reference_filter_spec.rb b/spec/lib/banzai/filter/label_reference_filter_spec.rb
index de7a70db1ac..0b697ab2040 100644
--- a/spec/lib/banzai/filter/label_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/label_reference_filter_spec.rb
@@ -47,14 +47,34 @@ describe Banzai::Filter::LabelReferenceFilter do
expect(link.attr('data-label')).to eq label.id.to_s
end
- it 'supports an :only_path context' do
+ it 'includes protocol when :only_path not present' do
+ doc = reference_filter("Label #{reference}")
+ link = doc.css('a').first.attr('href')
+
+ expect(link).to match %r(https?://)
+ end
+
+ it 'does not include protocol when :only_path true' do
doc = reference_filter("Label #{reference}", only_path: true)
link = doc.css('a').first.attr('href')
expect(link).not_to match %r(https?://)
+ end
+
+ it 'links to issue list when :label_url_method is not present' do
+ doc = reference_filter("Label #{reference}", only_path: true)
+ link = doc.css('a').first.attr('href')
+
expect(link).to eq urls.project_issues_path(project, label_name: label.name)
end
+ it 'links to merge request list when `label_url_method: :project_merge_requests_url`' do
+ doc = reference_filter("Label #{reference}", { only_path: true, label_url_method: "project_merge_requests_url" })
+ link = doc.css('a').first.attr('href')
+
+ expect(link).to eq urls.project_merge_requests_path(project, label_name: label.name)
+ end
+
context 'project that does not exist referenced' do
let(:result) { reference_filter('aaa/bbb~ccc') }
diff --git a/spec/lib/banzai/filter/repository_link_filter_spec.rb b/spec/lib/banzai/filter/repository_link_filter_spec.rb
index 460c76acd78..81f93f885f7 100644
--- a/spec/lib/banzai/filter/repository_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/repository_link_filter_spec.rb
@@ -12,7 +12,7 @@ describe Banzai::Filter::RepositoryLinkFilter do
project: project,
current_user: user,
group: group,
- project_wiki: project_wiki,
+ wiki: wiki,
ref: ref,
requested_path: requested_path,
only_path: only_path
@@ -53,7 +53,7 @@ describe Banzai::Filter::RepositoryLinkFilter do
let(:project_path) { project.full_path }
let(:ref) { 'markdown' }
let(:commit) { project.commit(ref) }
- let(:project_wiki) { nil }
+ let(:wiki) { nil }
let(:requested_path) { '/' }
let(:only_path) { true }
@@ -94,8 +94,8 @@ describe Banzai::Filter::RepositoryLinkFilter do
end
end
- context 'with a project_wiki' do
- let(:project_wiki) { double('ProjectWiki') }
+ context 'with a wiki' do
+ let(:wiki) { double('ProjectWiki') }
include_examples :preserve_unchanged
end
diff --git a/spec/lib/banzai/filter/wiki_link_filter_spec.rb b/spec/lib/banzai/filter/wiki_link_filter_spec.rb
index 4587bd85939..827f38ef717 100644
--- a/spec/lib/banzai/filter/wiki_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/wiki_link_filter_spec.rb
@@ -12,13 +12,13 @@ describe Banzai::Filter::WikiLinkFilter do
let(:repository_upload_folder) { Wikis::CreateAttachmentService::ATTACHMENT_PATH }
it "doesn't rewrite absolute links" do
- filtered_link = filter("<a href='http://example.com:8000/'>Link</a>", project_wiki: wiki).children[0]
+ filtered_link = filter("<a href='http://example.com:8000/'>Link</a>", wiki: wiki).children[0]
expect(filtered_link.attribute('href').value).to eq('http://example.com:8000/')
end
it "doesn't rewrite links to project uploads" do
- filtered_link = filter("<a href='/uploads/a.test'>Link</a>", project_wiki: wiki).children[0]
+ filtered_link = filter("<a href='/uploads/a.test'>Link</a>", wiki: wiki).children[0]
expect(filtered_link.attribute('href').value).to eq('/uploads/a.test')
end
@@ -26,7 +26,7 @@ describe Banzai::Filter::WikiLinkFilter do
describe "when links point to the #{Wikis::CreateAttachmentService::ATTACHMENT_PATH} folder" do
context 'with an "a" html tag' do
it 'rewrites links' do
- filtered_link = filter("<a href='#{repository_upload_folder}/a.test'>Link</a>", project_wiki: wiki).children[0]
+ filtered_link = filter("<a href='#{repository_upload_folder}/a.test'>Link</a>", wiki: wiki).children[0]
expect(filtered_link.attribute('href').value).to eq("#{wiki.wiki_base_path}/#{repository_upload_folder}/a.test")
end
@@ -37,7 +37,7 @@ describe Banzai::Filter::WikiLinkFilter do
context 'inside an "a" html tag' do
it 'rewrites links' do
- filtered_elements = filter("<a href='#{repository_upload_folder}/a.jpg'><img src='#{repository_upload_folder}/a.jpg'>example</img></a>", project_wiki: wiki)
+ filtered_elements = filter("<a href='#{repository_upload_folder}/a.jpg'><img src='#{repository_upload_folder}/a.jpg'>example</img></a>", wiki: wiki)
expect(filtered_elements.search('img').first.attribute('src').value).to eq(path)
expect(filtered_elements.search('a').first.attribute('href').value).to eq(path)
@@ -46,7 +46,7 @@ describe Banzai::Filter::WikiLinkFilter do
context 'outside an "a" html tag' do
it 'rewrites links' do
- filtered_link = filter("<img src='#{repository_upload_folder}/a.jpg'>example</img>", project_wiki: wiki).children[0]
+ filtered_link = filter("<img src='#{repository_upload_folder}/a.jpg'>example</img>", wiki: wiki).children[0]
expect(filtered_link.attribute('src').value).to eq(path)
end
@@ -55,7 +55,7 @@ describe Banzai::Filter::WikiLinkFilter do
context 'with "video" html tag' do
it 'rewrites links' do
- filtered_link = filter("<video src='#{repository_upload_folder}/a.mp4'></video>", project_wiki: wiki).children[0]
+ filtered_link = filter("<video src='#{repository_upload_folder}/a.mp4'></video>", wiki: wiki).children[0]
expect(filtered_link.attribute('src').value).to eq("#{wiki.wiki_base_path}/#{repository_upload_folder}/a.mp4")
end
@@ -63,7 +63,7 @@ describe Banzai::Filter::WikiLinkFilter do
context 'with "audio" html tag' do
it 'rewrites links' do
- filtered_link = filter("<audio src='#{repository_upload_folder}/a.wav'></audio>", project_wiki: wiki).children[0]
+ filtered_link = filter("<audio src='#{repository_upload_folder}/a.wav'></audio>", wiki: wiki).children[0]
expect(filtered_link.attribute('src').value).to eq("#{wiki.wiki_base_path}/#{repository_upload_folder}/a.wav")
end
@@ -75,7 +75,7 @@ describe Banzai::Filter::WikiLinkFilter do
invalid_links.each do |invalid_link|
it "doesn't rewrite invalid invalid_links like #{invalid_link}" do
- filtered_link = filter("<a href='#{invalid_link}'>Link</a>", project_wiki: wiki).children[0]
+ filtered_link = filter("<a href='#{invalid_link}'>Link</a>", wiki: wiki).children[0]
expect(filtered_link.attribute('href').value).to eq(invalid_link)
end
diff --git a/spec/lib/banzai/pipeline/description_pipeline_spec.rb b/spec/lib/banzai/pipeline/description_pipeline_spec.rb
index 5ecd3df5151..6778a273bba 100644
--- a/spec/lib/banzai/pipeline/description_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/description_pipeline_spec.rb
@@ -3,12 +3,14 @@
require 'spec_helper'
describe Banzai::Pipeline::DescriptionPipeline do
+ let_it_be(:project) { create(:project) }
+
def parse(html)
# When we pass HTML to Redcarpet, it gets wrapped in `p` tags...
# ...except when we pass it pre-wrapped text. Rabble rabble.
unwrap = !html.start_with?('<p ')
- output = described_class.to_html(html, project: spy)
+ output = described_class.to_html(html, project: project)
output.gsub!(%r{\A<p dir="auto">(.*)</p>(.*)\z}, '\1\2') if unwrap
diff --git a/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb b/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb
index 4d16c568c13..b2c24284eb9 100644
--- a/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb
@@ -3,6 +3,11 @@
require 'spec_helper'
describe Banzai::Pipeline::WikiPipeline do
+ let_it_be(:namespace) { create(:namespace, name: "wiki_link_ns") }
+ let_it_be(:project) { create(:project, :public, name: "wiki_link_project", namespace: namespace) }
+ let_it_be(:wiki) { ProjectWiki.new(project, double(:user)) }
+ let_it_be(:page) { build(:wiki_page, wiki: wiki, title: 'nested/twice/start-page') }
+
describe 'TableOfContents' do
it 'replaces the tag with the TableOfContentsFilter result' do
markdown = <<-MD.strip_heredoc
@@ -13,7 +18,7 @@ describe Banzai::Pipeline::WikiPipeline do
Foo
MD
- result = described_class.call(markdown, project: spy, project_wiki: spy)
+ result = described_class.call(markdown, project: project, wiki: wiki)
aggregate_failures do
expect(result[:output].text).not_to include '[['
@@ -31,7 +36,7 @@ describe Banzai::Pipeline::WikiPipeline do
Foo
MD
- output = described_class.to_html(markdown, project: spy, project_wiki: spy)
+ output = described_class.to_html(markdown, project: project, wiki: wiki)
expect(output).to include('[[<em>toc</em>]]')
end
@@ -44,7 +49,7 @@ describe Banzai::Pipeline::WikiPipeline do
Foo
MD
- output = described_class.to_html(markdown, project: spy, project_wiki: spy)
+ output = described_class.to_html(markdown, project: project, wiki: wiki)
aggregate_failures do
expect(output).not_to include('<ul>')
@@ -54,30 +59,25 @@ describe Banzai::Pipeline::WikiPipeline do
end
describe "Links" do
- let(:namespace) { create(:namespace, name: "wiki_link_ns") }
- let(:project) { create(:project, :public, name: "wiki_link_project", namespace: namespace) }
- let(:project_wiki) { ProjectWiki.new(project, double(:user)) }
- let(:page) { build(:wiki_page, wiki: project_wiki, title: 'nested/twice/start-page') }
-
{ 'when GitLab is hosted at a root URL' => '',
'when GitLab is hosted at a relative URL' => '/nested/relative/gitlab' }.each do |test_name, relative_url_root|
context test_name do
before do
- allow(Gitlab.config.gitlab).to receive(:relative_url_root).and_return(relative_url_root)
+ allow(Rails.application.routes).to receive(:default_url_options).and_return(script_name: relative_url_root)
end
describe "linking to pages within the wiki" do
context "when creating hierarchical links to the current directory" do
it "rewrites non-file links to be at the scope of the current directory" do
markdown = "[Page](./page)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ output = described_class.to_html(markdown, project: project, wiki: wiki, page_slug: page.slug)
expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/nested/twice/page\"")
end
it "rewrites file links to be at the scope of the current directory" do
markdown = "[Link to Page](./page.md)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ output = described_class.to_html(markdown, project: project, wiki: wiki, page_slug: page.slug)
expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/nested/twice/page.md\"")
end
@@ -86,14 +86,14 @@ describe Banzai::Pipeline::WikiPipeline do
context "when creating hierarchical links to the parent directory" do
it "rewrites non-file links to be at the scope of the parent directory" do
markdown = "[Link to Page](../page)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ output = described_class.to_html(markdown, project: project, wiki: wiki, page_slug: page.slug)
expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/nested/page\"")
end
it "rewrites file links to be at the scope of the parent directory" do
markdown = "[Link to Page](../page.md)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ output = described_class.to_html(markdown, project: project, wiki: wiki, page_slug: page.slug)
expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/nested/page.md\"")
end
@@ -102,14 +102,14 @@ describe Banzai::Pipeline::WikiPipeline do
context "when creating hierarchical links to a sub-directory" do
it "rewrites non-file links to be at the scope of the sub-directory" do
markdown = "[Link to Page](./subdirectory/page)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ output = described_class.to_html(markdown, project: project, wiki: wiki, page_slug: page.slug)
expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/nested/twice/subdirectory/page\"")
end
it "rewrites file links to be at the scope of the sub-directory" do
markdown = "[Link to Page](./subdirectory/page.md)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ output = described_class.to_html(markdown, project: project, wiki: wiki, page_slug: page.slug)
expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/nested/twice/subdirectory/page.md\"")
end
@@ -118,35 +118,35 @@ describe Banzai::Pipeline::WikiPipeline do
describe "when creating non-hierarchical links" do
it 'rewrites non-file links to be at the scope of the wiki root' do
markdown = "[Link to Page](page)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ output = described_class.to_html(markdown, project: project, wiki: wiki, page_slug: page.slug)
expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/page\"")
end
it 'rewrites non-file links (with spaces) to be at the scope of the wiki root' do
markdown = "[Link to Page](page slug)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ output = described_class.to_html(markdown, project: project, wiki: wiki, page_slug: page.slug)
expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/page%20slug\"")
end
it "rewrites file links to be at the scope of the current directory" do
markdown = "[Link to Page](page.md)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ output = described_class.to_html(markdown, project: project, wiki: wiki, page_slug: page.slug)
expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/nested/twice/page.md\"")
end
it 'rewrites links with anchor' do
markdown = '[Link to Header](start-page#title)'
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ output = described_class.to_html(markdown, project: project, wiki: wiki, page_slug: page.slug)
expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/start-page#title\"")
end
it 'rewrites links (with spaces) with anchor' do
markdown = '[Link to Header](start page#title)'
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ output = described_class.to_html(markdown, project: project, wiki: wiki, page_slug: page.slug)
expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/start%20page#title\"")
end
@@ -155,14 +155,14 @@ describe Banzai::Pipeline::WikiPipeline do
describe "when creating root links" do
it 'rewrites non-file links to be at the scope of the wiki root' do
markdown = "[Link to Page](/page)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ output = described_class.to_html(markdown, project: project, wiki: wiki, page_slug: page.slug)
expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/page\"")
end
it 'rewrites file links to be at the scope of the wiki root' do
markdown = "[Link to Page](/page.md)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ output = described_class.to_html(markdown, project: project, wiki: wiki, page_slug: page.slug)
expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/-/wikis/page.md\"")
end
@@ -172,7 +172,7 @@ describe Banzai::Pipeline::WikiPipeline do
describe "linking to pages outside the wiki (absolute)" do
it "doesn't rewrite links" do
markdown = "[Link to Page](http://example.com/page)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ output = described_class.to_html(markdown, project: project, wiki: wiki, page_slug: page.slug)
expect(output).to include('href="http://example.com/page"')
end
@@ -188,7 +188,7 @@ describe Banzai::Pipeline::WikiPipeline do
output = described_class.to_html(
"[Link](./alert(1);)",
project: project,
- project_wiki: project_wiki,
+ wiki: wiki,
page_slug: valid_slug
)
@@ -199,7 +199,7 @@ describe Banzai::Pipeline::WikiPipeline do
output = described_class.to_html(
"[Link](../alert(1);)",
project: project,
- project_wiki: project_wiki,
+ wiki: wiki,
page_slug: valid_slug
)
@@ -236,7 +236,7 @@ describe Banzai::Pipeline::WikiPipeline do
output = described_class.to_html(
"[Link](./#{link})",
project: project,
- project_wiki: project_wiki,
+ wiki: wiki,
page_slug: slug
)
@@ -247,7 +247,7 @@ describe Banzai::Pipeline::WikiPipeline do
output = described_class.to_html(
"[Link](../#{link})",
project: project,
- project_wiki: project_wiki,
+ wiki: wiki,
page_slug: slug
)
@@ -261,35 +261,30 @@ describe Banzai::Pipeline::WikiPipeline do
end
describe 'videos and audio' do
- let_it_be(:namespace) { create(:namespace, name: "wiki_link_ns") }
- let_it_be(:project) { create(:project, :public, name: "wiki_link_project", namespace: namespace) }
- let_it_be(:project_wiki) { ProjectWiki.new(project, double(:user)) }
- let_it_be(:page) { build(:wiki_page, wiki: project_wiki, title: 'nested/twice/start-page') }
-
it 'generates video html structure' do
markdown = "![video_file](video_file_name.mp4)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ output = described_class.to_html(markdown, project: project, wiki: wiki, page_slug: page.slug)
expect(output).to include('<video src="/wiki_link_ns/wiki_link_project/-/wikis/nested/twice/video_file_name.mp4"')
end
it 'rewrites and replaces video links names with white spaces to %20' do
markdown = "![video file](video file name.mp4)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ output = described_class.to_html(markdown, project: project, wiki: wiki, page_slug: page.slug)
expect(output).to include('<video src="/wiki_link_ns/wiki_link_project/-/wikis/nested/twice/video%20file%20name.mp4"')
end
it 'generates audio html structure' do
markdown = "![audio_file](audio_file_name.wav)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ output = described_class.to_html(markdown, project: project, wiki: wiki, page_slug: page.slug)
expect(output).to include('<audio src="/wiki_link_ns/wiki_link_project/-/wikis/nested/twice/audio_file_name.wav"')
end
it 'rewrites and replaces audio links names with white spaces to %20' do
markdown = "![audio file](audio file name.wav)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ output = described_class.to_html(markdown, project: project, wiki: wiki, page_slug: page.slug)
expect(output).to include('<audio src="/wiki_link_ns/wiki_link_project/-/wikis/nested/twice/audio%20file%20name.wav"')
end