project_spec.rb 11.5 KB
Newer Older
1 2 3 4
# == Schema Information
#
# Table name: projects
#
5
#  id                     :integer          not null, primary key
6 7 8
#  name                   :string(255)
#  path                   :string(255)
#  description            :text
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
9 10
#  created_at             :datetime
#  updated_at             :datetime
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
11
#  creator_id             :integer
12 13 14 15
#  issues_enabled         :boolean          default(TRUE), not null
#  wall_enabled           :boolean          default(TRUE), not null
#  merge_requests_enabled :boolean          default(TRUE), not null
#  wiki_enabled           :boolean          default(TRUE), not null
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
16
#  namespace_id           :integer
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
17
#  issues_tracker         :string(255)      default("gitlab"), not null
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
18
#  issues_tracker_id      :string(255)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
19
#  snippets_enabled       :boolean          default(TRUE), not null
20
#  last_activity_at       :datetime
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
21
#  import_url             :string(255)
22
#  visibility_level       :integer          default(0), not null
23
#  archived               :boolean          default(FALSE), not null
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
24
#  import_status          :string(255)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
25 26
#  repository_size        :float            default(0.0)
#  star_count             :integer          default(0), not null
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
27 28
#  import_type            :string(255)
#  import_source          :string(255)
29
#  avatar                 :string(255)
30 31
#

gitlabhq's avatar
gitlabhq committed
32 33 34
require 'spec_helper'

describe Project do
35
  describe 'Associations' do
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
    it { is_expected.to belong_to(:group) }
    it { is_expected.to belong_to(:namespace) }
    it { is_expected.to belong_to(:creator).class_name('User') }
    it { is_expected.to have_many(:users) }
    it { is_expected.to have_many(:events).dependent(:destroy) }
    it { is_expected.to have_many(:merge_requests).dependent(:destroy) }
    it { is_expected.to have_many(:issues).dependent(:destroy) }
    it { is_expected.to have_many(:milestones).dependent(:destroy) }
    it { is_expected.to have_many(:project_members).dependent(:destroy) }
    it { is_expected.to have_many(:notes).dependent(:destroy) }
    it { is_expected.to have_many(:snippets).class_name('ProjectSnippet').dependent(:destroy) }
    it { is_expected.to have_many(:deploy_keys_projects).dependent(:destroy) }
    it { is_expected.to have_many(:deploy_keys) }
    it { is_expected.to have_many(:hooks).dependent(:destroy) }
    it { is_expected.to have_many(:protected_branches).dependent(:destroy) }
    it { is_expected.to have_one(:forked_project_link).dependent(:destroy) }
    it { is_expected.to have_one(:slack_service).dependent(:destroy) }
    it { is_expected.to have_one(:pushover_service).dependent(:destroy) }
    it { is_expected.to have_one(:asana_service).dependent(:destroy) }
gitlabhq's avatar
gitlabhq committed
55 56
  end

57
  describe 'Mass assignment' do
58 59
  end

60
  describe 'Validation' do
61 62
    let!(:project) { create(:project) }

63 64 65
    it { is_expected.to validate_presence_of(:name) }
    it { is_expected.to validate_uniqueness_of(:name).scoped_to(:namespace_id) }
    it { is_expected.to ensure_length_of(:name).is_within(0..255) }
66

67 68 69 70 71 72 73
    it { is_expected.to validate_presence_of(:path) }
    it { is_expected.to validate_uniqueness_of(:path).scoped_to(:namespace_id) }
    it { is_expected.to ensure_length_of(:path).is_within(0..255) }
    it { is_expected.to ensure_length_of(:description).is_within(0..2000) }
    it { is_expected.to validate_presence_of(:creator) }
    it { is_expected.to ensure_length_of(:issues_tracker_id).is_within(0..255) }
    it { is_expected.to validate_presence_of(:namespace) }
74

75
    it 'should not allow new projects beyond user limits' do
76
      project2 = build(:project)
77 78 79
      allow(project2).to receive(:creator).and_return(double(can_create_project?: false, projects_limit: 0).as_null_object)
      expect(project2).not_to be_valid
      expect(project2.errors[:limit_reached].first).to match(/Your project limit is 0/)
80
    end
gitlabhq's avatar
gitlabhq committed
81 82
  end

83
  describe 'Respond to' do
84 85 86 87 88 89 90 91
    it { is_expected.to respond_to(:url_to_repo) }
    it { is_expected.to respond_to(:repo_exists?) }
    it { is_expected.to respond_to(:satellite) }
    it { is_expected.to respond_to(:update_merge_requests) }
    it { is_expected.to respond_to(:execute_hooks) }
    it { is_expected.to respond_to(:name_with_namespace) }
    it { is_expected.to respond_to(:owner) }
    it { is_expected.to respond_to(:path_with_namespace) }
gitlabhq's avatar
gitlabhq committed
92 93
  end

94 95
  it 'should return valid url to repo' do
    project = Project.new(path: 'somewhere')
96
    expect(project.url_to_repo).to eq(Gitlab.config.gitlab_shell.ssh_path_prefix + 'somewhere.git')
gitlabhq's avatar
gitlabhq committed
97 98
  end

99 100
  it 'returns the full web URL for this repo' do
    project = Project.new(path: 'somewhere')
101
    expect(project.web_url).to eq("#{Gitlab.config.gitlab.url}/somewhere")
102 103
  end

104 105
  it 'returns the web URL without the protocol for this repo' do
    project = Project.new(path: 'somewhere')
106
    expect(project.web_url_without_protocol).to eq("#{Gitlab.config.gitlab.url.split('://')[1]}/somewhere")
107 108
  end

109
  describe 'last_activity methods' do
110
    let(:project) { create(:project) }
111
    let(:last_event) { double(created_at: Time.now) }
gitlabhq's avatar
gitlabhq committed
112

113 114
    describe 'last_activity' do
      it 'should alias last_activity to last_event' do
115
        project.stub(last_event: last_event)
116
        expect(project.last_activity).to eq(last_event)
117
      end
gitlabhq's avatar
gitlabhq committed
118 119
    end

120 121
    describe 'last_activity_date' do
      it 'returns the creation date of the project\'s last event if present' do
Andrey Kumanyaev's avatar
Andrey Kumanyaev committed
122
        last_activity_event = create(:event, project: project)
123
        expect(project.last_activity_at.to_i).to eq(last_event.created_at.to_i)
124
      end
125

126
      it 'returns the project\'s last update date if it has no events' do
127
        expect(project.last_activity_date).to eq(project.updated_at)
128
      end
129 130
    end
  end
131

132
  describe :update_merge_requests do
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
133
    let(:project) { create(:project) }
134 135 136 137
    let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
    let(:key) { create(:key, user_id: project.owner.id) }
    let(:prev_commit_id) { merge_request.commits.last.id }
    let(:commit_id) { merge_request.commits.first.id }
138

139
    it 'should close merge request if last commit from source branch was pushed to target branch' do
140 141
      project.update_merge_requests(prev_commit_id, commit_id, "refs/heads/#{merge_request.target_branch}", key.user)
      merge_request.reload
142
      expect(merge_request.merged?).to be_truthy
143 144
    end

145
    it 'should update merge request commits with new one if pushed to source branch' do
146 147
      project.update_merge_requests(prev_commit_id, commit_id, "refs/heads/#{merge_request.source_branch}", key.user)
      merge_request.reload
148
      expect(merge_request.last_commit.id).to eq(commit_id)
149 150
    end
  end
151 152 153 154 155

  describe :find_with_namespace do
    context 'with namespace' do
      before do
        @group = create :group, name: 'gitlab'
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
156
        @project = create(:project, name: 'gitlabhq', namespace: @group)
157 158
      end

159 160
      it { expect(Project.find_with_namespace('gitlab/gitlabhq')).to eq(@project) }
      it { expect(Project.find_with_namespace('gitlab-ci')).to be_nil }
161 162 163 164 165 166 167
    end
  end

  describe :to_param do
    context 'with namespace' do
      before do
        @group = create :group, name: 'gitlab'
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
168
        @project = create(:project, name: 'gitlabhq', namespace: @group)
169 170
      end

Vinnie Okada's avatar
Vinnie Okada committed
171
      it { expect(@project.to_param).to eq('gitlabhq') }
172 173
    end
  end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
174

175
  describe :repository do
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
176 177
    let(:project) { create(:project) }

178
    it 'should return valid repo' do
179
      expect(project.repository).to be_kind_of(Repository)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
180 181
    end
  end
182 183 184 185 186 187 188

  describe :issue_exists? do
    let(:project) { create(:project) }
    let(:existed_issue) { create(:issue, project: project) }
    let(:not_existed_issue) { create(:issue) }
    let(:ext_project) { create(:redmine_project) }

189
    it 'should be true or if used internal tracker and issue exists' do
190
      expect(project.issue_exists?(existed_issue.iid)).to be_truthy
191 192
    end

193
    it 'should be false or if used internal tracker and issue not exists' do
194
      expect(project.issue_exists?(not_existed_issue.iid)).to be_falsey
195 196
    end

197
    it 'should always be true if used other tracker' do
198
      expect(ext_project.issue_exists?(rand(100))).to be_truthy
199 200 201
    end
  end

202
  describe :default_issues_tracker? do
203 204 205 206
    let(:project) { create(:project) }
    let(:ext_project) { create(:redmine_project) }

    it "should be true if used internal tracker" do
207
      expect(project.default_issues_tracker?).to be_truthy
208 209 210
    end

    it "should be false if used other tracker" do
211
      expect(ext_project.default_issues_tracker?).to be_falsey
212 213 214
    end
  end

Andrew8xx8's avatar
Andrew8xx8 committed
215 216 217 218
  describe :can_have_issues_tracker_id? do
    let(:project) { create(:project) }
    let(:ext_project) { create(:redmine_project) }

219
    it 'should be true for projects with external issues tracker if issues enabled' do
220
      expect(ext_project.can_have_issues_tracker_id?).to be_truthy
221
    end
Andrew8xx8's avatar
Andrew8xx8 committed
222

223
    it 'should be false for projects with internal issue tracker if issues enabled' do
224
      expect(project.can_have_issues_tracker_id?).to be_falsey
Andrew8xx8's avatar
Andrew8xx8 committed
225 226
    end

227
    it 'should be always false if issues disabled' do
Andrew8xx8's avatar
Andrew8xx8 committed
228 229 230
      project.issues_enabled = false
      ext_project.issues_enabled = false

231 232
      expect(project.can_have_issues_tracker_id?).to be_falsey
      expect(ext_project.can_have_issues_tracker_id?).to be_falsey
Andrew8xx8's avatar
Andrew8xx8 committed
233 234
    end
  end
235 236

  describe :open_branches do
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
237
    let(:project) { create(:project) }
238 239 240 241 242

    before do
      project.protected_branches.create(name: 'master')
    end

243 244
    it { expect(project.open_branches.map(&:name)).to include('feature') }
    it { expect(project.open_branches.map(&:name)).not_to include('master') }
245
  end
Ciro Santilli's avatar
Ciro Santilli committed
246

247 248
  describe '#star_count' do
    it 'counts stars from multiple users' do
Ciro Santilli's avatar
Ciro Santilli committed
249 250 251 252 253
      user1 = create :user
      user2 = create :user
      project = create :project, :public

      expect(project.star_count).to eq(0)
254

Ciro Santilli's avatar
Ciro Santilli committed
255
      user1.toggle_star(project)
256 257
      expect(project.reload.star_count).to eq(1)

Ciro Santilli's avatar
Ciro Santilli committed
258
      user2.toggle_star(project)
259 260 261
      project.reload
      expect(project.reload.star_count).to eq(2)

Ciro Santilli's avatar
Ciro Santilli committed
262
      user1.toggle_star(project)
263 264 265
      project.reload
      expect(project.reload.star_count).to eq(1)

Ciro Santilli's avatar
Ciro Santilli committed
266
      user2.toggle_star(project)
267 268 269 270
      project.reload
      expect(project.reload.star_count).to eq(0)
    end

271
    it 'counts stars on the right project' do
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
      user = create :user
      project1 = create :project, :public
      project2 = create :project, :public

      expect(project1.star_count).to eq(0)
      expect(project2.star_count).to eq(0)

      user.toggle_star(project1)
      project1.reload
      project2.reload
      expect(project1.star_count).to eq(1)
      expect(project2.star_count).to eq(0)

      user.toggle_star(project1)
      project1.reload
      project2.reload
      expect(project1.star_count).to eq(0)
      expect(project2.star_count).to eq(0)

      user.toggle_star(project2)
      project1.reload
      project2.reload
      expect(project1.star_count).to eq(0)
      expect(project2.star_count).to eq(1)

      user.toggle_star(project2)
      project1.reload
      project2.reload
      expect(project1.star_count).to eq(0)
      expect(project2.star_count).to eq(0)
Ciro Santilli's avatar
Ciro Santilli committed
302
    end
303 304 305 306 307 308 309 310 311 312 313

    it 'is decremented when an upvoter account is deleted' do
      user = create :user
      project = create :project, :public
      user.toggle_star(project)
      project.reload
      expect(project.star_count).to eq(1)
      user.destroy
      project.reload
      expect(project.star_count).to eq(0)
    end
Ciro Santilli's avatar
Ciro Santilli committed
314
  end
315 316 317 318 319 320

  describe :avatar_type do
    let(:project) { create(:project) }

    it 'should be true if avatar is image' do
      project.update_attribute(:avatar, 'uploads/avatar.png')
321
      expect(project.avatar_type).to be_truthy
322 323 324 325
    end

    it 'should be false if avatar is html page' do
      project.update_attribute(:avatar, 'uploads/avatar.html')
326
      expect(project.avatar_type).to eq(['only images allowed'])
327 328
    end
  end
gitlabhq's avatar
gitlabhq committed
329
end