summaryrefslogtreecommitdiff
path: root/spec/support/shared_examples/mentionable_shared_examples.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/support/shared_examples/mentionable_shared_examples.rb')
-rw-r--r--spec/support/shared_examples/mentionable_shared_examples.rb144
1 files changed, 144 insertions, 0 deletions
diff --git a/spec/support/shared_examples/mentionable_shared_examples.rb b/spec/support/shared_examples/mentionable_shared_examples.rb
new file mode 100644
index 00000000000..1685decbe94
--- /dev/null
+++ b/spec/support/shared_examples/mentionable_shared_examples.rb
@@ -0,0 +1,144 @@
+# Specifications for behavior common to all Mentionable implementations.
+# Requires a shared context containing:
+# - subject { "the mentionable implementation" }
+# - let(:backref_text) { "the way that +subject+ should refer to itself in backreferences " }
+# - let(:set_mentionable_text) { lambda { |txt| "block that assigns txt to the subject's mentionable_text" } }
+
+shared_context 'mentionable context' do
+ let(:project) { subject.project }
+ let(:author) { subject.author }
+
+ let(:mentioned_issue) { create(:issue, project: project) }
+ let!(:mentioned_mr) { create(:merge_request, source_project: project) }
+ let(:mentioned_commit) { project.commit("HEAD~1") }
+
+ let(:ext_proj) { create(:project, :public, :repository) }
+ let(:ext_issue) { create(:issue, project: ext_proj) }
+ let(:ext_mr) { create(:merge_request, :simple, source_project: ext_proj) }
+ let(:ext_commit) { ext_proj.commit("HEAD~2") }
+
+ # Override to add known commits to the repository stub.
+ let(:extra_commits) { [] }
+
+ # A string that mentions each of the +mentioned_.*+ objects above. Mentionables should add a self-reference
+ # to this string and place it in their +mentionable_text+.
+ let(:ref_string) do
+ <<-MSG.strip_heredoc
+ These references are new:
+ Issue: #{mentioned_issue.to_reference}
+ Merge: #{mentioned_mr.to_reference}
+ Commit: #{mentioned_commit.to_reference}
+
+ This reference is a repeat and should only be mentioned once:
+ Repeat: #{mentioned_issue.to_reference}
+
+ These references are cross-referenced:
+ Issue: #{ext_issue.to_reference(project)}
+ Merge: #{ext_mr.to_reference(project)}
+ Commit: #{ext_commit.to_reference(project)}
+
+ This is a self-reference and should not be mentioned at all:
+ Self: #{backref_text}
+ MSG
+ end
+
+ before do
+ # Wire the project's repository to return the mentioned commit, and +nil+
+ # for any unrecognized commits.
+ allow_any_instance_of(::Repository).to receive(:commit).and_call_original
+ allow_any_instance_of(::Repository).to receive(:commit).with(mentioned_commit.short_id).and_return(mentioned_commit)
+ extra_commits.each do |commit|
+ allow_any_instance_of(::Repository).to receive(:commit).with(commit.short_id).and_return(commit)
+ end
+
+ set_mentionable_text.call(ref_string)
+
+ project.add_developer(author)
+ end
+end
+
+shared_examples 'a mentionable' do
+ include_context 'mentionable context'
+
+ it 'generates a descriptive back-reference' do
+ expect(subject.gfm_reference).to eq(backref_text)
+ end
+
+ it "extracts references from its reference property" do
+ # De-duplicate and omit itself
+ refs = subject.referenced_mentionables
+ expect(refs.size).to eq(6)
+ expect(refs).to include(mentioned_issue)
+ expect(refs).to include(mentioned_mr)
+ expect(refs).to include(mentioned_commit)
+ expect(refs).to include(ext_issue)
+ expect(refs).to include(ext_mr)
+ expect(refs).to include(ext_commit)
+ end
+
+ it 'creates cross-reference notes' do
+ mentioned_objects = [mentioned_issue, mentioned_mr, mentioned_commit,
+ ext_issue, ext_mr, ext_commit]
+
+ mentioned_objects.each do |referenced|
+ expect(SystemNoteService).to receive(:cross_reference)
+ .with(referenced, subject.local_reference, author)
+ end
+
+ subject.create_cross_references!
+ end
+end
+
+shared_examples 'an editable mentionable' do
+ include_context 'mentionable context'
+
+ it_behaves_like 'a mentionable'
+
+ let(:new_issues) do
+ [create(:issue, project: project), create(:issue, project: ext_proj)]
+ end
+
+ it 'creates new cross-reference notes when the mentionable text is edited' do
+ subject.save
+ subject.create_cross_references!
+
+ new_text = <<-MSG.strip_heredoc
+ These references already existed:
+
+ Issue: #{mentioned_issue.to_reference}
+
+ Commit: #{mentioned_commit.to_reference}
+
+ ---
+
+ This cross-project reference already existed:
+
+ Issue: #{ext_issue.to_reference(project)}
+
+ ---
+
+ These two references are introduced in an edit:
+
+ Issue: #{new_issues[0].to_reference}
+
+ Cross: #{new_issues[1].to_reference(project)}
+ MSG
+
+ # These three objects were already referenced, and should not receive new
+ # notes
+ [mentioned_issue, mentioned_commit, ext_issue].each do |oldref|
+ expect(SystemNoteService).not_to receive(:cross_reference)
+ .with(oldref, any_args)
+ end
+
+ # These two issues are new and should receive reference notes
+ # In the case of MergeRequests remember that cannot mention commits included in the MergeRequest
+ new_issues.each do |newref|
+ expect(SystemNoteService).to receive(:cross_reference)
+ .with(newref, subject.local_reference, author)
+ end
+
+ set_mentionable_text.call(new_text)
+ subject.create_new_cross_references!(author)
+ end
+end