project_spec.rb 10.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
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
27
28
#

gitlabhq's avatar
gitlabhq committed
29
30
31
32
require 'spec_helper'

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

52
53
54
  describe "Mass assignment" do
  end

gitlabhq's avatar
gitlabhq committed
55
  describe "Validation" do
56
57
    let!(:project) { create(:project) }

gitlabhq's avatar
gitlabhq committed
58
    it { should validate_presence_of(:name) }
59
    it { should validate_uniqueness_of(:name).scoped_to(:namespace_id) }
60
61
    it { should ensure_length_of(:name).is_within(0..255) }

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

    it "should not allow new projects beyond user limits" do
71
      project2 = build(:project)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
72
      project2.stub(:creator).and_return(double(can_create_project?: false, projects_limit: 0).as_null_object)
73
      project2.should_not be_valid
74
      project2.errors[:limit_reached].first.should match(/Your project limit is 0/)
75
    end
gitlabhq's avatar
gitlabhq committed
76
77
78
79
80
  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
81
82
83
    it { should respond_to(:satellite) }
    it { should respond_to(:update_merge_requests) }
    it { should respond_to(:execute_hooks) }
84
    it { should respond_to(:name_with_namespace) }
85
    it { should respond_to(:owner) }
86
    it { should respond_to(:path_with_namespace) }
gitlabhq's avatar
gitlabhq committed
87
88
  end

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

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

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

104
  describe "last_activity methods" do
105
    let(:project) { create(:project) }
106
    let(:last_event) { double(created_at: Time.now) }
gitlabhq's avatar
gitlabhq committed
107

108
    describe "last_activity" do
109
      it "should alias last_activity to last_event" do
110
111
112
        project.stub(last_event: last_event)
        project.last_activity.should == last_event
      end
gitlabhq's avatar
gitlabhq committed
113
114
    end

115
116
    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
117
        last_activity_event = create(:event, project: project)
118
        project.last_activity_at.to_i.should == last_event.created_at.to_i
119
      end
120

121
122
123
      it 'returns the project\'s last update date if it has no events' do
        project.last_activity_date.should == project.updated_at
      end
124
125
    end
  end
126

127
  describe :update_merge_requests do
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
128
    let(:project) { create(:project) }
129
130
131
132
    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 }
133
134

    it "should close merge request if last commit from source branch was pushed to target branch" do
135
136
137
      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
138
139
    end

140
    it "should update merge request commits with new one if pushed to source branch" do
141
142
143
      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
144
145
    end
  end
146
147
148
149
150
151


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

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
155
      it { Project.find_with_namespace('gitlab/gitlabhq').should == @project }
156
157
158
159
160
161
162
163
      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
164
        @project = create(:project, name: 'gitlabhq', namespace: @group)
165
166
      end

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
167
      it { @project.to_param.should == "gitlab/gitlabhq" }
168
169
    end
  end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
170

171
  describe :repository do
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
172
173
174
    let(:project) { create(:project) }

    it "should return valid repo" do
175
      project.repository.should be_kind_of(Repository)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
176
177
    end
  end
178
179
180
181
182
183
184
185

  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
186
      project.issue_exists?(existed_issue.iid).should be_true
187
188
189
    end

    it "should be false or if used internal tracker and issue not exists" do
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
190
      project.issue_exists?(not_existed_issue.iid).should be_false
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
    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
211
212
213
214
215
216
  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
217
    end
Andrew8xx8's avatar
Andrew8xx8 committed
218
219
220
221
222

    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
223
    it "should be always false if issues disabled" do
Andrew8xx8's avatar
Andrew8xx8 committed
224
225
226
227
228
229
230
      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
231
232

  describe :open_branches do
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
233
    let(:project) { create(:project) }
234
235
236
237
238

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

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

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

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

Ciro Santilli's avatar
Ciro Santilli committed
251
      user1.toggle_star(project)
252
253
      expect(project.reload.star_count).to eq(1)

Ciro Santilli's avatar
Ciro Santilli committed
254
      user2.toggle_star(project)
255
256
257
      project.reload
      expect(project.reload.star_count).to eq(2)

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

Ciro Santilli's avatar
Ciro Santilli committed
262
      user2.toggle_star(project)
263
264
265
266
      project.reload
      expect(project.reload.star_count).to eq(0)
    end

267
    it 'counts stars on the right project' do
268
269
270
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
      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
298
    end
299
300
301
302
303
304
305
306
307
308
309

    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
310
  end
gitlabhq's avatar
gitlabhq committed
311
end