rmm5t-shoulda 2.0.6 → 2.9.1
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.
- data/README.rdoc +38 -10
- data/Rakefile +5 -3
- data/lib/shoulda.rb +7 -15
- data/lib/shoulda/action_mailer.rb +1 -1
- data/lib/shoulda/action_mailer/assertions.rb +32 -33
- data/lib/shoulda/active_record.rb +6 -2
- data/lib/shoulda/active_record/assertions.rb +62 -81
- data/lib/shoulda/active_record/helpers.rb +40 -0
- data/lib/shoulda/active_record/macros.rb +511 -640
- data/lib/shoulda/active_record/matchers.rb +42 -0
- data/lib/shoulda/active_record/matchers/allow_mass_assignment_of_matcher.rb +83 -0
- data/lib/shoulda/active_record/matchers/allow_value_matcher.rb +102 -0
- data/lib/shoulda/active_record/matchers/association_matcher.rb +226 -0
- data/lib/shoulda/active_record/matchers/ensure_inclusion_of_matcher.rb +87 -0
- data/lib/shoulda/active_record/matchers/ensure_length_of_matcher.rb +141 -0
- data/lib/shoulda/active_record/matchers/have_db_column_matcher.rb +169 -0
- data/lib/shoulda/active_record/matchers/have_index_matcher.rb +105 -0
- data/lib/shoulda/active_record/matchers/have_named_scope_matcher.rb +125 -0
- data/lib/shoulda/active_record/matchers/have_readonly_attribute_matcher.rb +59 -0
- data/lib/shoulda/active_record/matchers/validate_acceptance_of_matcher.rb +41 -0
- data/lib/shoulda/active_record/matchers/validate_numericality_of_matcher.rb +39 -0
- data/lib/shoulda/active_record/matchers/validate_presence_of_matcher.rb +60 -0
- data/lib/shoulda/active_record/matchers/validate_uniqueness_of_matcher.rb +148 -0
- data/lib/shoulda/active_record/matchers/validation_matcher.rb +56 -0
- data/lib/shoulda/assertions.rb +50 -40
- data/lib/shoulda/autoload_macros.rb +46 -0
- data/lib/shoulda/context.rb +124 -126
- data/lib/shoulda/helpers.rb +5 -7
- data/lib/shoulda/macros.rb +63 -64
- data/lib/shoulda/private_helpers.rb +16 -18
- data/lib/shoulda/rails.rb +5 -11
- data/lib/shoulda/rspec.rb +9 -0
- data/lib/shoulda/tasks/list_tests.rake +6 -1
- data/lib/shoulda/test_unit.rb +19 -0
- data/rails/init.rb +7 -1
- data/test/README +2 -2
- data/test/fail_macros.rb +16 -16
- data/test/functional/posts_controller_test.rb +33 -24
- data/test/functional/users_controller_test.rb +0 -19
- data/test/model_builder.rb +106 -0
- data/test/other/autoload_macro_test.rb +18 -0
- data/test/other/helpers_test.rb +58 -0
- data/test/other/private_helpers_test.rb +1 -1
- data/test/other/should_test.rb +16 -16
- data/test/rails_root/app/controllers/posts_controller.rb +6 -5
- data/test/rails_root/app/models/pets/dog.rb +10 -0
- data/test/rails_root/app/models/treat.rb +3 -0
- data/test/rails_root/app/models/user.rb +2 -2
- data/test/rails_root/app/views/layouts/posts.rhtml +2 -0
- data/test/rails_root/config/database.yml +1 -1
- data/test/rails_root/config/environments/{sqlite3.rb → test.rb} +0 -0
- data/test/rails_root/db/migrate/001_create_users.rb +3 -2
- data/test/rails_root/db/migrate/011_create_treats.rb +12 -0
- data/test/rails_root/test/shoulda_macros/custom_macro.rb +6 -0
- data/test/rails_root/vendor/gems/gem_with_macro-0.0.1/shoulda_macros/gem_macro.rb +6 -0
- data/test/rails_root/vendor/plugins/plugin_with_macro/shoulda_macros/plugin_macro.rb +6 -0
- data/test/test_helper.rb +3 -1
- data/test/unit/address_test.rb +1 -1
- data/test/unit/dog_test.rb +5 -2
- data/test/unit/post_test.rb +7 -3
- data/test/unit/product_test.rb +2 -2
- data/test/unit/tag_test.rb +2 -1
- data/test/unit/user_test.rb +17 -8
- metadata +54 -4
- data/lib/shoulda/controller.rb +0 -30
- data/lib/shoulda/controller/formats/html.rb +0 -201
- data/lib/shoulda/controller/formats/xml.rb +0 -170
- data/lib/shoulda/controller/helpers.rb +0 -64
- data/lib/shoulda/controller/macros.rb +0 -316
- data/lib/shoulda/controller/resource_options.rb +0 -236
- data/test/rails_root/app/models/dog.rb +0 -5
@@ -16,23 +16,4 @@ class UsersControllerTest < Test::Unit::TestCase
|
|
16
16
|
|
17
17
|
should_filter_params :ssn
|
18
18
|
|
19
|
-
should_be_restful do |resource|
|
20
|
-
resource.identifier = :id
|
21
|
-
resource.klass = User
|
22
|
-
resource.object = :user
|
23
|
-
resource.parent = []
|
24
|
-
resource.actions = [:index, :show, :new, :edit, :update, :create, :destroy]
|
25
|
-
resource.formats = [:html, :xml]
|
26
|
-
|
27
|
-
resource.create.params = { :name => "bob", :email => 'bob@bob.com', :age => 13, :ssn => "123456789"}
|
28
|
-
resource.update.params = { :name => "sue" }
|
29
|
-
|
30
|
-
resource.create.redirect = "user_url(@user)"
|
31
|
-
resource.update.redirect = "user_url(@user)"
|
32
|
-
resource.destroy.redirect = "users_url"
|
33
|
-
|
34
|
-
resource.create.flash = /created/i
|
35
|
-
resource.update.flash = /updated/i
|
36
|
-
resource.destroy.flash = /removed/i
|
37
|
-
end
|
38
19
|
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
class Test::Unit::TestCase
|
2
|
+
def create_table(table_name, &block)
|
3
|
+
connection = ActiveRecord::Base.connection
|
4
|
+
|
5
|
+
begin
|
6
|
+
connection.execute("DROP TABLE IF EXISTS #{table_name}")
|
7
|
+
connection.create_table(table_name, &block)
|
8
|
+
@created_tables ||= []
|
9
|
+
@created_tables << table_name
|
10
|
+
connection
|
11
|
+
rescue Exception => e
|
12
|
+
connection.execute("DROP TABLE IF EXISTS #{table_name}")
|
13
|
+
raise e
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def define_constant(class_name, base, &block)
|
18
|
+
class_name = class_name.to_s.camelize
|
19
|
+
|
20
|
+
klass = Class.new(base)
|
21
|
+
Object.const_set(class_name, klass)
|
22
|
+
|
23
|
+
klass.class_eval(&block) if block_given?
|
24
|
+
|
25
|
+
@defined_constants ||= []
|
26
|
+
@defined_constants << class_name
|
27
|
+
|
28
|
+
klass
|
29
|
+
end
|
30
|
+
|
31
|
+
def define_model_class(class_name, &block)
|
32
|
+
define_constant(class_name, ActiveRecord::Base, &block)
|
33
|
+
end
|
34
|
+
|
35
|
+
def define_model(name, columns = {}, &block)
|
36
|
+
class_name = name.to_s.pluralize.classify
|
37
|
+
table_name = class_name.tableize
|
38
|
+
|
39
|
+
create_table(table_name) do |table|
|
40
|
+
columns.each do |name, type|
|
41
|
+
table.column name, type
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
define_model_class(class_name, &block)
|
46
|
+
end
|
47
|
+
|
48
|
+
def define_controller(class_name, &block)
|
49
|
+
class_name = class_name.to_s
|
50
|
+
class_name << 'Controller' unless class_name =~ /Controller$/
|
51
|
+
define_constant(class_name, ActionController::Base, &block)
|
52
|
+
end
|
53
|
+
|
54
|
+
def define_routes(&block)
|
55
|
+
@replaced_routes = ActionController::Routing::Routes
|
56
|
+
new_routes = ActionController::Routing::RouteSet.new
|
57
|
+
silence_warnings do
|
58
|
+
ActionController::Routing.const_set('Routes', new_routes)
|
59
|
+
end
|
60
|
+
new_routes.draw(&block)
|
61
|
+
end
|
62
|
+
|
63
|
+
def build_response(&block)
|
64
|
+
klass = define_controller('Examples')
|
65
|
+
block ||= lambda { render :nothing => true }
|
66
|
+
klass.class_eval { define_method(:example, &block) }
|
67
|
+
define_routes do |map|
|
68
|
+
map.connect 'examples', :controller => 'examples', :action => 'example'
|
69
|
+
end
|
70
|
+
|
71
|
+
@controller = klass.new
|
72
|
+
@request = ActionController::TestRequest.new
|
73
|
+
@response = ActionController::TestResponse.new
|
74
|
+
get :example
|
75
|
+
|
76
|
+
@controller
|
77
|
+
end
|
78
|
+
|
79
|
+
def teardown_with_models
|
80
|
+
if @defined_constants
|
81
|
+
@defined_constants.each do |class_name|
|
82
|
+
Object.send(:remove_const, class_name)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
if @created_tables
|
87
|
+
@created_tables.each do |table_name|
|
88
|
+
ActiveRecord::Base.
|
89
|
+
connection.
|
90
|
+
execute("DROP TABLE IF EXISTS #{table_name}")
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
if @replaced_routes
|
95
|
+
ActionController::Routing::Routes.clear!
|
96
|
+
silence_warnings do
|
97
|
+
ActionController::Routing.const_set('Routes', @replaced_routes)
|
98
|
+
end
|
99
|
+
@replaced_routes.reload!
|
100
|
+
end
|
101
|
+
|
102
|
+
teardown_without_models
|
103
|
+
end
|
104
|
+
alias_method :teardown_without_models, :teardown
|
105
|
+
alias_method :teardown, :teardown_with_models
|
106
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
class AutoloadMacroTest < Test::Unit::TestCase # :nodoc:
|
4
|
+
context "The macro auto-loader" do
|
5
|
+
should "load macros from the plugins" do
|
6
|
+
assert self.class.respond_to?('plugin_macro')
|
7
|
+
end
|
8
|
+
|
9
|
+
should "load macros from the gems" do
|
10
|
+
assert self.class.respond_to?('gem_macro')
|
11
|
+
end
|
12
|
+
|
13
|
+
should "load custom macros from ROOT/test/shoulda_macros" do
|
14
|
+
assert self.class.respond_to?('custom_macro')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
data/test/other/helpers_test.rb
CHANGED
@@ -180,4 +180,62 @@ class HelpersTest < Test::Unit::TestCase # :nodoc:
|
|
180
180
|
end
|
181
181
|
end
|
182
182
|
end
|
183
|
+
|
184
|
+
context "a matching matcher" do
|
185
|
+
setup do
|
186
|
+
@matcher = stub('matcher', :matches? => true,
|
187
|
+
:failure_message => 'bad failure message',
|
188
|
+
:negative_failure_message => 'big time failure')
|
189
|
+
end
|
190
|
+
|
191
|
+
should "pass when given to assert_accepts" do
|
192
|
+
assert_accepts @matcher, 'target'
|
193
|
+
end
|
194
|
+
|
195
|
+
context "when given to assert_rejects" do
|
196
|
+
setup do
|
197
|
+
begin
|
198
|
+
assert_rejects @matcher, 'target'
|
199
|
+
rescue Test::Unit::AssertionFailedError => @error
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
should "fail" do
|
204
|
+
assert_not_nil @error
|
205
|
+
end
|
206
|
+
|
207
|
+
should "use the error message from the matcher" do
|
208
|
+
assert_equal 'big time failure', @error.message
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
context "a non-matching matcher" do
|
214
|
+
setup do
|
215
|
+
@matcher = stub('matcher', :matches? => false,
|
216
|
+
:failure_message => 'big time failure',
|
217
|
+
:negative_failure_message => 'bad failure message')
|
218
|
+
end
|
219
|
+
|
220
|
+
should "pass when given to assert_rejects" do
|
221
|
+
assert_rejects @matcher, 'target'
|
222
|
+
end
|
223
|
+
|
224
|
+
context "when given to assert_accepts" do
|
225
|
+
setup do
|
226
|
+
begin
|
227
|
+
assert_accepts @matcher, 'target'
|
228
|
+
rescue Test::Unit::AssertionFailedError => @error
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
should "fail" do
|
233
|
+
assert_not_nil @error
|
234
|
+
end
|
235
|
+
|
236
|
+
should "use the error message from the matcher" do
|
237
|
+
assert_equal 'big time failure', @error.message
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
183
241
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
2
|
|
3
3
|
class PrivateHelpersTest < Test::Unit::TestCase # :nodoc:
|
4
|
-
include
|
4
|
+
include Shoulda::Private
|
5
5
|
context "get_options!" do
|
6
6
|
should "remove opts from args" do
|
7
7
|
args = [:a, :b, {}]
|
data/test/other/should_test.rb
CHANGED
@@ -119,21 +119,21 @@ class ShouldTest < Test::Unit::TestCase # :nodoc:
|
|
119
119
|
|
120
120
|
def test_should_create_a_new_context
|
121
121
|
assert_nothing_raised do
|
122
|
-
|
122
|
+
Shoulda::Context.new("context name", self) do; end
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
126
|
def test_should_create_a_nested_context
|
127
127
|
assert_nothing_raised do
|
128
|
-
parent =
|
129
|
-
child =
|
128
|
+
parent = Shoulda::Context.new("Parent", self) do; end
|
129
|
+
child = Shoulda::Context.new("Child", parent) do; end
|
130
130
|
end
|
131
131
|
end
|
132
132
|
|
133
133
|
def test_should_name_a_contexts_correctly
|
134
|
-
parent =
|
135
|
-
child =
|
136
|
-
grandchild =
|
134
|
+
parent = Shoulda::Context.new("Parent", self) do; end
|
135
|
+
child = Shoulda::Context.new("Child", parent) do; end
|
136
|
+
grandchild = Shoulda::Context.new("GrandChild", child) do; end
|
137
137
|
|
138
138
|
assert_equal "Parent", parent.full_name
|
139
139
|
assert_equal "Parent Child", child.full_name
|
@@ -143,7 +143,7 @@ class ShouldTest < Test::Unit::TestCase # :nodoc:
|
|
143
143
|
# Should statements
|
144
144
|
|
145
145
|
def test_should_have_should_hashes_when_given_should_statements
|
146
|
-
context =
|
146
|
+
context = Shoulda::Context.new("name", self) do
|
147
147
|
should "be good" do; end
|
148
148
|
should "another" do; end
|
149
149
|
end
|
@@ -155,7 +155,7 @@ class ShouldTest < Test::Unit::TestCase # :nodoc:
|
|
155
155
|
# setup and teardown
|
156
156
|
|
157
157
|
def test_should_capture_setup_and_teardown_blocks
|
158
|
-
context =
|
158
|
+
context = Shoulda::Context.new("name", self) do
|
159
159
|
setup do; "setup"; end
|
160
160
|
teardown do; "teardown"; end
|
161
161
|
end
|
@@ -167,7 +167,7 @@ class ShouldTest < Test::Unit::TestCase # :nodoc:
|
|
167
167
|
# building
|
168
168
|
|
169
169
|
def test_should_create_shoulda_test_for_each_should_on_build
|
170
|
-
context =
|
170
|
+
context = Shoulda::Context.new("name", self) do
|
171
171
|
should "one" do; end
|
172
172
|
should "two" do; end
|
173
173
|
end
|
@@ -178,7 +178,7 @@ class ShouldTest < Test::Unit::TestCase # :nodoc:
|
|
178
178
|
|
179
179
|
def test_should_create_test_methods_on_build
|
180
180
|
tu_class = Test::Unit::TestCase
|
181
|
-
context =
|
181
|
+
context = Shoulda::Context.new("A Context", tu_class) do
|
182
182
|
should "define the test" do; end
|
183
183
|
end
|
184
184
|
|
@@ -188,7 +188,7 @@ class ShouldTest < Test::Unit::TestCase # :nodoc:
|
|
188
188
|
|
189
189
|
def test_should_create_test_methods_on_build_when_subcontext
|
190
190
|
tu_class = Test::Unit::TestCase
|
191
|
-
context =
|
191
|
+
context = Shoulda::Context.new("A Context", tu_class) do
|
192
192
|
context "with a child" do
|
193
193
|
should "define the test" do; end
|
194
194
|
end
|
@@ -203,21 +203,21 @@ class ShouldTest < Test::Unit::TestCase # :nodoc:
|
|
203
203
|
def test_should_create_a_new_context_and_build_it_on_Test_Unit_context
|
204
204
|
c = mock("context")
|
205
205
|
c.expects(:build)
|
206
|
-
|
206
|
+
Shoulda::Context.expects(:new).with("foo", kind_of(Class)).returns(c)
|
207
207
|
self.class.context "foo" do; end
|
208
208
|
end
|
209
209
|
|
210
210
|
def test_should_create_a_one_off_context_and_build_it_on_Test_Unit_should
|
211
211
|
s = mock("test")
|
212
|
-
|
213
|
-
|
212
|
+
Shoulda::Context.any_instance.expects(:should).with("rock", {}).returns(s)
|
213
|
+
Shoulda::Context.any_instance.expects(:build)
|
214
214
|
self.class.should "rock" do; end
|
215
215
|
end
|
216
216
|
|
217
217
|
def test_should_create_a_one_off_context_and_build_it_on_Test_Unit_should_eventually
|
218
218
|
s = mock("test")
|
219
|
-
|
220
|
-
|
219
|
+
Shoulda::Context.any_instance.expects(:should_eventually).with("rock").returns(s)
|
220
|
+
Shoulda::Context.any_instance.expects(:build)
|
221
221
|
self.class.should_eventually "rock" do; end
|
222
222
|
end
|
223
223
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class PostsController < ApplicationController
|
2
2
|
before_filter :ensure_logged_in
|
3
3
|
before_filter :load_user
|
4
|
-
|
4
|
+
|
5
5
|
def index
|
6
6
|
@posts = @user.posts
|
7
7
|
|
@@ -19,6 +19,7 @@ class PostsController < ApplicationController
|
|
19
19
|
|
20
20
|
def show
|
21
21
|
@post = @user.posts.find(params[:id])
|
22
|
+
@false_flag = false
|
22
23
|
|
23
24
|
respond_to do |format|
|
24
25
|
format.html { render :layout => 'wide' }
|
@@ -68,17 +69,17 @@ class PostsController < ApplicationController
|
|
68
69
|
def destroy
|
69
70
|
@post = @user.posts.find(params[:id])
|
70
71
|
@post.destroy
|
71
|
-
|
72
|
+
|
72
73
|
flash[:notice] = "Post was removed"
|
73
|
-
|
74
|
+
|
74
75
|
respond_to do |format|
|
75
76
|
format.html { redirect_to user_posts_url(@post.user) }
|
76
77
|
format.xml { head :ok }
|
77
78
|
end
|
78
79
|
end
|
79
|
-
|
80
|
+
|
80
81
|
private
|
81
|
-
|
82
|
+
|
82
83
|
def load_user
|
83
84
|
@user = User.find(params[:user_id])
|
84
85
|
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Pets
|
2
|
+
class Dog < ActiveRecord::Base
|
3
|
+
belongs_to :user, :foreign_key => :owner_id
|
4
|
+
belongs_to :address, :dependent => :destroy
|
5
|
+
has_many :treats
|
6
|
+
has_and_belongs_to_many :fleas, :join_table => :fleas
|
7
|
+
validates_presence_of :treats, :fleas
|
8
|
+
validates_presence_of :owner_id
|
9
|
+
end
|
10
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class User < ActiveRecord::Base
|
2
2
|
has_many :posts
|
3
|
-
has_many :dogs, :foreign_key => :owner_id
|
3
|
+
has_many :dogs, :foreign_key => :owner_id, :class_name => "Pets::Dog"
|
4
4
|
|
5
5
|
has_many :friendships
|
6
6
|
has_many :friends, :through => :friendships
|
@@ -22,7 +22,7 @@ class User < ActiveRecord::Base
|
|
22
22
|
validates_length_of :email, :in => 1..100
|
23
23
|
validates_inclusion_of :age, :in => 1..100
|
24
24
|
validates_acceptance_of :eula
|
25
|
-
validates_uniqueness_of :email, :scope => :name
|
25
|
+
validates_uniqueness_of :email, :scope => :name, :case_sensitive => false
|
26
26
|
validates_length_of :ssn, :is => 9, :message => "Social Security Number is not the right length"
|
27
27
|
validates_numericality_of :ssn
|
28
28
|
end
|
@@ -4,6 +4,8 @@
|
|
4
4
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
5
5
|
<head>
|
6
6
|
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
|
7
|
+
<meta name="description" content="Posts, posts and more posts" />
|
8
|
+
<meta name='keywords' content='posts' />
|
7
9
|
<title>Posts: <%= controller.action_name %></title>
|
8
10
|
<%= stylesheet_link_tag 'scaffold' %>
|
9
11
|
</head>
|
File without changes
|
@@ -5,11 +5,12 @@ class CreateUsers < ActiveRecord::Migration
|
|
5
5
|
t.column :email, :string
|
6
6
|
t.column :age, :integer
|
7
7
|
t.column :ssn, :string
|
8
|
+
t.column :phone, :string
|
8
9
|
end
|
9
|
-
add_index :users, :email
|
10
|
+
add_index :users, :email, :unique => true
|
10
11
|
add_index :users, :name
|
11
12
|
add_index :users, :age
|
12
|
-
add_index :users, [:email, :name]
|
13
|
+
add_index :users, [:email, :name], :unique => true
|
13
14
|
end
|
14
15
|
|
15
16
|
def self.down
|