BigW Consortium Gitlab

mentionable_shared_examples.rb 4.68 KB
Newer Older
1 2
# Specifications for behavior common to all Mentionable implementations.
# Requires a shared context containing:
3
# - subject { "the mentionable implementation" }
4 5 6 7
# - 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
8 9 10 11
  let(:project) { create :project }
  let(:author)  { subject.author }

  let(:mentioned_issue)  { create(:issue, project: project) }
12
  let!(:mentioned_mr)     { create(:merge_request, :simple, source_project: project) }
13
  let(:mentioned_commit) { project.commit }
14 15 16 17

  let(:ext_proj)   { create(:project, :public) }
  let(:ext_issue)  { create(:issue, project: ext_proj) }
  let(:ext_mr)     { create(:merge_request, :simple, source_project: ext_proj) }
18
  let(:ext_commit) { ext_proj.commit }
19

20 21 22 23 24 25
  # 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
26 27
    <<-MSG.strip_heredoc
      These references are new:
28 29 30
        Issue:  #{mentioned_issue.to_reference}
        Merge:  #{mentioned_mr.to_reference}
        Commit: #{mentioned_commit.to_reference}
31 32

      This reference is a repeat and should only be mentioned once:
33
        Repeat: #{mentioned_issue.to_reference}
34 35

      These references are cross-referenced:
36 37 38
        Issue:  #{ext_issue.to_reference(project)}
        Merge:  #{ext_mr.to_reference(project)}
        Commit: #{ext_commit.to_reference(project)}
39 40 41 42

      This is a self-reference and should not be mentioned at all:
        Self: #{backref_text}
    MSG
43 44 45
  end

  before do
46 47 48 49 50
    # Wire the project's repository to return the mentioned commit, and +nil+
    # for any unrecognized commits.
    commitmap = {
      mentioned_commit.id => mentioned_commit
    }
51
    extra_commits.each { |c| commitmap[c.short_id] = c }
52

Douwe Maan committed
53
    allow(project.repository).to receive(:commit) { |sha| commitmap[sha] }
54

55 56 57 58 59 60 61 62
    set_mentionable_text.call(ref_string)
  end
end

shared_examples 'a mentionable' do
  common_mentionable_setup

  it 'generates a descriptive back-reference' do
63
    expect(subject.gfm_reference).to eq(backref_text)
64 65 66 67
  end

  it "extracts references from its reference property" do
    # De-duplicate and omit itself
68
    refs = subject.references(project)
69 70 71 72 73 74 75
    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)
76 77 78
  end

  it 'creates cross-reference notes' do
79 80 81 82
    mentioned_objects = [mentioned_issue, mentioned_mr, mentioned_commit,
                         ext_issue, ext_mr, ext_commit]

    mentioned_objects.each do |referenced|
83
      expect(SystemNoteService).to receive(:cross_reference).
84
        with(referenced, subject.local_reference, author)
85 86
    end

87
    subject.create_cross_references!(project, author)
88 89 90
  end

  it 'detects existing cross-references' do
91
    SystemNoteService.cross_reference(mentioned_issue, subject.local_reference, author)
92

93 94
    expect(subject).to have_mentioned(mentioned_issue)
    expect(subject).not_to have_mentioned(mentioned_mr)
95 96 97 98 99 100 101 102
  end
end

shared_examples 'an editable mentionable' do
  common_mentionable_setup

  it_behaves_like 'a mentionable'

103 104 105 106
  let(:new_issues) do
    [create(:issue, project: project), create(:issue, project: ext_proj)]
  end

107
  it 'creates new cross-reference notes when the mentionable text is edited' do
Douwe Maan committed
108 109
    subject.save

Douwe Maan committed
110
    new_text = <<-MSG.strip_heredoc
111
      These references already existed:
Douwe Maan committed
112 113 114 115 116 117

      Issue:  #{mentioned_issue.to_reference}

      Commit: #{mentioned_commit.to_reference}

      ---
118 119

      This cross-project reference already existed:
Douwe Maan committed
120 121 122 123

      Issue:  #{ext_issue.to_reference(project)}

      ---
124 125

      These two references are introduced in an edit:
Douwe Maan committed
126 127 128 129

      Issue: #{new_issues[0].to_reference}

      Cross: #{new_issues[1].to_reference(project)}
130
    MSG
131

132 133
    # These three objects were already referenced, and should not receive new
    # notes
134
    [mentioned_issue, mentioned_commit, ext_issue].each do |oldref|
135
      expect(SystemNoteService).not_to receive(:cross_reference).
136
        with(oldref, any_args)
137 138
    end

139 140
    # These two issues are new and should receive reference notes
    new_issues.each do |newref|
141
      expect(SystemNoteService).to receive(:cross_reference).
142
        with(newref, subject.local_reference, author)
143
    end
144 145

    set_mentionable_text.call(new_text)
146
    subject.create_new_cross_references!(project, author)
147 148
  end
end