snippet_spec.rb 6.4 KB
Newer Older
gitlabhq's avatar
gitlabhq committed
1 2
require 'spec_helper'

3
describe Snippet do
4 5 6 7 8 9 10
  describe 'modules' do
    subject { described_class }

    it { is_expected.to include_module(Gitlab::VisibilityLevel) }
    it { is_expected.to include_module(Participable) }
    it { is_expected.to include_module(Referable) }
    it { is_expected.to include_module(Sortable) }
Z.J. van de Weg's avatar
Z.J. van de Weg committed
11
    it { is_expected.to include_module(Awardable) }
12 13 14
  end

  describe 'associations' do
15
    it { is_expected.to belong_to(:author).class_name('User') }
16
    it { is_expected.to belong_to(:project) }
17
    it { is_expected.to have_many(:notes).dependent(:destroy) }
Z.J. van de Weg's avatar
Z.J. van de Weg committed
18
    it { is_expected.to have_many(:award_emoji).dependent(:destroy) }
gitlabhq's avatar
gitlabhq committed
19 20
  end

21
  describe 'validation' do
22
    it { is_expected.to validate_presence_of(:author) }
23

24
    it { is_expected.to validate_presence_of(:title) }
25
    it { is_expected.to validate_length_of(:title).is_at_most(255) }
26

27
    it { is_expected.to validate_length_of(:file_name).is_at_most(255) }
28

29
    it { is_expected.to validate_presence_of(:content) }
30 31

    it { is_expected.to validate_inclusion_of(:visibility_level).in_array(Gitlab::VisibilityLevel.values) }
gitlabhq's avatar
gitlabhq committed
32
  end
33 34

  describe '#to_reference' do
35
    context 'when snippet belongs to a project' do
36
      let(:project) { build(:project, name: 'sample-project') }
37
      let(:snippet) { build(:snippet, id: 1, project: project) }
38

39 40 41 42 43
      it 'returns a String reference to the object' do
        expect(snippet.to_reference).to eq "$1"
      end

      it 'supports a cross-project reference' do
44
        another_project = build(:project, name: 'another-project', namespace: project.namespace)
45 46
        expect(snippet.to_reference(another_project)).to eq "sample-project$1"
      end
47 48
    end

49 50 51 52 53 54 55 56
    context 'when snippet does not belong to a project' do
      let(:snippet) { build(:snippet, id: 1, project: nil) }

      it 'returns a String reference to the object' do
        expect(snippet.to_reference).to eq "$1"
      end

      it 'still returns shortest reference when project arg present' do
57
        another_project = build(:project, name: 'another-project')
58 59
        expect(snippet.to_reference(another_project)).to eq "$1"
      end
60 61
    end
  end
62

63
  describe '#file_name' do
64
    let(:project) { create(:project) }
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82

    context 'file_name is nil' do
      let(:snippet) { create(:snippet, project: project, file_name: nil) }

      it 'returns an empty string' do
        expect(snippet.file_name).to eq ''
      end
    end

    context 'file_name is not nil' do
      let(:snippet) { create(:snippet, project: project, file_name: 'foo.txt') }

      it 'returns the file_name' do
        expect(snippet.file_name).to eq 'foo.txt'
      end
    end
  end

83 84 85 86 87 88 89
  describe "#content_html_invalidated?" do
    let(:snippet) { create(:snippet, content: "md", content_html: "html", file_name: "foo.md") }
    it "invalidates the HTML cache of content when the filename changes" do
      expect { snippet.file_name = "foo.rb" }.to change { snippet.content_html_invalidated? }.from(false).to(true)
    end
  end

90
  describe '.search' do
91
    let(:snippet) { create(:snippet, title: 'test snippet') }
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117

    it 'returns snippets with a matching title' do
      expect(described_class.search(snippet.title)).to eq([snippet])
    end

    it 'returns snippets with a partially matching title' do
      expect(described_class.search(snippet.title[0..2])).to eq([snippet])
    end

    it 'returns snippets with a matching title regardless of the casing' do
      expect(described_class.search(snippet.title.upcase)).to eq([snippet])
    end

    it 'returns snippets with a matching file name' do
      expect(described_class.search(snippet.file_name)).to eq([snippet])
    end

    it 'returns snippets with a partially matching file name' do
      expect(described_class.search(snippet.file_name[0..2])).to eq([snippet])
    end

    it 'returns snippets with a matching file name regardless of the casing' do
      expect(described_class.search(snippet.file_name.upcase)).to eq([snippet])
    end
  end

118
  describe '.search_code' do
119 120 121 122 123 124 125 126 127 128 129 130 131 132
    let(:snippet) { create(:snippet, content: 'class Foo; end') }

    it 'returns snippets with matching content' do
      expect(described_class.search_code(snippet.content)).to eq([snippet])
    end

    it 'returns snippets with partially matching content' do
      expect(described_class.search_code('class')).to eq([snippet])
    end

    it 'returns snippets with matching content regardless of the casing' do
      expect(described_class.search_code('FOO')).to eq([snippet])
    end
  end
133

Yorick Peterse's avatar
Yorick Peterse committed
134
  describe '#participants' do
135
    let(:project) { create(:project, :public) }
Yorick Peterse's avatar
Yorick Peterse committed
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
    let(:snippet) { create(:snippet, content: 'foo', project: project) }

    let!(:note1) do
      create(:note_on_project_snippet,
             noteable: snippet,
             project: project,
             note: 'a')
    end

    let!(:note2) do
      create(:note_on_project_snippet,
             noteable: snippet,
             project: project,
             note: 'b')
    end

    it 'includes the snippet author' do
      expect(snippet.participants).to include(snippet.author)
    end

    it 'includes the note authors' do
      expect(snippet.participants).to include(note1.author, note2.author)
    end
  end
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202

  describe '#check_for_spam' do
    let(:snippet) { create :snippet, visibility_level: visibility_level }

    subject do
      snippet.assign_attributes(title: title)
      snippet.check_for_spam?
    end

    context 'when public and spammable attributes changed' do
      let(:visibility_level) { Snippet::PUBLIC }
      let(:title) { 'woo' }

      it 'returns true' do
        is_expected.to be_truthy
      end
    end

    context 'when private' do
      let(:visibility_level) { Snippet::PRIVATE }
      let(:title) { snippet.title }

      it 'returns false' do
        is_expected.to be_falsey
      end

      it 'returns true when switching to public' do
        snippet.save!
        snippet.visibility_level = Snippet::PUBLIC

        expect(snippet.check_for_spam?).to be_truthy
      end
    end

    context 'when spammable attributes have not changed' do
      let(:visibility_level) { Snippet::PUBLIC }
      let(:title) { snippet.title }

      it 'returns false' do
        is_expected.to be_falsey
      end
    end
  end
203 204 205 206 207 208 209 210 211 212 213 214

  describe '#blob' do
    let(:snippet) { create(:snippet) }

    it 'returns a blob representing the snippet data' do
      blob = snippet.blob

      expect(blob).to be_a(Blob)
      expect(blob.path).to eq(snippet.file_name)
      expect(blob.data).to eq(snippet.content)
    end
  end
gitlabhq's avatar
gitlabhq committed
215
end