jcnetdev-shoulda 4.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.
- data/CONTRIBUTION_GUIDELINES.rdoc +12 -0
- data/MIT-LICENSE +22 -0
- data/README.rdoc +123 -0
- data/Rakefile +32 -0
- data/bin/convert_to_should_syntax +40 -0
- data/init.rb +1 -0
- data/lib/shoulda.rb +43 -0
- data/lib/shoulda/active_record_helpers.rb +670 -0
- data/lib/shoulda/color.rb +77 -0
- data/lib/shoulda/controller_tests/controller_tests.rb +467 -0
- data/lib/shoulda/controller_tests/formats/html.rb +201 -0
- data/lib/shoulda/controller_tests/formats/xml.rb +170 -0
- data/lib/shoulda/gem/proc_extensions.rb +14 -0
- data/lib/shoulda/gem/shoulda.rb +246 -0
- data/lib/shoulda/general.rb +118 -0
- data/lib/shoulda/private_helpers.rb +22 -0
- data/rails/init.rb +1 -0
- data/shoulda.gemspec +109 -0
- data/tasks/list_tests.rake +23 -0
- data/tasks/yaml_to_shoulda.rake +28 -0
- data/test/README +36 -0
- data/test/fixtures/addresses.yml +3 -0
- data/test/fixtures/posts.yml +5 -0
- data/test/fixtures/taggings.yml +0 -0
- data/test/fixtures/tags.yml +9 -0
- data/test/fixtures/users.yml +6 -0
- data/test/functional/posts_controller_test.rb +43 -0
- data/test/functional/users_controller_test.rb +36 -0
- data/test/other/context_test.rb +115 -0
- data/test/other/helpers_test.rb +80 -0
- data/test/other/private_helpers_test.rb +26 -0
- data/test/rails_root/app/controllers/application.rb +25 -0
- data/test/rails_root/app/controllers/posts_controller.rb +78 -0
- data/test/rails_root/app/controllers/users_controller.rb +81 -0
- data/test/rails_root/app/helpers/application_helper.rb +3 -0
- data/test/rails_root/app/helpers/posts_helper.rb +2 -0
- data/test/rails_root/app/helpers/users_helper.rb +2 -0
- data/test/rails_root/app/models/address.rb +4 -0
- data/test/rails_root/app/models/dog.rb +4 -0
- data/test/rails_root/app/models/flea.rb +3 -0
- data/test/rails_root/app/models/post.rb +11 -0
- data/test/rails_root/app/models/tag.rb +8 -0
- data/test/rails_root/app/models/tagging.rb +4 -0
- data/test/rails_root/app/models/user.rb +17 -0
- data/test/rails_root/app/views/layouts/posts.rhtml +17 -0
- data/test/rails_root/app/views/layouts/users.rhtml +17 -0
- data/test/rails_root/app/views/posts/edit.rhtml +27 -0
- data/test/rails_root/app/views/posts/index.rhtml +25 -0
- data/test/rails_root/app/views/posts/new.rhtml +26 -0
- data/test/rails_root/app/views/posts/show.rhtml +18 -0
- data/test/rails_root/app/views/users/edit.rhtml +22 -0
- data/test/rails_root/app/views/users/index.rhtml +22 -0
- data/test/rails_root/app/views/users/new.rhtml +21 -0
- data/test/rails_root/app/views/users/show.rhtml +13 -0
- data/test/rails_root/config/boot.rb +109 -0
- data/test/rails_root/config/database.yml +4 -0
- data/test/rails_root/config/environment.rb +18 -0
- data/test/rails_root/config/environments/sqlite3.rb +0 -0
- data/test/rails_root/config/initializers/new_rails_defaults.rb +15 -0
- data/test/rails_root/config/routes.rb +6 -0
- data/test/rails_root/db/migrate/001_create_users.rb +17 -0
- data/test/rails_root/db/migrate/002_create_posts.rb +13 -0
- data/test/rails_root/db/migrate/003_create_taggings.rb +12 -0
- data/test/rails_root/db/migrate/004_create_tags.rb +11 -0
- data/test/rails_root/db/migrate/005_create_dogs.rb +11 -0
- data/test/rails_root/db/migrate/006_create_addresses.rb +13 -0
- data/test/rails_root/db/migrate/007_create_fleas.rb +11 -0
- data/test/rails_root/db/migrate/008_create_dogs_fleas.rb +12 -0
- data/test/rails_root/db/migrate/009_add_ssn_to_users.rb +9 -0
- data/test/rails_root/db/schema.rb +0 -0
- data/test/rails_root/log/.keep +0 -0
- data/test/rails_root/public/.htaccess +40 -0
- data/test/rails_root/public/404.html +30 -0
- data/test/rails_root/public/422.html +30 -0
- data/test/rails_root/public/500.html +30 -0
- data/test/rails_root/script/console +3 -0
- data/test/rails_root/script/generate +3 -0
- data/test/rails_root/vendor/plugins/.keep +0 -0
- data/test/test_helper.rb +35 -0
- data/test/unit/address_test.rb +7 -0
- data/test/unit/dog_test.rb +7 -0
- data/test/unit/flea_test.rb +7 -0
- data/test/unit/post_test.rb +14 -0
- data/test/unit/tag_test.rb +12 -0
- data/test/unit/tagging_test.rb +8 -0
- data/test/unit/user_test.rb +32 -0
- metadata +148 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
|
2
|
+
|
|
3
|
+
class ContextTest < Test::Unit::TestCase # :nodoc:
|
|
4
|
+
|
|
5
|
+
context "context with setup block" do
|
|
6
|
+
setup do
|
|
7
|
+
@blah = "blah"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
should "have @blah == 'blah'" do
|
|
11
|
+
assert_equal "blah", @blah
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
should "have name set right" do
|
|
15
|
+
assert_match(/^test: context with setup block/, self.to_s)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context "and a subcontext" do
|
|
19
|
+
setup do
|
|
20
|
+
@blah = "#{@blah} twice"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
should "be named correctly" do
|
|
24
|
+
assert_match(/^test: context with setup block and a subcontext should be named correctly/, self.to_s)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
should "run the setup methods in order" do
|
|
28
|
+
assert_equal @blah, "blah twice"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context "another context with setup block" do
|
|
34
|
+
setup do
|
|
35
|
+
@blah = "foo"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
should "have @blah == 'foo'" do
|
|
39
|
+
assert_equal "foo", @blah
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
should "have name set right" do
|
|
43
|
+
assert_match(/^test: another context with setup block/, self.to_s)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
context "context with method definition" do
|
|
48
|
+
setup do
|
|
49
|
+
def hello; "hi"; end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
should "be able to read that method" do
|
|
53
|
+
assert_equal "hi", hello
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
should "have name set right" do
|
|
57
|
+
assert_match(/^test: context with method definition/, self.to_s)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
context "another context" do
|
|
62
|
+
should "not define @blah" do
|
|
63
|
+
assert_nil @blah
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context "context with multiple setups and/or teardowns" do
|
|
68
|
+
|
|
69
|
+
cleanup_count = 0
|
|
70
|
+
|
|
71
|
+
2.times do |i|
|
|
72
|
+
setup { cleanup_count += 1 }
|
|
73
|
+
teardown { cleanup_count -= 1 }
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
2.times do |i|
|
|
77
|
+
should "call all setups and all teardowns (check ##{i + 1})" do
|
|
78
|
+
assert_equal 2, cleanup_count
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
context "subcontexts" do
|
|
83
|
+
|
|
84
|
+
2.times do |i|
|
|
85
|
+
setup { cleanup_count += 1 }
|
|
86
|
+
teardown { cleanup_count -= 1 }
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
2.times do |i|
|
|
90
|
+
should "also call all setups and all teardowns in parent and subcontext (check ##{i + 1})" do
|
|
91
|
+
assert_equal 4, cleanup_count
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
should_eventually "pass, since it's unimplemented" do
|
|
100
|
+
flunk "what?"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
should_eventually "not require a block when using should_eventually"
|
|
104
|
+
should "pass without a block, as that causes it to piggyback to should_eventually"
|
|
105
|
+
|
|
106
|
+
context "context for testing should piggybacking" do
|
|
107
|
+
should "call should_eventually as we are not passing a block"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
context "context" do
|
|
111
|
+
context "with nested subcontexts" do
|
|
112
|
+
should_eventually "only print this statement once for a should_eventually"
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
|
2
|
+
require 'action_mailer'
|
|
3
|
+
require 'mocha'
|
|
4
|
+
|
|
5
|
+
class HelpersTest < Test::Unit::TestCase # :nodoc:
|
|
6
|
+
|
|
7
|
+
context "given delivered emails" do
|
|
8
|
+
setup do
|
|
9
|
+
email1 = stub(:subject => "one", :to => ["none1@email.com"])
|
|
10
|
+
email2 = stub(:subject => "two", :to => ["none2@email.com"])
|
|
11
|
+
ActionMailer::Base.stubs(:deliveries).returns([email1, email2])
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
should "have sent an email" do
|
|
15
|
+
assert_sent_email
|
|
16
|
+
|
|
17
|
+
assert_raises(Test::Unit::AssertionFailedError) do
|
|
18
|
+
assert_did_not_send_email
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
should "find email one" do
|
|
23
|
+
assert_sent_email do |e|
|
|
24
|
+
e.subject =~ /one/
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
should "not find an email that doesn't exist" do
|
|
29
|
+
assert_raises(Test::Unit::AssertionFailedError) do
|
|
30
|
+
assert_sent_email do |e|
|
|
31
|
+
e.subject =~ /whatever/
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
context "when there are no emails" do
|
|
38
|
+
setup do
|
|
39
|
+
ActionMailer::Base.stubs(:deliveries).returns([])
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
should "not have sent an email" do
|
|
43
|
+
assert_did_not_send_email
|
|
44
|
+
|
|
45
|
+
assert_raises(Test::Unit::AssertionFailedError) do
|
|
46
|
+
assert_sent_email
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context "an array of values" do
|
|
52
|
+
setup do
|
|
53
|
+
@a = ['abc', 'def', 3]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
[/b/, 'abc', 3].each do |x|
|
|
57
|
+
should "contain #{x.inspect}" do
|
|
58
|
+
assert_raises(Test::Unit::AssertionFailedError) do
|
|
59
|
+
assert_does_not_contain @a, x
|
|
60
|
+
end
|
|
61
|
+
assert_contains @a, x
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
should "not contain 'wtf'" do
|
|
66
|
+
assert_raises(Test::Unit::AssertionFailedError) {assert_contains @a, 'wtf'}
|
|
67
|
+
assert_does_not_contain @a, 'wtf'
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
should "be the same as another array, ordered differently" do
|
|
71
|
+
assert_same_elements(@a, [3, "def", "abc"])
|
|
72
|
+
assert_raises(Test::Unit::AssertionFailedError) do
|
|
73
|
+
assert_same_elements(@a, [3, 3, "def", "abc"])
|
|
74
|
+
end
|
|
75
|
+
assert_raises(Test::Unit::AssertionFailedError) do
|
|
76
|
+
assert_same_elements([@a, "abc"].flatten, [3, 3, "def", "abc"])
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
|
2
|
+
|
|
3
|
+
class PrivateHelpersTest < Test::Unit::TestCase # :nodoc:
|
|
4
|
+
include ThoughtBot::Shoulda::ActiveRecord
|
|
5
|
+
context "get_options!" do
|
|
6
|
+
should "remove opts from args" do
|
|
7
|
+
args = [:a, :b, {}]
|
|
8
|
+
get_options!(args)
|
|
9
|
+
assert_equal [:a, :b], args
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
should "return wanted opts in order" do
|
|
13
|
+
args = [{:one => 1, :two => 2}]
|
|
14
|
+
one, two = get_options!(args, :one, :two)
|
|
15
|
+
assert_equal 1, one
|
|
16
|
+
assert_equal 2, two
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
should "raise ArgumentError if given unwanted option" do
|
|
20
|
+
args = [{:one => 1, :two => 2}]
|
|
21
|
+
assert_raises ArgumentError do
|
|
22
|
+
get_options!(args, :one)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Filters added to this controller apply to all controllers in the application.
|
|
2
|
+
# Likewise, all the methods added will be available for all controllers.
|
|
3
|
+
|
|
4
|
+
class ApplicationController < ActionController::Base
|
|
5
|
+
# Pick a unique cookie name to distinguish our session data from others'
|
|
6
|
+
session :session_key => '_rails_root_session_id'
|
|
7
|
+
|
|
8
|
+
def ensure_logged_in
|
|
9
|
+
unless session[:logged_in]
|
|
10
|
+
respond_to do |accepts|
|
|
11
|
+
accepts.html do
|
|
12
|
+
flash[:error] = 'What do you think you\'re doing?'
|
|
13
|
+
redirect_to '/'
|
|
14
|
+
end
|
|
15
|
+
accepts.xml do
|
|
16
|
+
headers["Status"] = "Unauthorized"
|
|
17
|
+
headers["WWW-Authenticate"] = %(Basic realm="Web Password")
|
|
18
|
+
render :text => "Couldn't authenticate you", :status => '401 Unauthorized'
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
return false
|
|
22
|
+
end
|
|
23
|
+
return true
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
class PostsController < ApplicationController
|
|
2
|
+
before_filter :ensure_logged_in
|
|
3
|
+
before_filter :load_user
|
|
4
|
+
|
|
5
|
+
def index
|
|
6
|
+
@posts = @user.posts
|
|
7
|
+
|
|
8
|
+
respond_to do |format|
|
|
9
|
+
format.html # index.rhtml
|
|
10
|
+
format.xml { render :xml => @posts.to_xml }
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def show
|
|
15
|
+
@post = @user.posts.find(params[:id])
|
|
16
|
+
|
|
17
|
+
respond_to do |format|
|
|
18
|
+
format.html # show.rhtml
|
|
19
|
+
format.xml { render :xml => @post.to_xml }
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def new
|
|
24
|
+
@post = @user.posts.build
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def edit
|
|
28
|
+
@post = @user.posts.find(params[:id])
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def create
|
|
32
|
+
@post = @user.posts.build(params[:post])
|
|
33
|
+
|
|
34
|
+
respond_to do |format|
|
|
35
|
+
if @post.save
|
|
36
|
+
flash[:notice] = 'Post was successfully created.'
|
|
37
|
+
format.html { redirect_to user_post_url(@post.user, @post) }
|
|
38
|
+
format.xml { head :created, :location => user_post_url(@post.user, @post) }
|
|
39
|
+
else
|
|
40
|
+
format.html { render :action => "new" }
|
|
41
|
+
format.xml { render :xml => @post.errors.to_xml }
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def update
|
|
47
|
+
@post = @user.posts.find(params[:id])
|
|
48
|
+
|
|
49
|
+
respond_to do |format|
|
|
50
|
+
if @post.update_attributes(params[:post])
|
|
51
|
+
flash[:notice] = 'Post was successfully updated.'
|
|
52
|
+
format.html { redirect_to user_post_url(@post.user, @post) }
|
|
53
|
+
format.xml { head :ok }
|
|
54
|
+
else
|
|
55
|
+
format.html { render :action => "edit" }
|
|
56
|
+
format.xml { render :xml => @post.errors.to_xml }
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def destroy
|
|
62
|
+
@post = @user.posts.find(params[:id])
|
|
63
|
+
@post.destroy
|
|
64
|
+
|
|
65
|
+
flash[:notice] = "Post was removed"
|
|
66
|
+
|
|
67
|
+
respond_to do |format|
|
|
68
|
+
format.html { redirect_to user_posts_url(@post.user) }
|
|
69
|
+
format.xml { head :ok }
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def load_user
|
|
76
|
+
@user = User.find(params[:user_id])
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
class UsersController < ApplicationController
|
|
2
|
+
# GET /users
|
|
3
|
+
# GET /users.xml
|
|
4
|
+
def index
|
|
5
|
+
@users = User.find(:all)
|
|
6
|
+
|
|
7
|
+
respond_to do |format|
|
|
8
|
+
format.html # index.rhtml
|
|
9
|
+
format.xml { render :xml => @users.to_xml }
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# GET /users/1
|
|
14
|
+
# GET /users/1.xml
|
|
15
|
+
def show
|
|
16
|
+
@user = User.find(params[:id])
|
|
17
|
+
|
|
18
|
+
respond_to do |format|
|
|
19
|
+
format.html # show.rhtml
|
|
20
|
+
format.xml { render :xml => @user.to_xml }
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# GET /users/new
|
|
25
|
+
def new
|
|
26
|
+
@user = User.new
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# GET /users/1;edit
|
|
30
|
+
def edit
|
|
31
|
+
@user = User.find(params[:id])
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# POST /users
|
|
35
|
+
# POST /users.xml
|
|
36
|
+
def create
|
|
37
|
+
@user = User.new(params[:user])
|
|
38
|
+
|
|
39
|
+
respond_to do |format|
|
|
40
|
+
if @user.save
|
|
41
|
+
flash[:notice] = 'User was successfully created.'
|
|
42
|
+
format.html { redirect_to user_url(@user) }
|
|
43
|
+
format.xml { head :created, :location => user_url(@user) }
|
|
44
|
+
else
|
|
45
|
+
format.html { render :action => "new" }
|
|
46
|
+
format.xml { render :xml => @user.errors.to_xml }
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# PUT /users/1
|
|
52
|
+
# PUT /users/1.xml
|
|
53
|
+
def update
|
|
54
|
+
@user = User.find(params[:id])
|
|
55
|
+
|
|
56
|
+
respond_to do |format|
|
|
57
|
+
if @user.update_attributes(params[:user])
|
|
58
|
+
flash[:notice] = 'User was successfully updated.'
|
|
59
|
+
format.html { redirect_to user_url(@user) }
|
|
60
|
+
format.xml { head :ok }
|
|
61
|
+
else
|
|
62
|
+
format.html { render :action => "edit" }
|
|
63
|
+
format.xml { render :xml => @user.errors.to_xml }
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# DELETE /users/1
|
|
69
|
+
# DELETE /users/1.xml
|
|
70
|
+
def destroy
|
|
71
|
+
@user = User.find(params[:id])
|
|
72
|
+
@user.destroy
|
|
73
|
+
|
|
74
|
+
flash[:notice] = "User was removed"
|
|
75
|
+
|
|
76
|
+
respond_to do |format|
|
|
77
|
+
format.html { redirect_to users_url }
|
|
78
|
+
format.xml { head :ok }
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class Post < ActiveRecord::Base
|
|
2
|
+
belongs_to :user
|
|
3
|
+
belongs_to :owner, :foreign_key => :user_id, :class_name => 'User'
|
|
4
|
+
has_many :taggings
|
|
5
|
+
has_many :tags, :through => :taggings
|
|
6
|
+
|
|
7
|
+
validates_uniqueness_of :title
|
|
8
|
+
validates_presence_of :title
|
|
9
|
+
validates_presence_of :body, :message => 'Seriously... wtf'
|
|
10
|
+
validates_numericality_of :user_id
|
|
11
|
+
end
|