summaryrefslogtreecommitdiff
path: root/spec/support/mentionable_shared_examples.rb
diff options
context:
space:
mode:
authorash wilson <smashwilson@gmail.com>2013-05-30 23:16:49 +0000
committerAsh Wilson <smashwilson@gmail.com>2013-08-25 18:58:41 -0400
commitc8a115c0e3a9c8242c2a422572d47a49e0cb2874 (patch)
tree5a36c3e0f364fdfb710e01090fc81b9676ea53c4 /spec/support/mentionable_shared_examples.rb
parent2b36dee64485062c69779217d4a202e5ca1b67bd (diff)
downloadgitlab-ce-c8a115c0e3a9c8242c2a422572d47a49e0cb2874.tar.gz
Link issues from comments and automatically close them
Any mention of Issues, MergeRequests, or Commits via GitLab-flavored markdown references in descriptions, titles, or attached Notes creates a back-reference Note that links to the original referencer. Furthermore, pushing commits with commit messages that match a (configurable) regexp to a project's default branch will close any issues mentioned by GFM in the matched closing phrase. If accepting a merge request would close any Issues in this way, a banner is appended to the merge request's main panel to indicate this.
Diffstat (limited to 'spec/support/mentionable_shared_examples.rb')
-rw-r--r--spec/support/mentionable_shared_examples.rb94
1 files changed, 94 insertions, 0 deletions
diff --git a/spec/support/mentionable_shared_examples.rb b/spec/support/mentionable_shared_examples.rb
new file mode 100644
index 00000000000..a7f189777c8
--- /dev/null
+++ b/spec/support/mentionable_shared_examples.rb
@@ -0,0 +1,94 @@
+# Specifications for behavior common to all Mentionable implementations.
+# Requires a shared context containing:
+# - let(: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" } }
+
+def common_mentionable_setup
+ # Avoid name collisions with let(:project) or let(:author) in the surrounding scope.
+ let(:mproject) { create :project }
+ let(:mauthor) { subject.author }
+
+ let(:mentioned_issue) { create :issue, project: mproject }
+ let(:other_issue) { create :issue, project: mproject }
+ let(:mentioned_mr) { create :merge_request, target_project: mproject, source_branch: 'different' }
+ let(:mentioned_commit) { mock('commit', sha: '1234567890abcdef').as_null_object }
+
+ # 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
+ "mentions ##{mentioned_issue.iid} twice ##{mentioned_issue.iid}, !#{mentioned_mr.iid}, " +
+ "#{mentioned_commit.sha[0..5]} and itself as #{backref_text}"
+ end
+
+ before do
+ # Wire the project's repository to return the mentioned commit, and +nil+ for any
+ # unrecognized commits.
+ commitmap = { '123456' => mentioned_commit }
+ extra_commits.each { |c| commitmap[c.sha[0..5]] = c }
+
+ repo = mock('repository')
+ repo.stub(:commit) { |sha| commitmap[sha] }
+ mproject.stub(repository: repo)
+
+ set_mentionable_text.call(ref_string)
+ end
+end
+
+shared_examples 'a mentionable' do
+ common_mentionable_setup
+
+ it 'generates a descriptive back-reference' do
+ subject.gfm_reference.should == backref_text
+ end
+
+ it "extracts references from its reference property" do
+ # De-duplicate and omit itself
+ refs = subject.references(mproject)
+
+ refs.should have(3).items
+ refs.should include(mentioned_issue)
+ refs.should include(mentioned_mr)
+ refs.should include(mentioned_commit)
+ end
+
+ it 'creates cross-reference notes' do
+ [mentioned_issue, mentioned_mr, mentioned_commit].each do |referenced|
+ Note.should_receive(:create_cross_reference_note).with(referenced, subject.local_reference, mauthor, mproject)
+ end
+
+ subject.create_cross_references!(mproject, mauthor)
+ end
+
+ it 'detects existing cross-references' do
+ Note.create_cross_reference_note(mentioned_issue, subject.local_reference, mauthor, mproject)
+
+ subject.has_mentioned?(mentioned_issue).should be_true
+ subject.has_mentioned?(mentioned_mr).should be_false
+ end
+end
+
+shared_examples 'an editable mentionable' do
+ common_mentionable_setup
+
+ it_behaves_like 'a mentionable'
+
+ it 'creates new cross-reference notes when the mentionable text is edited' do
+ new_text = "this text still mentions ##{mentioned_issue.iid} and #{mentioned_commit.sha[0..5]}, " +
+ "but now it mentions ##{other_issue.iid}, too."
+
+ [mentioned_issue, mentioned_commit].each do |oldref|
+ Note.should_not_receive(:create_cross_reference_note).with(oldref, subject.local_reference,
+ mauthor, mproject)
+ end
+
+ Note.should_receive(:create_cross_reference_note).with(other_issue, subject.local_reference, mauthor, mproject)
+
+ subject.save
+ set_mentionable_text.call(new_text)
+ subject.notice_added_references(mproject, mauthor)
+ end
+end