remockable 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. data/.gitignore +6 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +6 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE +1 -1
  6. data/README.markdown +50 -36
  7. data/Rakefile +1 -0
  8. data/lib/remockable/active_model/helpers.rb +2 -0
  9. data/lib/remockable/active_record/helpers.rb +2 -0
  10. data/lib/remockable/version.rb +1 -1
  11. data/remockable.gemspec +23 -0
  12. data/spec/active_model/allow_mass_assignment_of_spec.rb +86 -0
  13. data/spec/active_model/allow_values_for_spec.rb +46 -0
  14. data/spec/active_model/validate_acceptance_of_spec.rb +16 -0
  15. data/spec/active_model/validate_confirmation_of_spec.rb +14 -0
  16. data/spec/active_model/validate_exclusion_of_spec.rb +16 -0
  17. data/spec/active_model/validate_format_of_spec.rb +18 -0
  18. data/spec/active_model/validate_inclusion_of_spec.rb +16 -0
  19. data/spec/active_model/validate_length_of_spec.rb +26 -0
  20. data/spec/active_model/validate_numericality_of_spec.rb +23 -0
  21. data/spec/active_model/validate_presence_of_spec.rb +14 -0
  22. data/spec/active_record/accept_nested_attributes_for_spec.rb +47 -0
  23. data/spec/active_record/belong_to_spec.rb +62 -0
  24. data/spec/active_record/have_and_belong_to_many_spec.rb +67 -0
  25. data/spec/active_record/have_column_spec.rb +109 -0
  26. data/spec/active_record/have_default_scope_spec.rb +169 -0
  27. data/spec/active_record/have_index_spec.rb +89 -0
  28. data/spec/active_record/have_many_spec.rb +70 -0
  29. data/spec/active_record/have_one_spec.rb +61 -0
  30. data/spec/active_record/have_scope_spec.rb +229 -0
  31. data/spec/active_record/validate_associated_spec.rb +27 -0
  32. data/spec/active_record/validate_uniqueness_of_spec.rb +23 -0
  33. data/spec/spec_helper.rb +17 -0
  34. data/spec/support/active_record_example_group.rb +22 -0
  35. data/spec/support/class_builder.rb +39 -0
  36. data/spec/support/shared/a_validation_matcher.rb +130 -0
  37. data/spec/support/shared/an_active_record_matcher.rb +53 -0
  38. metadata +134 -40
@@ -0,0 +1,109 @@
1
+ require 'spec_helper'
2
+
3
+ describe :have_column do
4
+ let(:options) { :one }
5
+
6
+ it_behaves_like 'an Active Record matcher' do
7
+ let(:model) { build_class(:User, ActiveRecord::Base) }
8
+
9
+ before do
10
+ create_table(:users) { |table| }
11
+ end
12
+
13
+ subject { model.new }
14
+
15
+ context 'description' do
16
+ let(:matcher) { send(matcher_name, *options) }
17
+
18
+ it 'has a custom description' do
19
+ name = matcher.instance_variable_get(:@name).to_s.gsub(/_/, ' ')
20
+ with = " with #{matcher.expected}" if matcher.expected.any?
21
+
22
+ matcher.description.should == "#{name} #{options}#{with}"
23
+ end
24
+ end
25
+
26
+ context 'with a column' do
27
+ it 'matches if the column exists' do
28
+ ActiveRecord::Base.connection.add_column(:users, :one, :string)
29
+ model.should have_column(:one)
30
+ end
31
+
32
+ it 'does not match if the column does not exist' do
33
+ model.should_not have_column(:one)
34
+ end
35
+ end
36
+
37
+ context 'with option :default' do
38
+ it 'matches if the column exists' do
39
+ ActiveRecord::Base.connection.add_column(:users, :one, :integer, :default => 1)
40
+ model.should have_column(:one, :default => 1)
41
+ end
42
+
43
+ it 'does not match if the column does not have the same default' do
44
+ ActiveRecord::Base.connection.add_column(:users, :one, :integer, :default => 2)
45
+ model.should_not have_column(:one, :default => 1)
46
+ end
47
+ end
48
+
49
+ context 'with option :limit' do
50
+ it 'matches if the column exists' do
51
+ ActiveRecord::Base.connection.add_column(:users, :one, :string, :limit => 10)
52
+ model.should have_column(:one, :limit => 10)
53
+ end
54
+
55
+ it 'does not match if the column does not have the same limit' do
56
+ ActiveRecord::Base.connection.add_column(:users, :one, :string, :limit => 5)
57
+ model.should_not have_column(:one, :limit => 10)
58
+ end
59
+ end
60
+
61
+ context 'with option :null' do
62
+ it 'matches if the column exists' do
63
+ ActiveRecord::Base.connection.add_column(:users, :one, :integer, :null => false, :default => 1)
64
+ model.should have_column(:one, :null => false)
65
+ end
66
+
67
+ it 'does not match if the column does not have the same null' do
68
+ ActiveRecord::Base.connection.add_column(:users, :one, :integer)
69
+ model.should_not have_column(:one, :null => false)
70
+ end
71
+ end
72
+
73
+ context 'with option :precision' do
74
+ it 'matches if the column exists' do
75
+ ActiveRecord::Base.connection.add_column(:users, :one, :decimal, :precision => 8)
76
+ model.should have_column(:one, :precision => 8)
77
+ end
78
+
79
+ it 'does not match if the column does not have the same null' do
80
+ ActiveRecord::Base.connection.add_column(:users, :one, :decimal, :precision => 8)
81
+ model.should_not have_column(:one, :precision => 5)
82
+ end
83
+ end
84
+
85
+ context 'with option :scale' do
86
+ it 'matches if the column exists' do
87
+ ActiveRecord::Base.connection.add_column(:users, :one, :decimal, :precision => 8, :scale => 2)
88
+ model.should have_column(:one, :scale => 2)
89
+ end
90
+
91
+ it 'does not match if the column does not have the same null' do
92
+ ActiveRecord::Base.connection.add_column(:users, :one, :decimal, :precision => 8, :scale => 2)
93
+ model.should_not have_column(:one, :scale => 3)
94
+ end
95
+ end
96
+
97
+ context 'with option :type' do
98
+ it 'matches if the column exists' do
99
+ ActiveRecord::Base.connection.add_column(:users, :one, :integer)
100
+ model.should have_column(:one, :type => :integer)
101
+ end
102
+
103
+ it 'does not match if the column does not have the same type' do
104
+ ActiveRecord::Base.connection.add_column(:users, :one, :string)
105
+ model.should_not have_column(:one, :type => :integer)
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,169 @@
1
+ require 'spec_helper'
2
+
3
+ describe :have_default_scope do
4
+ let(:options) { :one }
5
+
6
+ it_behaves_like 'an Active Record matcher' do
7
+ let(:model) { build_class(:User, ActiveRecord::Base) }
8
+
9
+ before do
10
+ create_table(:users) { |table| table.string(:one) }
11
+ end
12
+
13
+ subject { model.new }
14
+
15
+ context 'description' do
16
+ let(:matcher) { send(matcher_name, *options) }
17
+
18
+ it 'has a custom description' do
19
+ name = matcher.instance_variable_get(:@name).to_s.gsub(/_/, ' ')
20
+ with = " with #{matcher.expected}" if matcher.expected.any?
21
+
22
+ matcher.description.should == "have a default scope#{with}"
23
+ end
24
+ end
25
+
26
+ context 'without arguments' do
27
+ it 'matches if a default scope exists' do
28
+ model.instance_eval { default_scope(order(:id)) }
29
+ model.should have_default_scope
30
+ end
31
+
32
+ it 'does not match if a default scope does not exist' do
33
+ model.should_not have_default_scope
34
+ end
35
+ end
36
+
37
+ context 'with a from value' do
38
+ it 'matches if the scope exists and the query matches' do
39
+ model.instance_eval { default_scope(from('users')) }
40
+ model.should have_default_scope.from('users')
41
+ end
42
+
43
+ it 'does not match if the query does not match' do
44
+ model.instance_eval { default_scope(from('users')) }
45
+ model.should_not have_default_scope.from('friends')
46
+ end
47
+ end
48
+
49
+ context 'with a group value' do
50
+ it 'matches if the scope exists and the query matches' do
51
+ model.instance_eval { default_scope(group('one')) }
52
+ model.should have_default_scope.group('one')
53
+ end
54
+
55
+ it 'does not match if the query does not match' do
56
+ model.instance_eval { default_scope(group('one')) }
57
+ model.should_not have_default_scope.group('two')
58
+ end
59
+ end
60
+
61
+ context 'with a having value' do
62
+ it 'matches if the scope exists and the query matches' do
63
+ model.instance_eval { default_scope(having('COUNT(*) > 1')) }
64
+ model.should have_default_scope.having('COUNT(*) > 1')
65
+ end
66
+
67
+ it 'does not match if the query does not match' do
68
+ model.instance_eval { default_scope(having('COUNT(*) > 1')) }
69
+ model.should_not have_default_scope.having('COUNT(*) > 2')
70
+ end
71
+ end
72
+
73
+ context 'with a having value' do
74
+ it 'matches if the scope exists and the query matches' do
75
+ model.instance_eval { default_scope(having('COUNT(*) > 1')) }
76
+ model.should have_default_scope.having('COUNT(*) > 1')
77
+ end
78
+
79
+ it 'does not match if the query does not match' do
80
+ model.instance_eval { default_scope(having('COUNT(*) > 1')) }
81
+ model.should_not have_default_scope.having('COUNT(*) > 2')
82
+ end
83
+ end
84
+
85
+ context 'with a joins value' do
86
+ it 'matches if the scope exists and the query matches' do
87
+ model.instance_eval { default_scope(joins('INNER JOIN friends')) }
88
+ model.should have_default_scope.joins('INNER JOIN friends')
89
+ end
90
+
91
+ it 'does not match if the query does not match' do
92
+ model.instance_eval { default_scope(joins('INNER JOIN friends')) }
93
+ model.should_not have_default_scope.joins('INNER JOIN enemies')
94
+ end
95
+ end
96
+
97
+ context 'with a limit value' do
98
+ it 'matches if the scope exists and the query matches' do
99
+ model.instance_eval { default_scope(limit(10)) }
100
+ model.should have_default_scope.limit(10)
101
+ end
102
+
103
+ it 'does not match if the query does not match' do
104
+ model.instance_eval { default_scope(limit(10)) }
105
+ model.should_not have_default_scope.limit(15)
106
+ end
107
+ end
108
+
109
+ context 'with an offset value' do
110
+ it 'matches if the scope exists and the query matches' do
111
+ model.instance_eval { default_scope(offset(10)) }
112
+ model.should have_default_scope.offset(10)
113
+ end
114
+
115
+ it 'does not match if the query does not match' do
116
+ model.instance_eval { default_scope(offset(10)) }
117
+ model.should_not have_default_scope.offset(15)
118
+ end
119
+ end
120
+
121
+ context 'with an order value' do
122
+ it 'matches if the scope exists and the query matches' do
123
+ model.instance_eval { default_scope(order('one')) }
124
+ model.should have_default_scope.order('one')
125
+ end
126
+
127
+ it 'does not match if the query does not match' do
128
+ model.instance_eval { default_scope(order('one')) }
129
+ model.should_not have_default_scope.order('id')
130
+ end
131
+ end
132
+
133
+ context 'with a reorder value' do
134
+ it 'matches if the scope exists and the query matches' do
135
+ model.instance_eval { default_scope(reorder('one')) }
136
+ model.should have_default_scope.reorder('one')
137
+ end
138
+
139
+ it 'does not match if the query does not match' do
140
+ model.instance_eval { default_scope(reorder('one')) }
141
+ model.should_not have_default_scope.reorder('id')
142
+ end
143
+ end
144
+
145
+ context 'with a select value' do
146
+ it 'matches if the scope exists and the query matches' do
147
+ model.instance_eval { default_scope(select('one')) }
148
+ model.should have_default_scope.select('one')
149
+ end
150
+
151
+ it 'does not match if the query does not match' do
152
+ model.instance_eval { default_scope(select('one')) }
153
+ model.should_not have_default_scope.select('id')
154
+ end
155
+ end
156
+
157
+ context 'with a where value' do
158
+ it 'matches if the scope exists and the query matches' do
159
+ model.instance_eval { default_scope(where(:one => nil)) }
160
+ model.should have_default_scope.where(:one => nil)
161
+ end
162
+
163
+ it 'does not match if the query does not match' do
164
+ model.instance_eval { default_scope(where(:one => nil)) }
165
+ model.should_not have_default_scope.where(:one => 1)
166
+ end
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+
3
+ describe :have_index do
4
+ let(:options) { :one }
5
+
6
+ it_behaves_like 'an Active Record matcher' do
7
+ let(:model) { build_class(:User, ActiveRecord::Base) }
8
+
9
+ before do
10
+ create_table(:users) do |table|
11
+ table.string(:one)
12
+ table.string(:two)
13
+ end
14
+ end
15
+
16
+ subject { model.new }
17
+
18
+ context 'description' do
19
+ let(:matcher) { send(matcher_name, *options) }
20
+
21
+ it 'has a custom description' do
22
+ name = matcher.instance_variable_get(:@name).to_s.gsub(/_/, ' ')
23
+ with = " with #{matcher.expected}" if matcher.expected.any?
24
+
25
+ matcher.description.should == "#{name} on #{options}#{with}"
26
+ end
27
+ end
28
+
29
+ context 'with a single column' do
30
+ it 'matches if the index exists' do
31
+ ActiveRecord::Base.connection.add_index(:users, :one)
32
+ model.should have_index(:one)
33
+ end
34
+
35
+ it 'does not match if the index does not exist' do
36
+ model.should_not have_index(:one)
37
+ end
38
+ end
39
+
40
+ context 'with multiple columns' do
41
+ it 'matches if the index exists' do
42
+ ActiveRecord::Base.connection.add_index(:users, [:one, :two])
43
+ model.should have_index([:one, :two])
44
+ end
45
+
46
+ it 'does not match if the index does not exist' do
47
+ model.should_not have_index([:one, :two])
48
+ end
49
+ end
50
+
51
+ context 'with option :unique' do
52
+ it 'matches if the index exists' do
53
+ ActiveRecord::Base.connection.add_index(:users, :one, :unique => true)
54
+ model.should have_index(:one, :unique => true)
55
+ end
56
+
57
+ it 'does not match if the index is not unique' do
58
+ ActiveRecord::Base.connection.add_index(:users, :one)
59
+ model.should_not have_index(:one, :unique => true)
60
+ end
61
+
62
+ it 'does not match if the index does not exist' do
63
+ model.should_not have_index(:one, :unique => true)
64
+ end
65
+ end
66
+
67
+ context 'with option :name' do
68
+ it 'matches if the index exists' do
69
+ ActiveRecord::Base.connection.add_index(:users, :one, :name => :oneness)
70
+ model.should have_index(:one, :name => :oneness)
71
+ end
72
+
73
+ it 'does not match if the index does not exist' do
74
+ model.should_not have_index(:one, :name => :oneness)
75
+ end
76
+ end
77
+
78
+ context 'with option :name and without :one' do
79
+ it 'matches if the index exists' do
80
+ ActiveRecord::Base.connection.add_index(:users, :one, :name => :oneness)
81
+ model.should have_index(:name => :oneness)
82
+ end
83
+
84
+ it 'does not match if the index does not exist' do
85
+ model.should_not have_index(:name => :oneness)
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ describe :have_many do
4
+ let(:macro) { :has_many }
5
+ let(:options) { [:posts, { :dependent => :destroy }] }
6
+
7
+ it_behaves_like 'an Active Record matcher' do
8
+ let(:model) { build_class(:User, ActiveRecord::Base) }
9
+
10
+ before do
11
+ create_table(:users) { |table| table.string(:name) }
12
+ end
13
+
14
+ subject { model.new }
15
+
16
+ context 'description' do
17
+ let(:matcher) { send(matcher_name, *options) }
18
+
19
+ it 'has a custom description' do
20
+ association = matcher.instance_variable_get(:@association)
21
+ with = " with #{matcher.expected.inspect}" if matcher.expected.any?
22
+ matcher.description.should == "have many #{association}#{with}"
23
+ end
24
+ end
25
+
26
+ context 'with no options' do
27
+ let(:options) { :posts }
28
+
29
+ it 'matches if the association exists' do
30
+ model.has_many(*options)
31
+ model.should have_many(*options)
32
+ end
33
+
34
+ it 'does not match if the association does not exist' do
35
+ model.should_not have_many(*options)
36
+ end
37
+
38
+ it 'does not match if the association is of the wrong type' do
39
+ model.belongs_to(*options)
40
+ model.should_not have_many(*options)
41
+ end
42
+ end
43
+
44
+ with_option(:class_name, 'Post', 'Blog')
45
+ with_option(:conditions, { :published => true }, { :published => false })
46
+ with_option(:order, %w(published_at), %w(title))
47
+ with_option(:foreign_key, :post_id, :blog_id)
48
+ with_option(:primary_key, :id, :post_id)
49
+ with_option(:dependent, :destroy, :nullify)
50
+ with_option(:finder_sql, 'SELECT * FROM posts', 'SELECT * FROM blogs')
51
+ with_option(:counter_sql, 'SELECT COUNT(*) FROM posts', 'SELECT COUNT(*) FROM blogs')
52
+ with_option(:include, :comments, :trackbacks)
53
+ with_option(:group, 'comments_count', 'trackbacks_count')
54
+ with_option(:having, 'comments_count > 5', 'trackbacks_count > 5')
55
+ with_option(:limit, 5, 10)
56
+ with_option(:offset, 10, 20)
57
+ with_option(:select, %w(id), %w(title))
58
+ with_option(:as, :postable, :bloggable)
59
+ with_option(:through, :postings, :bloggings)
60
+ with_option(:source, :piece, :work)
61
+ with_option(:source_type, 'Post', 'Blog')
62
+ with_option(:uniq, true, false)
63
+ with_option(:readonly, true, false)
64
+ with_option(:validate, true, false)
65
+ with_option(:autosave, true, false)
66
+ with_option(:inverse_of, :users, :employees)
67
+
68
+ with_unsupported_option(:extend, Module.new)
69
+ end
70
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe :have_one do
4
+ let(:macro) { :has_one }
5
+ let(:options) { [:address, { :dependent => :destroy }] }
6
+
7
+ it_behaves_like 'an Active Record matcher' do
8
+ let(:model) { build_class(:User, ActiveRecord::Base) }
9
+
10
+ before do
11
+ create_table(:users) { |table| table.string(:name) }
12
+ end
13
+
14
+ subject { model.new }
15
+
16
+ context 'description' do
17
+ let(:matcher) { send(matcher_name, *options) }
18
+
19
+ it 'has a custom description' do
20
+ association = matcher.instance_variable_get(:@association)
21
+ with = " with #{matcher.expected.inspect}" if matcher.expected.any?
22
+ matcher.description.should == "have a #{association}#{with}"
23
+ end
24
+ end
25
+
26
+ context 'with no options' do
27
+ let(:options) { :address }
28
+
29
+ it 'matches if the association exists' do
30
+ model.has_one(*options)
31
+ model.should have_one(*options)
32
+ end
33
+
34
+ it 'does not match if the association does not exist' do
35
+ model.should_not have_one(*options)
36
+ end
37
+
38
+ it 'does not match if the association is of the wrong type' do
39
+ model.has_many(*options)
40
+ model.should_not have_one(*options)
41
+ end
42
+ end
43
+
44
+ with_option(:class_name, 'Address', 'Location')
45
+ with_option(:conditions, { :id => 1 }, { :id => 2 })
46
+ with_option(:order, %w(id), %w(name))
47
+ with_option(:dependent, :destroy, :nullify)
48
+ with_option(:foreign_key, :address_id, :location_id)
49
+ with_option(:primary_key, :id, :address_id)
50
+ with_option(:include, :country, :state)
51
+ with_option(:as, :addressable, :locatable)
52
+ with_option(:select, %w(id), %w(name))
53
+ with_option(:through, :offices, :locations)
54
+ with_option(:readonly, true, false)
55
+ with_option(:validate, true, false)
56
+ with_option(:autosave, true, false)
57
+ with_option(:inverse_of, :user, :employee)
58
+
59
+ with_unsupported_option(:extend, Module.new)
60
+ end
61
+ end