project_spec.rb 10.5 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# == Schema Information
#
# Table name: projects
#
#  id                     :integer         not null, primary key
#  name                   :string(255)
#  path                   :string(255)
#  description            :text
#  created_at             :datetime        not null
#  updated_at             :datetime        not null
#  private_flag           :boolean         default(TRUE), not null
#  code                   :string(255)
#  owner_id               :integer
#  default_branch         :string(255)
#  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
#  group_id               :integer
#

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

describe Project do
  describe "Associations" do
26
    it { should belong_to(:group) }
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
43
44
45
46
  describe "Mass assignment" do
    it { should_not allow_mass_assignment_of(:owner_id) }
    it { should_not allow_mass_assignment_of(:private_flag) }
  end

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

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

gitlabhq's avatar
gitlabhq committed
54
    it { should validate_presence_of(:path) }
55
56
57
58
59
60
    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) }

gitlabhq's avatar
gitlabhq committed
61
    it { should validate_presence_of(:code) }
62
63
64
65
66
    it { should validate_uniqueness_of(:code) }
    it { should ensure_length_of(:code).is_within(1..255) }
    # TODO: Formats

    it { should validate_presence_of(:owner) }
67
68
69
70
    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]) }
71
72
73
74
75
76
77
78
79
80
81

    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
82
83
84
85
86
87
88
89
90
  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
91
92
93
94

    # Repository Role
    it { should respond_to(:tree) }
    it { should respond_to(:root_ref) }
gitlabhq's avatar
gitlabhq committed
95
96
97
    it { should respond_to(:repo) }
    it { should respond_to(:tags) }
    it { should respond_to(:commit) }
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
98
    it { should respond_to(:commits) }
99
    it { should respond_to(:commits_between) }
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
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
132
133
    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
134
135
  end

136
137
138
139
140
  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
141
142
  end

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

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

153
  it "returns the full web URL for this repo" do
154
    project = Project.new(code: "somewhere")
155
    project.web_url.should == "#{Gitlab.config.url}/somewhere"
156
157
  end

Nihad Abbasov's avatar
Nihad Abbasov committed
158
159
  describe :valid_repo? do
    it "should be valid repo" do
gitlabhq's avatar
gitlabhq committed
160
      project = Factory :project
Nihad Abbasov's avatar
Nihad Abbasov committed
161
      project.valid_repo?.should be_true
gitlabhq's avatar
gitlabhq committed
162
163
164
    end

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

170
  describe "last_activity" do
171
172
    let(:project)    { Factory :project }
    let(:last_event) { double }
gitlabhq's avatar
gitlabhq committed
173

174
    before do
randx's avatar
randx committed
175
      project.stub_chain(:events, :order).and_return( [ double, double, last_event ] )
gitlabhq's avatar
gitlabhq committed
176
177
    end

178
    it { project.last_activity.should == last_event }
gitlabhq's avatar
gitlabhq committed
179
180
  end

181
182
183
184
  describe 'last_activity_date' do
    let(:project)    { Factory :project }

    it 'returns the creation date of the project\'s last event if present' do
185
      last_event = double(created_at: 'now')
186
187
188
189
190
191
192
193
      project.stub(:events).and_return( [double, double, last_event] )
      project.last_activity_date.should == last_event.created_at
    end

    it 'returns the project\'s last update date if it has no events' do
      project.last_activity_date.should == project.updated_at
    end
  end
194
  describe "fresh commits" do
gitlabhq's avatar
gitlabhq committed
195
196
197
    let(:project) { Factory :project }

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

202
203
204
205
  describe "commits_between" do
    let(:project) { Factory :project }

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

211
212
213
    it { should have(3).elements }
    it { should include("f0f14c8eaba69ebddd766498a9d0b0e79becd633") }
    it { should_not include("bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a") }
214
215
  end

Nihad Abbasov's avatar
Nihad Abbasov committed
216
  describe "Git methods" do
gitlabhq's avatar
gitlabhq committed
217
218
    let(:project) { Factory :project }

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

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

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

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

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

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

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

Nihad Abbasov's avatar
Nihad Abbasov committed
252
      it "should raise error w/o arguments" do
gitlabhq's avatar
gitlabhq committed
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
        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
272

273
  describe :update_merge_requests do
274
275
276
277
    let(:project) { Factory :project }

    before do
      @merge_request = Factory :merge_request,
278
279
280
281
        project: project,
        merged: false,
        closed: false
      @key = Factory :key, user_id: project.owner.id
282
283
284
285
286
    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"
287
      project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a", "refs/heads/stable", @key.user)
288
289
290
291
292
      @merge_request.reload
      @merge_request.merged.should be_true
      @merge_request.closed.should be_true
    end

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