Read about our upcoming Code of Conduct on this issue

project_spec.rb 11.1 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
18
#  issues_tracker         :string(255)      default("gitlab"), not null
#  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
35
require 'spec_helper'

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

56
57
58
  describe "Mass assignment" do
  end

gitlabhq's avatar
gitlabhq committed
59
  describe "Validation" do
60
61
    let!(:project) { create(:project) }

gitlabhq's avatar
gitlabhq committed
62
    it { should validate_presence_of(:name) }
63
    it { should validate_uniqueness_of(:name).scoped_to(:namespace_id) }
64
65
    it { should ensure_length_of(:name).is_within(0..255) }

gitlabhq's avatar
gitlabhq committed
66
    it { should validate_presence_of(:path) }
67
    it { should validate_uniqueness_of(:path).scoped_to(:namespace_id) }
68
69
    it { should ensure_length_of(:path).is_within(0..255) }
    it { should ensure_length_of(:description).is_within(0..2000) }
70
    it { should validate_presence_of(:creator) }
Andrew8xx8's avatar
Andrew8xx8 committed
71
    it { should ensure_length_of(:issues_tracker_id).is_within(0..255) }
72
    it { should validate_presence_of(:namespace) }
73
74

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

  describe "Respond to" do
    it { should respond_to(:url_to_repo) }
    it { should respond_to(:repo_exists?) }
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
85
86
87
    it { should respond_to(:satellite) }
    it { should respond_to(:update_merge_requests) }
    it { should respond_to(:execute_hooks) }
88
    it { should respond_to(:name_with_namespace) }
89
    it { should respond_to(:owner) }
90
    it { should respond_to(:path_with_namespace) }
gitlabhq's avatar
gitlabhq committed
91
92
  end

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

98
  it "returns the full web URL for this repo" do
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
99
    project = Project.new(path: "somewhere")
100
    project.web_url.should == "#{Gitlab.config.gitlab.url}/somewhere"
101
102
  end

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

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

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

119
120
    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
121
        last_activity_event = create(:event, project: project)
122
        project.last_activity_at.to_i.should == last_event.created_at.to_i
123
      end
124

125
126
127
      it 'returns the project\'s last update date if it has no events' do
        project.last_activity_date.should == project.updated_at
      end
128
129
    end
  end
130

131
  describe :update_merge_requests do
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
132
    let(:project) { create(:project) }
133
134
135
136
    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 }
137
138

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

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

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

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
158
      it { Project.find_with_namespace('gitlab/gitlabhq').should == @project }
159
160
161
162
163
164
165
166
      it { Project.find_with_namespace('gitlab-ci').should be_nil }
    end
  end

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

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
170
      it { @project.to_param.should == "gitlab/gitlabhq" }
171
172
    end
  end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
173

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

    it "should return valid repo" do
178
      project.repository.should be_kind_of(Repository)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
179
180
    end
  end
181
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) }

    it "should be true or if used internal tracker and issue exists" do
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
189
      project.issue_exists?(existed_issue.iid).should be_true
190
191
192
    end

    it "should be false or if used internal tracker and issue not exists" do
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
193
      project.issue_exists?(not_existed_issue.iid).should be_false
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
    end

    it "should always be true if used other tracker" do
      ext_project.issue_exists?(rand(100)).should be_true
    end
  end

  describe :used_default_issues_tracker? do
    let(:project) { create(:project) }
    let(:ext_project) { create(:redmine_project) }

    it "should be true if used internal tracker" do
      project.used_default_issues_tracker?.should be_true
    end

    it "should be false if used other tracker" do
      ext_project.used_default_issues_tracker?.should be_false
    end
  end

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

    it "should be true for projects with external issues tracker if issues enabled" do
      ext_project.can_have_issues_tracker_id?.should be_true
220
    end
Andrew8xx8's avatar
Andrew8xx8 committed
221
222
223
224
225

    it "should be false for projects with internal issue tracker if issues enabled" do
      project.can_have_issues_tracker_id?.should be_false
    end

Johannes Schleifenbaum's avatar
Johannes Schleifenbaum committed
226
    it "should be always false if issues disabled" do
Andrew8xx8's avatar
Andrew8xx8 committed
227
228
229
230
231
232
233
      project.issues_enabled = false
      ext_project.issues_enabled = false

      project.can_have_issues_tracker_id?.should be_false
      ext_project.can_have_issues_tracker_id?.should be_false
    end
  end
234
235

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

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

242
    it { project.open_branches.map(&:name).should include('feature') }
243
244
    it { project.open_branches.map(&:name).should_not include('master') }
  end
Ciro Santilli's avatar
Ciro Santilli committed
245

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

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

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

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

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

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

270
    it 'counts stars on the right project' do
271
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
      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
301
    end
302
303
304
305
306
307
308
309
310
311
312

    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
313
  end
314
315
316
317
318
319
320
321
322
323
324
325
326
327

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

    it 'should be true if avatar is image' do
      project.update_attribute(:avatar, 'uploads/avatar.png')
      project.avatar_type.should be_true
    end

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