Organizando plugins e gems.

This commit is contained in:
2009-07-16 11:51:47 -03:00
parent 4e22c87074
commit dcfc38eb09
506 changed files with 10538 additions and 45562 deletions

View File

@@ -0,0 +1,36 @@
The Shoulda test suite (in particular - the tests that test shoulda)
Quick overview:
The test directory contains the following files and subdirectories:
* rails_root - contains the stripped down rails application that the tests run against. The rails root contains:
** the models, controllers, and views defined under app/
** the test.rb environment file
** a migration file for each model
** a shoulda initializer that simulates loading the plugin but without relying on vendor/plugins
* fixtures - contain the sample DB data for each model
* functional - controller tests for each of the controllers under rails_root/app
* unit - model tests for each of the models under rails_root/app
* other - tests for the shoulda contexts, should statements, and assertions
* test_helper.rb - responsible for initializing the test environment
** sets the rails_env to test
** sets the rails_root
** runs all the migrations against the in-memory sqlite3 db
** adds some magic to load the right fixture files
In order to add a new model (or controller) to the test suite:
* add that model to rails_root/app/models
* add a migration for that model
* add a fixture file
* add a test for that file under test/units
Dependencies:
* Rails gem installed in the host system
* A working sqlite3 installation.
If you have problems running these tests, please notify the mailing list: shoulda@googlegroups.com
- Tammer Saleh <tsaleh@thoughtbot.com>

View File

@@ -0,0 +1,34 @@
module Shoulda
class << self
attr_accessor :expected_exceptions
end
module ClassMethods
# Enables the core shoulda test suite to test for failure scenarios. For
# example, to ensure that a set of test macros should fail, do this:
#
# should_fail do
# should_validate_presence_of :comments
# should_not_allow_mass_assignment_of :name
# end
def should_fail(&block)
context "should fail when trying to run:" do
Shoulda.expected_exceptions = [Test::Unit::AssertionFailedError]
yield block
Shoulda.expected_exceptions = nil
end
end
end
class Context
# alias_method_chain hack to allow the should_fail macro to work
def should_with_failure_scenario(name, options = {}, &block)
if Shoulda.expected_exceptions
expected_exceptions = Shoulda.expected_exceptions
failure_block = lambda { assert_raise(*expected_exceptions, &block.bind(self)) }
end
should_without_failure_scenario(name, options, &(failure_block || block))
end
alias_method_chain :should, :failure_scenario
end
end

View File

@@ -0,0 +1,3 @@
first:
title: Home
addressable: first (User)

View File

@@ -0,0 +1,5 @@
first:
id: 1
title: My Cute Kitten!
body: This is totally a cute kitten
user_id: 1

View File

@@ -0,0 +1,9 @@
first:
id: 1
name: Stuff
second:
id: 2
name: Rails
third:
id: 3
name: Nothing

View File

@@ -0,0 +1,6 @@
first:
id: 1
name: Some dude
age: 2
email: none@none.com
ssn: 123456789

View File

@@ -0,0 +1,125 @@
require File.dirname(__FILE__) + '/../test_helper'
require 'posts_controller'
# Re-raise errors caught by the controller.
class PostsController; def rescue_action(e) raise e end; end
class PostsControllerTest < Test::Unit::TestCase
fixtures :all
def setup
@controller = PostsController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
@post = Post.find(:first)
end
# autodetects the :controller
should_route :get, '/posts', :action => :index
# explicitly specify :controller
should_route :post, '/posts', :controller => :posts, :action => :create
# non-string parameter
should_route :get, '/posts/1', :action => :show, :id => 1
# string-parameter
should_route :put, '/posts/1', :action => :update, :id => "1"
should_route :delete, '/posts/1', :action => :destroy, :id => 1
should_route :get, '/posts/new', :action => :new
# Test the nested routes
should_route :get, '/users/5/posts', :action => :index, :user_id => 5
should_route :post, '/users/5/posts', :action => :create, :user_id => 5
should_route :get, '/users/5/posts/1', :action => :show, :id => 1, :user_id => 5
should_route :delete, '/users/5/posts/1', :action => :destroy, :id => 1, :user_id => 5
should_route :get, '/users/5/posts/new', :action => :new, :user_id => 5
should_route :put, '/users/5/posts/1', :action => :update, :id => 1, :user_id => 5
context "Logged in" do
setup do
@request.session[:logged_in] = true
end
context "viewing posts for a user" do
setup do
get :index, :user_id => users(:first)
end
should_respond_with :success
should_assign_to :user, :class => User, :equals => 'users(:first)'
should_assign_to(:user) { users(:first) }
should_fail do
should_assign_to :user, :class => Post
end
should_fail do
should_assign_to :user, :equals => 'posts(:first)'
end
should_fail do
should_assign_to(:user) { posts(:first) }
end
should_assign_to :posts
should_not_assign_to :foo, :bar
should_render_page_with_metadata :description => /Posts/, :title => /index/
should_render_page_with_metadata :keywords => "posts"
end
context "viewing posts for a user with rss format" do
setup do
get :index, :user_id => users(:first), :format => 'rss'
@user = users(:first)
end
should_respond_with :success
should_respond_with_content_type 'application/rss+xml'
should_respond_with_content_type :rss
should_respond_with_content_type /rss/
context "deprecated" do # to avoid redefining a test
should_return_from_session :special, "'$2 off your next purchase'"
end
should_fail do
should_return_from_session :special, "'not special'"
end
should_set_session(:mischief) { nil }
should_return_from_session :malarky, "nil"
should_set_session :special, "'$2 off your next purchase'"
should_set_session :special_user_id, '@user.id'
context "with a block" do
should_set_session(:special_user_id) { @user.id }
end
should_fail do # to avoid redefining a test
should_set_session(:special_user_id) { 'value' }
end
should_assign_to :user, :posts
should_not_assign_to :foo, :bar
end
context "viewing a post on GET to #show" do
setup { get :show, :user_id => users(:first), :id => posts(:first) }
should_render_with_layout 'wide'
context "with a symbol" do # to avoid redefining a test
should_render_with_layout :wide
end
should_assign_to :false_flag
end
context "on GET to #new" do
setup { get :new, :user_id => users(:first) }
should_render_without_layout
end
context "on POST to #create" do
setup do
post :create, :user_id => users(:first),
:post => { :title => "first post",
:body => 'blah blah blah' }
end
should_redirect_to 'user_post_url(@post.user, @post)'
should_redirect_to('the created post') { user_post_url(users(:first),
assigns(:post)) }
should_fail do
should_redirect_to 'user_posts_url(@post.user)'
end
should_fail do
should_redirect_to('elsewhere') { user_posts_url(users(:first)) }
end
end
end
end

View File

@@ -0,0 +1,19 @@
require File.dirname(__FILE__) + '/../test_helper'
require 'users_controller'
# Re-raise errors caught by the controller.
class UsersController; def rescue_action(e) raise e end; end
class UsersControllerTest < Test::Unit::TestCase
fixtures :all
def setup
@controller = UsersController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
@user = User.find(:first)
end
should_filter_params :ssn
end

View File

@@ -0,0 +1,68 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class AllowMassAssignmentOfMatcherTest < Test::Unit::TestCase # :nodoc:
context "an attribute that is blacklisted from mass-assignment" do
setup do
define_model :example, :attr => :string do
attr_protected :attr
end
@model = Example.new
end
should "reject being mass-assignable" do
assert_rejects allow_mass_assignment_of(:attr), @model
end
end
context "an attribute that is not whitelisted for mass-assignment" do
setup do
define_model :example, :attr => :string, :other => :string do
attr_accessible :other
end
@model = Example.new
end
should "reject being mass-assignable" do
assert_rejects allow_mass_assignment_of(:attr), @model
end
end
context "an attribute that is whitelisted for mass-assignment" do
setup do
define_model :example, :attr => :string do
attr_accessible :attr
end
@model = Example.new
end
should "accept being mass-assignable" do
assert_accepts allow_mass_assignment_of(:attr), @model
end
end
context "an attribute not included in the mass-assignment blacklist" do
setup do
define_model :example, :attr => :string, :other => :string do
attr_protected :other
end
@model = Example.new
end
should "accept being mass-assignable" do
assert_accepts allow_mass_assignment_of(:attr), @model
end
end
context "an attribute on a class with no protected attributes" do
setup do
define_model :example, :attr => :string
@model = Example.new
end
should "accept being mass-assignable" do
assert_accepts allow_mass_assignment_of(:attr), @model
end
end
end

View File

@@ -0,0 +1,41 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class AllowValueMatcherTest < Test::Unit::TestCase # :nodoc:
context "an attribute with a format validation" do
setup do
define_model :example, :attr => :string do
validates_format_of :attr, :with => /abc/
end
@model = Example.new
end
should "allow a good value" do
assert_accepts allow_value("abcde").for(:attr), @model
end
should "not allow a bad value" do
assert_rejects allow_value("xyz").for(:attr), @model
end
end
context "an attribute with a format validation and a custom message" do
setup do
define_model :example, :attr => :string do
validates_format_of :attr, :with => /abc/, :message => 'bad value'
end
@model = Example.new
end
should "allow a good value" do
assert_accepts allow_value('abcde').for(:attr).with_message(/bad/),
@model
end
should "not allow a bad value" do
assert_rejects allow_value('xyz').for(:attr).with_message(/bad/),
@model
end
end
end

View File

@@ -0,0 +1,258 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class AssociationMatcherTest < Test::Unit::TestCase # :nodoc:
context "belong_to" do
setup do
@matcher = belong_to(:parent)
end
should "accept a good association with the default foreign key" do
define_model :parent
define_model :child, :parent_id => :integer do
belongs_to :parent
end
assert_accepts @matcher, Child.new
end
should "reject a nonexistent association" do
define_model :child
assert_rejects @matcher, Child.new
end
should "reject an association of the wrong type" do
define_model :parent, :child_id => :integer
child_class = define_model :child do
has_one :parent
end
assert_rejects @matcher, Child.new
end
should "reject an association that has a nonexistent foreign key" do
define_model :parent
define_model :child do
belongs_to :parent
end
assert_rejects @matcher, Child.new
end
should "accept an association with an existing custom foreign key" do
define_model :parent
define_model :child, :guardian_id => :integer do
belongs_to :parent, :foreign_key => 'guardian_id'
end
assert_accepts @matcher, Child.new
end
should "accept a polymorphic association" do
define_model :child, :parent_type => :string,
:parent_id => :integer do
belongs_to :parent, :polymorphic => true
end
assert_accepts @matcher, Child.new
end
should "accept an association with a valid :dependent option" do
define_model :parent
define_model :child, :parent_id => :integer do
belongs_to :parent, :dependent => :destroy
end
assert_accepts @matcher.dependent(:destroy), Child.new
end
should "reject an association with a bad :dependent option" do
define_model :parent
define_model :child, :parent_id => :integer do
belongs_to :parent
end
assert_rejects @matcher.dependent(:destroy), Child.new
end
end
context "have_many" do
setup do
@matcher = have_many(:children)
end
should "accept a valid association without any options" do
define_model :child, :parent_id => :integer
define_model :parent do
has_many :children
end
assert_accepts @matcher, Parent.new
end
should "accept a valid association with a :through option" do
define_model :child
define_model :conception, :child_id => :integer,
:parent_id => :integer do
belongs_to :child
end
define_model :parent do
has_many :conceptions
has_many :children, :through => :conceptions
end
assert_accepts @matcher, Parent.new
end
should "accept a valid association with an :as option" do
define_model :child, :guardian_type => :string,
:guardian_id => :integer
define_model :parent do
has_many :children, :as => :guardian
end
assert_accepts @matcher, Parent.new
end
should "reject an association that has a nonexistent foreign key" do
define_model :child
define_model :parent do
has_many :children
end
assert_rejects @matcher, Parent.new
end
should "reject an association with a bad :as option" do
define_model :child, :caretaker_type => :string,
:caretaker_id => :integer
define_model :parent do
has_many :children, :as => :guardian
end
assert_rejects @matcher, Parent.new
end
should "reject an association that has a bad :through option" do
define_model :child, :parent_id => :integer
define_model :parent do
has_many :children
end
assert_rejects @matcher.through(:conceptions), Parent.new
end
should "reject an association that has the wrong :through option" do
define_model :child
define_model :conception, :child_id => :integer,
:parent_id => :integer do
belongs_to :child
end
define_model :parent do
has_many :conceptions
has_many :children, :through => :conceptions
end
assert_rejects @matcher.through(:relationships), Parent.new
end
should "accept an association with a valid :dependent option" do
define_model :child, :parent_id => :integer
define_model :parent do
has_many :children, :dependent => :destroy
end
assert_accepts @matcher.dependent(:destroy), Parent.new
end
should "reject an association with a bad :dependent option" do
define_model :child, :parent_id => :integer
define_model :parent do
has_many :children
end
assert_rejects @matcher.dependent(:destroy), Parent.new
end
end
context "have_one" do
setup do
@matcher = have_one(:profile)
end
should "accept a valid association without any options" do
define_model :profile, :person_id => :integer
define_model :person do
has_one :profile
end
assert_accepts @matcher, Person.new
end
should "accept a valid association with an :as option" do
define_model :profile, :profilable_id => :integer,
:profilable_type => :string
define_model :person do
has_one :profile, :as => :profilable
end
assert_accepts @matcher, Person.new
end
should "reject an association that has a nonexistent foreign key" do
define_model :profile
define_model :person do
has_one :profile
end
assert_rejects @matcher, Person.new
end
should "reject an association with a bad :as option" do
define_model :profile, :profilable_id => :integer,
:profilable_type => :string
define_model :person do
has_one :profile, :as => :describable
end
assert_rejects @matcher, Person.new
end
should "accept an association with a valid :dependent option" do
define_model :profile, :person_id => :integer
define_model :person do
has_one :profile, :dependent => :destroy
end
assert_accepts @matcher.dependent(:destroy), Person.new
end
should "reject an association with a bad :dependent option" do
define_model :profile, :person_id => :integer
define_model :person do
has_one :profile
end
assert_rejects @matcher.dependent(:destroy), Person.new
end
end
context "have_and_belong_to_many" do
setup do
@matcher = have_and_belong_to_many(:relatives)
end
should "accept a valid association" do
define_model :relatives
define_model :person do
has_and_belongs_to_many :relatives
end
define_model :people_relative, :person_id => :integer,
:relative_id => :integer
assert_accepts @matcher, Person.new
end
should "reject a nonexistent association" do
define_model :relatives
define_model :person
define_model :people_relative, :person_id => :integer,
:relative_id => :integer
assert_rejects @matcher, Person.new
end
should "reject an association with a nonexistent join table" do
define_model :relatives
define_model :person do
has_and_belongs_to_many :relatives
end
assert_rejects @matcher, Person.new
end
should "reject an association of the wrong type" do
define_model :relatives, :person_id => :integer
define_model :person do
has_many :relatives
end
assert_rejects @matcher, Person.new
end
end
end

View File

@@ -0,0 +1,80 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class EnsureInclusionOfMatcherTest < Test::Unit::TestCase # :nodoc:
context "an attribute which must be included in a range" do
setup do
@model = define_model(:example, :attr => :integer) do
validates_inclusion_of :attr, :in => 2..5
end.new
end
should "accept ensuring the correct range" do
assert_accepts ensure_inclusion_of(:attr).in_range(2..5), @model
end
should "reject ensuring a lower minimum value" do
assert_rejects ensure_inclusion_of(:attr).in_range(1..5), @model
end
should "reject ensuring a higher minimum value" do
assert_rejects ensure_inclusion_of(:attr).in_range(3..5), @model
end
should "reject ensuring a lower maximum value" do
assert_rejects ensure_inclusion_of(:attr).in_range(2..4), @model
end
should "reject ensuring a higher maximum value" do
assert_rejects ensure_inclusion_of(:attr).in_range(2..6), @model
end
should "not override the default message with a blank" do
assert_accepts ensure_inclusion_of(:attr).
in_range(2..5).
with_message(nil),
@model
end
end
context "an attribute with a custom ranged value validation" do
setup do
@model = define_model(:example, :attr => :string) do
validates_inclusion_of :attr, :in => 2..4, :message => 'not good'
end.new
end
should "accept ensuring the correct range" do
assert_accepts ensure_inclusion_of(:attr).
in_range(2..4).
with_message(/not good/),
@model
end
end
context "an attribute with custom range validations" do
setup do
define_model :example, :attr => :integer do
def validate
if attr < 2
errors.add(:attr, 'too low')
elsif attr > 5
errors.add(:attr, 'too high')
end
end
end
@model = Example.new
end
should "accept ensuring the correct range and messages" do
assert_accepts ensure_inclusion_of(:attr).
in_range(2..5).
with_low_message(/low/).
with_high_message(/high/),
@model
end
end
end

View File

@@ -0,0 +1,158 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class EnsureLengthOfMatcher < Test::Unit::TestCase # :nodoc:
context "an attribute with a non-zero minimum length validation" do
setup do
@model = define_model(:example, :attr => :string) do
validates_length_of :attr, :minimum => 4
end.new
end
should "accept ensuring the correct minimum length" do
assert_accepts ensure_length_of(:attr).is_at_least(4), @model
end
should "reject ensuring a lower minimum length with any message" do
assert_rejects ensure_length_of(:attr).
is_at_least(3).
with_short_message(/.*/),
@model
end
should "reject ensuring a higher minimum length with any message" do
assert_rejects ensure_length_of(:attr).
is_at_least(5).
with_short_message(/.*/),
@model
end
should "not override the default message with a blank" do
assert_accepts ensure_length_of(:attr).
is_at_least(4).
with_short_message(nil),
@model
end
end
context "an attribute with a minimum length validation of 0" do
setup do
@model = define_model(:example, :attr => :string) do
validates_length_of :attr, :minimum => 0
end.new
end
should "accept ensuring the correct minimum length" do
assert_accepts ensure_length_of(:attr).is_at_least(0), @model
end
end
context "an attribute with a maximum length" do
setup do
@model = define_model(:example, :attr => :string) do
validates_length_of :attr, :maximum => 4
end.new
end
should "accept ensuring the correct maximum length" do
assert_accepts ensure_length_of(:attr).is_at_most(4), @model
end
should "reject ensuring a lower maximum length with any message" do
assert_rejects ensure_length_of(:attr).
is_at_most(3).
with_long_message(/.*/),
@model
end
should "reject ensuring a higher maximum length with any message" do
assert_rejects ensure_length_of(:attr).
is_at_most(5).
with_long_message(/.*/),
@model
end
should "not override the default message with a blank" do
assert_accepts ensure_length_of(:attr).
is_at_most(4).
with_long_message(nil),
@model
end
end
context "an attribute with a required exact length" do
setup do
@model = define_model(:example, :attr => :string) do
validates_length_of :attr, :is => 4
end.new
end
should "accept ensuring the correct length" do
assert_accepts ensure_length_of(:attr).is_equal_to(4), @model
end
should "reject ensuring a lower maximum length with any message" do
assert_rejects ensure_length_of(:attr).
is_equal_to(3).
with_message(/.*/),
@model
end
should "reject ensuring a higher maximum length with any message" do
assert_rejects ensure_length_of(:attr).
is_equal_to(5).
with_message(/.*/),
@model
end
should "not override the default message with a blank" do
assert_accepts ensure_length_of(:attr).
is_equal_to(4).
with_message(nil),
@model
end
end
context "an attribute with a custom minimum length validation" do
setup do
@model = define_model(:example, :attr => :string) do
validates_length_of :attr, :minimum => 4, :too_short => 'short'
end.new
end
should "accept ensuring the correct minimum length" do
assert_accepts ensure_length_of(:attr).
is_at_least(4).
with_short_message(/short/),
@model
end
end
context "an attribute with a custom maximum length validation" do
setup do
@model = define_model(:example, :attr => :string) do
validates_length_of :attr, :maximum => 4, :too_long => 'long'
end.new
end
should "accept ensuring the correct minimum length" do
assert_accepts ensure_length_of(:attr).
is_at_most(4).
with_long_message(/long/),
@model
end
end
context "an attribute without a length validation" do
setup do
@model = define_model(:example, :attr => :string).new
end
should "reject ensuring a minimum length" do
assert_rejects ensure_length_of(:attr).is_at_least(1), @model
end
end
end

View File

@@ -0,0 +1,169 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class HaveDbColumnMatcherTest < Test::Unit::TestCase # :nodoc:
context "have_db_column" do
setup do
@matcher = have_db_column(:nickname)
end
should "accept an existing database column" do
create_table 'superheros' do |table|
table.string :nickname
end
define_model_class 'Superhero'
assert_accepts @matcher, Superhero.new
end
should "reject a nonexistent database column" do
define_model :superhero
assert_rejects @matcher, Superhero.new
end
end
context "have_db_column of type string" do
setup do
@matcher = have_db_column(:nickname).of_type(:string)
end
should "accept a column of correct type" do
create_table 'superheros' do |table|
table.string :nickname
end
define_model_class 'Superhero'
assert_accepts @matcher, Superhero.new
end
should "reject a nonexistent database column" do
define_model :superhero
assert_rejects @matcher, Superhero.new
end
should "reject a column of wrong type" do
create_table 'superheros' do |table|
table.integer :nickname
end
define_model_class 'Superhero'
assert_rejects @matcher, Superhero.new
end
end
context "have_db_column with precision option" do
setup do
@matcher = have_db_column(:salary).with_options(:precision => 5)
end
should "accept a column of correct precision" do
create_table 'superheros' do |table|
table.decimal :salary, :precision => 5
end
define_model_class 'Superhero'
assert_accepts @matcher, Superhero.new
end
should "reject a column of wrong precision" do
create_table 'superheros' do |table|
table.decimal :salary, :precision => 15
end
define_model_class 'Superhero'
assert_rejects @matcher, Superhero.new
end
end
context "have_db_column with limit option" do
setup do
@matcher = have_db_column(:email).
of_type(:string).
with_options(:limit => 255)
end
should "accept a column of correct limit" do
create_table 'superheros' do |table|
table.string :email, :limit => 255
end
define_model_class 'Superhero'
assert_accepts @matcher, Superhero.new
end
should "reject a column of wrong limit" do
create_table 'superheros' do |table|
table.string :email, :limit => 500
end
define_model_class 'Superhero'
assert_rejects @matcher, Superhero.new
end
end
context "have_db_column with default option" do
setup do
@matcher = have_db_column(:admin).
of_type(:boolean).
with_options(:default => false)
end
should "accept a column of correct default" do
create_table 'superheros' do |table|
table.boolean :admin, :default => false
end
define_model_class 'Superhero'
assert_accepts @matcher, Superhero.new
end
should "reject a column of wrong default" do
create_table 'superheros' do |table|
table.boolean :admin, :default => true
end
define_model_class 'Superhero'
assert_rejects @matcher, Superhero.new
end
end
context "have_db_column with null option" do
setup do
@matcher = have_db_column(:admin).
of_type(:boolean).
with_options(:null => false)
end
should "accept a column of correct null" do
create_table 'superheros' do |table|
table.boolean :admin, :null => false
end
define_model_class 'Superhero'
assert_accepts @matcher, Superhero.new
end
should "reject a column of wrong null" do
create_table 'superheros' do |table|
table.boolean :admin, :null => true
end
define_model_class 'Superhero'
assert_rejects @matcher, Superhero.new
end
end
context "have_db_column with scale option" do
setup do
@matcher = have_db_column(:salary).
of_type(:decimal).
with_options(:scale => 2)
end
should "accept a column of correct scale" do
create_table 'superheros' do |table|
table.decimal :salary, :precision => 10, :scale => 2
end
define_model_class 'Superhero'
assert_accepts @matcher, Superhero.new
end
should "reject a column of wrong scale" do
create_table 'superheros' do |table|
table.decimal :salary, :precision => 10, :scale => 4
end
define_model_class 'Superhero'
assert_rejects @matcher, Superhero.new
end
end
end

View File

@@ -0,0 +1,74 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class HaveIndexMatcherTest < Test::Unit::TestCase # :nodoc:
context "have_index" do
setup do
@matcher = have_index(:age)
end
should "accept an existing index" do
db_connection = create_table 'superheros' do |table|
table.integer :age
end
db_connection.add_index :superheros, :age
define_model_class 'Superhero'
assert_accepts @matcher, Superhero.new
end
should "reject a nonexistent index" do
define_model :superhero
assert_rejects @matcher, Superhero.new
end
end
context "have_index with unique option" do
setup do
@matcher = have_index(:ssn).unique(true)
end
should "accept an index of correct unique" do
db_connection = create_table 'superheros' do |table|
table.integer :ssn
end
db_connection.add_index :superheros, :ssn, :unique => true
define_model_class 'Superhero'
assert_accepts @matcher, Superhero.new
end
should "reject an index of wrong unique" do
db_connection = create_table 'superheros' do |table|
table.integer :ssn
end
db_connection.add_index :superheros, :ssn, :unique => false
define_model_class 'Superhero'
assert_rejects @matcher, Superhero.new
end
end
context "have_index on multiple columns" do
setup do
@matcher = have_index([:geocodable_type, :geocodable_id])
end
should "accept an existing index" do
db_connection = create_table 'geocodings' do |table|
table.integer :geocodable_id
table.string :geocodable_type
end
db_connection.add_index :geocodings, [:geocodable_type, :geocodable_id]
define_model_class 'Geocoding'
assert_accepts @matcher, Geocoding.new
end
should "reject a nonexistant index" do
db_connection = create_table 'geocodings' do |table|
table.integer :geocodable_id
table.string :geocodable_type
end
define_model_class 'Geocoding'
assert_rejects @matcher, Geocoding.new
end
end
end

View File

@@ -0,0 +1,65 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class HaveNamedScopeMatcherTest < Test::Unit::TestCase # :nodoc:
context "an attribute with a named scope" do
setup do
define_model :example, :attr => :string do
named_scope :xyz, lambda {|n|
{ :order => :attr }
}
end
@model = Example.new
end
should "accept having a scope with the correct signature" do
assert_accepts have_named_scope("xyz(1)"), @model
end
should "accept having a scope with the correct signature and find options" do
assert_accepts have_named_scope("xyz(1)").finding(:order => :attr), @model
end
should "reject having a scope with incorrect find options" do
assert_rejects have_named_scope("xyz(1)").
finding(:order => 'attr DESC'),
@model
end
should "reject having a scope with another name" do
assert_rejects have_named_scope("abc(1)"), @model
end
end
should "evaluate the scope in the correct context" do
define_model :example, :attr => :string do
named_scope :xyz, lambda {|n|
{ :order => n }
}
end
model = Example.new
@order = :attr
assert_accepts have_named_scope("xyz(@order)").
finding(:order => @order).
in_context(self),
model
end
context "a method that does not return a scope" do
setup do
klass = Class.new
klass.class_eval do
def self.xyz
'xyz'
end
end
@model = klass.new
end
should "reject having a named scope with that name" do
assert_rejects have_named_scope(:xyz), @model
end
end
end

View File

@@ -0,0 +1,29 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class HaveReadonlyAttributesMatcherTest < Test::Unit::TestCase # :nodoc:
context "an attribute that cannot be set after being saved" do
setup do
define_model :example, :attr => :string do
attr_readonly :attr
end
@model = Example.new
end
should "accept being read-only" do
assert_accepts have_readonly_attribute(:attr), @model
end
end
context "an attribute that can be set after being saved" do
setup do
define_model :example, :attr => :string
@model = Example.new
end
should "accept being read-only" do
assert_rejects have_readonly_attribute(:attr), @model
end
end
end

View File

@@ -0,0 +1,44 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class ValidateAcceptanceOfMatcherTest < Test::Unit::TestCase # :nodoc:
context "an attribute which must be accepted" do
setup do
@model = define_model(:example) do
validates_acceptance_of :attr
end.new
end
should "require that attribute to be accepted" do
assert_accepts validate_acceptance_of(:attr), @model
end
should "not overwrite the default message with nil" do
assert_accepts validate_acceptance_of(:attr).with_message(nil), @model
end
end
context "an attribute that does not need to be accepted" do
setup do
@model = define_model(:example, :attr => :string).new
end
should "not require that attribute to be accepted" do
assert_rejects validate_acceptance_of(:attr), @model
end
end
context "an attribute which must be accepted with a custom message" do
setup do
@model = define_model(:example) do
validates_acceptance_of :attr, :message => 'custom'
end.new
end
should "require that attribute to be accepted with that message" do
assert_accepts validate_acceptance_of(:attr).with_message(/custom/),
@model
end
end
end

View File

@@ -0,0 +1,52 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class ValidateNumericalityOfMatcherTest < Test::Unit::TestCase # :nodoc:
context "a numeric attribute" do
setup do
define_model :example, :attr => :string do
validates_numericality_of :attr
end
@model = Example.new
end
should "only allow numeric values for that attribute" do
assert_accepts validate_numericality_of(:attr), @model
end
should "not override the default message with a blank" do
assert_accepts validate_numericality_of(:attr).with_message(nil),
@model
end
end
context "a numeric attribute with a custom validation message" do
setup do
define_model :example, :attr => :string do
validates_numericality_of :attr, :message => 'custom'
end
@model = Example.new
end
should "only allow numeric values for that attribute with that message" do
assert_accepts validate_numericality_of(:attr).
with_message(/custom/),
@model
end
should "not allow numeric values for that attribute with another message" do
assert_rejects validate_numericality_of(:attr), @model
end
end
context "a non-numeric attribute" do
setup do
@model = define_model(:example, :attr => :string).new
end
should "not only allow numeric values for that attribute" do
assert_rejects validate_numericality_of(:attr), @model
end
end
end

View File

@@ -0,0 +1,86 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class ValidatePresenceOfMatcherTest < Test::Unit::TestCase # :nodoc:
context "a required attribute" do
setup do
define_model :example, :attr => :string do
validates_presence_of :attr
end
@model = Example.new
end
should "require a value" do
assert_accepts validate_presence_of(:attr), @model
end
should "not override the default message with a blank" do
assert_accepts validate_presence_of(:attr).with_message(nil), @model
end
end
context "an optional attribute" do
setup do
@model = define_model(:example, :attr => :string).new
end
should "not require a value" do
assert_rejects validate_presence_of(:attr), @model
end
end
context "a required has_many association" do
setup do
define_model :child
@model = define_model :parent do
has_many :children
validates_presence_of :children
end.new
end
should "require the attribute to be set" do
assert_accepts validate_presence_of(:children), @model
end
end
context "an optional has_many association" do
setup do
define_model :child
@model = define_model :parent do
has_many :children
end.new
end
should "not require the attribute to be set" do
assert_rejects validate_presence_of(:children), @model
end
end
context "a required has_and_belongs_to_many association" do
setup do
define_model :child
@model = define_model :parent do
has_and_belongs_to_many :children
validates_presence_of :children
end.new
end
should "require the attribute to be set" do
assert_accepts validate_presence_of(:children), @model
end
end
context "an optional has_and_belongs_to_many association" do
setup do
define_model :child
@model = define_model :parent do
has_and_belongs_to_many :children
end.new
end
should "not require the attribute to be set" do
assert_rejects validate_presence_of(:children), @model
end
end
end

View File

@@ -0,0 +1,147 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class ValidateUniquenessOfMatcherTest < Test::Unit::TestCase # :nodoc:
context "a unique attribute" do
setup do
@model = define_model(:example, :attr => :string,
:other => :integer) do
validates_uniqueness_of :attr
end.new
end
context "with an existing value" do
setup do
@existing = Example.create!(:attr => 'value', :other => 1)
end
should "require a unique value for that attribute" do
assert_accepts validate_uniqueness_of(:attr), @model
end
should "pass when the subject is an existing record" do
assert_accepts validate_uniqueness_of(:attr), @existing
end
should "fail when a scope is specified" do
assert_rejects validate_uniqueness_of(:attr).scoped_to(:other), @model
end
end
context "without an existing value" do
setup do
assert_nil Example.find(:first)
@matcher = validate_uniqueness_of(:attr)
end
should "fail to require a unique value" do
assert_rejects @matcher, @model
end
should "alert the tester that an existing value is not present" do
@matcher.matches?(@model)
assert @matcher.negative_failure_message =~ /^Can't find first .*/
end
end
end
context "a unique attribute with a custom error and an existing value" do
setup do
@model = define_model(:example, :attr => :string) do
validates_uniqueness_of :attr, :message => 'Bad value'
end.new
Example.create!
end
should "fail when checking the default message" do
assert_rejects validate_uniqueness_of(:attr), @model
end
should "fail when checking a message that doesn't match" do
assert_rejects validate_uniqueness_of(:attr).with_message(/abc/i), @model
end
should "pass when checking a message that matches" do
assert_accepts validate_uniqueness_of(:attr).with_message(/bad/i), @model
end
end
context "a scoped unique attribute with an existing value" do
setup do
@model = define_model(:example, :attr => :string,
:scope1 => :integer,
:scope2 => :integer) do
validates_uniqueness_of :attr, :scope => [:scope1, :scope2]
end.new
@existing = Example.create!(:attr => 'value', :scope1 => 1, :scope2 => 2)
end
should "pass when the correct scope is specified" do
assert_accepts validate_uniqueness_of(:attr).scoped_to(:scope1, :scope2),
@model
end
should "pass when the subject is an existing record" do
assert_accepts validate_uniqueness_of(:attr).scoped_to(:scope1, :scope2),
@existing
end
should "fail when a different scope is specified" do
assert_rejects validate_uniqueness_of(:attr).scoped_to(:scope1), @model
end
should "fail when no scope is specified" do
assert_rejects validate_uniqueness_of(:attr), @model
end
should "fail when a non-existent attribute is specified as a scope" do
assert_rejects validate_uniqueness_of(:attr).scoped_to(:fake), @model
end
end
context "a non-unique attribute with an existing value" do
setup do
@model = define_model(:example, :attr => :string).new
Example.create!(:attr => 'value')
end
should "not require a unique value for that attribute" do
assert_rejects validate_uniqueness_of(:attr), @model
end
end
context "a case sensitive unique attribute with an existing value" do
setup do
@model = define_model(:example, :attr => :string) do
validates_uniqueness_of :attr, :case_sensitive => true
end.new
Example.create!(:attr => 'value')
end
should "not require a unique, case-insensitive value for that attribute" do
assert_rejects validate_uniqueness_of(:attr).case_insensitive, @model
end
should "require a unique, case-sensitive value for that attribute" do
assert_accepts validate_uniqueness_of(:attr), @model
end
end
context "a case sensitive unique integer attribute with an existing value" do
setup do
@model = define_model(:example, :attr => :integer) do
validates_uniqueness_of :attr, :case_sensitive => true
end.new
Example.create!(:attr => 'value')
end
should "require a unique, case-insensitive value for that attribute" do
assert_accepts validate_uniqueness_of(:attr).case_insensitive, @model
end
should "require a unique, case-sensitive value for that attribute" do
assert_accepts validate_uniqueness_of(:attr), @model
end
end
end

View File

@@ -0,0 +1,35 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class AssignToMatcherTest < Test::Unit::TestCase # :nodoc:
context "a controller that assigns to an instance variable" do
setup do
@controller = build_response { @var = 'value' }
end
should "accept assigning to that variable" do
assert_accepts assign_to(:var), @controller
end
should "accept assigning to that variable with the correct class" do
assert_accepts assign_to(:var).with_kind_of(String), @controller
end
should "reject assigning to that variable with another class" do
assert_rejects assign_to(:var).with_kind_of(Fixnum), @controller
end
should "accept assigning the correct value to that variable" do
assert_accepts assign_to(:var).with('value'), @controller
end
should "reject assigning another value to that variable" do
assert_rejects assign_to(:var).with('other'), @controller
end
should "reject assigning to another variable" do
assert_rejects assign_to(:other), @controller
end
end
end

View File

@@ -0,0 +1,32 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class FilterParamMatcherTest < Test::Unit::TestCase # :nodoc:
context "a controller that filters no parameters" do
setup do
@controller = define_controller(:examples).new
end
should "reject filtering any parameter" do
assert_rejects filter_param(:any), @controller
end
end
context "a controller that filters a parameter" do
setup do
@controller = define_controller :examples do
filter_parameter_logging :password
end.new
end
should "accept filtering that parameter" do
assert_accepts filter_param(:password), @controller
end
should "reject filtering another parameter" do
assert_rejects filter_param(:other), @controller
end
end
end

View File

@@ -0,0 +1,33 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class RenderWithLayoutMatcherTest < Test::Unit::TestCase # :nodoc:
context "a controller that renders with a layout" do
setup do
@controller = build_response { render :layout => 'wide' }
end
should "accept rendering with any layout" do
assert_accepts render_with_layout, @controller
end
should "accept rendering with that layout" do
assert_accepts render_with_layout(:wide), @controller
end
should "reject rendering with another layout" do
assert_rejects render_with_layout(:other), @controller
end
end
context "a controller that renders without a layout" do
setup do
@controller = build_response { render :layout => false }
end
should "reject rendering with a layout" do
assert_rejects render_with_layout, @controller
end
end
end

View File

@@ -0,0 +1,27 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class RespondWithContentTypeMatcherTest < Test::Unit::TestCase # :nodoc:
context "a controller responding with content type :xml" do
setup do
@controller = build_response { render :xml => { :user => "thoughtbot" }.to_xml }
end
should "accept responding with content type :xml" do
assert_accepts respond_with_content_type(:xml), @controller
end
should "accept responding with content type 'application/xml'" do
assert_accepts respond_with_content_type('application/xml'), @controller
end
should "accept responding with content type /xml/" do
assert_accepts respond_with_content_type(/xml/), @controller
end
should "reject responding with another content type" do
assert_rejects respond_with_content_type(:json), @controller
end
end
end

View File

@@ -0,0 +1,106 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class RespondWithMatcherTest < Test::Unit::TestCase # :nodoc:
context "a controller responding with success" do
setup do
@controller = build_response { render :text => "text", :status => 200 }
end
should "accept responding with 200" do
assert_accepts respond_with(200), @controller
end
should "accept responding with :success" do
assert_accepts respond_with(:success), @controller
end
should "reject responding with another status" do
assert_rejects respond_with(:error), @controller
end
end
context "a controller responding with redirect" do
setup do
@controller = build_response { render :text => "text", :status => 301 }
end
should "accept responding with 301" do
assert_accepts respond_with(301), @controller
end
should "accept responding with :redirect" do
assert_accepts respond_with(:redirect), @controller
end
should "reject responding with another status" do
assert_rejects respond_with(:error), @controller
end
end
context "a controller responding with missing" do
setup do
@controller = build_response { render :text => "text", :status => 404 }
end
should "accept responding with 404" do
assert_accepts respond_with(404), @controller
end
should "accept responding with :missing" do
assert_accepts respond_with(:missing), @controller
end
should "reject responding with another status" do
assert_rejects respond_with(:success), @controller
end
end
context "a controller responding with error" do
setup do
@controller = build_response { render :text => "text", :status => 500 }
end
should "accept responding with 500" do
assert_accepts respond_with(500), @controller
end
should "accept responding with :error" do
assert_accepts respond_with(:error), @controller
end
should "reject responding with another status" do
assert_rejects respond_with(:success), @controller
end
end
context "a controller responding with not implemented" do
setup do
@controller = build_response { render :text => "text", :status => 501 }
end
should "accept responding with 501" do
assert_accepts respond_with(501), @controller
end
should "accept responding with :not_implemented" do
assert_accepts respond_with(:not_implemented), @controller
end
should "reject responding with another status" do
assert_rejects respond_with(:success), @controller
end
end
context "a controller raising an error" do
setup do
@controller = build_response { raise RailsError }
end
should "reject responding with any status" do
assert_rejects respond_with(:success), @controller
end
end
end

View File

@@ -0,0 +1,58 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class RouteToMatcherTest < Test::Unit::TestCase # :nodoc:
context "given a controller with a defined route" do
setup do
@controller = define_controller('Examples').new
define_routes do |map|
map.connect 'examples/:id', :controller => 'examples',
:action => 'example'
end
end
should "accept routing the correct path to the correct parameters" do
assert_accepts route(:get, '/examples/1').
to(:action => 'example', :id => '1'),
@controller
end
should "accept a symbol controller" do
assert_accepts route(:get, '/examples/1').
to(:controller => :examples,
:action => 'example',
:id => '1'),
self
end
should "accept a symbol action" do
assert_accepts route(:get, '/examples/1').
to(:action => :example, :id => '1'),
@controller
end
should "accept a non-string parameter" do
assert_accepts route(:get, '/examples/1').
to(:action => 'example', :id => 1),
@controller
end
should "reject an undefined route" do
assert_rejects route(:get, '/bad_route').to(:var => 'value'), @controller
end
should "reject a route for another controller" do
@other = define_controller('Other').new
assert_rejects route(:get, '/examples/1').
to(:action => 'example', :id => '1'),
@other
end
should "reject a route for different parameters" do
assert_rejects route(:get, '/examples/1').
to(:action => 'other', :id => '1'),
@controller
end
end
end

View File

@@ -0,0 +1,31 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class SetSessionMatcherTest < Test::Unit::TestCase # :nodoc:
context "a controller that sets a session variable" do
setup do
@controller = build_response { session[:var] = 'value' }
end
should "accept assigning to that variable" do
assert_accepts set_session(:var), @controller
end
should "accept assigning the correct value to that variable" do
assert_accepts set_session(:var).to('value'), @controller
end
should "reject assigning another value to that variable" do
assert_rejects set_session(:var).to('other'), @controller
end
should "reject assigning to another variable" do
assert_rejects set_session(:other), @controller
end
should "accept assigning nil to another variable" do
assert_accepts set_session(:other).to(nil), @controller
end
end
end

View File

@@ -0,0 +1,41 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class SetTheFlashMatcherTest < Test::Unit::TestCase # :nodoc:
context "a controller that sets a flash message" do
setup do
@controller = build_response { flash[:notice] = 'value' }
end
should "accept setting any flash message" do
assert_accepts set_the_flash, @controller
end
should "accept setting the exact flash message" do
assert_accepts set_the_flash.to('value'), @controller
end
should "accept setting a matched flash message" do
assert_accepts set_the_flash.to(/value/), @controller
end
should "reject setting a different flash message" do
assert_rejects set_the_flash.to('other'), @controller
end
should "reject setting a different pattern" do
assert_rejects set_the_flash.to(/other/), @controller
end
end
context "a controller that doesn't set a flash message" do
setup do
@controller = build_response
end
should "reject setting any flash message" do
assert_rejects set_the_flash, @controller
end
end
end

View File

@@ -0,0 +1,106 @@
class Test::Unit::TestCase
def create_table(table_name, &block)
connection = ActiveRecord::Base.connection
begin
connection.execute("DROP TABLE IF EXISTS #{table_name}")
connection.create_table(table_name, &block)
@created_tables ||= []
@created_tables << table_name
connection
rescue Exception => e
connection.execute("DROP TABLE IF EXISTS #{table_name}")
raise e
end
end
def define_constant(class_name, base, &block)
class_name = class_name.to_s.camelize
klass = Class.new(base)
Object.const_set(class_name, klass)
klass.class_eval(&block) if block_given?
@defined_constants ||= []
@defined_constants << class_name
klass
end
def define_model_class(class_name, &block)
define_constant(class_name, ActiveRecord::Base, &block)
end
def define_model(name, columns = {}, &block)
class_name = name.to_s.pluralize.classify
table_name = class_name.tableize
create_table(table_name) do |table|
columns.each do |name, type|
table.column name, type
end
end
define_model_class(class_name, &block)
end
def define_controller(class_name, &block)
class_name = class_name.to_s
class_name << 'Controller' unless class_name =~ /Controller$/
define_constant(class_name, ActionController::Base, &block)
end
def define_routes(&block)
@replaced_routes = ActionController::Routing::Routes
new_routes = ActionController::Routing::RouteSet.new
silence_warnings do
ActionController::Routing.const_set('Routes', new_routes)
end
new_routes.draw(&block)
end
def build_response(&block)
klass = define_controller('Examples')
block ||= lambda { render :nothing => true }
klass.class_eval { define_method(:example, &block) }
define_routes do |map|
map.connect 'examples', :controller => 'examples', :action => 'example'
end
@controller = klass.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
get :example
@controller
end
def teardown_with_models
if @defined_constants
@defined_constants.each do |class_name|
Object.send(:remove_const, class_name)
end
end
if @created_tables
@created_tables.each do |table_name|
ActiveRecord::Base.
connection.
execute("DROP TABLE IF EXISTS #{table_name}")
end
end
if @replaced_routes
ActionController::Routing::Routes.clear!
silence_warnings do
ActionController::Routing.const_set('Routes', @replaced_routes)
end
@replaced_routes.reload!
end
teardown_without_models
end
alias_method :teardown_without_models, :teardown
alias_method :teardown, :teardown_with_models
end

View File

@@ -0,0 +1,18 @@
require File.join(File.dirname(__FILE__), '..', 'test_helper')
class AutoloadMacroTest < Test::Unit::TestCase # :nodoc:
context "The macro auto-loader" do
should "load macros from the plugins" do
assert self.class.respond_to?('plugin_macro')
end
should "load macros from the gems" do
assert self.class.respond_to?('gem_macro')
end
should "load custom macros from ROOT/test/shoulda_macros" do
assert self.class.respond_to?('custom_macro')
end
end
end

View File

@@ -0,0 +1,145 @@
require File.join(File.dirname(__FILE__), '..', 'test_helper')
class ContextTest < Test::Unit::TestCase # :nodoc:
def self.context_macro(&blk)
context "with a subcontext made by a macro" do
setup { @context_macro = :foo }
merge_block &blk
end
end
# def self.context_macro(&blk)
# context "with a subcontext made by a macro" do
# setup { @context_macro = :foo }
# yield # <- this doesn't work.
# end
# end
context "context with setup block" do
setup do
@blah = "blah"
end
should "run the setup block" do
assert_equal "blah", @blah
end
should "have name set right" do
assert_match(/^test: context with setup block/, self.to_s)
end
context "and a subcontext" do
setup do
@blah = "#{@blah} twice"
end
should "be named correctly" do
assert_match(/^test: context with setup block and a subcontext should be named correctly/, self.to_s)
end
should "run the setup blocks in order" do
assert_equal @blah, "blah twice"
end
end
context_macro do
should "have name set right" do
assert_match(/^test: context with setup block with a subcontext made by a macro should have name set right/, self.to_s)
end
should "run the setup block of that context macro" do
assert_equal :foo, @context_macro
end
should "run the setup block of the main context" do
assert_equal "blah", @blah
end
end
end
context "another context with setup block" do
setup do
@blah = "foo"
end
should "have @blah == 'foo'" do
assert_equal "foo", @blah
end
should "have name set right" do
assert_match(/^test: another context with setup block/, self.to_s)
end
end
context "context with method definition" do
setup do
def hello; "hi"; end
end
should "be able to read that method" do
assert_equal "hi", hello
end
should "have name set right" do
assert_match(/^test: context with method definition/, self.to_s)
end
end
context "another context" do
should "not define @blah" do
assert_nil @blah
end
end
context "context with multiple setups and/or teardowns" do
cleanup_count = 0
2.times do |i|
setup { cleanup_count += 1 }
teardown { cleanup_count -= 1 }
end
2.times do |i|
should "call all setups and all teardowns (check ##{i + 1})" do
assert_equal 2, cleanup_count
end
end
context "subcontexts" do
2.times do |i|
setup { cleanup_count += 1 }
teardown { cleanup_count -= 1 }
end
2.times do |i|
should "also call all setups and all teardowns in parent and subcontext (check ##{i + 1})" do
assert_equal 4, cleanup_count
end
end
end
end
should_eventually "pass, since it's unimplemented" do
flunk "what?"
end
should_eventually "not require a block when using should_eventually"
should "pass without a block, as that causes it to piggyback to should_eventually"
context "context for testing should piggybacking" do
should "call should_eventually as we are not passing a block"
end
context "context" do
context "with nested subcontexts" do
should_eventually "only print this statement once for a should_eventually"
end
end
end

View File

@@ -0,0 +1,63 @@
require 'test/unit'
class ConvertToShouldSyntaxTest < Test::Unit::TestCase # :nodoc:
BEFORE_FIXTURE = <<-EOS
class DummyTest < Test::Unit::TestCase
should "Not change this_word_with_underscores" do
end
def test_should_be_working
assert true
end
def test_some_cool_stuff
assert true
end
def non_test_method
end
end
EOS
AFTER_FIXTURE = <<-EOS
class DummyTest < Test::Unit::TestCase
should "Not change this_word_with_underscores" do
end
should "be working" do
assert true
end
should "RENAME ME: test some cool stuff" do
assert true
end
def non_test_method
end
end
EOS
FIXTURE_PATH = "./convert_to_should_syntax_fixture.dat"
RUBY = ENV['RUBY'] || 'ruby'
def test_convert_to_should_syntax
File.open(FIXTURE_PATH, "w") {|f| f.write(BEFORE_FIXTURE)}
cmd = "#{RUBY} #{File.join(File.dirname(__FILE__), '../../bin/convert_to_should_syntax')} #{FIXTURE_PATH}"
output = `#{cmd}`
File.unlink($1) if output.match(/has been stored in '([^']+)/)
assert_match(/has been converted/, output)
result = IO.read(FIXTURE_PATH)
assert_equal result, AFTER_FIXTURE
end
def teardown
File.unlink(FIXTURE_PATH)
end
end

View File

@@ -0,0 +1,241 @@
require File.join(File.dirname(__FILE__), '..', 'test_helper')
require 'action_mailer'
require 'mocha'
class HelpersTest < Test::Unit::TestCase # :nodoc:
context "given delivered emails" do
setup do
email1 = stub(:subject => "one", :to => ["none1@email.com"])
email2 = stub(:subject => "two", :to => ["none2@email.com"])
ActionMailer::Base.stubs(:deliveries).returns([email1, email2])
end
should "have sent an email" do
assert_sent_email
assert_raises(Test::Unit::AssertionFailedError) do
assert_did_not_send_email
end
end
should "find email one" do
assert_sent_email do |e|
e.subject =~ /one/
end
end
should "not find an email that doesn't exist" do
assert_raises(Test::Unit::AssertionFailedError) do
assert_sent_email do |e|
e.subject =~ /whatever/
end
end
end
end
context "when there are no emails" do
setup do
ActionMailer::Base.stubs(:deliveries).returns([])
end
should "not have sent an email" do
assert_did_not_send_email
assert_raises(Test::Unit::AssertionFailedError) do
assert_sent_email
end
end
end
context "an array of values" do
setup do
@a = ['abc', 'def', 3]
end
[/b/, 'abc', 3].each do |x|
should "contain #{x.inspect}" do
assert_raises(Test::Unit::AssertionFailedError) do
assert_does_not_contain @a, x
end
assert_contains @a, x
end
end
should "not contain 'wtf'" do
assert_raises(Test::Unit::AssertionFailedError) {assert_contains @a, 'wtf'}
assert_does_not_contain @a, 'wtf'
end
should "be the same as another array, ordered differently" do
assert_same_elements(@a, [3, "def", "abc"])
assert_raises(Test::Unit::AssertionFailedError) do
assert_same_elements(@a, [3, 3, "def", "abc"])
end
assert_raises(Test::Unit::AssertionFailedError) do
assert_same_elements([@a, "abc"].flatten, [3, 3, "def", "abc"])
end
end
end
context "an array of values" do
setup do
@a = [1, 2, "(3)"]
end
context "after adding another value" do
setup do
@a.push(4)
end
should_change "@a.length", :by => 1
should_change "@a.length", :from => 3
should_change "@a.length", :to => 4
should_change "@a[0]", :by => 0
should_not_change "@a[0]"
end
context "after replacing it with an array of strings" do
setup do
@a = %w(a b c d e f)
end
should_change "@a.length", :by => 3
should_change "@a.length", :from => 3, :to => 6, :by => 3
should_change "@a[0]"
should_change "@a[1]", :from => 2, :to => "b"
should_change "@a[2]", :from => /\d/, :to => /\w/
should_change "@a[3]", :to => String
end
end
context "assert_good_value" do
should "validate a good email address" do
assert_good_value User.new, :email, "good@example.com"
end
should "validate a good SSN with a custom message" do
assert_good_value User.new, :ssn, "xxxxxxxxx", /length/
end
should "fail to validate a bad email address" do
assert_raises Test::Unit::AssertionFailedError do
assert_good_value User.new, :email, "bad"
end
end
should "fail to validate a bad SSN that is too short" do
assert_raises Test::Unit::AssertionFailedError do
assert_good_value User.new, :ssn, "x", /length/
end
end
should "accept a class as the first argument" do
assert_good_value User, :email, "good@example.com"
end
context "with an instance variable" do
setup do
@product = Product.new(:tangible => true)
end
should "use that instance variable" do
assert_good_value Product, :price, "9999", /included/
end
end
end
context "assert_bad_value" do
should "invalidate a bad email address" do
assert_bad_value User.new, :email, "bad"
end
should "invalidate a bad SSN with a custom message" do
assert_bad_value User.new, :ssn, "x", /length/
end
should "fail to invalidate a good email address" do
assert_raises Test::Unit::AssertionFailedError do
assert_bad_value User.new, :email, "good@example.com"
end
end
should "fail to invalidate a good SSN" do
assert_raises Test::Unit::AssertionFailedError do
assert_bad_value User.new, :ssn, "xxxxxxxxx", /length/
end
end
should "accept a class as the first argument" do
assert_bad_value User, :email, "bad"
end
context "with an instance variable" do
setup do
@product = Product.new(:tangible => true)
end
should "use that instance variable" do
assert_bad_value Product, :price, "0", /included/
end
end
end
context "a matching matcher" do
setup do
@matcher = stub('matcher', :matches? => true,
:failure_message => 'bad failure message',
:negative_failure_message => 'big time failure')
end
should "pass when given to assert_accepts" do
assert_accepts @matcher, 'target'
end
context "when given to assert_rejects" do
setup do
begin
assert_rejects @matcher, 'target'
rescue Test::Unit::AssertionFailedError => @error
end
end
should "fail" do
assert_not_nil @error
end
should "use the error message from the matcher" do
assert_equal 'big time failure', @error.message
end
end
end
context "a non-matching matcher" do
setup do
@matcher = stub('matcher', :matches? => false,
:failure_message => 'big time failure',
:negative_failure_message => 'bad failure message')
end
should "pass when given to assert_rejects" do
assert_rejects @matcher, 'target'
end
context "when given to assert_accepts" do
setup do
begin
assert_accepts @matcher, 'target'
rescue Test::Unit::AssertionFailedError => @error
end
end
should "fail" do
assert_not_nil @error
end
should "use the error message from the matcher" do
assert_equal 'big time failure', @error.message
end
end
end
end

View File

@@ -0,0 +1,34 @@
require File.join(File.dirname(__FILE__), '..', 'test_helper')
class PrivateHelpersTest < Test::Unit::TestCase # :nodoc:
include Shoulda::Private
context "get_options!" do
should "remove opts from args" do
args = [:a, :b, {}]
get_options!(args)
assert_equal [:a, :b], args
end
should "return wanted opts in order" do
args = [{:one => 1, :two => 2}]
one, two = get_options!(args, :one, :two)
assert_equal 1, one
assert_equal 2, two
end
should "raise ArgumentError if given unwanted option" do
args = [{:one => 1, :two => 2}]
assert_raises ArgumentError do
get_options!(args, :one)
end
end
end
class ::SomeModel; end
context "model_class" do
should "sniff the class constant from the test class" do
self.expects(:name).returns("SomeModelTest")
assert_equal SomeModel, model_class
end
end
end

View File

@@ -0,0 +1,266 @@
require File.join(File.dirname(__FILE__), '..', 'test_helper')
class ShouldTest < Test::Unit::TestCase # :nodoc:
should "be able to define a should statement outside of a context" do
assert true
end
should "see the name of my class as ShouldTest" do
assert_equal "ShouldTest", self.class.name
end
def self.should_see_class_methods
should "be able to see class methods" do
assert true
end
end
def self.should_see_a_context_block_like_a_Test_Unit_class
should "see a context block as a Test::Unit class" do
assert_equal "ShouldTest", self.class.name
end
end
def self.should_see_blah
should "see @blah through a macro" do
assert @blah
end
end
def self.should_not_see_blah
should "not see @blah through a macro" do
assert_nil @blah
end
end
def self.should_be_able_to_make_context_macros(prefix = nil)
context "a macro" do
should "have the tests named correctly" do
assert_match(/^test: #{prefix}a macro should have the tests named correctly/, self.to_s)
end
end
end
context "Context" do
should_see_class_methods
should_see_a_context_block_like_a_Test_Unit_class
should_be_able_to_make_context_macros("Context ")
should "not define @blah" do
assert ! self.instance_variables.include?("@blah")
end
should_not_see_blah
should "be able to define a should statement" do
assert true
end
should "see the name of my class as ShouldTest" do
assert_equal "ShouldTest", self.class.name
end
context "with a subcontext" do
should_be_able_to_make_context_macros("Context with a subcontext ")
end
end
context "Context with setup block" do
setup do
@blah = "blah"
end
should "have @blah == 'blah'" do
assert_equal "blah", @blah
end
should_see_blah
should "have name set right" do
assert_match(/^test: Context with setup block/, self.to_s)
end
context "and a subcontext" do
setup do
@blah = "#{@blah} twice"
end
should "be named correctly" do
assert_match(/^test: Context with setup block and a subcontext should be named correctly/, self.to_s)
end
should "run the setup methods in order" do
assert_equal @blah, "blah twice"
end
should_see_blah
end
end
context "Another context with setup block" do
setup do
@blah = "foo"
end
should "have @blah == 'foo'" do
assert_equal "foo", @blah
end
should "have name set right" do
assert_match(/^test: Another context with setup block/, self.to_s)
end
should_see_blah
end
should_eventually "pass, since it's a should_eventually" do
flunk "what?"
end
# Context creation and naming
def test_should_create_a_new_context
assert_nothing_raised do
Shoulda::Context.new("context name", self) do; end
end
end
def test_should_create_a_nested_context
assert_nothing_raised do
parent = Shoulda::Context.new("Parent", self) do; end
child = Shoulda::Context.new("Child", parent) do; end
end
end
def test_should_name_a_contexts_correctly
parent = Shoulda::Context.new("Parent", self) do; end
child = Shoulda::Context.new("Child", parent) do; end
grandchild = Shoulda::Context.new("GrandChild", child) do; end
assert_equal "Parent", parent.full_name
assert_equal "Parent Child", child.full_name
assert_equal "Parent Child GrandChild", grandchild.full_name
end
# Should statements
def test_should_have_should_hashes_when_given_should_statements
context = Shoulda::Context.new("name", self) do
should "be good" do; end
should "another" do; end
end
names = context.shoulds.map {|s| s[:name]}
assert_equal ["another", "be good"], names.sort
end
# setup and teardown
def test_should_capture_setup_and_teardown_blocks
context = Shoulda::Context.new("name", self) do
setup do; "setup"; end
teardown do; "teardown"; end
end
assert_equal "setup", context.setup_blocks.first.call
assert_equal "teardown", context.teardown_blocks.first.call
end
# building
def test_should_create_shoulda_test_for_each_should_on_build
context = Shoulda::Context.new("name", self) do
should "one" do; end
should "two" do; end
end
context.expects(:create_test_from_should_hash).with(has_entry(:name => "one"))
context.expects(:create_test_from_should_hash).with(has_entry(:name => "two"))
context.build
end
def test_should_create_test_methods_on_build
tu_class = Test::Unit::TestCase
context = Shoulda::Context.new("A Context", tu_class) do
should "define the test" do; end
end
tu_class.expects(:define_method).with(:"test: A Context should define the test. ")
context.build
end
def test_should_create_test_methods_on_build_when_subcontext
tu_class = Test::Unit::TestCase
context = Shoulda::Context.new("A Context", tu_class) do
context "with a child" do
should "define the test" do; end
end
end
tu_class.expects(:define_method).with(:"test: A Context with a child should define the test. ")
context.build
end
# Test::Unit integration
def test_should_create_a_new_context_and_build_it_on_Test_Unit_context
c = mock("context")
c.expects(:build)
Shoulda::Context.expects(:new).with("foo", kind_of(Class)).returns(c)
self.class.context "foo" do; end
end
def test_should_create_a_one_off_context_and_build_it_on_Test_Unit_should
s = mock("test")
Shoulda::Context.any_instance.expects(:should).with("rock", {}).returns(s)
Shoulda::Context.any_instance.expects(:build)
self.class.should "rock" do; end
end
def test_should_create_a_one_off_context_and_build_it_on_Test_Unit_should_eventually
s = mock("test")
Shoulda::Context.any_instance.expects(:should_eventually).with("rock").returns(s)
Shoulda::Context.any_instance.expects(:build)
self.class.should_eventually "rock" do; end
end
should "run a :before proc", :before => lambda { @value = "before" } do
assert_equal "before", @value
end
context "A :before proc" do
setup do
assert_equal "before", @value
@value = "setup"
end
should "run before the current setup", :before => lambda { @value = "before" } do
assert_equal "setup", @value
end
end
context "a before statement" do
setup do
assert_equal "before", @value
@value = "setup"
end
before_should "run before the current setup" do
@value = "before"
end
end
context "A context" do
setup do
@value = "outer"
end
context "with a subcontext and a :before proc" do
before = lambda do
assert "outer", @value
@value = "before"
end
should "run after the parent setup", :before => before do
assert_equal "before", @value
end
end
end
end

View File

@@ -0,0 +1,25 @@
# Filters added to this controller apply to all controllers in the application.
# Likewise, all the methods added will be available for all controllers.
class ApplicationController < ActionController::Base
# Pick a unique cookie name to distinguish our session data from others'
session :session_key => '_rails_root_session_id'
def ensure_logged_in
unless session[:logged_in]
respond_to do |accepts|
accepts.html do
flash[:error] = 'What do you think you\'re doing?'
redirect_to '/'
end
accepts.xml do
headers["Status"] = "Unauthorized"
headers["WWW-Authenticate"] = %(Basic realm="Web Password")
render :text => "Couldn't authenticate you", :status => '401 Unauthorized'
end
end
return false
end
return true
end
end

View File

@@ -0,0 +1,86 @@
class PostsController < ApplicationController
before_filter :ensure_logged_in
before_filter :load_user
def index
@posts = @user.posts
respond_to do |format|
format.html # index.rhtml
format.xml { render :xml => @posts.to_xml }
format.rss do
headers['Content-Type'] = 'application/rss+xml'
session[:special] = '$2 off your next purchase'
session[:special_user_id] = @user.id
head :ok
end
end
end
def show
@post = @user.posts.find(params[:id])
@false_flag = false
respond_to do |format|
format.html { render :layout => 'wide' }
format.xml { render :xml => @post.to_xml }
end
end
def new
@post = @user.posts.build
render :layout => false
end
def edit
@post = @user.posts.find(params[:id])
end
def create
@post = @user.posts.build(params[:post])
respond_to do |format|
if @post.save
flash[:notice] = 'Post was successfully created.'
format.html { redirect_to user_post_url(@post.user, @post) }
format.xml { head :created, :location => user_post_url(@post.user, @post) }
else
format.html { render :action => "new" }
format.xml { render :xml => @post.errors.to_xml }
end
end
end
def update
@post = @user.posts.find(params[:id])
respond_to do |format|
if @post.update_attributes(params[:post])
flash[:notice] = 'Post was successfully updated.'
format.html { redirect_to user_post_url(@post.user, @post) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @post.errors.to_xml }
end
end
end
def destroy
@post = @user.posts.find(params[:id])
@post.destroy
flash[:notice] = "Post was removed"
respond_to do |format|
format.html { redirect_to user_posts_url(@post.user) }
format.xml { head :ok }
end
end
private
def load_user
@user = User.find(params[:user_id])
end
end

View File

@@ -0,0 +1,84 @@
class UsersController < ApplicationController
filter_parameter_logging :ssn
# GET /users
# GET /users.xml
def index
@users = User.find(:all)
respond_to do |format|
format.html # index.rhtml
format.xml { render :xml => @users.to_xml }
end
end
# GET /users/1
# GET /users/1.xml
def show
@user = User.find(params[:id])
respond_to do |format|
format.html # show.rhtml
format.xml { render :xml => @user.to_xml }
end
end
# GET /users/new
def new
@user = User.new
end
# GET /users/1;edit
def edit
@user = User.find(params[:id])
end
# POST /users
# POST /users.xml
def create
@user = User.new(params[:user])
respond_to do |format|
if @user.save
flash[:notice] = 'User was successfully created.'
format.html { redirect_to user_url(@user) }
format.xml { head :created, :location => user_url(@user) }
else
format.html { render :action => "new" }
format.xml { render :xml => @user.errors.to_xml }
end
end
end
# PUT /users/1
# PUT /users/1.xml
def update
@user = User.find(params[:id])
respond_to do |format|
if @user.update_attributes(params[:user])
flash[:notice] = 'User was successfully updated.'
format.html { redirect_to user_url(@user) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @user.errors.to_xml }
end
end
end
# DELETE /users/1
# DELETE /users/1.xml
def destroy
@user = User.find(params[:id])
@user.destroy
flash[:notice] = "User was removed"
respond_to do |format|
format.html { redirect_to users_url }
format.xml { head :ok }
end
end
end

View File

@@ -0,0 +1,3 @@
# Methods added to this helper will be available to all templates in the application.
module ApplicationHelper
end

View File

@@ -0,0 +1,2 @@
module PostsHelper
end

View File

@@ -0,0 +1,2 @@
module UsersHelper
end

View File

@@ -0,0 +1,7 @@
class Address < ActiveRecord::Base
belongs_to :addressable, :polymorphic => true
validates_uniqueness_of :title, :scope => [:addressable_type, :addressable_id]
validates_length_of :zip, :minimum => 5
validates_numericality_of :zip
end

View File

@@ -0,0 +1,3 @@
class Flea < ActiveRecord::Base
has_and_belongs_to_many :dogs
end

View File

@@ -0,0 +1,4 @@
class Friendship < ActiveRecord::Base
belongs_to :user
belongs_to :friend, :class_name => "User"
end

View File

@@ -0,0 +1,10 @@
module Pets
class Dog < ActiveRecord::Base
belongs_to :user, :foreign_key => :owner_id
belongs_to :address, :dependent => :destroy
has_many :treats
has_and_belongs_to_many :fleas, :join_table => :fleas
validates_presence_of :treats, :fleas
validates_presence_of :owner_id
end
end

View File

@@ -0,0 +1,12 @@
class Post < ActiveRecord::Base
belongs_to :user
belongs_to :owner, :foreign_key => :user_id, :class_name => 'User'
has_many :taggings
has_many :tags, :through => :taggings
has_many :through_tags, :through => :taggings, :source => :tag
validates_uniqueness_of :title
validates_presence_of :title
validates_presence_of :body, :message => 'Seriously... wtf'
validates_numericality_of :user_id
end

View File

@@ -0,0 +1,12 @@
class Product < ActiveRecord::Base
validates_presence_of :title
validates_inclusion_of :price, :in => 0..99, :unless => :tangible
validates_format_of :size, :with => /^\d+\D+$/, :unless => :tangible
validates_presence_of :price, :if => :tangible
validates_inclusion_of :price, :in => 1..9999, :if => :tangible
validates_inclusion_of :weight, :in => 1..100, :if => :tangible
validates_format_of :size, :with => /.+x.+x.+/, :if => :tangible
validates_length_of :size, :in => 5..20, :if => :tangible
end

View File

@@ -0,0 +1,8 @@
class Tag < ActiveRecord::Base
has_many :taggings, :dependent => :destroy
has_many :posts, :through => :taggings
validates_length_of :name, :minimum => 2
attr_accessible :name
end

View File

@@ -0,0 +1,4 @@
class Tagging < ActiveRecord::Base
belongs_to :post
belongs_to :tag
end

View File

@@ -0,0 +1,3 @@
class Treat < ActiveRecord::Base
end

View File

@@ -0,0 +1,29 @@
class User < ActiveRecord::Base
has_many :posts
has_many :dogs, :foreign_key => :owner_id, :class_name => "Pets::Dog"
has_many :friendships
has_many :friends, :through => :friendships
has_one :address, :as => :addressable, :dependent => :destroy
named_scope :old, :conditions => "age > 50"
named_scope :eighteen, :conditions => { :age => 18 }
named_scope :recent, lambda {|count| { :limit => count } }
def self.recent_via_method(count)
scoped(:limit => count)
end
attr_protected :password
attr_readonly :name
validates_format_of :email, :with => /\w*@\w*.com/
validates_length_of :email, :in => 1..100
validates_numericality_of :age, :greater_than_or_equal_to => 1,
:less_than_or_equal_to => 100
validates_acceptance_of :eula
validates_uniqueness_of :email, :scope => :name, :case_sensitive => false
validates_length_of :ssn, :is => 9, :message => "Social Security Number is not the right length"
validates_numericality_of :ssn
end

View File

@@ -0,0 +1,19 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<meta name="description" content="Posts, posts and more posts" />
<meta name='keywords' content='posts' />
<title>Posts: <%= controller.action_name %></title>
<%= stylesheet_link_tag 'scaffold' %>
</head>
<body>
<p style="color: green"><%= flash[:notice] %></p>
<%= yield %>
</body>
</html>

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<title>Users: <%= controller.action_name %></title>
<%= stylesheet_link_tag 'scaffold' %>
</head>
<body>
<p style="color: green"><%= flash[:notice] %></p>
<%= yield %>
</body>
</html>

View File

@@ -0,0 +1 @@
<html><%= yield %></html>

View File

@@ -0,0 +1,27 @@
<h1>Editing post</h1>
<%= error_messages_for :post %>
<% form_for(:post, :url => user_post_path(@post.user, @post), :html => { :method => :put }) do |f| %>
<p>
<b>User</b><br />
<%= f.text_field :user_id %>
</p>
<p>
<b>Title</b><br />
<%= f.text_field :title %>
</p>
<p>
<b>Body</b><br />
<%= f.text_area :body %>
</p>
<p>
<%= submit_tag "Update" %>
</p>
<% end %>
<%= link_to 'Show', user_post_path(@post.user, @post) %> |
<%= link_to 'Back', user_posts_path(@post.user) %>

View File

@@ -0,0 +1,25 @@
<h1>Listing posts</h1>
<table>
<tr>
<th>User</th>
<th>Title</th>
<th>Body</th>
</tr>
<% for post in @posts %>
<tr>
<td><%=h post.user_id %></td>
<td><%=h post.title %></td>
<td><%=h post.body %></td>
<td><%= link_to 'Show', user_post_path(post.user, post) %></td>
<td><%= link_to 'Edit', edit_user_post_path(post.user, post) %></td>
<td><%= link_to 'Destroy', user_post_path(post.user, post), :confirm => 'Are you sure?',
:method => :delete %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New post', new_user_post_path(post.user) %>

View File

@@ -0,0 +1,26 @@
<h1>New post</h1>
<%= error_messages_for :post %>
<% form_for(:post, :url => user_posts_path(@user)) do |f| %>
<p>
<b>User</b><br />
<%= f.text_field :user_id %>
</p>
<p>
<b>Title</b><br />
<%= f.text_field :title %>
</p>
<p>
<b>Body</b><br />
<%= f.text_area :body %>
</p>
<p>
<%= submit_tag "Create" %>
</p>
<% end %>
<%= link_to 'Back', user_posts_path(@user) %>

View File

@@ -0,0 +1,18 @@
<p>
<b>User:</b>
<%=h @post.user_id %>
</p>
<p>
<b>Title:</b>
<%=h @post.title %>
</p>
<p>
<b>Body:</b>
<%=h @post.body %>
</p>
<%= link_to 'Edit', edit_user_post_path(@post.user, @post) %> |
<%= link_to 'Back', user_posts_path(@post.user) %>

View File

@@ -0,0 +1,22 @@
<h1>Editing user</h1>
<%= error_messages_for :user %>
<% form_for(:user, :url => user_path(@user), :html => { :method => :put }) do |f| %>
<p>
<b>Email</b><br />
<%= f.text_field :email %>
</p>
<p>
<b>Age</b><br />
<%= f.text_field :age %>
</p>
<p>
<%= submit_tag "Update" %>
</p>
<% end %>
<%= link_to 'Show', user_path(@user) %> |
<%= link_to 'Back', users_path %>

View File

@@ -0,0 +1,22 @@
<h1>Listing users</h1>
<table>
<tr>
<th>Email</th>
<th>Age</th>
</tr>
<% for user in @users %>
<tr>
<td><%=h user.email %></td>
<td><%=h user.age %></td>
<td><%= link_to 'Show', user_path(user) %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user_path(user), :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New user', new_user_path %>

View File

@@ -0,0 +1,21 @@
<h1>New user</h1>
<%= error_messages_for :user %>
<% form_for(:user, :url => users_path) do |f| %>
<p>
<b>Email</b><br />
<%= f.text_field :email %>
</p>
<p>
<b>Age</b><br />
<%= f.text_field :age %>
</p>
<p>
<%= submit_tag "Create" %>
</p>
<% end %>
<%= link_to 'Back', users_path %>

View File

@@ -0,0 +1,13 @@
<p>
<b>Email:</b>
<%=h @user.email %>
</p>
<p>
<b>Age:</b>
<%=h @user.age %>
</p>
<%= link_to 'Edit', edit_user_path(@user) %> |
<%= link_to 'Back', users_path %>

View File

@@ -0,0 +1,109 @@
# Don't change this file!
# Configure your app in config/environment.rb and config/environments/*.rb
RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
module Rails
class << self
def boot!
unless booted?
preinitialize
pick_boot.run
end
end
def booted?
defined? Rails::Initializer
end
def pick_boot
(vendor_rails? ? VendorBoot : GemBoot).new
end
def vendor_rails?
File.exist?("#{RAILS_ROOT}/vendor/rails")
end
def preinitialize
load(preinitializer_path) if File.exist?(preinitializer_path)
end
def preinitializer_path
"#{RAILS_ROOT}/config/preinitializer.rb"
end
end
class Boot
def run
load_initializer
Rails::Initializer.run(:set_load_path)
end
end
class VendorBoot < Boot
def load_initializer
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
Rails::Initializer.run(:install_gem_spec_stubs)
end
end
class GemBoot < Boot
def load_initializer
self.class.load_rubygems
load_rails_gem
require 'initializer'
end
def load_rails_gem
if version = self.class.gem_version
gem 'rails', version
else
gem 'rails'
end
rescue Gem::LoadError => load_error
$stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
exit 1
end
class << self
def rubygems_version
Gem::RubyGemsVersion if defined? Gem::RubyGemsVersion
end
def gem_version
if defined? RAILS_GEM_VERSION
RAILS_GEM_VERSION
elsif ENV.include?('RAILS_GEM_VERSION')
ENV['RAILS_GEM_VERSION']
else
parse_gem_version(read_environment_rb)
end
end
def load_rubygems
require 'rubygems'
unless rubygems_version >= '0.9.4'
$stderr.puts %(Rails requires RubyGems >= 0.9.4 (you have #{rubygems_version}). Please `gem update --system` and try again.)
exit 1
end
rescue LoadError
$stderr.puts %(Rails requires RubyGems >= 0.9.4. Please install RubyGems and try again: http://rubygems.rubyforge.org)
exit 1
end
def parse_gem_version(text)
$1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
end
private
def read_environment_rb
File.read("#{RAILS_ROOT}/config/environment.rb")
end
end
end
end
# All that for this:
Rails.boot!

View File

@@ -0,0 +1,14 @@
# Specifies gem version of Rails to use when vendor/rails is not present
old_verbose, $VERBOSE = $VERBOSE, nil
RAILS_GEM_VERSION = '= 2.2.2' unless defined? RAILS_GEM_VERSION
$VERBOSE = old_verbose
require File.join(File.dirname(__FILE__), 'boot')
Rails::Initializer.run do |config|
config.log_level = :debug
config.cache_classes = false
config.whiny_nils = true
end
# Dependencies.log_activity = true

View File

@@ -0,0 +1,15 @@
# These settings change the behavior of Rails 2 apps and will be defaults
# for Rails 3. You can remove this initializer when Rails 3 is released.
# Include Active Record class name as root for JSON serialized output.
ActiveRecord::Base.include_root_in_json = true
# Store the full class name (including module namespace) in STI type column.
ActiveRecord::Base.store_full_sti_class = true
# Use ISO 8601 format for JSON serialized times and dates.
ActiveSupport.use_standard_json_time_format = true
# Don't escape HTML entities in JSON, leave that for the #json_escape helper.
# if you're including raw json in an HTML page.
ActiveSupport.escape_html_entities_in_json = false

View File

@@ -0,0 +1,8 @@
# This simulates loading the shoulda plugin, but without relying on
# vendor/plugins
shoulda_path = File.join(File.dirname(__FILE__), *%w(.. .. .. ..))
shoulda_lib_path = File.join(shoulda_path, "lib")
$LOAD_PATH.unshift(shoulda_lib_path)
load File.join(shoulda_path, "init.rb")

View File

@@ -0,0 +1,6 @@
ActionController::Routing::Routes.draw do |map|
map.resources :posts
map.resources :users, :has_many => :posts
end

View File

@@ -0,0 +1,19 @@
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.column :name, :string
t.column :email, :string
t.column :age, :integer
t.column :ssn, :string
t.column :phone, :string
end
add_index :users, :email, :unique => true
add_index :users, :name
add_index :users, :age
add_index :users, [:email, :name], :unique => true
end
def self.down
drop_table :users
end
end

View File

@@ -0,0 +1,13 @@
class CreatePosts < ActiveRecord::Migration
def self.up
create_table :posts do |t|
t.column :user_id, :integer
t.column :title, :string
t.column :body, :text
end
end
def self.down
drop_table :posts
end
end

View File

@@ -0,0 +1,12 @@
class CreateTaggings < ActiveRecord::Migration
def self.up
create_table :taggings do |t|
t.column :post_id, :integer
t.column :tag_id, :integer
end
end
def self.down
drop_table :taggings
end
end

View File

@@ -0,0 +1,11 @@
class CreateTags < ActiveRecord::Migration
def self.up
create_table :tags do |t|
t.column :name, :string
end
end
def self.down
drop_table :tags
end
end

View File

@@ -0,0 +1,12 @@
class CreateDogs < ActiveRecord::Migration
def self.up
create_table :dogs do |t|
t.column :owner_id, :integer
t.column :address_id, :integer
end
end
def self.down
drop_table :dogs
end
end

View File

@@ -0,0 +1,14 @@
class CreateAddresses < ActiveRecord::Migration
def self.up
create_table :addresses do |t|
t.column :title, :string
t.column :addressable_id, :integer
t.column :addressable_type, :string
t.column :zip, :string
end
end
def self.down
drop_table :addresses
end
end

View File

@@ -0,0 +1,11 @@
class CreateFleas < ActiveRecord::Migration
def self.up
create_table :fleas do |t|
t.string :name
end
end
def self.down
drop_table :fleas
end
end

View File

@@ -0,0 +1,12 @@
class CreateDogsFleas < ActiveRecord::Migration
def self.up
create_table :dogs_fleas do |t|
t.integer :dog_id
t.integer :flea_id
end
end
def self.down
drop_table :dogs_fleas
end
end

View File

@@ -0,0 +1,17 @@
class CreateProducts < ActiveRecord::Migration
def self.up
create_table :products do |t|
t.string :title
t.integer :price
t.integer :weight
t.string :size
t.boolean :tangible
t.timestamps
end
end
def self.down
drop_table :products
end
end

View File

@@ -0,0 +1,14 @@
class CreateFriendships < ActiveRecord::Migration
def self.up
create_table :friendships do |t|
t.integer :user_id
t.integer :friend_id
t.timestamps
end
end
def self.down
drop_table :friendships
end
end

View File

@@ -0,0 +1,12 @@
class CreateTreats < ActiveRecord::Migration
def self.up
create_table :treats do |t|
t.integer :dog_id
t.timestamps
end
end
def self.down
drop_table :treats
end
end

View File

@@ -0,0 +1,30 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>The page you were looking for doesn't exist (404)</title>
<style type="text/css">
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
div.dialog {
width: 25em;
padding: 0 4em;
margin: 4em auto 0 auto;
border: 1px solid #ccc;
border-right-color: #999;
border-bottom-color: #999;
}
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
</style>
</head>
<body>
<!-- This file lives in public/404.html -->
<div class="dialog">
<h1>The page you were looking for doesn't exist.</h1>
<p>You may have mistyped the address or the page may have moved.</p>
</div>
</body>
</html>

View File

@@ -0,0 +1,30 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>The change you wanted was rejected (422)</title>
<style type="text/css">
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
div.dialog {
width: 25em;
padding: 0 4em;
margin: 4em auto 0 auto;
border: 1px solid #ccc;
border-right-color: #999;
border-bottom-color: #999;
}
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
</style>
</head>
<body>
<!-- This file lives in public/422.html -->
<div class="dialog">
<h1>The change you wanted was rejected.</h1>
<p>Maybe you tried to change something you didn't have access to.</p>
</div>
</body>
</html>

View File

@@ -0,0 +1,30 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>We're sorry, but something went wrong (500)</title>
<style type="text/css">
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
div.dialog {
width: 25em;
padding: 0 4em;
margin: 4em auto 0 auto;
border: 1px solid #ccc;
border-right-color: #999;
border-bottom-color: #999;
}
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
</style>
</head>
<body>
<!-- This file lives in public/500.html -->
<div class="dialog">
<h1>We're sorry, but something went wrong.</h1>
<p>We've been notified about this issue and we'll take a look at it shortly.</p>
</div>
</body>
</html>

View File

@@ -0,0 +1,3 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../config/boot'
require 'commands/console'

View File

@@ -0,0 +1,3 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../config/boot'
require 'commands/generate'

View File

@@ -0,0 +1,6 @@
module CustomMacro
def custom_macro
end
end
Test::Unit::TestCase.extend(CustomMacro)

View File

@@ -0,0 +1,6 @@
module GemMacro
def gem_macro
end
end
Test::Unit::TestCase.extend(GemMacro)

View File

@@ -0,0 +1,6 @@
module PluginMacro
def plugin_macro
end
end
Test::Unit::TestCase.extend(PluginMacro)

View File

@@ -0,0 +1,207 @@
require 'test_helper'
begin
gem 'rspec'
gem 'rspec-rails'
rescue LoadError => exception
puts exception.message
puts "RSpec integration was not tested because RSpec is not available"
else
class RspecTest < Test::Unit::TestCase
SHOULDA_ROOT =
File.expand_path(File.join(File.dirname(__FILE__), '..')).freeze
def setup
build_gemspec
end
def teardown
FileUtils.rm_rf(project_dir)
FileUtils.rm_rf("#{shoulda_root}/pkg")
end
should "integrate correctly when using config.gem in test.rb" do
create_project
insert(rspec_dependencies, "config/environments/test.rb")
vendor_gems('test')
configure_spec_rails
assert_configured
end
should "integrate correctly when using config.gem in environment.rb" do
create_project
insert(rspec_dependencies,
"config/environment.rb",
/Rails::Initializer\.run/)
vendor_gems('development')
configure_spec_rails
assert_configured
end
should "integrate correctly when using require in spec_helper" do
create_project
configure_spec_rails
insert(%{gem 'shoulda'; require 'shoulda'},
"spec/spec_helper.rb",
%{require 'spec/rails'})
assert_configured
end
should "integrate correctly when unpacked and required in spec_helper" do
create_project
configure_spec_rails
insert(%{require 'shoulda'},
"spec/spec_helper.rb",
%{require 'spec/rails'})
unpack_gems
assert_configured
end
def create_project
command "rails #{project_dir}"
end
def vendor_gems(env)
project_command "rake gems:unpack RAILS_ENV=#{env}"
end
def unpack_gems
FileUtils.mkdir_p "#{project_dir}/vendor/gems"
FileUtils.cd "#{project_dir}/vendor/gems" do
%w(rspec rspec-rails shoulda).each do |gem|
command "gem unpack #{gem}"
end
end
insert('config.load_paths += Dir["#{RAILS_ROOT}/vendor/gems/*/lib"]',
"config/environment.rb",
/Rails::Initializer\.run/)
end
def command(command)
output = `GEM_PATH=#{shoulda_root}/pkg #{command} 2>&1`
unless $? == 0
flunk("Command failed with status #{$?}\n#{command}\n#{output}")
end
@command_output ||= ''
@command_output << output
output
end
def project_command(command)
result = nil
FileUtils.cd project_dir do
result = command(command)
end
result
end
def shoulda_command(command)
FileUtils.cd shoulda_root do
command(command)
end
end
def project_name
'example_rails_project'
end
def project_dir
File.expand_path(File.join(File.dirname(__FILE__), project_name))
end
def insert(content, path, after = nil)
path = File.join(project_dir, path)
contents = IO.read(path)
if after
contents.gsub!(/^(.*#{after}.*)$/, "\\1\n#{content}")
else
contents << "\n" << content
end
File.open(path, 'w') {|file| file.write(contents) }
end
def rspec_dependencies
return <<-EOS
config.gem 'rspec', :lib => 'spec'
config.gem 'rspec-rails', :lib => false
config.gem 'shoulda', :lib => 'shoulda'
EOS
end
def configure_spec_rails
project_command "script/generate rspec"
end
def assert_configured
create_model
migrate
create_controller
assert_spec_passes
end
def create_model
project_command "script/generate rspec_model person name:string"
insert "validates_presence_of :name",
"app/models/person.rb",
/class Person/
insert "it { should validate_presence_of(:name) }",
"spec/models/person_spec.rb",
/describe Person do/
end
def create_controller
project_command "script/generate rspec_controller people"
insert "def index; render :text => 'Hello'; end",
"app/controllers/people_controller.rb",
/class PeopleController/
shoulda_controller_example = <<-EOS
describe PeopleController, "on GET index" do
integrate_views
subject { controller }
before(:each) { get :index }
it { should respond_with(:success) }
end
EOS
insert shoulda_controller_example,
"spec/controllers/people_controller_spec.rb"
end
def migrate
project_command "rake db:migrate"
end
def assert_spec_passes
result = project_command("rake spec SPEC_OPTS=-fs")
assert_match /should require name to be set/, result
assert_match /should respond with 200/, result
end
def shoulda_root
SHOULDA_ROOT
end
def build_gemspec
backup_gemspec do
shoulda_command "rake gemspec"
shoulda_command "rake gem"
shoulda_command "gem install --no-ri --no-rdoc -i pkg pkg/shoulda*.gem"
end
end
def backup_gemspec
actual = "#{shoulda_root}/shoulda.gemspec"
backup = "#{shoulda_root}/backup.gemspec"
FileUtils.mv(actual, backup)
begin
yield
ensure
FileUtils.mv(backup, actual)
end
end
end
end

View File

@@ -0,0 +1,35 @@
require 'fileutils'
# Load the environment
ENV['RAILS_ENV'] = 'test'
rails_root = File.dirname(__FILE__) + '/rails_root'
require "#{rails_root}/config/environment.rb"
# Load the testing framework
require 'test_help'
silence_warnings { RAILS_ENV = ENV['RAILS_ENV'] }
# Run the migrations
ActiveRecord::Migration.verbose = false
ActiveRecord::Migrator.migrate("#{RAILS_ROOT}/db/migrate")
# Setup the fixtures path
Test::Unit::TestCase.fixture_path = File.join(File.dirname(__FILE__), "fixtures")
class Test::Unit::TestCase #:nodoc:
def create_fixtures(*table_names)
if block_given?
Fixtures.create_fixtures(Test::Unit::TestCase.fixture_path, table_names) { yield }
else
Fixtures.create_fixtures(Test::Unit::TestCase.fixture_path, table_names)
end
end
self.use_transactional_fixtures = false
self.use_instantiated_fixtures = false
end
require 'test/fail_macros'
require 'test/model_builder'

View File

@@ -0,0 +1,10 @@
require File.dirname(__FILE__) + '/../test_helper'
class AddressTest < Test::Unit::TestCase
fixtures :all
should_belong_to :addressable
should_validate_uniqueness_of :title, :scoped_to => [:addressable_id, :addressable_type]
should_ensure_length_at_least :zip, 5
should_only_allow_numeric_values_for :zip
end

View File

@@ -0,0 +1,10 @@
require File.dirname(__FILE__) + '/../test_helper'
class Pets::DogTest < Test::Unit::TestCase
should_belong_to :user
should_belong_to :address, :dependent => :destroy
should_have_many :treats
should_have_and_belong_to_many :fleas
should_require_attributes :treats, :fleas
should_validate_presence_of :owner_id
end

View File

@@ -0,0 +1,6 @@
require File.dirname(__FILE__) + '/../test_helper'
class FleaTest < Test::Unit::TestCase
should_have_and_belong_to_many :dogs
end

View File

@@ -0,0 +1,6 @@
require File.dirname(__FILE__) + '/../test_helper'
class FriendshipTest < ActiveSupport::TestCase
should_belong_to :user
should_belong_to :friend
end

View File

@@ -0,0 +1,19 @@
require File.dirname(__FILE__) + '/../test_helper'
class PostTest < Test::Unit::TestCase
fixtures :all
should_belong_to :user
should_belong_to :owner
should_have_many :tags, :through => :taggings
should_have_many :through_tags, :through => :taggings
should_require_unique_attributes :title
should_validate_presence_of :body, :message => /wtf/
should_validate_presence_of :title
should_validate_numericality_of :user_id
should_fail do
should_validate_uniqueness_of :title, :case_sensitive => false
end
end

View File

@@ -0,0 +1,27 @@
require File.dirname(__FILE__) + '/../test_helper'
class ProductTest < ActiveSupport::TestCase
context "An intangible product" do
setup do
@product = Product.new(:tangible => false)
end
should_validate_presence_of :title
should_not_allow_values_for :size, "22"
should_allow_values_for :size, "22kb"
should_ensure_value_in_range :price, 0..99
end
context "A tangible product" do
setup do
@product = Product.new(:tangible => true)
end
should_validate_presence_of :price
should_ensure_value_in_range :price, 1..9999
should_ensure_value_in_range :weight, 1..100
should_not_allow_values_for :size, "22", "10x15"
should_allow_values_for :size, "12x12x1"
should_ensure_length_in_range :size, 5..20
end
end

Some files were not shown because too many files have changed in this diff Show More