Commit 5b0a998920d9357446c89ba7352f38622fb1323f

Authored by Dmitriy Zaporozhets
2 parents 8c44789e 97423a0b

Merge pull request #1333 from tsigo/model_specs

Increased model spec coverage
spec/factories.rb
@@ -18,11 +18,15 @@ FactoryGirl.define do @@ -18,11 +18,15 @@ FactoryGirl.define do
18 Faker::Lorem.sentence 18 Faker::Lorem.sentence
19 end 19 end
20 20
  21 + sequence :name, aliases: [:file_name] do
  22 + Faker::Name.name
  23 + end
  24 +
21 sequence(:url) { Faker::Internet.uri('http') } 25 sequence(:url) { Faker::Internet.uri('http') }
22 26
23 factory :user, aliases: [:author, :assignee, :owner] do 27 factory :user, aliases: [:author, :assignee, :owner] do
24 email { Faker::Internet.email } 28 email { Faker::Internet.email }
25 - name { Faker::Name.name } 29 + name
26 password "123456" 30 password "123456"
27 password_confirmation "123456" 31 password_confirmation "123456"
28 32
@@ -116,6 +120,11 @@ FactoryGirl.define do @@ -116,6 +120,11 @@ FactoryGirl.define do
116 author 120 author
117 title 121 title
118 content 122 content
119 - file_name { Faker::Lorem.sentence } 123 + file_name
  124 + end
  125 +
  126 + factory :protected_branch do
  127 + name
  128 + project
120 end 129 end
121 end 130 end
spec/models/event_spec.rb
1 -# == Schema Information  
2 -#  
3 -# Table name: events  
4 -#  
5 -# id :integer(4) not null, primary key  
6 -# target_type :string(255)  
7 -# target_id :integer(4)  
8 -# title :string(255)  
9 -# data :text  
10 -# project_id :integer(4)  
11 -# created_at :datetime not null  
12 -# updated_at :datetime not null  
13 -# action :integer(4)  
14 -# author_id :integer(4)  
15 -#  
16 -  
17 require 'spec_helper' 1 require 'spec_helper'
18 2
19 describe Event do 3 describe Event do
20 describe "Associations" do 4 describe "Associations" do
21 it { should belong_to(:project) } 5 it { should belong_to(:project) }
  6 + it { should belong_to(:target) }
22 end 7 end
23 8
24 describe "Respond to" do 9 describe "Respond to" do
@@ -29,16 +14,6 @@ describe Event do @@ -29,16 +14,6 @@ describe Event do
29 it { should respond_to(:commits) } 14 it { should respond_to(:commits) }
30 end 15 end
31 16
32 - describe "Creation" do  
33 - before do  
34 - @event = Factory :event  
35 - end  
36 -  
37 - it "should create a valid event" do  
38 - @event.should be_valid  
39 - end  
40 - end  
41 -  
42 describe "Push event" do 17 describe "Push event" do
43 before do 18 before do
44 project = Factory :project 19 project = Factory :project
spec/models/issue_spec.rb
@@ -2,21 +2,16 @@ require 'spec_helper' @@ -2,21 +2,16 @@ require 'spec_helper'
2 2
3 describe Issue do 3 describe Issue do
4 describe "Associations" do 4 describe "Associations" do
5 - it { should belong_to(:project) }  
6 - it { should belong_to(:author) }  
7 - it { should belong_to(:assignee) }  
8 it { should belong_to(:milestone) } 5 it { should belong_to(:milestone) }
9 end 6 end
10 7
11 describe "Validation" do 8 describe "Validation" do
12 - it { should validate_presence_of(:title) }  
13 - it { should validate_presence_of(:author_id) }  
14 - it { should validate_presence_of(:project_id) } 9 + it { should ensure_length_of(:description).is_within(0..2000) }
15 end 10 end
16 11
17 - describe "Scope" do  
18 - it { Issue.should respond_to :closed }  
19 - it { Issue.should respond_to :opened } 12 + describe 'modules' do
  13 + it { should include_module(IssueCommonality) }
  14 + it { should include_module(Upvote) }
20 end 15 end
21 16
22 subject { Factory.create(:issue) } 17 subject { Factory.create(:issue) }
@@ -61,57 +56,4 @@ describe Issue do @@ -61,57 +56,4 @@ describe Issue do
61 subject.is_being_reopened?.should be_false 56 subject.is_being_reopened?.should be_false
62 end 57 end
63 end 58 end
64 -  
65 - describe "plus 1" do  
66 - subject { Factory.create(:issue) }  
67 -  
68 - it "with no notes has a 0/0 score" do  
69 - subject.upvotes.should == 0  
70 - end  
71 -  
72 - it "should recognize non-+1 notes" do  
73 - subject.notes << Factory(:note, note: "No +1 here")  
74 - subject.should have(1).note  
75 - subject.notes.first.upvote?.should be_false  
76 - subject.upvotes.should == 0  
77 - end  
78 -  
79 - it "should recognize a single +1 note" do  
80 - subject.notes << Factory(:note, note: "+1 This is awesome")  
81 - subject.upvotes.should == 1  
82 - end  
83 -  
84 - it "should recognize a multiple +1 notes" do  
85 - subject.notes << Factory(:note, note: "+1 This is awesome")  
86 - subject.notes << Factory(:note, note: "+1 I want this")  
87 - subject.upvotes.should == 2  
88 - end  
89 - end  
90 -  
91 - describe ".search" do  
92 - let!(:issue) { Factory.create(:issue, title: "Searchable issue") }  
93 -  
94 - it "matches by title" do  
95 - Issue.search('able').all.should == [issue]  
96 - end  
97 - end  
98 end 59 end
99 -# == Schema Information  
100 -#  
101 -# Table name: issues  
102 -#  
103 -# id :integer(4) not null, primary key  
104 -# title :string(255)  
105 -# assignee_id :integer(4)  
106 -# author_id :integer(4)  
107 -# project_id :integer(4)  
108 -# created_at :datetime not null  
109 -# updated_at :datetime not null  
110 -# closed :boolean(1) default(FALSE), not null  
111 -# position :integer(4) default(0)  
112 -# critical :boolean(1) default(FALSE), not null  
113 -# branch_name :string(255)  
114 -# description :text  
115 -# milestone_id :integer(4)  
116 -#  
117 -  
spec/models/key_spec.rb
@@ -2,12 +2,15 @@ require &#39;spec_helper&#39; @@ -2,12 +2,15 @@ require &#39;spec_helper&#39;
2 2
3 describe Key do 3 describe Key do
4 describe "Associations" do 4 describe "Associations" do
5 - it { should belong_to(:user) or belong_to(:project) } 5 + it { should belong_to(:user) }
  6 + it { should belong_to(:project) }
6 end 7 end
7 8
8 describe "Validation" do 9 describe "Validation" do
9 it { should validate_presence_of(:title) } 10 it { should validate_presence_of(:title) }
10 it { should validate_presence_of(:key) } 11 it { should validate_presence_of(:key) }
  12 + it { should ensure_length_of(:title).is_within(0..255) }
  13 + it { should ensure_length_of(:key).is_within(0..5000) }
11 end 14 end
12 15
13 describe "Methods" do 16 describe "Methods" do
@@ -44,17 +47,3 @@ describe Key do @@ -44,17 +47,3 @@ describe Key do
44 end 47 end
45 end 48 end
46 end 49 end
47 -# == Schema Information  
48 -#  
49 -# Table name: keys  
50 -#  
51 -# id :integer(4) not null, primary key  
52 -# user_id :integer(4)  
53 -# created_at :datetime not null  
54 -# updated_at :datetime not null  
55 -# key :text  
56 -# title :string(255)  
57 -# identifier :string(255)  
58 -# project_id :integer(4)  
59 -#  
60 -  
spec/models/merge_request_spec.rb
1 require 'spec_helper' 1 require 'spec_helper'
2 2
3 describe MergeRequest do 3 describe MergeRequest do
4 - describe "Associations" do  
5 - it { should belong_to(:project) }  
6 - it { should belong_to(:author) }  
7 - it { should belong_to(:assignee) }  
8 - end  
9 -  
10 describe "Validation" do 4 describe "Validation" do
11 it { should validate_presence_of(:target_branch) } 5 it { should validate_presence_of(:target_branch) }
12 it { should validate_presence_of(:source_branch) } 6 it { should validate_presence_of(:source_branch) }
13 - it { should validate_presence_of(:title) }  
14 - it { should validate_presence_of(:author_id) }  
15 - it { should validate_presence_of(:project_id) }  
16 - end  
17 -  
18 - describe "Scope" do  
19 - it { MergeRequest.should respond_to :closed }  
20 - it { MergeRequest.should respond_to :opened }  
21 - end  
22 -  
23 - describe "plus 1" do  
24 - subject { Factory.create(:merge_request) }  
25 -  
26 - it "with no notes has a 0/0 score" do  
27 - subject.upvotes.should == 0  
28 - end  
29 -  
30 - it "should recognize non-+1 notes" do  
31 - subject.notes << Factory(:note, note: "No +1 here")  
32 - subject.should have(1).note  
33 - subject.notes.first.upvote?.should be_false  
34 - subject.upvotes.should == 0  
35 - end  
36 -  
37 - it "should recognize a single +1 note" do  
38 - subject.notes << Factory(:note, note: "+1 This is awesome")  
39 - subject.upvotes.should == 1  
40 - end  
41 -  
42 - it "should recognize a multiple +1 notes" do  
43 - subject.notes << Factory(:note, note: "+1 This is awesome")  
44 - subject.notes << Factory(:note, note: "+1 I want this")  
45 - subject.upvotes.should == 2  
46 - end  
47 end 7 end
48 8
49 - describe ".search" do  
50 - let!(:issue) { Factory.create(:issue, title: "Searchable issue") }  
51 -  
52 - it "matches by title" do  
53 - Issue.search('able').all.should == [issue]  
54 - end 9 + describe 'modules' do
  10 + it { should include_module(IssueCommonality) }
  11 + it { should include_module(Upvote) }
55 end 12 end
56 end 13 end
57 -# == Schema Information  
58 -#  
59 -# Table name: merge_requests  
60 -#  
61 -# id :integer(4) not null, primary key  
62 -# target_branch :string(255) not null  
63 -# source_branch :string(255) not null  
64 -# project_id :integer(4) not null  
65 -# author_id :integer(4)  
66 -# assignee_id :integer(4)  
67 -# title :string(255)  
68 -# closed :boolean(1) default(FALSE), not null  
69 -# created_at :datetime not null  
70 -# updated_at :datetime not null  
71 -# st_commits :text(2147483647  
72 -# st_diffs :text(2147483647  
73 -# merged :boolean(1) default(FALSE), not null  
74 -# state :integer(4) default(1), not null  
75 -#  
76 -  
spec/models/milestone_spec.rb
1 -# == Schema Information  
2 -#  
3 -# Table name: milestones  
4 -#  
5 -# id :integer(4) not null, primary key  
6 -# title :string(255) not null  
7 -# project_id :integer(4) not null  
8 -# description :text  
9 -# due_date :date  
10 -# closed :boolean(1) default(FALSE), not null  
11 -# created_at :datetime not null  
12 -# updated_at :datetime not null  
13 -#  
14 -  
15 require 'spec_helper' 1 require 'spec_helper'
16 2
17 describe Milestone do 3 describe Milestone do
spec/models/note_spec.rb
@@ -3,6 +3,8 @@ require &#39;spec_helper&#39; @@ -3,6 +3,8 @@ require &#39;spec_helper&#39;
3 describe Note do 3 describe Note do
4 describe "Associations" do 4 describe "Associations" do
5 it { should belong_to(:project) } 5 it { should belong_to(:project) }
  6 + it { should belong_to(:noteable) }
  7 + it { should belong_to(:author).class_name('User') }
6 end 8 end
7 9
8 describe "Validation" do 10 describe "Validation" do
@@ -130,19 +132,3 @@ describe Note do @@ -130,19 +132,3 @@ describe Note do
130 end 132 end
131 end 133 end
132 end 134 end
133 -# == Schema Information  
134 -#  
135 -# Table name: notes  
136 -#  
137 -# id :integer(4) not null, primary key  
138 -# note :text  
139 -# noteable_id :string(255)  
140 -# noteable_type :string(255)  
141 -# author_id :integer(4)  
142 -# created_at :datetime not null  
143 -# updated_at :datetime not null  
144 -# project_id :integer(4)  
145 -# attachment :string(255)  
146 -# line_code :string(255)  
147 -#  
148 -  
spec/models/project_spec.rb
@@ -2,23 +2,52 @@ require &#39;spec_helper&#39; @@ -2,23 +2,52 @@ require &#39;spec_helper&#39;
2 2
3 describe Project do 3 describe Project do
4 describe "Associations" do 4 describe "Associations" do
  5 + it { should belong_to(:owner).class_name('User') }
5 it { should have_many(:users) } 6 it { should have_many(:users) }
6 - it { should have_many(:protected_branches).dependent(:destroy) }  
7 it { should have_many(:events).dependent(:destroy) } 7 it { should have_many(:events).dependent(:destroy) }
8 - it { should have_many(:wikis).dependent(:destroy) }  
9 it { should have_many(:merge_requests).dependent(:destroy) } 8 it { should have_many(:merge_requests).dependent(:destroy) }
10 - it { should have_many(:users_projects).dependent(:destroy) }  
11 it { should have_many(:issues).dependent(:destroy) } 9 it { should have_many(:issues).dependent(:destroy) }
  10 + it { should have_many(:milestones).dependent(:destroy) }
  11 + it { should have_many(:users_projects).dependent(:destroy) }
12 it { should have_many(:notes).dependent(:destroy) } 12 it { should have_many(:notes).dependent(:destroy) }
13 it { should have_many(:snippets).dependent(:destroy) } 13 it { should have_many(:snippets).dependent(:destroy) }
14 - it { should have_many(:hooks).dependent(:destroy) }  
15 it { should have_many(:deploy_keys).dependent(:destroy) } 14 it { should have_many(:deploy_keys).dependent(:destroy) }
  15 + it { should have_many(:hooks).dependent(:destroy) }
  16 + it { should have_many(:wikis).dependent(:destroy) }
  17 + it { should have_many(:protected_branches).dependent(:destroy) }
16 end 18 end
17 19
18 describe "Validation" do 20 describe "Validation" do
  21 + let!(:project) { create(:project) }
  22 +
19 it { should validate_presence_of(:name) } 23 it { should validate_presence_of(:name) }
  24 + it { should validate_uniqueness_of(:name) }
  25 + it { should ensure_length_of(:name).is_within(0..255) }
  26 +
20 it { should validate_presence_of(:path) } 27 it { should validate_presence_of(:path) }
  28 + it { should validate_uniqueness_of(:path) }
  29 + it { should ensure_length_of(:path).is_within(0..255) }
  30 + # TODO: Formats
  31 +
  32 + it { should ensure_length_of(:description).is_within(0..2000) }
  33 +
21 it { should validate_presence_of(:code) } 34 it { should validate_presence_of(:code) }
  35 + it { should validate_uniqueness_of(:code) }
  36 + it { should ensure_length_of(:code).is_within(1..255) }
  37 + # TODO: Formats
  38 +
  39 + it { should validate_presence_of(:owner) }
  40 +
  41 + it "should not allow new projects beyond user limits" do
  42 + project.stub(:owner).and_return(double(can_create_project?: false, projects_limit: 1))
  43 + project.should_not be_valid
  44 + project.errors[:base].first.should match(/Your own projects limit is 1/)
  45 + end
  46 +
  47 + it "should not allow 'gitolite-admin' as repo name" do
  48 + should allow_value("blah").for(:path)
  49 + should_not allow_value("gitolite-admin").for(:path)
  50 + end
22 end 51 end
23 52
24 describe "Respond to" do 53 describe "Respond to" do
@@ -73,9 +102,11 @@ describe Project do @@ -73,9 +102,11 @@ describe Project do
73 it { should respond_to(:trigger_post_receive) } 102 it { should respond_to(:trigger_post_receive) }
74 end 103 end
75 104
76 - it "should not allow 'gitolite-admin' as repo name" do  
77 - should allow_value("blah").for(:path)  
78 - should_not allow_value("gitolite-admin").for(:path) 105 + describe 'modules' do
  106 + it { should include_module(Repository) }
  107 + it { should include_module(PushObserver) }
  108 + it { should include_module(Authority) }
  109 + it { should include_module(Team) }
79 end 110 end
80 111
81 it "should return valid url to repo" do 112 it "should return valid url to repo" do
@@ -236,23 +267,3 @@ describe Project do @@ -236,23 +267,3 @@ describe Project do
236 end 267 end
237 end 268 end
238 end 269 end
239 -# == Schema Information  
240 -#  
241 -# Table name: projects  
242 -#  
243 -# id :integer(4) not null, primary key  
244 -# name :string(255)  
245 -# path :string(255)  
246 -# description :text  
247 -# created_at :datetime not null  
248 -# updated_at :datetime not null  
249 -# private_flag :boolean(1) default(TRUE), not null  
250 -# code :string(255)  
251 -# owner_id :integer(4)  
252 -# default_branch :string(255) default("master"), not null  
253 -# issues_enabled :boolean(1) default(TRUE), not null  
254 -# wall_enabled :boolean(1) default(TRUE), not null  
255 -# merge_requests_enabled :boolean(1) default(TRUE), not null  
256 -# wiki_enabled :boolean(1) default(TRUE), not null  
257 -#  
258 -  
spec/models/protected_branch_spec.rb
1 -# == Schema Information  
2 -#  
3 -# Table name: protected_branches  
4 -#  
5 -# id :integer(4) not null, primary key  
6 -# project_id :integer(4) not null  
7 -# name :string(255) not null  
8 -# created_at :datetime not null  
9 -# updated_at :datetime not null  
10 -#  
11 -  
12 require 'spec_helper' 1 require 'spec_helper'
13 2
14 describe ProtectedBranch do 3 describe ProtectedBranch do
15 - let(:project) { Factory(:project) }  
16 -  
17 describe 'Associations' do 4 describe 'Associations' do
18 it { should belong_to(:project) } 5 it { should belong_to(:project) }
19 end 6 end
@@ -24,26 +11,26 @@ describe ProtectedBranch do @@ -24,26 +11,26 @@ describe ProtectedBranch do
24 end 11 end
25 12
26 describe 'Callbacks' do 13 describe 'Callbacks' do
27 - subject { ProtectedBranch.new(project: project, name: 'branch_name') } 14 + let(:branch) { build(:protected_branch) }
28 15
29 it 'call update_repository after save' do 16 it 'call update_repository after save' do
30 - subject.should_receive(:update_repository)  
31 - subject.save 17 + branch.should_receive(:update_repository)
  18 + branch.save
32 end 19 end
33 20
34 it 'call update_repository after destroy' do 21 it 'call update_repository after destroy' do
35 - subject.should_receive(:update_repository)  
36 - subject.destroy 22 + branch.save
  23 + branch.should_receive(:update_repository)
  24 + branch.destroy
37 end 25 end
38 end 26 end
39 27
40 describe '#commit' do 28 describe '#commit' do
41 - subject { ProtectedBranch.new(project: project, name: 'cant_touch_this') } 29 + let(:branch) { create(:protected_branch) }
42 30
43 it 'commits itself to its project' do 31 it 'commits itself to its project' do
44 - project.should_receive(:commit).with('cant_touch_this')  
45 -  
46 - subject.commit 32 + branch.project.should_receive(:commit).with(branch.name)
  33 + branch.commit
47 end 34 end
48 end 35 end
49 end 36 end
spec/models/snippet_spec.rb
@@ -3,29 +3,21 @@ require &#39;spec_helper&#39; @@ -3,29 +3,21 @@ require &#39;spec_helper&#39;
3 describe Snippet do 3 describe Snippet do
4 describe "Associations" do 4 describe "Associations" do
5 it { should belong_to(:project) } 5 it { should belong_to(:project) }
6 - it { should belong_to(:author) } 6 + it { should belong_to(:author).class_name('User') }
  7 + it { should have_many(:notes).dependent(:destroy) }
7 end 8 end
8 9
9 describe "Validation" do 10 describe "Validation" do
10 - it { should validate_presence_of(:title) }  
11 it { should validate_presence_of(:author_id) } 11 it { should validate_presence_of(:author_id) }
12 it { should validate_presence_of(:project_id) } 12 it { should validate_presence_of(:project_id) }
  13 +
  14 + it { should validate_presence_of(:title) }
  15 + it { should ensure_length_of(:title).is_within(0..255) }
  16 +
13 it { should validate_presence_of(:file_name) } 17 it { should validate_presence_of(:file_name) }
  18 + it { should ensure_length_of(:title).is_within(0..255) }
  19 +
14 it { should validate_presence_of(:content) } 20 it { should validate_presence_of(:content) }
  21 + it { should ensure_length_of(:content).is_within(0..10_000) }
15 end 22 end
16 end 23 end
17 -# == Schema Information  
18 -#  
19 -# Table name: snippets  
20 -#  
21 -# id :integer(4) not null, primary key  
22 -# title :string(255)  
23 -# content :text  
24 -# author_id :integer(4) not null  
25 -# project_id :integer(4) not null  
26 -# created_at :datetime not null  
27 -# updated_at :datetime not null  
28 -# file_name :string(255)  
29 -# expires_at :datetime  
30 -#  
31 -  
spec/models/user_spec.rb
@@ -2,13 +2,26 @@ require &#39;spec_helper&#39; @@ -2,13 +2,26 @@ require &#39;spec_helper&#39;
2 2
3 describe User do 3 describe User do
4 describe "Associations" do 4 describe "Associations" do
5 - it { should have_many(:projects) }  
6 it { should have_many(:users_projects).dependent(:destroy) } 5 it { should have_many(:users_projects).dependent(:destroy) }
  6 + it { should have_many(:projects) }
  7 + it { should have_many(:my_own_projects).class_name('Project') }
  8 + it { should have_many(:keys).dependent(:destroy) }
  9 + it { should have_many(:events).class_name('Event').dependent(:destroy) }
  10 + it { should have_many(:recent_events).class_name('Event') }
7 it { should have_many(:issues).dependent(:destroy) } 11 it { should have_many(:issues).dependent(:destroy) }
  12 + it { should have_many(:notes).dependent(:destroy) }
8 it { should have_many(:assigned_issues).dependent(:destroy) } 13 it { should have_many(:assigned_issues).dependent(:destroy) }
9 it { should have_many(:merge_requests).dependent(:destroy) } 14 it { should have_many(:merge_requests).dependent(:destroy) }
10 it { should have_many(:assigned_merge_requests).dependent(:destroy) } 15 it { should have_many(:assigned_merge_requests).dependent(:destroy) }
11 - it { should have_many(:notes).dependent(:destroy) } 16 + end
  17 +
  18 + describe 'validations' do
  19 + it { should validate_presence_of(:projects_limit) }
  20 + it { should validate_numericality_of(:projects_limit) }
  21 + it { should allow_value(0).for(:projects_limit) }
  22 + it { should_not allow_value(-1).for(:projects_limit) }
  23 +
  24 + it { should ensure_length_of(:bio).is_within(0..255) }
12 end 25 end
13 26
14 describe "Respond to" do 27 describe "Respond to" do
@@ -51,33 +64,3 @@ describe User do @@ -51,33 +64,3 @@ describe User do
51 user.authentication_token.should_not == "" 64 user.authentication_token.should_not == ""
52 end 65 end
53 end 66 end
54 -# == Schema Information  
55 -#  
56 -# Table name: users  
57 -#  
58 -# id :integer(4) not null, primary key  
59 -# email :string(255) default(""), not null  
60 -# encrypted_password :string(128) default(""), not null  
61 -# reset_password_token :string(255)  
62 -# reset_password_sent_at :datetime  
63 -# remember_created_at :datetime  
64 -# sign_in_count :integer(4) default(0)  
65 -# current_sign_in_at :datetime  
66 -# last_sign_in_at :datetime  
67 -# current_sign_in_ip :string(255)  
68 -# last_sign_in_ip :string(255)  
69 -# created_at :datetime not null  
70 -# updated_at :datetime not null  
71 -# name :string(255)  
72 -# admin :boolean(1) default(FALSE), not null  
73 -# projects_limit :integer(4) default(10)  
74 -# skype :string(255) default(""), not null  
75 -# linkedin :string(255) default(""), not null  
76 -# twitter :string(255) default(""), not null  
77 -# authentication_token :string(255)  
78 -# dark_scheme :boolean(1) default(FALSE), not null  
79 -# theme_id :integer(4) default(1), not null  
80 -# bio :string(255)  
81 -# blocked :boolean(1) default(FALSE), not null  
82 -#  
83 -  
spec/models/users_project_spec.rb
@@ -7,7 +7,11 @@ describe UsersProject do @@ -7,7 +7,11 @@ describe UsersProject do
7 end 7 end
8 8
9 describe "Validation" do 9 describe "Validation" do
  10 + let!(:users_project) { create(:users_project) }
  11 +
10 it { should validate_presence_of(:user_id) } 12 it { should validate_presence_of(:user_id) }
  13 + it { should validate_uniqueness_of(:user_id).scoped_to(:project_id) }
  14 +
11 it { should validate_presence_of(:project_id) } 15 it { should validate_presence_of(:project_id) }
12 end 16 end
13 17
@@ -16,15 +20,3 @@ describe UsersProject do @@ -16,15 +20,3 @@ describe UsersProject do
16 it { should respond_to(:user_email) } 20 it { should respond_to(:user_email) }
17 end 21 end
18 end 22 end
19 -# == Schema Information  
20 -#  
21 -# Table name: users_projects  
22 -#  
23 -# id :integer(4) not null, primary key  
24 -# user_id :integer(4) not null  
25 -# project_id :integer(4) not null  
26 -# created_at :datetime not null  
27 -# updated_at :datetime not null  
28 -# project_access :integer(4) default(0), not null  
29 -#  
30 -  
spec/models/web_hook_spec.rb
@@ -52,14 +52,3 @@ describe ProjectHook do @@ -52,14 +52,3 @@ describe ProjectHook do
52 end 52 end
53 end 53 end
54 end 54 end
55 -# == Schema Information  
56 -#  
57 -# Table name: web_hooks  
58 -#  
59 -# id :integer(4) not null, primary key  
60 -# url :string(255)  
61 -# project_id :integer(4)  
62 -# created_at :datetime not null  
63 -# updated_at :datetime not null  
64 -#  
65 -  
spec/models/wiki_spec.rb
@@ -4,27 +4,13 @@ describe Wiki do @@ -4,27 +4,13 @@ describe Wiki do
4 describe "Associations" do 4 describe "Associations" do
5 it { should belong_to(:project) } 5 it { should belong_to(:project) }
6 it { should belong_to(:user) } 6 it { should belong_to(:user) }
  7 + it { should have_many(:notes).dependent(:destroy) }
7 end 8 end
8 9
9 describe "Validation" do 10 describe "Validation" do
10 it { should validate_presence_of(:title) } 11 it { should validate_presence_of(:title) }
  12 + it { should ensure_length_of(:title).is_within(1..250) }
11 it { should validate_presence_of(:content) } 13 it { should validate_presence_of(:content) }
12 it { should validate_presence_of(:user_id) } 14 it { should validate_presence_of(:user_id) }
13 end 15 end
14 -  
15 - it { Factory(:wiki).should be_valid }  
16 end 16 end
17 -# == Schema Information  
18 -#  
19 -# Table name: wikis  
20 -#  
21 -# id :integer(4) not null, primary key  
22 -# title :string(255)  
23 -# content :text  
24 -# project_id :integer(4)  
25 -# created_at :datetime not null  
26 -# updated_at :datetime not null  
27 -# slug :string(255)  
28 -# user_id :integer(4)  
29 -#  
30 -  
spec/roles/issue_commonality_spec.rb 0 → 100644
@@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
  1 +require 'spec_helper'
  2 +
  3 +describe Issue, "IssueCommonality" do
  4 + let(:issue) { create(:issue) }
  5 +
  6 + describe "Associations" do
  7 + it { should belong_to(:project) }
  8 + it { should belong_to(:author) }
  9 + it { should belong_to(:assignee) }
  10 + it { should have_many(:notes).dependent(:destroy) }
  11 + end
  12 +
  13 + describe "Validation" do
  14 + it { should validate_presence_of(:project_id) }
  15 + it { should validate_presence_of(:author_id) }
  16 + it { should validate_presence_of(:title) }
  17 + it { should ensure_length_of(:title).is_at_least(0).is_at_most(255) }
  18 + end
  19 +
  20 + describe "Scope" do
  21 + it { described_class.should respond_to(:opened) }
  22 + it { described_class.should respond_to(:closed) }
  23 + it { described_class.should respond_to(:assigned) }
  24 + end
  25 +
  26 + it "has an :author_id_of_changes accessor" do
  27 + issue.should respond_to(:author_id_of_changes)
  28 + issue.should respond_to(:author_id_of_changes=)
  29 + end
  30 +
  31 + describe ".search" do
  32 + let!(:searchable_issue) { create(:issue, title: "Searchable issue") }
  33 +
  34 + it "matches by title" do
  35 + described_class.search('able').all.should == [searchable_issue]
  36 + end
  37 + end
  38 +
  39 + describe "#today?" do
  40 + it "returns true when created today" do
  41 + # Avoid timezone differences and just return exactly what we want
  42 + Date.stub(:today).and_return(issue.created_at.to_date)
  43 + issue.today?.should be_true
  44 + end
  45 +
  46 + it "returns false when not created today" do
  47 + Date.stub(:today).and_return(Date.yesterday)
  48 + issue.today?.should be_false
  49 + end
  50 + end
  51 +
  52 + describe "#new?" do
  53 + it "returns true when created today and record hasn't been updated" do
  54 + issue.stub(:today?).and_return(true)
  55 + issue.new?.should be_true
  56 + end
  57 +
  58 + it "returns false when not created today" do
  59 + issue.stub(:today?).and_return(false)
  60 + issue.new?.should be_false
  61 + end
  62 +
  63 + it "returns false when record has been updated" do
  64 + issue.stub(:today?).and_return(true)
  65 + issue.touch
  66 + issue.new?.should be_false
  67 + end
  68 + end
  69 +end
spec/roles/upvote_spec.rb 0 → 100644
@@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
  1 +require 'spec_helper'
  2 +
  3 +describe Issue, "Upvote" do
  4 + let(:issue) { create(:issue) }
  5 +
  6 + it "with no notes has a 0/0 score" do
  7 + issue.upvotes.should == 0
  8 + end
  9 +
  10 + it "should recognize non-+1 notes" do
  11 + issue.notes << create(:note, note: "No +1 here")
  12 + issue.should have(1).note
  13 + issue.notes.first.upvote?.should be_false
  14 + issue.upvotes.should == 0
  15 + end
  16 +
  17 + it "should recognize a single +1 note" do
  18 + issue.notes << create(:note, note: "+1 This is awesome")
  19 + issue.upvotes.should == 1
  20 + end
  21 +
  22 + it "should recognize multiple +1 notes" do
  23 + issue.notes << create(:note, note: "+1 This is awesome")
  24 + issue.notes << create(:note, note: "+1 I want this")
  25 + issue.upvotes.should == 2
  26 + end
  27 +end
spec/support/matchers.rb
@@ -28,6 +28,16 @@ RSpec::Matchers.define :be_404_for do |user| @@ -28,6 +28,16 @@ RSpec::Matchers.define :be_404_for do |user|
28 end 28 end
29 end 29 end
30 30
  31 +RSpec::Matchers.define :include_module do |expected|
  32 + match do
  33 + described_class.included_modules.include?(expected)
  34 + end
  35 +
  36 + failure_message_for_should do
  37 + "expected #{described_class} to include the #{expected} module"
  38 + end
  39 +end
  40 +
31 module UrlAccess 41 module UrlAccess
32 def url_allowed?(user, url) 42 def url_allowed?(user, url)
33 emulate_user(user) 43 emulate_user(user)
@@ -57,3 +67,17 @@ module UrlAccess @@ -57,3 +67,17 @@ module UrlAccess
57 login_with(user) if user 67 login_with(user) if user
58 end 68 end
59 end 69 end
  70 +
  71 +# Extend shoulda-matchers
  72 +module Shoulda::Matchers::ActiveModel
  73 + class EnsureLengthOfMatcher
  74 + # Shortcut for is_at_least and is_at_most
  75 + def is_within(range)
  76 + if range.exclude_end?
  77 + is_at_least(range.first) && is_at_most(range.last - 1)
  78 + else
  79 + is_at_least(range.first) && is_at_most(range.last)
  80 + end
  81 + end
  82 + end
  83 +end