Commit 5b0a998920d9357446c89ba7352f38622fb1323f
Exists in
master
and in
4 other branches
Merge pull request #1333 from tsigo/model_specs
Increased model spec coverage
Showing
17 changed files
with
222 additions
and
338 deletions
Show diff stats
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 'spec_helper' | @@ -2,12 +2,15 @@ require 'spec_helper' | ||
| 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 'spec_helper' | @@ -3,6 +3,8 @@ require 'spec_helper' | ||
| 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 'spec_helper' | @@ -2,23 +2,52 @@ require 'spec_helper' | ||
| 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 'spec_helper' | @@ -3,29 +3,21 @@ require 'spec_helper' | ||
| 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 'spec_helper' | @@ -2,13 +2,26 @@ require 'spec_helper' | ||
| 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 | - |
| @@ -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 |
| @@ -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 |