summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouwe Maan <douwe@gitlab.com>2015-11-30 21:14:46 +0100
committerDouwe Maan <douwe@gitlab.com>2015-11-30 21:36:34 +0100
commitd6a5b45c8ea5ec7a68e213636fde405c52bb90e4 (patch)
treee711cd92c57e20cc7900875017fb93d670537c00
parenta7be01cd07430a4302668224947b2ed135c2d7bb (diff)
downloadgitlab-ce-d6a5b45c8ea5ec7a68e213636fde405c52bb90e4.tar.gz
Recognize issue/MR/snippet/commit links as references.
-rw-r--r--app/models/commit.rb15
-rw-r--r--app/models/commit_range.rb11
-rw-r--r--app/models/concerns/referable.rb19
-rw-r--r--app/models/issue.rb11
-rw-r--r--app/models/merge_request.rb11
-rw-r--r--app/models/snippet.rb11
-rw-r--r--lib/gitlab/markdown.rb5
-rw-r--r--lib/gitlab/markdown/abstract_reference_filter.rb31
-rw-r--r--lib/gitlab/markdown/commit_range_reference_filter.rb70
-rw-r--r--lib/gitlab/markdown/commit_reference_filter.rb68
-rw-r--r--lib/gitlab/markdown/external_link_filter.rb3
-rw-r--r--lib/gitlab/markdown/merge_request_reference_filter.rb10
-rw-r--r--lib/gitlab/markdown/redactor_filter.rb5
-rw-r--r--spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb39
-rw-r--r--spec/lib/gitlab/markdown/commit_reference_filter_spec.rb31
-rw-r--r--spec/lib/gitlab/markdown/issue_reference_filter_spec.rb32
-rw-r--r--spec/lib/gitlab/markdown/merge_request_reference_filter_spec.rb29
-rw-r--r--spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb30
18 files changed, 301 insertions, 130 deletions
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 492f6be1ce3..fc03d2580d7 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -73,16 +73,23 @@ class Commit
# This pattern supports cross-project references.
def self.reference_pattern
%r{
- (?:#{Project.reference_pattern}#{reference_prefix})?
- (?<commit>\h{6,40})
+ #{link_reference_pattern} |
+ (?:
+ (?:#{Project.reference_pattern}#{reference_prefix})?
+ (?<commit>\h{6,40})
+ )
}x
end
+ def self.link_reference_pattern
+ super("commit", /(?<commit>\h{6,40})/)
+ end
+
def to_reference(from_project = nil)
if cross_project_reference?(from_project)
- "#{project.to_reference}@#{id}"
+ project.to_reference + self.class.reference_prefix + self.short_id
else
- id
+ self.short_id
end
end
diff --git a/app/models/commit_range.rb b/app/models/commit_range.rb
index fd23e24aff6..98067771b71 100644
--- a/app/models/commit_range.rb
+++ b/app/models/commit_range.rb
@@ -42,11 +42,18 @@ class CommitRange
# This pattern supports cross-project references.
def self.reference_pattern
%r{
- (?:#{Project.reference_pattern}#{reference_prefix})?
- (?<commit_range>#{PATTERN})
+ #{link_reference_pattern} |
+ (?:
+ (?:#{Project.reference_pattern}#{reference_prefix})?
+ (?<commit_range>#{PATTERN})
+ )
}x
end
+ def self.link_reference_pattern
+ super("compare", /(?<commit_range>#{PATTERN})/)
+ end
+
# Initialize a CommitRange
#
# range_string - The String commit range.
diff --git a/app/models/concerns/referable.rb b/app/models/concerns/referable.rb
index cced66cc1e4..16e4d054869 100644
--- a/app/models/concerns/referable.rb
+++ b/app/models/concerns/referable.rb
@@ -44,6 +44,25 @@ module Referable
def reference_pattern
raise NotImplementedError, "#{self} does not implement #{__method__}"
end
+
+ def link_reference_pattern(route, pattern)
+ %r{
+ (?<url>
+ #{Regexp.escape(Gitlab.config.gitlab.url)}
+ \/#{Project.reference_pattern}
+ \/#{Regexp.escape(route)}
+ \/#{pattern}
+ (?<path>
+ (\/[a-z0-9_=-]+)*
+ )?
+ (?<query>
+ \?[a-z0-9_=-]+
+ (&[a-z0-9_=-]+)*
+ )?
+ (?<anchor>\#[a-z0-9_-]+)?
+ )
+ }x
+ end
end
private
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 72183108033..e62acfdfd91 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -64,11 +64,18 @@ class Issue < ActiveRecord::Base
# This pattern supports cross-project references.
def self.reference_pattern
%r{
- (#{Project.reference_pattern})?
- #{Regexp.escape(reference_prefix)}(?<issue>\d+)
+ #{link_reference_pattern} |
+ (?:
+ (#{Project.reference_pattern})?
+ #{Regexp.escape(reference_prefix)}(?<issue>\d+)
+ )
}x
end
+ def self.link_reference_pattern
+ super("issues", /(?<issue>\d+)/)
+ end
+
def to_reference(from_project = nil)
reference = "#{self.class.reference_prefix}#{iid}"
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 939df8cd8d1..c1d3874adee 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -146,11 +146,18 @@ class MergeRequest < ActiveRecord::Base
# This pattern supports cross-project references.
def self.reference_pattern
%r{
- (#{Project.reference_pattern})?
- #{Regexp.escape(reference_prefix)}(?<merge_request>\d+)
+ #{link_reference_pattern} |
+ (?:
+ (#{Project.reference_pattern})?
+ #{Regexp.escape(reference_prefix)}(?<merge_request>\d+)
+ )
}x
end
+ def self.link_reference_pattern
+ super("merge_requests", /(?<merge_request>\d+)/)
+ end
+
def to_reference(from_project = nil)
reference = "#{self.class.reference_prefix}#{iid}"
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index b0831982aa7..8ec12ddf6ef 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -60,11 +60,18 @@ class Snippet < ActiveRecord::Base
# This pattern supports cross-project references.
def self.reference_pattern
%r{
- (#{Project.reference_pattern})?
- #{Regexp.escape(reference_prefix)}(?<snippet>\d+)
+ #{link_reference_pattern} |
+ (?:
+ (#{Project.reference_pattern})?
+ #{Regexp.escape(reference_prefix)}(?<snippet>\d+)
+ )
}x
end
+ def self.link_reference_pattern
+ super("snippets", /(?<snippet>\d+)/)
+ end
+
def to_reference(from_project = nil)
reference = "#{self.class.reference_prefix}#{id}"
diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb
index b082bfc434b..ee458eda025 100644
--- a/lib/gitlab/markdown.rb
+++ b/lib/gitlab/markdown.rb
@@ -181,8 +181,6 @@ module Gitlab
Gitlab::Markdown::RelativeLinkFilter,
Gitlab::Markdown::EmojiFilter,
Gitlab::Markdown::TableOfContentsFilter,
- Gitlab::Markdown::AutolinkFilter,
- Gitlab::Markdown::ExternalLinkFilter,
Gitlab::Markdown::UserReferenceFilter,
Gitlab::Markdown::IssueReferenceFilter,
@@ -193,6 +191,9 @@ module Gitlab
Gitlab::Markdown::CommitReferenceFilter,
Gitlab::Markdown::LabelReferenceFilter,
+ Gitlab::Markdown::AutolinkFilter,
+ Gitlab::Markdown::ExternalLinkFilter,
+
Gitlab::Markdown::TaskListFilter
]
end
diff --git a/lib/gitlab/markdown/abstract_reference_filter.rb b/lib/gitlab/markdown/abstract_reference_filter.rb
index fd5b7eb9332..4adc44361b7 100644
--- a/lib/gitlab/markdown/abstract_reference_filter.rb
+++ b/lib/gitlab/markdown/abstract_reference_filter.rb
@@ -40,7 +40,7 @@ module Gitlab
# Returns a String replaced with the return of the block.
def self.references_in(text)
text.gsub(object_class.reference_pattern) do |match|
- yield match, $~[object_sym].to_i, $~[:project]
+ yield match, $~[object_sym].to_i, $~[:project], $~
end
end
@@ -74,26 +74,41 @@ module Gitlab
# Returns a String with references replaced with links. All links
# have `gfm` and `gfm-OBJECT_NAME` class names attached for styling.
def object_link_filter(text)
- references_in(text) do |match, id, project_ref|
+ references_in(text) do |match, id, project_ref, matches|
project = project_from_ref(project_ref)
if project && object = find_object(project, id)
- title = escape_once("#{object_title}: #{object.title}")
+ title = escape_once(object_link_title(object))
klass = reference_class(object_sym)
- data = data_attribute(project: project.id, object_sym => object.id)
- url = url_for_object(object, project)
+ data = data_attribute(project: project.id, object_sym => object.id, original: match)
+ url = matches[:url] || url_for_object(object, project)
+
+ text = object.to_reference(context[:project])
+
+ extras = object_link_text_extras(object, matches)
+ text += " (#{extras.join(", ")})" if extras.any?
%(<a href="#{url}" #{data}
title="#{title}"
- class="#{klass}">#{match}</a>)
+ class="#{klass}">#{text}</a>)
else
match
end
end
end
- def object_title
- object_class.name.titleize
+ def object_link_text_extras(object, matches)
+ extras = []
+
+ if matches[:anchor] && matches[:anchor] =~ /\A\#note_(\d+)\z/
+ extras << "comment #{$1}"
+ end
+
+ extras
+ end
+
+ def object_link_title(object)
+ "#{object_class.name.titleize}: #{object.title}"
end
end
end
diff --git a/lib/gitlab/markdown/commit_range_reference_filter.rb b/lib/gitlab/markdown/commit_range_reference_filter.rb
index e070edae0a4..f24bed76193 100644
--- a/lib/gitlab/markdown/commit_range_reference_filter.rb
+++ b/lib/gitlab/markdown/commit_range_reference_filter.rb
@@ -5,24 +5,14 @@ module Gitlab
# HTML filter that replaces commit range references with links.
#
# This filter supports cross-project references.
- class CommitRangeReferenceFilter < ReferenceFilter
- include CrossProjectReference
+ class CommitRangeReferenceFilter < AbstractReferenceFilter
+ def self.object_class
+ CommitRange
+ end
- # Public: Find commit range references in text
- #
- # CommitRangeReferenceFilter.references_in(text) do |match, commit_range, project_ref|
- # "<a href=...>#{commit_range}</a>"
- # end
- #
- # text - String text to search.
- #
- # Yields the String match, the String commit range, and an optional String
- # of the external project reference.
- #
- # Returns a String replaced with the return of the block.
def self.references_in(text)
text.gsub(CommitRange.reference_pattern) do |match|
- yield match, $~[:commit_range], $~[:project]
+ yield match, $~[:commit_range], $~[:project], $~
end
end
@@ -31,9 +21,9 @@ module Gitlab
return unless project
id = node.attr("data-commit-range")
- range = CommitRange.new(id, project)
+ range = find_object(project, id)
- return unless range.valid_commits?
+ return unless range
{ commit_range: range }
end
@@ -44,49 +34,25 @@ module Gitlab
@commit_map = {}
end
- def call
- replace_text_nodes_matching(CommitRange.reference_pattern) do |content|
- commit_range_link_filter(content)
- end
- end
-
- # Replace commit range references in text with links to compare the commit
- # ranges.
- #
- # text - String text to replace references in.
- #
- # Returns a String with commit range references replaced with links. All
- # links have `gfm` and `gfm-commit_range` class names attached for
- # styling.
- def commit_range_link_filter(text)
- self.class.references_in(text) do |match, id, project_ref|
- project = self.project_from_ref(project_ref)
-
- range = CommitRange.new(id, project)
-
- if range.valid_commits?
- url = url_for_commit_range(project, range)
-
- title = range.reference_title
- klass = reference_class(:commit_range)
- data = data_attribute(project: project.id, commit_range: id)
+ def self.find_object(project, id)
+ range = CommitRange.new(id, project)
- project_ref += '@' if project_ref
+ range.valid_commits? ? range : nil
+ end
- %(<a href="#{url}" #{data}
- title="#{title}"
- class="#{klass}">#{project_ref}#{range}</a>)
- else
- match
- end
- end
+ def find_object(*args)
+ self.class.find_object(*args)
end
- def url_for_commit_range(project, range)
+ def url_for_object(range, project)
h = Gitlab::Application.routes.url_helpers
h.namespace_project_compare_url(project.namespace, project,
range.to_param.merge(only_path: context[:only_path]))
end
+
+ def object_link_title(range)
+ range.reference_title
+ end
end
end
end
diff --git a/lib/gitlab/markdown/commit_reference_filter.rb b/lib/gitlab/markdown/commit_reference_filter.rb
index 8cdbeb1f9cf..cc7abc08c87 100644
--- a/lib/gitlab/markdown/commit_reference_filter.rb
+++ b/lib/gitlab/markdown/commit_reference_filter.rb
@@ -5,24 +5,14 @@ module Gitlab
# HTML filter that replaces commit references with links.
#
# This filter supports cross-project references.
- class CommitReferenceFilter < ReferenceFilter
- include CrossProjectReference
+ class CommitReferenceFilter < AbstractReferenceFilter
+ def self.object_class
+ Commit
+ end
- # Public: Find commit references in text
- #
- # CommitReferenceFilter.references_in(text) do |match, commit, project_ref|
- # "<a href=...>#{commit}</a>"
- # end
- #
- # text - String text to search.
- #
- # Yields the String match, the String commit identifier, and an optional
- # String of the external project reference.
- #
- # Returns a String replaced with the return of the block.
def self.references_in(text)
text.gsub(Commit.reference_pattern) do |match|
- yield match, $~[:commit], $~[:project]
+ yield match, $~[:commit], $~[:project], $~
end
end
@@ -31,58 +21,32 @@ module Gitlab
return unless project
id = node.attr("data-commit")
- commit = commit_from_ref(project, id)
+ commit = find_object(project, id)
return unless commit
{ commit: commit }
end
- def call
- replace_text_nodes_matching(Commit.reference_pattern) do |content|
- commit_link_filter(content)
- end
- end
-
- # Replace commit references in text with links to the commit specified.
- #
- # text - String text to replace references in.
- #
- # Returns a String with commit references replaced with links. All links
- # have `gfm` and `gfm-commit` class names attached for styling.
- def commit_link_filter(text)
- self.class.references_in(text) do |match, id, project_ref|
- project = self.project_from_ref(project_ref)
-
- if commit = self.class.commit_from_ref(project, id)
- url = url_for_commit(project, commit)
-
- title = escape_once(commit.link_title)
- klass = reference_class(:commit)
- data = data_attribute(project: project.id, commit: id)
-
- project_ref += '@' if project_ref
-
- %(<a href="#{url}" #{data}
- title="#{title}"
- class="#{klass}">#{project_ref}#{commit.short_id}</a>)
- else
- match
- end
- end
- end
-
- def self.commit_from_ref(project, id)
+ def self.find_object(project, id)
if project && project.valid_repo?
project.commit(id)
end
end
- def url_for_commit(project, commit)
+ def find_object(*args)
+ self.class.find_object(*args)
+ end
+
+ def url_for_object(commit, project)
h = Gitlab::Application.routes.url_helpers
h.namespace_project_commit_url(project.namespace, project, commit,
only_path: context[:only_path])
end
+
+ def object_link_title(commit)
+ commit.link_title
+ end
end
end
end
diff --git a/lib/gitlab/markdown/external_link_filter.rb b/lib/gitlab/markdown/external_link_filter.rb
index 29e51b6ade6..b6792932016 100644
--- a/lib/gitlab/markdown/external_link_filter.rb
+++ b/lib/gitlab/markdown/external_link_filter.rb
@@ -10,6 +10,9 @@ module Gitlab
doc.search('a').each do |node|
next unless node.has_attribute?('href')
+ klass = node.attribute('class')
+ next if klass && klass.include?('gfm')
+
link = node.attribute('href').value
# Skip non-HTTP(S) links
diff --git a/lib/gitlab/markdown/merge_request_reference_filter.rb b/lib/gitlab/markdown/merge_request_reference_filter.rb
index 1f47f03c94e..3780a14a130 100644
--- a/lib/gitlab/markdown/merge_request_reference_filter.rb
+++ b/lib/gitlab/markdown/merge_request_reference_filter.rb
@@ -20,6 +20,16 @@ module Gitlab
h.namespace_project_merge_request_url(project.namespace, project, mr,
only_path: context[:only_path])
end
+
+ def object_link_text_extras(object, matches)
+ extras = super
+
+ if matches[:path] && matches[:path] == '/diffs'
+ extras.unshift "diffs"
+ end
+
+ extras
+ end
end
end
end
diff --git a/lib/gitlab/markdown/redactor_filter.rb b/lib/gitlab/markdown/redactor_filter.rb
index a1f3a8a8ebf..2a58c798f9f 100644
--- a/lib/gitlab/markdown/redactor_filter.rb
+++ b/lib/gitlab/markdown/redactor_filter.rb
@@ -12,7 +12,10 @@ module Gitlab
def call
doc.css('a.gfm').each do |node|
unless user_can_reference?(node)
- node.replace(node.text)
+ # The reference should be replaced by the original text,
+ # which is not always the same as the rendered text.
+ text = node.attribute('data-original') || node.text
+ node.replace(text)
end
end
diff --git a/spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb b/spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb
index e078ff26814..753140d60e6 100644
--- a/spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb
+++ b/spec/lib/gitlab/markdown/commit_range_reference_filter_spec.rb
@@ -125,7 +125,44 @@ module Gitlab::Markdown
it 'links with adjacent text' do
doc = filter("Fixed (#{reference}.)")
- exp = Regexp.escape("#{project2.to_reference}@#{range.to_s}")
+ exp = Regexp.escape("#{project2.to_reference}@#{range.to_reference}")
+ expect(doc.to_html).to match(/\(<a.+>#{exp}<\/a>\.\)/)
+ end
+
+ it 'ignores invalid commit IDs on the referenced project' do
+ exp = act = "Fixed #{project2.to_reference}@#{commit1.id.reverse}...#{commit2.id}"
+ expect(filter(act).to_html).to eq exp
+
+ exp = act = "Fixed #{project2.to_reference}@#{commit1.id}...#{commit2.id.reverse}"
+ expect(filter(act).to_html).to eq exp
+ end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("See #{reference}")
+ expect(result[:references][:commit_range]).not_to be_empty
+ end
+ end
+
+ context 'URL cross-project reference' do
+ let(:namespace) { create(:namespace, name: 'cross-reference') }
+ let(:project2) { create(:project, :public, namespace: namespace) }
+ let(:reference) { urls.namespace_project_compare_url(project2.namespace, project2, range.to_param) }
+
+ before do
+ range.project = project2
+ end
+
+ it 'links to a valid reference' do
+ doc = filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).
+ to eq urls.namespace_project_compare_url(project2.namespace, project2, range.to_param)
+ end
+
+ it 'links with adjacent text' do
+ doc = filter("Fixed (#{reference}.)")
+
+ exp = Regexp.escape(range.to_reference(project))
expect(doc.to_html).to match(/\(<a.+>#{exp}<\/a>\.\)/)
end
diff --git a/spec/lib/gitlab/markdown/commit_reference_filter_spec.rb b/spec/lib/gitlab/markdown/commit_reference_filter_spec.rb
index d080efbf3d4..c1bcf29b1ba 100644
--- a/spec/lib/gitlab/markdown/commit_reference_filter_spec.rb
+++ b/spec/lib/gitlab/markdown/commit_reference_filter_spec.rb
@@ -131,5 +131,36 @@ module Gitlab::Markdown
expect(result[:references][:commit]).not_to be_empty
end
end
+
+ context 'URL cross-project reference' do
+ let(:namespace) { create(:namespace, name: 'cross-reference') }
+ let(:project2) { create(:project, :public, namespace: namespace) }
+ let(:commit) { project2.commit }
+ let(:reference) { urls.namespace_project_commit_url(project2.namespace, project2, commit.id) }
+
+ it 'links to a valid reference' do
+ doc = filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).
+ to eq urls.namespace_project_commit_url(project2.namespace, project2, commit.id)
+ end
+
+ it 'links with adjacent text' do
+ doc = filter("Fixed (#{reference}.)")
+
+ exp = Regexp.escape(project2.to_reference)
+ expect(doc.to_html).to match(/\(<a.+>#{commit.to_reference(project)}<\/a>\.\)/)
+ end
+
+ it 'ignores invalid commit IDs on the referenced project' do
+ exp = act = "Committed #{invalidate_reference(reference)}"
+ expect(filter(act).to_html).to eq exp
+ end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("See #{reference}")
+ expect(result[:references][:commit]).not_to be_empty
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/markdown/issue_reference_filter_spec.rb b/spec/lib/gitlab/markdown/issue_reference_filter_spec.rb
index 94c80ae6611..296e8868f46 100644
--- a/spec/lib/gitlab/markdown/issue_reference_filter_spec.rb
+++ b/spec/lib/gitlab/markdown/issue_reference_filter_spec.rb
@@ -135,5 +135,37 @@ module Gitlab::Markdown
expect(result[:references][:issue]).to eq [issue]
end
end
+
+ context 'URL cross-project reference' do
+ let(:namespace) { create(:namespace, name: 'cross-reference') }
+ let(:project2) { create(:empty_project, :public, namespace: namespace) }
+ let(:issue) { create(:issue, project: project2) }
+ let(:reference) { helper.url_for_issue(issue.iid, project2) + "#note_123" }
+
+ it 'ignores valid references when cross-reference project uses external tracker' do
+ expect_any_instance_of(Project).to receive(:get_issue).
+ with(issue.iid).and_return(nil)
+
+ exp = act = "Issue #{reference}"
+ expect(filter(act).to_html).to eq exp
+ end
+
+ it 'links to a valid reference' do
+ doc = filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).
+ to eq reference
+ end
+
+ it 'links with adjacent text' do
+ doc = filter("Fixed (#{reference}.)")
+ expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(issue.to_reference(project))} \(comment 123\)<\/a>\.\)/)
+ end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("Fixed #{reference}")
+ expect(result[:references][:issue]).to eq [issue]
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/markdown/merge_request_reference_filter_spec.rb b/spec/lib/gitlab/markdown/merge_request_reference_filter_spec.rb
index 3ef6cdfff33..49d8a6e44da 100644
--- a/spec/lib/gitlab/markdown/merge_request_reference_filter_spec.rb
+++ b/spec/lib/gitlab/markdown/merge_request_reference_filter_spec.rb
@@ -89,7 +89,7 @@ module Gitlab::Markdown
context 'cross-project reference' do
let(:namespace) { create(:namespace, name: 'cross-reference') }
let(:project2) { create(:project, :public, namespace: namespace) }
- let(:merge) { create(:merge_request, source_project: project2) }
+ let(:merge) { create(:merge_request, source_project: project2, target_project: project2) }
let(:reference) { merge.to_reference(project) }
it 'links to a valid reference' do
@@ -97,7 +97,7 @@ module Gitlab::Markdown
expect(doc.css('a').first.attr('href')).
to eq urls.namespace_project_merge_request_url(project2.namespace,
- project, merge)
+ project2, merge)
end
it 'links with adjacent text' do
@@ -116,5 +116,30 @@ module Gitlab::Markdown
expect(result[:references][:merge_request]).to eq [merge]
end
end
+
+ context 'URL cross-project reference' do
+ let(:namespace) { create(:namespace, name: 'cross-reference') }
+ let(:project2) { create(:project, :public, namespace: namespace) }
+ let(:merge) { create(:merge_request, source_project: project2, target_project: project2) }
+ let(:reference) { urls.namespace_project_merge_request_url(project2.namespace,
+ project2, merge) + '/diffs#note_123' }
+
+ it 'links to a valid reference' do
+ doc = filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).
+ to eq reference
+ end
+
+ it 'links with adjacent text' do
+ doc = filter("Merge (#{reference}.)")
+ expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(merge.to_reference(project))} \(diffs, comment 123\)<\/a>\.\)/)
+ end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("Merge #{reference}")
+ expect(result[:references][:merge_request]).to eq [merge]
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb b/spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb
index 9d9652dba46..3080a8a3608 100644
--- a/spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb
+++ b/spec/lib/gitlab/markdown/snippet_reference_filter_spec.rb
@@ -114,5 +114,35 @@ module Gitlab::Markdown
expect(result[:references][:snippet]).to eq [snippet]
end
end
+
+ context 'URL cross-project reference' do
+ let(:namespace) { create(:namespace, name: 'cross-reference') }
+ let(:project2) { create(:empty_project, :public, namespace: namespace) }
+ let(:snippet) { create(:project_snippet, project: project2) }
+ let(:reference) { urls.namespace_project_snippet_url(project2.namespace, project2, snippet) }
+
+ it 'links to a valid reference' do
+ doc = filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).
+ to eq urls.namespace_project_snippet_url(project2.namespace, project2, snippet)
+ end
+
+ it 'links with adjacent text' do
+ doc = filter("See (#{reference}.)")
+ expect(doc.to_html).to match(/\(<a.+>#{Regexp.escape(snippet.to_reference(project))}<\/a>\.\)/)
+ end
+
+ it 'ignores invalid snippet IDs on the referenced project' do
+ exp = act = "See #{invalidate_reference(reference)}"
+
+ expect(filter(act).to_html).to eq exp
+ end
+
+ it 'adds to the results hash' do
+ result = reference_pipeline_result("Snippet #{reference}")
+ expect(result[:references][:snippet]).to eq [snippet]
+ end
+ end
end
end