project_spec.rb 10.4 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
9
10
11
#  created_at             :datetime         not null
#  updated_at             :datetime         not null
#  private_flag           :boolean          default(TRUE), not null
12
13
#  owner_id               :integer
#  default_branch         :string(255)
14
15
16
17
#  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
18
#  namespace_id           :integer
19
20
#

gitlabhq's avatar
gitlabhq committed
21
22
23
24
require 'spec_helper'

describe Project do
  describe "Associations" do
25
    it { should belong_to(:group) }
26
    it { should belong_to(:namespace) }
27
    it { should belong_to(:owner).class_name('User') }
gitlabhq's avatar
gitlabhq committed
28
    it { should have_many(:users) }
29
30
31
    it { should have_many(:events).dependent(:destroy) }
    it { should have_many(:merge_requests).dependent(:destroy) }
    it { should have_many(:issues).dependent(:destroy) }
32
33
    it { should have_many(:milestones).dependent(:destroy) }
    it { should have_many(:users_projects).dependent(:destroy) }
34
35
36
    it { should have_many(:notes).dependent(:destroy) }
    it { should have_many(:snippets).dependent(:destroy) }
    it { should have_many(:deploy_keys).dependent(:destroy) }
37
38
39
    it { should have_many(:hooks).dependent(:destroy) }
    it { should have_many(:wikis).dependent(:destroy) }
    it { should have_many(:protected_branches).dependent(:destroy) }
gitlabhq's avatar
gitlabhq committed
40
41
  end

42
  describe "Mass assignment" do
43
    it { should_not allow_mass_assignment_of(:namespace_id) }
44
45
46
47
    it { should_not allow_mass_assignment_of(:owner_id) }
    it { should_not allow_mass_assignment_of(:private_flag) }
  end

gitlabhq's avatar
gitlabhq committed
48
  describe "Validation" do
49
50
    let!(:project) { create(:project) }

gitlabhq's avatar
gitlabhq committed
51
    it { should validate_presence_of(:name) }
52
53
54
    it { should validate_uniqueness_of(:name) }
    it { should ensure_length_of(:name).is_within(0..255) }

gitlabhq's avatar
gitlabhq committed
55
    it { should validate_presence_of(:path) }
56
57
58
59
60
61
62
63
64
    it { should validate_uniqueness_of(:path) }
    it { should ensure_length_of(:path).is_within(0..255) }
    # TODO: Formats

    it { should ensure_length_of(:description).is_within(0..2000) }

    # TODO: Formats

    it { should validate_presence_of(:owner) }
65
66
67
68
    it { should ensure_inclusion_of(:issues_enabled).in_array([true, false]) }
    it { should ensure_inclusion_of(:wall_enabled).in_array([true, false]) }
    it { should ensure_inclusion_of(:merge_requests_enabled).in_array([true, false]) }
    it { should ensure_inclusion_of(:wiki_enabled).in_array([true, false]) }
69
70
71
72
73
74
75
76
77
78
79

    it "should not allow new projects beyond user limits" do
      project.stub(:owner).and_return(double(can_create_project?: false, projects_limit: 1))
      project.should_not be_valid
      project.errors[:base].first.should match(/Your own projects limit is 1/)
    end

    it "should not allow 'gitolite-admin' as repo name" do
      should allow_value("blah").for(:path)
      should_not allow_value("gitolite-admin").for(:path)
    end
gitlabhq's avatar
gitlabhq committed
80
81
82
83
84
85
86
87
88
  end

  describe "Respond to" do
    it { should respond_to(:public?) }
    it { should respond_to(:private?) }
    it { should respond_to(:url_to_repo) }
    it { should respond_to(:path_to_repo) }
    it { should respond_to(:valid_repo?) }
    it { should respond_to(:repo_exists?) }
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
89
90
91
92

    # Repository Role
    it { should respond_to(:tree) }
    it { should respond_to(:root_ref) }
gitlabhq's avatar
gitlabhq committed
93
94
95
    it { should respond_to(:repo) }
    it { should respond_to(:tags) }
    it { should respond_to(:commit) }
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
96
    it { should respond_to(:commits) }
97
    it { should respond_to(:commits_between) }
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
    it { should respond_to(:commits_with_refs) }
    it { should respond_to(:commits_since) }
    it { should respond_to(:commits_between) }
    it { should respond_to(:satellite) }
    it { should respond_to(:update_repository) }
    it { should respond_to(:destroy_repository) }
    it { should respond_to(:archive_repo) }

    # Authority Role
    it { should respond_to(:add_access) }
    it { should respond_to(:reset_access) }
    it { should respond_to(:repository_writers) }
    it { should respond_to(:repository_masters) }
    it { should respond_to(:repository_readers) }
    it { should respond_to(:allow_read_for?) }
    it { should respond_to(:guest_access_for?) }
    it { should respond_to(:report_access_for?) }
    it { should respond_to(:dev_access_for?) }
    it { should respond_to(:master_access_for?) }

    # Team Role
    it { should respond_to(:team_member_by_name_or_email) }
    it { should respond_to(:team_member_by_id) }
    it { should respond_to(:add_user_to_team) }
    it { should respond_to(:add_users_to_team) }
    it { should respond_to(:add_user_id_to_team) }
    it { should respond_to(:add_users_ids_to_team) }

    # Project Push Role
    it { should respond_to(:observe_push) }
    it { should respond_to(:update_merge_requests) }
    it { should respond_to(:execute_hooks) }
    it { should respond_to(:post_receive_data) }
    it { should respond_to(:trigger_post_receive) }
gitlabhq's avatar
gitlabhq committed
132
133
  end

134
135
136
137
138
  describe 'modules' do
    it { should include_module(Repository) }
    it { should include_module(PushObserver) }
    it { should include_module(Authority) }
    it { should include_module(Team) }
gitlabhq's avatar
gitlabhq committed
139
140
  end

Nihad Abbasov's avatar
Nihad Abbasov committed
141
  it "should return valid url to repo" do
142
    project = Project.new(path: "somewhere")
143
    project.url_to_repo.should == Gitlab.config.ssh_path + "somewhere.git"
gitlabhq's avatar
gitlabhq committed
144
145
  end

Nihad Abbasov's avatar
Nihad Abbasov committed
146
  it "should return path to repo" do
147
    project = Project.new(path: "somewhere")
148
    project.path_to_repo.should == Rails.root.join("tmp", "repositories", "somewhere")
gitlabhq's avatar
gitlabhq committed
149
150
  end

151
  it "returns the full web URL for this repo" do
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
152
    project = Project.new(path: "somewhere")
153
    project.web_url.should == "#{Gitlab.config.url}/somewhere"
154
155
  end

Nihad Abbasov's avatar
Nihad Abbasov committed
156
157
  describe :valid_repo? do
    it "should be valid repo" do
158
      project = create(:project)
Nihad Abbasov's avatar
Nihad Abbasov committed
159
      project.valid_repo?.should be_true
gitlabhq's avatar
gitlabhq committed
160
161
162
    end

    it "should be invalid repo" do
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
163
      project = Project.new(name: "ok_name", path: "/INVALID_PATH/", path: "NEOK")
gitlabhq's avatar
gitlabhq committed
164
165
166
167
      project.valid_repo?.should be_false
    end
  end

168
  describe "last_activity methods" do
169
    let(:project)    { create(:project) }
170
    let(:last_event) { double(created_at: Time.now) }
gitlabhq's avatar
gitlabhq committed
171

172
173
174
175
176
    describe "last_activity" do
      it "should alias last_activity to last_event"do
        project.stub(last_event: last_event)
        project.last_activity.should == last_event
      end
gitlabhq's avatar
gitlabhq committed
177
178
    end

179
180
181
182
183
    describe 'last_activity_date' do
      it 'returns the creation date of the project\'s last event if present' do
        project.stub(last_event: last_event)
        project.last_activity_date.should == last_event.created_at
      end
184

185
186
187
      it 'returns the project\'s last update date if it has no events' do
        project.last_activity_date.should == project.updated_at
      end
188
189
    end
  end
190

191
  describe "fresh commits" do
192
    let(:project) { create(:project) }
gitlabhq's avatar
gitlabhq committed
193
194

    it { project.fresh_commits(3).count.should == 3 }
195
196
    it { project.fresh_commits.first.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" }
    it { project.fresh_commits.last.id.should == "f403da73f5e62794a0447aca879360494b08f678" }
gitlabhq's avatar
gitlabhq committed
197
198
  end

199
  describe "commits_between" do
200
    let(:project) { create(:project) }
201
202

    subject do
203
204
      commits = project.commits_between("3a4b4fb4cde7809f033822a171b9feae19d41fff",
                                        "8470d70da67355c9c009e4401746b1d5410af2e3")
205
206
207
      commits.map { |c| c.id }
    end

208
209
210
    it { should have(3).elements }
    it { should include("f0f14c8eaba69ebddd766498a9d0b0e79becd633") }
    it { should_not include("bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a") }
211
212
  end

Nihad Abbasov's avatar
Nihad Abbasov committed
213
  describe "Git methods" do
214
    let(:project) { create(:project) }
gitlabhq's avatar
gitlabhq committed
215

Nihad Abbasov's avatar
Nihad Abbasov committed
216
217
    describe :repo do
      it "should return valid repo" do
gitlabhq's avatar
gitlabhq committed
218
219
220
        project.repo.should be_kind_of(Grit::Repo)
      end

Nihad Abbasov's avatar
Nihad Abbasov committed
221
      it "should return nil" do
222
        lambda { Project.new(path: "invalid").repo }.should raise_error(Grit::NoSuchPathError)
gitlabhq's avatar
gitlabhq committed
223
224
      end

Nihad Abbasov's avatar
Nihad Abbasov committed
225
      it "should return nil" do
gitlabhq's avatar
gitlabhq committed
226
227
228
229
        lambda { Project.new.repo }.should raise_error(TypeError)
      end
    end

Nihad Abbasov's avatar
Nihad Abbasov committed
230
231
    describe :commit do
      it "should return first head commit if without params" do
gitlabhq's avatar
gitlabhq committed
232
233
234
        project.commit.id.should == project.repo.commits.first.id
      end

Nihad Abbasov's avatar
Nihad Abbasov committed
235
      it "should return valid commit" do
gitlabhq's avatar
gitlabhq committed
236
237
238
        project.commit(ValidCommit::ID).should be_valid_commit
      end

Nihad Abbasov's avatar
Nihad Abbasov committed
239
      it "should return nil" do
gitlabhq's avatar
gitlabhq committed
240
241
242
243
        project.commit("+123_4532530XYZ").should be_nil
      end
    end

Nihad Abbasov's avatar
Nihad Abbasov committed
244
245
    describe :tree do
      before do
gitlabhq's avatar
gitlabhq committed
246
247
248
        @commit = project.commit(ValidCommit::ID)
      end

Nihad Abbasov's avatar
Nihad Abbasov committed
249
      it "should raise error w/o arguments" do
gitlabhq's avatar
gitlabhq committed
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
        lambda { project.tree }.should raise_error
      end

      it "should return root tree for commit" do
        tree = project.tree(@commit)
        tree.contents.size.should == ValidCommit::FILES_COUNT
        tree.contents.map(&:name).should == ValidCommit::FILES
      end

      it "should return root tree for commit with correct path" do
        tree = project.tree(@commit, ValidCommit::C_FILE_PATH)
        tree.contents.map(&:name).should == ValidCommit::C_FILES
      end

      it "should return root tree for commit with incorrect path" do
        project.tree(@commit, "invalid_path").should be_nil
      end
    end
  end
269

270
  describe :update_merge_requests do
271
    let(:project) { create(:project) }
272
273

    before do
274
275
276
277
278
      @merge_request = create(:merge_request,
                              project: project,
                              merged: false,
                              closed: false)
      @key = create(:key, user_id: project.owner.id)
279
280
281
282
283
    end

    it "should close merge request if last commit from source branch was pushed to target branch" do
      @merge_request.reloaded_commits
      @merge_request.last_commit.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a"
284
      project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a", "refs/heads/stable", @key.user)
285
286
287
288
289
      @merge_request.reload
      @merge_request.merged.should be_true
      @merge_request.closed.should be_true
    end

290
    it "should update merge request commits with new one if pushed to source branch" do
291
      @merge_request.last_commit.should == nil
292
      project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a", "refs/heads/master", @key.user)
293
294
295
296
      @merge_request.reload
      @merge_request.last_commit.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a"
    end
  end
gitlabhq's avatar
gitlabhq committed
297
end