mirror of
https://github.com/thoughtbot/shoulda-matchers.git
synced 2022-11-09 12:01:38 -05:00
Extract examples in README to inline documentation
This commit is contained in:
parent
ed428417a3
commit
c22d7c89e0
73 changed files with 3577 additions and 1878 deletions
|
@ -13,26 +13,6 @@ require 'shoulda/matchers/action_controller/strong_parameters_matcher'
|
|||
|
||||
module Shoulda
|
||||
module Matchers
|
||||
# By using the matchers you can quickly and easily create concise and
|
||||
# easy to read test suites.
|
||||
#
|
||||
# This code segment:
|
||||
#
|
||||
# describe UsersController, 'on GET to show with a valid id' do
|
||||
# before(:each) do
|
||||
# get :show, id: User.first.to_param
|
||||
# end
|
||||
#
|
||||
# it { should respond_with(:success) }
|
||||
# it { should render_template(:show) }
|
||||
# it { should not_set_the_flash) }
|
||||
#
|
||||
# it 'does something else really cool' do
|
||||
# expect(assigns[:user].id).to eq 1
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# Would produce 5 tests for the show action
|
||||
module ActionController
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,67 +1,158 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActionController # :nodoc:
|
||||
# Ensure a controller uses a given before_filter
|
||||
module ActionController
|
||||
# The `use_before_filter` matcher is used to test that a before_filter
|
||||
# callback is defined within your controller.
|
||||
#
|
||||
# Example:
|
||||
# class UsersController < ApplicationController
|
||||
# before_filter :authenticate_user!
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe UsersController do
|
||||
# it { should use_before_filter(:authenticate_user!) }
|
||||
# it { should_not use_before_filter(:prevent_ssl) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class UsersControllerTest < ActionController::TestCase
|
||||
# should use_before_filter(:authenticate_user!)
|
||||
# should_not use_before_filter(:prevent_ssl)
|
||||
# end
|
||||
#
|
||||
# @return [CallbackMatcher]
|
||||
#
|
||||
# it { should use_before_filter(:authenticate_user!) }
|
||||
# it { should_not use_before_filter(:prevent_ssl) }
|
||||
def use_before_filter(callback)
|
||||
CallbackMatcher.new(callback, :before, :filter)
|
||||
end
|
||||
|
||||
# Ensure a controller uses a given before_filter
|
||||
# The `use_after_filter` matcher is used to test that an after_filter
|
||||
# callback is defined within your controller.
|
||||
#
|
||||
# Example:
|
||||
# class IssuesController < ApplicationController
|
||||
# after_filter :log_activity
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe IssuesController do
|
||||
# it { should use_after_filter(:log_activity) }
|
||||
# it { should_not use_after_filter(:destroy_user) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class IssuesControllerTest < ActionController::TestCase
|
||||
# should use_after_filter(:log_activity)
|
||||
# should_not use_after_filter(:destroy_user)
|
||||
# end
|
||||
#
|
||||
# @return [CallbackMatcher]
|
||||
#
|
||||
# it { should use_after_filter(:log_activity) }
|
||||
# it { should_not use_after_filter(:destroy_user) }
|
||||
def use_after_filter(callback)
|
||||
CallbackMatcher.new(callback, :after, :filter)
|
||||
end
|
||||
|
||||
# Ensure a controller uses a given before_action
|
||||
# The `use_before_action` matcher is used to test that a before_action
|
||||
# callback is defined within your controller.
|
||||
#
|
||||
# Example:
|
||||
# class UsersController < ApplicationController
|
||||
# before_action :authenticate_user!
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe UsersController do
|
||||
# it { should use_before_action(:authenticate_user!) }
|
||||
# it { should_not use_before_action(:prevent_ssl) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class UsersControllerTest < ActionController::TestCase
|
||||
# should use_before_action(:authenticate_user!)
|
||||
# should_not use_before_action(:prevent_ssl)
|
||||
# end
|
||||
#
|
||||
# @return [CallbackMatcher]
|
||||
#
|
||||
# it { should use_before_action(:authenticate_user!) }
|
||||
# it { should_not use_before_action(:prevent_ssl) }
|
||||
def use_before_action(callback)
|
||||
CallbackMatcher.new(callback, :before, :action)
|
||||
end
|
||||
|
||||
# Ensure a controller uses a given after_action
|
||||
# The `use_after_action` matcher is used to test that an after_action
|
||||
# callback is defined within your controller.
|
||||
#
|
||||
# Example:
|
||||
# class IssuesController < ApplicationController
|
||||
# after_action :log_activity
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe IssuesController do
|
||||
# it { should use_after_action(:log_activity) }
|
||||
# it { should_not use_after_action(:destroy_user) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class IssuesControllerTest < ActionController::TestCase
|
||||
# should use_after_action(:log_activity)
|
||||
# should_not use_after_action(:destroy_user)
|
||||
# end
|
||||
#
|
||||
# @return [CallbackMatcher]
|
||||
#
|
||||
# it { should use_after_action(:log_activity) }
|
||||
# it { should_not use_after_action(:destroy_user) }
|
||||
def use_after_action(callback)
|
||||
CallbackMatcher.new(callback, :after, :action)
|
||||
end
|
||||
|
||||
# Ensure a controller uses a given around_filter
|
||||
# The `use_around_filter` matcher is used to test that an around_filter
|
||||
# callback is defined within your controller.
|
||||
#
|
||||
# Example:
|
||||
# class ChangesController < ApplicationController
|
||||
# around_filter :wrap_in_transaction
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe ChangesController do
|
||||
# it { should use_around_filter(:wrap_in_transaction) }
|
||||
# it { should_not use_around_filter(:save_view_context) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class ChangesControllerTest < ActionController::TestCase
|
||||
# should use_around_filter(:wrap_in_transaction)
|
||||
# should_not use_around_filter(:save_view_context)
|
||||
# end
|
||||
#
|
||||
# @return [CallbackMatcher]
|
||||
#
|
||||
# it { should use_around_filter(:log_activity) }
|
||||
# it { should_not use_around_filter(:destroy_user) }
|
||||
def use_around_filter(callback)
|
||||
CallbackMatcher.new(callback, :around, :filter)
|
||||
end
|
||||
|
||||
# Ensure a controller uses a given around_action
|
||||
# The `use_around_action` matcher is used to test that an around_action
|
||||
# callback is defined within your controller.
|
||||
#
|
||||
# Example:
|
||||
# class ChangesController < ApplicationController
|
||||
# around_action :wrap_in_transaction
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe ChangesController do
|
||||
# it { should use_around_action(:wrap_in_transaction) }
|
||||
# it { should_not use_around_action(:save_view_context) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class ChangesControllerTest < ActionController::TestCase
|
||||
# should use_around_action(:wrap_in_transaction)
|
||||
# should_not use_around_action(:save_view_context)
|
||||
# end
|
||||
#
|
||||
# @return [CallbackMatcher]
|
||||
#
|
||||
# it { should use_around_action(:log_activity) }
|
||||
# it { should_not use_around_action(:destroy_user) }
|
||||
def use_around_action(callback)
|
||||
CallbackMatcher.new(callback, :around, :action)
|
||||
end
|
||||
|
||||
class CallbackMatcher # :nodoc:
|
||||
# @private
|
||||
class CallbackMatcher
|
||||
def initialize(method_name, kind, callback_type)
|
||||
@method_name = method_name
|
||||
@kind = kind
|
||||
|
|
|
@ -1,16 +1,32 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActionController # :nodoc:
|
||||
# Ensures that filter_parameter_logging is set for the specified key.
|
||||
module ActionController
|
||||
# The `filter_param` matcher is used to test parameter filtering
|
||||
# configuration. Specifically, it asserts that the given parameter is
|
||||
# present in `config.filter_parameters`.
|
||||
#
|
||||
# Example:
|
||||
# class MyApplication < Rails::Application
|
||||
# config.filter_parameters << :secret_key
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe ApplicationController do
|
||||
# it { should filter_param(:secret_key) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class ApplicationControllerTest < ActionController::TestCase
|
||||
# should filter_param(:secret_key)
|
||||
# end
|
||||
#
|
||||
# @return [FilterParamMatcher]
|
||||
#
|
||||
# it { should filter_param(:password) }
|
||||
def filter_param(key)
|
||||
FilterParamMatcher.new(key)
|
||||
end
|
||||
|
||||
class FilterParamMatcher # :nodoc:
|
||||
# @private
|
||||
class FilterParamMatcher
|
||||
def initialize(key)
|
||||
@key = key.to_s
|
||||
end
|
||||
|
|
|
@ -1,17 +1,46 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActionController # :nodoc:
|
||||
# Ensures a controller redirected to the given url.
|
||||
module ActionController
|
||||
# The `redirect_to` matcher tests that an action redirects to a certain
|
||||
# location. In a test suite using RSpec, it is very similar to
|
||||
# rspec-rails's `redirect_to` matcher. In a test suite using Test::Unit /
|
||||
# Shoulda, it provides a more expressive syntax over
|
||||
# `assert_redirected_to`.
|
||||
#
|
||||
# Example:
|
||||
# class PostsController < ApplicationController
|
||||
# def show
|
||||
# redirect_to :index
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe PostsController do
|
||||
# describe 'GET #show' do
|
||||
# before { get :show }
|
||||
#
|
||||
# it { should redirect_to(posts_path) }
|
||||
# it { should redirect_to(action: :index) }
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostsControllerTest < ActionController::TestCase
|
||||
# context 'GET #show' do
|
||||
# setup { get :show }
|
||||
#
|
||||
# should redirect_to { posts_path }
|
||||
# should redirect_to(action: :index)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# @return [RedirectToMatcher]
|
||||
#
|
||||
# it { should redirect_to('http://somewhere.com') }
|
||||
# it { should redirect_to(users_path) }
|
||||
def redirect_to(url_or_description, &block)
|
||||
RedirectToMatcher.new(url_or_description, self, &block)
|
||||
end
|
||||
|
||||
class RedirectToMatcher # :nodoc:
|
||||
# @private
|
||||
class RedirectToMatcher
|
||||
attr_reader :failure_message, :failure_message_when_negated
|
||||
|
||||
alias failure_message_for_should failure_message
|
||||
|
|
|
@ -1,25 +1,49 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActionController # :nodoc:
|
||||
# Ensures a controller rendered the given template.
|
||||
module ActionController
|
||||
# The `render_template` matcher tests that an action renders a template
|
||||
# or partial. In RSpec, it is very similar to rspec-rails's
|
||||
# `render_template` matcher. In Test::Unit, it provides a more expressive
|
||||
# syntax over `assert_template`.
|
||||
#
|
||||
# Example:
|
||||
# class PostsController < ApplicationController
|
||||
# def show
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# it { should render_template(:show) }
|
||||
# # app/views/posts/show.html.erb
|
||||
# <%= render 'sidebar' %>
|
||||
#
|
||||
# assert that the "_customer" partial was rendered
|
||||
# it { should render_template(partial: '_customer') }
|
||||
# # RSpec
|
||||
# describe PostsController do
|
||||
# describe 'GET #show' do
|
||||
# before { get :show }
|
||||
#
|
||||
# assert that the "_customer" partial was rendered twice
|
||||
# it { should render_template(partial: '_customer', count: 2) }
|
||||
# it { should render_template('show') }
|
||||
# it { should render_template(partial: 'sidebar') }
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostsControllerTest < ActionController::TestCase
|
||||
# context 'GET #show' do
|
||||
# setup { get :show }
|
||||
#
|
||||
# should render_template('show')
|
||||
# should render_template(partial: 'sidebar')
|
||||
# end
|
||||
# end
|
||||
#
|
||||
#
|
||||
#
|
||||
# @return [RenderTemplateMatcher]
|
||||
#
|
||||
# assert that no partials were rendered
|
||||
# it { should render_template(partial: false) }
|
||||
def render_template(options = {}, message = nil)
|
||||
RenderTemplateMatcher.new(options, message, self)
|
||||
end
|
||||
|
||||
class RenderTemplateMatcher # :nodoc:
|
||||
# @private
|
||||
class RenderTemplateMatcher
|
||||
attr_reader :failure_message, :failure_message_when_negated
|
||||
|
||||
alias failure_message_for_should failure_message
|
||||
|
|
|
@ -1,20 +1,68 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActionController # :nodoc:
|
||||
|
||||
# Ensures that the controller rendered with the given layout.
|
||||
module ActionController
|
||||
# The `render_with_layout` matcher asserts that an action is rendered with
|
||||
# a particular layout.
|
||||
#
|
||||
# Example:
|
||||
# class PostsController < ApplicationController
|
||||
# def show
|
||||
# render layout: 'posts'
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe PostsController do
|
||||
# describe 'GET #show' do
|
||||
# before { get :show }
|
||||
#
|
||||
# it { should render_with_layout('posts') }
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostsControllerTest < ActionController::TestCase
|
||||
# context 'GET #show' do
|
||||
# setup { get :show }
|
||||
#
|
||||
# should render_with_layout('posts')
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# It can also be used to assert that the action is not rendered with a
|
||||
# layout at all:
|
||||
#
|
||||
# class PostsController < ApplicationController
|
||||
# def sidebar
|
||||
# render layout: false
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe PostsController do
|
||||
# describe 'GET #sidebar' do
|
||||
# before { get :sidebar }
|
||||
#
|
||||
# it { should_not render_with_layout }
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostsControllerTest < ActionController::TestCase
|
||||
# context 'GET #sidebar' do
|
||||
# setup { get :sidebar }
|
||||
#
|
||||
# should_not render_with_layout
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# @return [RenderWithLayoutMatcher]
|
||||
#
|
||||
# it { should render_with_layout }
|
||||
# it { should render_with_layout(:special) }
|
||||
# it { should_not render_with_layout }
|
||||
def render_with_layout(expected_layout = nil)
|
||||
RenderWithLayoutMatcher.new(expected_layout).in_context(self)
|
||||
end
|
||||
|
||||
class RenderWithLayoutMatcher # :nodoc:
|
||||
|
||||
# @private
|
||||
class RenderWithLayoutMatcher
|
||||
def initialize(expected_layout)
|
||||
unless expected_layout.nil?
|
||||
@expected_layout = expected_layout.to_s
|
||||
|
|
|
@ -1,10 +1,41 @@
|
|||
module Shoulda
|
||||
module Matchers
|
||||
module ActionController
|
||||
# The `rescue_from` matcher tests usage of the `rescue_from` macro. It
|
||||
# asserts that an exception and method are present in the list of
|
||||
# exception handlers, and that the handler method exists.
|
||||
#
|
||||
# class ApplicationController < ActionController::Base
|
||||
# rescue_from ActiveRecord::RecordNotFound, with: :handle_not_found
|
||||
#
|
||||
# private
|
||||
#
|
||||
# def handle_not_found
|
||||
# # ...
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe ApplicationController do
|
||||
# it do
|
||||
# should rescue_from(ActiveRecord::RecordNotFound).
|
||||
# with(:handle_not_found)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class ApplicationControllerTest < ActionController::TestCase
|
||||
# should rescue_from(ActiveRecord::RecordNotFound).
|
||||
# with(:handle_not_found)
|
||||
# end
|
||||
#
|
||||
# @return [RescueFromMatcher]
|
||||
#
|
||||
def rescue_from(exception)
|
||||
RescueFromMatcher.new exception
|
||||
end
|
||||
|
||||
# @private
|
||||
class RescueFromMatcher
|
||||
def initialize(exception)
|
||||
@exception = exception
|
||||
|
|
|
@ -1,26 +1,95 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActionController # :nodoc:
|
||||
|
||||
# Ensures a controller responded with expected 'response' status code.
|
||||
module ActionController
|
||||
# The `respond_with` matcher tests that an action responds with a certain
|
||||
# status code.
|
||||
#
|
||||
# You can pass an explicit status number like 200, 301, 404, 500
|
||||
# or its symbolic equivalent :success, :redirect, :missing, :error.
|
||||
# See ActionController::StatusCodes for a full list.
|
||||
# You can specify that the status should be a number:
|
||||
#
|
||||
# Example:
|
||||
# class PostsController < ApplicationController
|
||||
# def index
|
||||
# render status: 403
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe PostsController do
|
||||
# describe 'GET #index' do
|
||||
# before { get :index }
|
||||
#
|
||||
# it { should respond_with(403) }
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostsControllerTest < ActionController::TestCase
|
||||
# context 'GET #index' do
|
||||
# setup { get :index }
|
||||
#
|
||||
# should respond_with(403)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# You can specify that the status should be within a range of numbers:
|
||||
#
|
||||
# class PostsController < ApplicationController
|
||||
# def destroy
|
||||
# render status: 508
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe PostsController do
|
||||
# describe 'DELETE #destroy' do
|
||||
# before { delete :destroy }
|
||||
#
|
||||
# it { should respond_with(500..600) }
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostsControllerTest < ActionController::TestCase
|
||||
# context 'DELETE #destroy' do
|
||||
# setup { delete :destroy }
|
||||
#
|
||||
# should respond_with(500..600)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# Finally, you can specify that the status should be a symbol:
|
||||
#
|
||||
# class PostsController < ApplicationController
|
||||
# def show
|
||||
# render status: :locked
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe PostsController do
|
||||
# describe 'GET #show' do
|
||||
# before { get :show }
|
||||
#
|
||||
# it { should respond_with(:locked) }
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostsControllerTest < ActionController::TestCase
|
||||
# context 'GET #show' do
|
||||
# setup { get :show }
|
||||
#
|
||||
# should respond_with(:locked)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# @return [RespondWithMatcher]
|
||||
#
|
||||
# it { should respond_with(:success) }
|
||||
# it { should respond_with(:redirect) }
|
||||
# it { should respond_with(:missing) }
|
||||
# it { should respond_with(:error) }
|
||||
# it { should respond_with(501) }
|
||||
def respond_with(status)
|
||||
RespondWithMatcher.new(status)
|
||||
end
|
||||
|
||||
class RespondWithMatcher # :nodoc:
|
||||
|
||||
# @private
|
||||
class RespondWithMatcher
|
||||
def initialize(status)
|
||||
@status = symbol_to_status_code(status)
|
||||
end
|
||||
|
|
|
@ -1,36 +1,92 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActionController # :nodoc:
|
||||
|
||||
# Ensures that requesting +path+ using +method+ routes to +options+.
|
||||
module ActionController
|
||||
# The `route` matcher tests that a route resolves to a controller,
|
||||
# action, and params; and that the controller, action, and params
|
||||
# generates the same route. For an RSpec suite, this is like using a
|
||||
# combination of `route_to` and `be_routable`. For a Test::Unit suite, it
|
||||
# provides a more expressive syntax over `assert_routing`.
|
||||
#
|
||||
# If you don't specify a controller, it will use the controller from the
|
||||
# example group.
|
||||
# You can use this matcher either in a controller test case or in a
|
||||
# routing test case. For instance, given these routes:
|
||||
#
|
||||
# +to_param+ is called on the +options+ given.
|
||||
# My::Application.routes.draw do
|
||||
# get '/posts', controller: 'posts', action: 'index'
|
||||
# get '/posts/:id' => 'posts#show'
|
||||
# end
|
||||
#
|
||||
# Examples:
|
||||
# You could choose to write tests for these routes alongside other tests
|
||||
# for PostsController:
|
||||
#
|
||||
# class PostsController < ApplicationController
|
||||
# # ...
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe PostsController do
|
||||
# it { should route(:get, '/posts').to(action: :index) }
|
||||
# it { should route(:get, '/posts/1').to(action: :show, id: 1) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostsControllerTest < ActionController::TestCase
|
||||
# should route(:get, '/posts').to(action: 'index')
|
||||
# should route(:get, '/posts/1').to(action: :show, id: 1)
|
||||
# end
|
||||
#
|
||||
# Or you could place the tests along with other route tests:
|
||||
#
|
||||
# # RSpec
|
||||
# describe 'Routing' do
|
||||
# it do
|
||||
# should route(:get, '/posts').
|
||||
# to(controller: :posts, action: :index)
|
||||
# end
|
||||
#
|
||||
# it do
|
||||
# should route(:get, '/posts/1').
|
||||
# to('posts#show', id: 1)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class RoutesTest < ActionController::IntegrationTest
|
||||
# should route(:get, '/posts').
|
||||
# to(controller: :posts, action: :index)
|
||||
#
|
||||
# should route(:get, '/posts/1').
|
||||
# to('posts#show', id: 1)
|
||||
# end
|
||||
#
|
||||
# Notice that in the former case, as we are inside of a test case for
|
||||
# PostsController, we do not have to specify that the routes resolve to
|
||||
# this controller. In the latter case we specify this using the
|
||||
# `controller` key passed to the `to` qualifier.
|
||||
#
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### to
|
||||
#
|
||||
# Use `to` to specify the action (along with the controller, if needed)
|
||||
# that the route resolves to.
|
||||
#
|
||||
# # Three ways of saying the same thing (using the example above)
|
||||
# route(:get, '/posts').to(action: index)
|
||||
# route(:get, '/posts').to(controller: :posts, action: index)
|
||||
# route(:get, '/posts').to('posts#index')
|
||||
#
|
||||
# If there are parameters in your route, then specify those too:
|
||||
#
|
||||
# route(:get, '/posts/1').to('posts#show', id: 1)
|
||||
#
|
||||
# @return [RouteMatcher]
|
||||
#
|
||||
# it { should route(:get, '/posts').
|
||||
# to(controller: :posts, action: :index) }
|
||||
# it { should route(:get, '/posts').to('posts#index') }
|
||||
# it { should route(:get, '/posts/new').to(action: :new) }
|
||||
# it { should route(:post, '/posts').to(action: :create) }
|
||||
# it { should route(:get, '/posts/1').to(action: :show, id: 1) }
|
||||
# it { should route(:get, '/posts/1').to('posts#show', id: 1) }
|
||||
# it { should route(:get, '/posts/1/edit').to(action: :edit, id: 1) }
|
||||
# it { should route(:put, '/posts/1').to(action: :update, id: 1) }
|
||||
# it { should route(:delete, '/posts/1').
|
||||
# to(action: :destroy, id: 1) }
|
||||
# it { should route(:get, '/users/1/posts/1').
|
||||
# to(action: :show, id: 1, user_id: 1) }
|
||||
# it { should route(:get, '/users/1/posts/1').
|
||||
# to('posts#show', id: 1, user_id: 1) }
|
||||
def route(method, path)
|
||||
RouteMatcher.new(method, path, self)
|
||||
end
|
||||
|
||||
class RouteMatcher # :nodoc:
|
||||
# @private
|
||||
class RouteMatcher
|
||||
def initialize(method, path, context)
|
||||
@method = method
|
||||
@path = path
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActionController # :nodoc:
|
||||
module ActionController
|
||||
# @private
|
||||
class RouteParams
|
||||
def initialize(args)
|
||||
@args = args
|
||||
|
|
|
@ -1,19 +1,76 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActionController # :nodoc:
|
||||
|
||||
# Ensures that a session key was set to the expected value.
|
||||
module ActionController
|
||||
# The `set_session` matcher is used to make assertions about the
|
||||
# `session` hash.
|
||||
#
|
||||
# Example:
|
||||
# class PostsController < ApplicationController
|
||||
# def show
|
||||
# session[:foo] = 'bar'
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe PostsController do
|
||||
# describe 'GET #show' do
|
||||
# before { get :show }
|
||||
#
|
||||
# it { should set_session(:foo) }
|
||||
# it { should_not set_session(:baz) }
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostsControllerTest < ActionController::TestCase
|
||||
# context 'GET #show' do
|
||||
# setup { get :show }
|
||||
#
|
||||
# should set_session(:foo)
|
||||
# should_not set_session(:baz)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### to
|
||||
#
|
||||
# Use `to` to assert that the key in the session hash was set to a
|
||||
# particular value.
|
||||
#
|
||||
# class PostsController < ApplicationController
|
||||
# def show
|
||||
# session[:foo] = 'bar'
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe PostsController do
|
||||
# describe 'GET #show' do
|
||||
# before { get :show }
|
||||
#
|
||||
# it { should set_session(:foo).to('bar') }
|
||||
# it { should_not set_session(:foo).to('something else') }
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostsControllerTest < ActionController::TestCase
|
||||
# context 'GET #show' do
|
||||
# setup { get :show }
|
||||
#
|
||||
# should set_session(:foo).to('bar')
|
||||
# should_not set_session(:foo).to('something else')
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# @return [SetSessionMatcher]
|
||||
#
|
||||
# it { should set_session(:message) }
|
||||
# it { should set_session(:user_id).to(@user.id) }
|
||||
# it { should_not set_session(:user_id) }
|
||||
def set_session(key)
|
||||
SetSessionMatcher.new(key)
|
||||
end
|
||||
|
||||
class SetSessionMatcher # :nodoc:
|
||||
# @private
|
||||
class SetSessionMatcher
|
||||
def initialize(key)
|
||||
@key = key.to_s
|
||||
end
|
||||
|
|
|
@ -1,23 +1,156 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActionController # :nodoc:
|
||||
|
||||
# Ensures that the flash contains the given value. Can be a String, a
|
||||
# Regexp, or nil (indicating that the flash should not be set).
|
||||
module ActionController
|
||||
# The `set_the_flash` matcher is used to make assertions about the
|
||||
# `flash` hash.
|
||||
#
|
||||
# Example:
|
||||
# class PostsController < ApplicationController
|
||||
# def index
|
||||
# flash[:foo] = 'A candy bar'
|
||||
# end
|
||||
#
|
||||
# def destroy
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe PostsController do
|
||||
# describe 'GET #index' do
|
||||
# before { get :index }
|
||||
#
|
||||
# it { should set_the_flash }
|
||||
# end
|
||||
#
|
||||
# describe 'DELETE #destroy' do
|
||||
# before { delete :destroy }
|
||||
#
|
||||
# it { should_not set_the_flash }
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostsControllerTest < ActionController::TestCase
|
||||
# context 'GET #index' do
|
||||
# setup { get :index }
|
||||
#
|
||||
# should set_the_flash
|
||||
# end
|
||||
#
|
||||
# context 'DELETE #destroy' do
|
||||
# setup { delete :destroy }
|
||||
#
|
||||
# should_not set_the_flash
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### []
|
||||
#
|
||||
# Use `[]` to narrow the scope of the matcher to a particular key.
|
||||
#
|
||||
# class PostsController < ApplicationController
|
||||
# def index
|
||||
# flash[:foo] = 'A candy bar'
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe PostsController do
|
||||
# describe 'GET #index' do
|
||||
# before { get :index }
|
||||
#
|
||||
# it { should set_the_flash[:foo] }
|
||||
# it { should_not set_the_flash[:bar] }
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostsControllerTest < ActionController::TestCase
|
||||
# context 'GET #index' do
|
||||
# setup { get :show }
|
||||
#
|
||||
# should set_the_flash[:foo]
|
||||
# should_not set_the_flash[:bar]
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# ##### to
|
||||
#
|
||||
# Use `to` to assert that some key was set to a particular value, or that
|
||||
# some key matches a particular regex.
|
||||
#
|
||||
# class PostsController < ApplicationController
|
||||
# def index
|
||||
# flash[:foo] = 'A candy bar'
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe PostsController do
|
||||
# describe 'GET #index' do
|
||||
# before { get :index }
|
||||
#
|
||||
# it { should set_the_flash.to('A candy bar') }
|
||||
# it { should set_the_flash.to(/bar/) }
|
||||
# it { should set_the_flash[:foo].to('bar') }
|
||||
# it { should_not set_the_flash[:foo].to('something else') }
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostsControllerTest < ActionController::TestCase
|
||||
# context 'GET #index' do
|
||||
# setup { get :show }
|
||||
#
|
||||
# should set_the_flash.to('A candy bar')
|
||||
# should set_the_flash.to(/bar/)
|
||||
# should set_the_flash[:foo].to('bar')
|
||||
# should_not set_the_flash[:foo].to('something else')
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# ##### now
|
||||
#
|
||||
# Use `now` to change the scope of the matcher to use the "now" hash
|
||||
# instead of the usual "future" hash.
|
||||
#
|
||||
# class PostsController < ApplicationController
|
||||
# def show
|
||||
# flash.now[:foo] = 'bar'
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe PostsController do
|
||||
# describe 'GET #show' do
|
||||
# before { get :show }
|
||||
#
|
||||
# it { should set_the_flash.now }
|
||||
# it { should set_the_flash[:foo].now }
|
||||
# it { should set_the_flash[:foo].to('bar').now }
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostsControllerTest < ActionController::TestCase
|
||||
# context 'GET #index' do
|
||||
# setup { get :show }
|
||||
#
|
||||
# should set_the_flash.now
|
||||
# should set_the_flash[:foo].now
|
||||
# should set_the_flash[:foo].to('bar').now
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# @return [SetTheFlashMatcher]
|
||||
#
|
||||
# it { should set_the_flash }
|
||||
# it { should set_the_flash.to('Thank you for placing this order.') }
|
||||
# it { should set_the_flash.to(/created/i) }
|
||||
# it { should set_the_flash[:alert].to('Password does not match') }
|
||||
# it { should set_the_flash.to(/logged in/i).now }
|
||||
# it { should_not set_the_flash }
|
||||
def set_the_flash
|
||||
SetTheFlashMatcher.new
|
||||
end
|
||||
|
||||
class SetTheFlashMatcher # :nodoc:
|
||||
# @private
|
||||
class SetTheFlashMatcher
|
||||
def initialize
|
||||
@options = {}
|
||||
end
|
||||
|
|
|
@ -10,10 +10,154 @@ require 'active_support/hash_with_indifferent_access'
|
|||
module Shoulda
|
||||
module Matchers
|
||||
module ActionController
|
||||
# The `permit` matcher tests that an action in your controller receives a
|
||||
# whitelist of parameters using Rails' Strong Parameters feature
|
||||
# (specifically that `permit` was called with the correct arguments).
|
||||
#
|
||||
# Here's an example:
|
||||
#
|
||||
# class UsersController < ApplicationController
|
||||
# def create
|
||||
# user = User.create(user_params)
|
||||
# # ...
|
||||
# end
|
||||
#
|
||||
# private
|
||||
#
|
||||
# def user_params
|
||||
# params.require(:user).permit(
|
||||
# :first_name,
|
||||
# :last_name,
|
||||
# :email,
|
||||
# :password
|
||||
# )
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe UsersController do
|
||||
# it do
|
||||
# should permit(:first_name, :last_name, :email, :password).
|
||||
# for(:create)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class UsersControllerTest < ActionController::TestCase
|
||||
# should permit(:first_name, :last_name, :email, :password).
|
||||
# for(:create)
|
||||
# end
|
||||
#
|
||||
# If your action requires query parameters in order to work, then you'll
|
||||
# need to supply them:
|
||||
#
|
||||
# class UsersController < ApplicationController
|
||||
# def update
|
||||
# user = User.find(params[:id])
|
||||
#
|
||||
# if user.update_attributes(user_params)
|
||||
# # ...
|
||||
# else
|
||||
# # ...
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# private
|
||||
#
|
||||
# def user_params
|
||||
# params.require(:user).permit(
|
||||
# :first_name,
|
||||
# :last_name,
|
||||
# :email,
|
||||
# :password
|
||||
# )
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe UsersController do
|
||||
# before do
|
||||
# create(:user, id: 1)
|
||||
# end
|
||||
#
|
||||
# it do
|
||||
# should permit(:first_name, :last_name, :email, :password).
|
||||
# for(:update, params: { id: 1 })
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class UsersControllerTest < ActionController::TestCase
|
||||
# setup do
|
||||
# create(:user, id: 1)
|
||||
# end
|
||||
#
|
||||
# should permit(:first_name, :last_name, :email, :password).
|
||||
# for(:update, params: { id: 1 })
|
||||
# end
|
||||
#
|
||||
# Finally, if you have an action that isn't one of the seven resourceful
|
||||
# actions, then you'll need to provide the HTTP verb that it responds to:
|
||||
#
|
||||
# Rails.application.routes.draw do
|
||||
# resources :users do
|
||||
# member do
|
||||
# put :toggle
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# class UsersController < ApplicationController
|
||||
# def toggle
|
||||
# user = User.find(params[:id])
|
||||
#
|
||||
# if user.update_attributes(user_params)
|
||||
# # ...
|
||||
# else
|
||||
# # ...
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# private
|
||||
#
|
||||
# def user_params
|
||||
# params.require(:user).permit(:activated)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe UsersController do
|
||||
# before do
|
||||
# create(:user, id: 1)
|
||||
# end
|
||||
#
|
||||
# it do
|
||||
# should permit(:activated).for(:toggle,
|
||||
# params: { id: 1 },
|
||||
# verb: :put
|
||||
# )
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class UsersControllerTest < ActionController::TestCase
|
||||
# setup do
|
||||
# create(:user, id: 1)
|
||||
# end
|
||||
#
|
||||
# should permit(:activated).for(:toggle,
|
||||
# params: { id: 1 },
|
||||
# verb: :put
|
||||
# )
|
||||
# end
|
||||
#
|
||||
# @return [StrongParametersMatcher]
|
||||
#
|
||||
def permit(*params)
|
||||
StrongParametersMatcher.new(params).in_context(self)
|
||||
end
|
||||
|
||||
# @private
|
||||
class StrongParametersMatcher
|
||||
attr_writer :stubbed_params
|
||||
|
||||
|
@ -114,12 +258,14 @@ module Shoulda
|
|||
expected_permitted_params.map(&:inspect).to_sentence
|
||||
end
|
||||
|
||||
# @private
|
||||
class ActionNotDefinedError < StandardError
|
||||
def message
|
||||
'You must specify the controller action using the #for method.'
|
||||
end
|
||||
end
|
||||
|
||||
# @private
|
||||
class VerbNotDefinedError < StandardError
|
||||
def message
|
||||
'You must specify an HTTP verb when using a non-RESTful action. For example: for(:authorize, verb: :post)'
|
||||
|
|
|
@ -22,33 +22,8 @@ require 'shoulda/matchers/active_model/allow_mass_assignment_of_matcher'
|
|||
require 'shoulda/matchers/active_model/errors'
|
||||
require 'shoulda/matchers/active_model/have_secure_password_matcher'
|
||||
|
||||
|
||||
module Shoulda
|
||||
module Matchers
|
||||
# = Matchers for your active record models
|
||||
#
|
||||
# These matchers will test most of the validations of ActiveModel::Validations.
|
||||
#
|
||||
# describe User do
|
||||
# it { should validate_presence_of(:name) }
|
||||
# it { should validate_presence_of(:phone_number) }
|
||||
# %w(abcd 1234).each do |value|
|
||||
# it { should_not allow_value(value).for(:phone_number) }
|
||||
# end
|
||||
# it { should allow_value('(123) 456-7890').for(:phone_number) }
|
||||
# it { should_not allow_mass_assignment_of(:password) }
|
||||
# it { should allow_value('Activated', 'Pending').for(:status).strict }
|
||||
# it { should_not allow_value('Amazing').for(:status).strict }
|
||||
# end
|
||||
#
|
||||
# These tests work with the following model:
|
||||
#
|
||||
# class User < ActiveRecord::Base
|
||||
# validates_presence_of :name
|
||||
# validates_presence_of :phone_number
|
||||
# validates_inclusion_of :status, in: %w(Activated Pending), strict: true
|
||||
# attr_accessible :name, :phone_number
|
||||
# end
|
||||
module ActiveModel
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,21 +1,78 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
|
||||
# Ensures that the attribute can be set on mass update.
|
||||
module ActiveModel
|
||||
# The `allow_mass_assignment_of` matcher tests usage of Rails 3's
|
||||
# `attr_accessible` and `attr_protected` macros, asserting that an
|
||||
# attribute in your model is contained in either the whitelist or
|
||||
# blacklist and thus can or cannot be set via mass assignment.
|
||||
#
|
||||
# it { should_not allow_mass_assignment_of(:password) }
|
||||
# it { should allow_mass_assignment_of(:first_name) }
|
||||
# class Post
|
||||
# include ActiveModel::Model
|
||||
# include ActiveModel::MassAssignmentSecurity
|
||||
# attr_accessor :title
|
||||
#
|
||||
# In Rails 3.1 you can check role as well:
|
||||
# attr_accessible :title
|
||||
# end
|
||||
#
|
||||
# it { should allow_mass_assignment_of(:first_name).as(:admin) }
|
||||
# class User
|
||||
# include ActiveModel::Model
|
||||
# include ActiveModel::MassAssignmentSecurity
|
||||
# attr_accessor :encrypted_password
|
||||
#
|
||||
# attr_protected :encrypted_password
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Post do
|
||||
# it { should allow_mass_assignment_of(:title) }
|
||||
# end
|
||||
#
|
||||
# describe User do
|
||||
# it { should_not allow_mass_assignment_of(:encrypted_password) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostTest < ActiveSupport::TestCase
|
||||
# should allow_mass_assignment_of(:title)
|
||||
# end
|
||||
#
|
||||
# class UserTest < ActiveSupport::TestCase
|
||||
# should_not allow_mass_assignment_of(:encrypted_password)
|
||||
# end
|
||||
#
|
||||
# #### Optional qualifiers
|
||||
#
|
||||
# ##### as
|
||||
#
|
||||
# Use `as` if your mass-assignment rules apply only under a certain role
|
||||
# *(Rails >= 3.1 only)*.
|
||||
#
|
||||
# class Post
|
||||
# include ActiveModel::Model
|
||||
# include ActiveModel::MassAssignmentSecurity
|
||||
# attr_accessor :title
|
||||
#
|
||||
# attr_accessible :title, as: :admin
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Post do
|
||||
# it { should allow_mass_assignment_of(:title).as(:admin) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostTest < ActiveSupport::TestCase
|
||||
# should allow_mass_assignment_of(:title).as(:admin)
|
||||
# end
|
||||
#
|
||||
# @return [AllowMassAssignmentOfMatcher]
|
||||
#
|
||||
def allow_mass_assignment_of(value)
|
||||
AllowMassAssignmentOfMatcher.new(value)
|
||||
end
|
||||
|
||||
class AllowMassAssignmentOfMatcher # :nodoc:
|
||||
# @private
|
||||
class AllowMassAssignmentOfMatcher
|
||||
attr_reader :failure_message, :failure_message_when_negated
|
||||
|
||||
alias failure_message_for_should failure_message
|
||||
|
|
|
@ -1,23 +1,164 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
|
||||
# Ensures that the attribute can be set to the given value or values. If
|
||||
# multiple values are given the match succeeds only if all given values
|
||||
# are allowed. Otherwise, the matcher fails at the first bad value in the
|
||||
# argument list (the remaining arguments are not processed then).
|
||||
module ActiveModel
|
||||
# The `allow_value` matcher is used to test that an attribute of a model
|
||||
# can or cannot be set to a particular value or values. It is most
|
||||
# commonly used in conjunction with the `validates_format_of` validation.
|
||||
#
|
||||
# Options:
|
||||
# * <tt>with_message</tt> - value the test expects to find in
|
||||
# <tt>errors.on(:attribute)</tt>. Regexp or string. If omitted,
|
||||
# the test looks for any errors in <tt>errors.on(:attribute)</tt>.
|
||||
# * <tt>strict</tt> - expects the model to raise an exception when the
|
||||
# validation fails rather than adding to the errors collection. Used for
|
||||
# testing `validates!` and the `strict: true` validation options.
|
||||
# #### should
|
||||
#
|
||||
# Example:
|
||||
# it { should_not allow_value('bad').for(:isbn) }
|
||||
# it { should allow_value('isbn 1 2345 6789 0').for(:isbn) }
|
||||
# In the positive form, `allow_value` asserts that an attribute can be
|
||||
# set to one or more values, succeeding if none of the values cause the
|
||||
# record to be invalid:
|
||||
#
|
||||
# class UserProfile
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :website_url
|
||||
#
|
||||
# validates_format_of :website_url, with: URI.regexp
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe UserProfile do
|
||||
# it do
|
||||
# should allow_value('http://foo.com', 'http://bar.com/baz').
|
||||
# for(:website_url)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class UserProfileTest < ActiveSupport::TestCase
|
||||
# should allow_value('http://foo.com', 'http://bar.com/baz').
|
||||
# for(:website_url)
|
||||
# end
|
||||
#
|
||||
# #### should_not
|
||||
#
|
||||
# In the negative form, `allow_value` asserts that an attribute cannot be
|
||||
# set to one or more values, succeeding if the *first* value causes the
|
||||
# record to be invalid.
|
||||
#
|
||||
# **This can be surprising** so in this case if you need to check that
|
||||
# *all* of the values are invalid, use separate assertions:
|
||||
#
|
||||
# class UserProfile
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :website_url
|
||||
#
|
||||
# validates_format_of :website_url, with: URI.regexp
|
||||
# end
|
||||
#
|
||||
# describe UserProfile do
|
||||
# # One assertion: 'buz' and 'bar' will not be tested
|
||||
# it { should_not allow_value('fiz', 'buz', 'bar').for(:website_url) }
|
||||
#
|
||||
# # Three assertions, all tested separately
|
||||
# it { should_not allow_value('fiz').for(:website_url) }
|
||||
# it { should_not allow_value('buz').for(:website_url) }
|
||||
# it { should_not allow_value('bar').for(:website_url) }
|
||||
# end
|
||||
#
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### on
|
||||
#
|
||||
# Use `on` if your validation applies only under a certain context.
|
||||
#
|
||||
# class UserProfile
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :birthday_as_string
|
||||
#
|
||||
# validates_format_of :birthday_as_string,
|
||||
# with: /^(\d+)-(\d+)-(\d+)$/,
|
||||
# on: :create
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe UserProfile do
|
||||
# it do
|
||||
# should allow_value('2013-01-01').
|
||||
# for(:birthday_as_string).
|
||||
# on(:create)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class UserProfileTest < ActiveSupport::TestCase
|
||||
# should allow_value('2013-01-01').
|
||||
# for(:birthday_as_string).
|
||||
# on(:create)
|
||||
# end
|
||||
#
|
||||
# ##### with_message
|
||||
#
|
||||
# Use `with_message` if you are using a custom validation message.
|
||||
#
|
||||
# class UserProfile
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :state
|
||||
#
|
||||
# validates_format_of :state,
|
||||
# with: /^(open|closed)$/,
|
||||
# message: 'State must be open or closed'
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe UserProfile do
|
||||
# it do
|
||||
# should allow_value('open', 'closed').
|
||||
# for(:state).
|
||||
# with_message('State must be open or closed')
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class UserProfileTest < ActiveSupport::TestCase
|
||||
# should allow_value('open', 'closed').
|
||||
# for(:state).
|
||||
# with_message('State must be open or closed')
|
||||
# end
|
||||
#
|
||||
# Use `with_message` with the `:against` option if the attribute the
|
||||
# validation message is stored under is different from the attribute
|
||||
# being validated.
|
||||
#
|
||||
# class UserProfile
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :sports_team
|
||||
#
|
||||
# validate :sports_team_must_be_valid
|
||||
#
|
||||
# private
|
||||
#
|
||||
# def sports_team_must_be_valid
|
||||
# if sports_team !~ /^(Broncos|Titans)$/i
|
||||
# self.errors.add :chosen_sports_team,
|
||||
# 'Must be either a Broncos fan or a Titans fan'
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe UserProfile do
|
||||
# it do
|
||||
# should allow_value('Broncos', 'Titans').
|
||||
# for(:sports_team).
|
||||
# with_message('Must be either a Broncos or Titans fan',
|
||||
# against: :chosen_sports_team
|
||||
# )
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class UserProfileTest < ActiveSupport::TestCase
|
||||
# should allow_value('Broncos', 'Titans').
|
||||
# for(:sports_team).
|
||||
# with_message('Must be either a Broncos or Titans fan',
|
||||
# against: :chosen_sports_team
|
||||
# )
|
||||
# end
|
||||
#
|
||||
# @return [AllowValueMatcher]
|
||||
#
|
||||
def allow_value(*values)
|
||||
if values.empty?
|
||||
|
@ -27,7 +168,8 @@ module Shoulda # :nodoc:
|
|||
end
|
||||
end
|
||||
|
||||
class AllowValueMatcher # :nodoc:
|
||||
# @private
|
||||
class AllowValueMatcher
|
||||
include Helpers
|
||||
|
||||
attr_accessor :attribute_with_message
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
require 'forwardable'
|
||||
|
||||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
class DisallowValueMatcher # :nodoc:
|
||||
module ActiveModel
|
||||
# @private
|
||||
class DisallowValueMatcher
|
||||
extend Forwardable
|
||||
|
||||
def_delegators :allow_matcher, :_after_setting_value
|
||||
|
||||
def initialize(value)
|
||||
@allow_matcher = AllowValueMatcher.new(value)
|
||||
end
|
||||
|
|
|
@ -1,24 +1,96 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
|
||||
# Ensure that the attribute's value is not in the range specified
|
||||
module ActiveModel
|
||||
# The `ensure_exclusion_of` matcher tests usage of the
|
||||
# `validates_exclusion_of` validation, asserting that an attribute cannot
|
||||
# take a blacklist of values, and inversely, can take values outside of
|
||||
# this list.
|
||||
#
|
||||
# Options:
|
||||
# * <tt>in_array</tt> - the array of not allowed values for this attribute
|
||||
# * <tt>in_range</tt> - the range of not allowed values for this attribute
|
||||
# * <tt>with_message</tt> - value the test expects to find in
|
||||
# <tt>errors.on(:attribute)</tt>. Regexp or string. Defaults to the
|
||||
# translation for :exclusion.
|
||||
# If your blacklist is an array of values, use `in_array`:
|
||||
#
|
||||
# Example:
|
||||
# it { should ensure_exclusion_of(:age).in_range(30..60) }
|
||||
# class Game
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :supported_os
|
||||
#
|
||||
# validates_exclusion_of :supported_os, in: ['Mac', 'Linux']
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Game do
|
||||
# it do
|
||||
# should ensure_exclusion_of(:supported_os).
|
||||
# in_array(['Mac', 'Linux'])
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class GameTest < ActiveSupport::TestCase
|
||||
# should ensure_exclusion_of(:supported_os).
|
||||
# in_array(['Mac', 'Linux'])
|
||||
# end
|
||||
#
|
||||
# If your blacklist is a range of values, use `in_rnage`:
|
||||
#
|
||||
# class Game
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :supported_os
|
||||
#
|
||||
# validates_exclusion_of :supported_os, in: ['Mac', 'Linux']
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Game do
|
||||
# it do
|
||||
# should ensure_exclusion_of(:floors_with_enemies).
|
||||
# in_range(5..8)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class GameTest < ActiveSupport::TestCase
|
||||
# should ensure_exclusion_of(:floors_with_enemies).
|
||||
# in_range(5..8)
|
||||
# end
|
||||
#
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### with_message
|
||||
#
|
||||
# Use `with_message` if you are using a custom validation message.
|
||||
#
|
||||
# class Game
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :weapon
|
||||
#
|
||||
# validates_exclusion_of :weapon,
|
||||
# in: ['pistol', 'paintball gun', 'stick'],
|
||||
# message: 'You chose a puny weapon'
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Game do
|
||||
# it do
|
||||
# should ensure_exclusion_of(:weapon).
|
||||
# in_array(['pistol', 'paintball gun', 'stick']).
|
||||
# with_message('You chose a puny weapon')
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class GameTest < ActiveSupport::TestCase
|
||||
# should ensure_exclusion_of(:weapon).
|
||||
# in_array(['pistol', 'paintball gun', 'stick']).
|
||||
# with_message('You chose a puny weapon')
|
||||
# end
|
||||
#
|
||||
# @return [EnsureExclusionOfMatcher]
|
||||
#
|
||||
def ensure_exclusion_of(attr)
|
||||
EnsureExclusionOfMatcher.new(attr)
|
||||
end
|
||||
|
||||
class EnsureExclusionOfMatcher < ValidationMatcher # :nodoc:
|
||||
# @private
|
||||
class EnsureExclusionOfMatcher < ValidationMatcher
|
||||
def in_array(array)
|
||||
@array = array
|
||||
self
|
||||
|
|
|
@ -1,29 +1,225 @@
|
|||
require 'bigdecimal'
|
||||
|
||||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
|
||||
# Ensure that the attribute's value is in the range specified
|
||||
module ActiveModel
|
||||
# The `ensure_inclusion_of` matcher tests usage of the
|
||||
# `validates_inclusion_of` validation, asserting that an attribute can
|
||||
# take a whitelist of values and cannot take values outside of this list.
|
||||
#
|
||||
# Options:
|
||||
# * <tt>in_array</tt> - the array of allowed values for this attribute
|
||||
# * <tt>in_range</tt> - the range of allowed values for this attribute
|
||||
# * <tt>with_low_message</tt> - value the test expects to find in
|
||||
# <tt>errors.on(:attribute)</tt>. Regexp or string. Defaults to the
|
||||
# translation for :inclusion.
|
||||
# * <tt>with_high_message</tt> - value the test expects to find in
|
||||
# <tt>errors.on(:attribute)</tt>. Regexp or string. Defaults to the
|
||||
# translation for :inclusion.
|
||||
# If your whitelist is an array of values, use `in_array`:
|
||||
#
|
||||
# Example:
|
||||
# it { should ensure_inclusion_of(:age).in_range(0..100) }
|
||||
# class Issue
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :state
|
||||
#
|
||||
# validates_inclusion_of :state, in: %w(open resolved unresolved)
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Issue do
|
||||
# it do
|
||||
# should ensure_inclusion_of(:state).
|
||||
# in_array(%w(open resolved unresolved))
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class IssueTest < ActiveSupport::TestCase
|
||||
# should ensure_inclusion_of(:state).
|
||||
# in_array(%w(open resolved unresolved))
|
||||
# end
|
||||
#
|
||||
# If your whitelist is a range of values, use `in_range`:
|
||||
#
|
||||
# class Issue
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :priority
|
||||
#
|
||||
# validates_inclusion_of :priority, in: 1..5
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Issue do
|
||||
# it { should ensure_inclusion_of(:state).in_range(1..5) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class IssueTest < ActiveSupport::TestCase
|
||||
# should ensure_inclusion_of(:state).in_range(1..5)
|
||||
# end
|
||||
#
|
||||
# #### Optional qualifiers
|
||||
#
|
||||
# ##### with_message
|
||||
#
|
||||
# Use `with_message` if you are using a custom validation message.
|
||||
#
|
||||
# class Issue
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :severity
|
||||
#
|
||||
# validates_inclusion_of :severity,
|
||||
# in: %w(low medium high),
|
||||
# message: 'Severity must be low, medium, or high'
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Issue do
|
||||
# it do
|
||||
# should ensure_inclusion_of(:severity).
|
||||
# in_array(%w(low medium high)).
|
||||
# with_message('Severity must be low, medium, or high')
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class IssueTest < ActiveSupport::TestCase
|
||||
# should ensure_inclusion_of(:severity).
|
||||
# in_array(%w(low medium high)).
|
||||
# with_message('Severity must be low, medium, or high')
|
||||
# end
|
||||
#
|
||||
# ##### with_low_message
|
||||
#
|
||||
# Use `with_low_message` if you have a custom validation message for when
|
||||
# a given value is too low.
|
||||
#
|
||||
# class Person
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :age
|
||||
#
|
||||
# validate :age_must_be_valid
|
||||
#
|
||||
# private
|
||||
#
|
||||
# def age_must_be_valid
|
||||
# if age < 65
|
||||
# self.errors.add :age, 'You do not receive any benefits'
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it do
|
||||
# should ensure_inclusion_of(:age).
|
||||
# in_range(0..65).
|
||||
# with_low_message('You do not receive any benefits')
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should ensure_inclusion_of(:age).
|
||||
# in_range(0..65).
|
||||
# with_low_message('You do not receive any benefits')
|
||||
# end
|
||||
#
|
||||
# ##### with_high_message
|
||||
#
|
||||
# Use `with_high_message` if you have a custom validation message for
|
||||
# when a given value is too high.
|
||||
#
|
||||
# class Person
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :age
|
||||
#
|
||||
# validate :age_must_be_valid
|
||||
#
|
||||
# private
|
||||
#
|
||||
# def age_must_be_valid
|
||||
# if age > 21
|
||||
# self.errors.add :age, "You're too old for this stuff"
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it do
|
||||
# should ensure_inclusion_of(:age).
|
||||
# in_range(0..21).
|
||||
# with_high_message("You're too old for this stuff")
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should ensure_inclusion_of(:age).
|
||||
# in_range(0..21).
|
||||
# with_high_message("You're too old for this stuff")
|
||||
# end
|
||||
#
|
||||
# ##### allow_nil
|
||||
#
|
||||
# Use `allow_nil` to assert that the attribute allows nil.
|
||||
#
|
||||
# class Issue
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :state
|
||||
#
|
||||
# validates_presence_of :state
|
||||
# validates_inclusion_of :state,
|
||||
# in: %w(open resolved unresolved),
|
||||
# allow_nil: true
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Issue do
|
||||
# it do
|
||||
# should ensure_inclusion_of(:state).
|
||||
# in_array(%w(open resolved unresolved)).
|
||||
# allow_nil
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class IssueTest < ActiveSupport::TestCase
|
||||
# should ensure_inclusion_of(:state).
|
||||
# in_array(%w(open resolved unresolved)).
|
||||
# allow_nil
|
||||
# end
|
||||
#
|
||||
# ##### allow_blank
|
||||
#
|
||||
# Use `allow_blank` to assert that the attribute allows blank.
|
||||
#
|
||||
# class Issue
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :state
|
||||
#
|
||||
# validates_presence_of :state
|
||||
# validates_inclusion_of :state,
|
||||
# in: %w(open resolved unresolved),
|
||||
# allow_blank: true
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Issue do
|
||||
# it do
|
||||
# should ensure_inclusion_of(:state).
|
||||
# in_array(%w(open resolved unresolved)).
|
||||
# allow_blank
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class IssueTest < ActiveSupport::TestCase
|
||||
# should ensure_inclusion_of(:state).
|
||||
# in_array(%w(open resolved unresolved)).
|
||||
# allow_blank
|
||||
# end
|
||||
#
|
||||
# @return [EnsureInclusionOfMatcher]
|
||||
#
|
||||
def ensure_inclusion_of(attr)
|
||||
EnsureInclusionOfMatcher.new(attr)
|
||||
end
|
||||
|
||||
class EnsureInclusionOfMatcher < ValidationMatcher # :nodoc:
|
||||
# @private
|
||||
class EnsureInclusionOfMatcher < ValidationMatcher
|
||||
ARBITRARY_OUTSIDE_STRING = 'shouldamatchersteststring'
|
||||
ARBITRARY_OUTSIDE_FIXNUM = 123456789
|
||||
ARBITRARY_OUTSIDE_DECIMAL = BigDecimal.new('0.123456789')
|
||||
|
|
|
@ -1,40 +1,204 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
|
||||
# Ensures that the length of the attribute is validated. Only works with
|
||||
# string/text columns because it uses a string to check length.
|
||||
module ActiveModel
|
||||
# The `ensure_length_of` matcher tests usage of the `validates_length_of`
|
||||
# matcher. Note that this matcher is intended to be used against string
|
||||
# columns and not integer columns.
|
||||
#
|
||||
# Options:
|
||||
# * <tt>is_at_least</tt> - minimum length of this attribute
|
||||
# * <tt>is_at_most</tt> - maximum length of this attribute
|
||||
# * <tt>is_equal_to</tt> - exact requred length of this attribute
|
||||
# * <tt>with_short_message</tt> - value the test expects to find in
|
||||
# <tt>errors.on(:attribute)</tt>. Regexp or string. Defaults to the
|
||||
# translation for :too_short.
|
||||
# * <tt>with_long_message</tt> - value the test expects to find in
|
||||
# <tt>errors.on(:attribute)</tt>. Regexp or string. Defaults to the
|
||||
# translation for :too_long.
|
||||
# * <tt>with_message</tt> - value the test expects to find in
|
||||
# <tt>errors.on(:attribute)</tt>. Regexp or string. Defaults to the
|
||||
# translation for :wrong_length. Used in conjunction with
|
||||
# <tt>is_equal_to</tt>.
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### is_at_least
|
||||
#
|
||||
# Use `is_at_least` to test usage of the `:minimum` option. This asserts
|
||||
# that the attribute can take a string which is equal to or longer than
|
||||
# the given length and cannot take a string which is shorter.
|
||||
#
|
||||
# class User
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :bio
|
||||
#
|
||||
# validates_length_of :bio, minimum: 15
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
#
|
||||
# describe User do
|
||||
# it { should ensure_length_of(:bio).is_at_least(15) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
#
|
||||
# class UserTest < ActiveSupport::TestCase
|
||||
# should ensure_length_of(:bio).is_at_least(15)
|
||||
# end
|
||||
#
|
||||
# ##### is_at_most
|
||||
#
|
||||
# Use `is_at_most` to test usage of the `:maximum` option. This asserts
|
||||
# that the attribute can take a string which is equal to or shorter than
|
||||
# the given length and cannot take a string which is longer.
|
||||
#
|
||||
# class User
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :status_update
|
||||
#
|
||||
# validates_length_of :status_update, maximum: 140
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe User do
|
||||
# it { should ensure_length_of(:status_update).is_at_most(140) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class UserTest < ActiveSupport::TestCase
|
||||
# should ensure_length_of(:status_update).is_at_most(140)
|
||||
# end
|
||||
#
|
||||
# ##### is_equal_to
|
||||
#
|
||||
# Use `is_at_equal` to test usage of the `:is` option. This asserts that
|
||||
# the attribute can take a string which is exactly equal to the given
|
||||
# length and cannot take a string which is shorter or longer.
|
||||
#
|
||||
# class User
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :favorite_superhero
|
||||
#
|
||||
# validates_length_of :favorite_superhero, is: 6
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe User do
|
||||
# it { should ensure_length_of(:favorite_superhero).is_equal_to(6) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class UserTest < ActiveSupport::TestCase
|
||||
# should ensure_length_of(:favorite_superhero).is_equal_to(6)
|
||||
# end
|
||||
#
|
||||
# ##### is_at_least + is_at_most
|
||||
#
|
||||
# Use `is_at_least` and `is_at_most` together to test usage of the `:in`
|
||||
# option.
|
||||
#
|
||||
# class User
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :password
|
||||
#
|
||||
# validates_length_of :password, in: 5..30
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe User do
|
||||
# it do
|
||||
# should ensure_length_of(:password).
|
||||
# is_at_least(5).is_at_most(30)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class UserTest < ActiveSupport::TestCase
|
||||
# should ensure_length_of(:password).
|
||||
# is_at_least(5).is_at_most(30)
|
||||
# end
|
||||
#
|
||||
# ##### with_message
|
||||
#
|
||||
# Use `with_message` if you are using a custom validation message.
|
||||
#
|
||||
# class User
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :api_token
|
||||
#
|
||||
# validates_length_of :api_token,
|
||||
# minimum: 10,
|
||||
# message: "Password isn't long enough"
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe User do
|
||||
# it do
|
||||
# should ensure_length_of(:password).
|
||||
# is_at_least(10).
|
||||
# with_message("Password isn't long enough")
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class UserTest < ActiveSupport::TestCase
|
||||
# should ensure_length_of(:password).
|
||||
# is_at_least(10).
|
||||
# with_message("Password isn't long enough")
|
||||
# end
|
||||
#
|
||||
# ##### with_short_message
|
||||
#
|
||||
# Use `with_short_message` if you are using a custom "too short" message.
|
||||
#
|
||||
# class User
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :secret_key
|
||||
#
|
||||
# validates_length_of :secret_key,
|
||||
# in: 15..100,
|
||||
# too_short: 'Secret key must be more than 15 characters'
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe User do
|
||||
# it do
|
||||
# should ensure_length_of(:secret_key).
|
||||
# is_at_least(15).
|
||||
# with_short_message('Secret key must be more than 15 characters')
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class UserTest < ActiveSupport::TestCase
|
||||
# should ensure_length_of(:secret_key).
|
||||
# is_at_least(15).
|
||||
# with_short_message('Secret key must be more than 15 characters')
|
||||
# end
|
||||
#
|
||||
# ##### with_long_message
|
||||
#
|
||||
# Use `with_long_message` if you are using a custom "too long" message.
|
||||
#
|
||||
# class User
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :secret_key
|
||||
#
|
||||
# validates_length_of :secret_key,
|
||||
# in: 15..100,
|
||||
# too_long: 'Secret key must be less than 100 characters'
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe User do
|
||||
# it do
|
||||
# should ensure_length_of(:secret_key).
|
||||
# is_at_most(100).
|
||||
# with_long_message('Secret key must be less than 100 characters')
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class UserTest < ActiveSupport::TestCase
|
||||
# should ensure_length_of(:secret_key).
|
||||
# is_at_most(100).
|
||||
# with_long_message('Secret key must be less than 100 characters')
|
||||
# end
|
||||
#
|
||||
# @return [EnsureLengthOfMatcher]
|
||||
#
|
||||
# Examples:
|
||||
# it { should ensure_length_of(:password).
|
||||
# is_at_least(6).
|
||||
# is_at_most(20) }
|
||||
# it { should ensure_length_of(:name).
|
||||
# is_at_least(3).
|
||||
# with_short_message(/not long enough/) }
|
||||
# it { should ensure_length_of(:ssn).
|
||||
# is_equal_to(9).
|
||||
# with_message(/is invalid/) }
|
||||
def ensure_length_of(attr)
|
||||
EnsureLengthOfMatcher.new(attr)
|
||||
end
|
||||
|
||||
class EnsureLengthOfMatcher < ValidationMatcher # :nodoc:
|
||||
# @private
|
||||
class EnsureLengthOfMatcher < ValidationMatcher
|
||||
include Helpers
|
||||
|
||||
def initialize(attribute)
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
module ActiveModel
|
||||
# @private
|
||||
class CouldNotDetermineValueOutsideOfArray < RuntimeError; end
|
||||
|
||||
# @private
|
||||
class NonNullableBooleanError < Shoulda::Matchers::Error
|
||||
def self.create(attribute)
|
||||
super(attribute: attribute)
|
||||
|
@ -19,6 +21,7 @@ Hence, this test will fail and there is no way to make it pass.
|
|||
end
|
||||
end
|
||||
|
||||
# @private
|
||||
class CouldNotSetPasswordError < Shoulda::Matchers::Error
|
||||
def self.create(model)
|
||||
super(model: model)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel
|
||||
# Finds message information from exceptions thrown by #valid?
|
||||
# @private
|
||||
class ExceptionMessageFinder
|
||||
def initialize(instance, attribute, context=nil)
|
||||
@instance = instance
|
||||
|
|
|
@ -1,16 +1,37 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
|
||||
# Ensures that the model exhibits behavior added by has_secure_password.
|
||||
module ActiveModel
|
||||
# The `have_secure_password` matcher tests usage of the
|
||||
# `has_secure_password` macro.
|
||||
#
|
||||
# #### Example
|
||||
#
|
||||
# class User
|
||||
# include ActiveModel::Model
|
||||
# include ActiveModel::SecurePassword
|
||||
# attr_accessor :password
|
||||
#
|
||||
# has_secure_password
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe User do
|
||||
# it { should have_secure_password }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class UserTest < ActiveSupport::TestCase
|
||||
# should have_secure_password
|
||||
# end
|
||||
#
|
||||
# @return [HaveSecurePasswordMatcher]
|
||||
#
|
||||
# Example:
|
||||
# it { should have_secure_password }
|
||||
def have_secure_password
|
||||
HaveSecurePasswordMatcher.new
|
||||
end
|
||||
|
||||
class HaveSecurePasswordMatcher # :nodoc:
|
||||
# @private
|
||||
class HaveSecurePasswordMatcher
|
||||
attr_reader :failure_message
|
||||
|
||||
alias failure_message_for_should failure_message
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
module ActiveModel
|
||||
# @private
|
||||
module Helpers
|
||||
def pretty_error_messages(obj) # :nodoc:
|
||||
def pretty_error_messages(obj)
|
||||
obj.errors.map do |attribute, model|
|
||||
msg = "#{attribute} #{model}"
|
||||
if attribute.to_sym != :base && obj.respond_to?(attribute)
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel
|
||||
# @private
|
||||
module NumericalityMatchers
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,11 +1,8 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
module ActiveModel
|
||||
module NumericalityMatchers
|
||||
# Examples:
|
||||
# it { should validate_numericality_of(:attr).
|
||||
# is_greater_than(6).
|
||||
# less_than(20)...(and so on) }
|
||||
# @private
|
||||
class ComparisonMatcher < ValidationMatcher
|
||||
ERROR_MESSAGES = {
|
||||
:> => :greater_than,
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
module ActiveModel
|
||||
module NumericalityMatchers
|
||||
class EvenNumberMatcher < NumericTypeMatcher # :nodoc:
|
||||
# @private
|
||||
class EvenNumberMatcher < NumericTypeMatcher
|
||||
NON_EVEN_NUMBER_VALUE = 1
|
||||
|
||||
def initialize(attribute, options = {})
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
module ActiveModel
|
||||
module NumericalityMatchers
|
||||
# @private
|
||||
class NumericTypeMatcher
|
||||
def initialize
|
||||
raise NotImplementedError
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
module ActiveModel
|
||||
module NumericalityMatchers
|
||||
class OddNumberMatcher < NumericTypeMatcher # :nodoc:
|
||||
# @private
|
||||
class OddNumberMatcher < NumericTypeMatcher
|
||||
NON_ODD_NUMBER_VALUE = 2
|
||||
|
||||
def initialize(attribute, options = {})
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
module ActiveModel
|
||||
module NumericalityMatchers
|
||||
class OnlyIntegerMatcher < NumericTypeMatcher # :nodoc:
|
||||
# @private
|
||||
class OnlyIntegerMatcher
|
||||
NON_INTEGER_VALUE = 0.1
|
||||
def initialize(attribute)
|
||||
@attribute = attribute
|
||||
|
|
|
@ -1,24 +1,62 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
|
||||
# Ensures that the model is not valid if the given attribute is present.
|
||||
module ActiveModel
|
||||
# The `validate_absence_of` matcher tests the usage of the
|
||||
# `validates_absence_of` validation.
|
||||
#
|
||||
# Options:
|
||||
# * <tt>with_message</tt> - value the test expects to find in
|
||||
# <tt>errors.on(:attribute)</tt>. <tt>Regexp</tt> or <tt>String</tt>.
|
||||
# Defaults to the translation for <tt>:present</tt>.
|
||||
# class Artillery
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :arms
|
||||
#
|
||||
# validates_absence_of :arms
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Artillery do
|
||||
# it { should validate_absence_of(:arms) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class ArtilleryTest < ActiveSupport::TestCase
|
||||
# should validate_absence_of(:arms)
|
||||
# end
|
||||
#
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### with_message
|
||||
#
|
||||
# Use `with_message` if you are using a custom validation message.
|
||||
#
|
||||
# class Artillery
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :arms
|
||||
#
|
||||
# validates_absence_of :arms,
|
||||
# message: "We're fresh outta arms here, soldier!"
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Artillery do
|
||||
# it do
|
||||
# should validate_absence_of(:arms).
|
||||
# with_message("We're fresh outta arms here, soldier!")
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class ArtilleryTest < ActiveSupport::TestCase
|
||||
# should validate_absence_of(:arms).
|
||||
# with_message("We're fresh outta arms here, soldier!")
|
||||
# end
|
||||
#
|
||||
# @return [ValidateAbsenceOfMatcher}
|
||||
#
|
||||
# Examples:
|
||||
# it { should validate_absence_of(:name) }
|
||||
# it { should validate_absence_of(:name).
|
||||
# with_message(/may not be set/) }
|
||||
def validate_absence_of(attr)
|
||||
ValidateAbsenceOfMatcher.new(attr)
|
||||
end
|
||||
|
||||
class ValidateAbsenceOfMatcher < ValidationMatcher # :nodoc:
|
||||
|
||||
# @private
|
||||
class ValidateAbsenceOfMatcher < ValidationMatcher
|
||||
def with_message(message)
|
||||
@expected_message = message
|
||||
self
|
||||
|
|
|
@ -1,24 +1,62 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
|
||||
# Ensures that the model cannot be saved if the given attribute is not
|
||||
# accepted.
|
||||
module ActiveModel
|
||||
# The `validate_acceptance_of` matcher tests usage of the
|
||||
# `validates_acceptance_of` validation.
|
||||
#
|
||||
# Options:
|
||||
# * <tt>with_message</tt> - value the test expects to find in
|
||||
# <tt>errors.on(:attribute)</tt>. Regexp or string. Defaults to the
|
||||
# translation for <tt>:accepted</tt>.
|
||||
# class Registration
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :eula
|
||||
#
|
||||
# Example:
|
||||
# it { should validate_acceptance_of(:eula) }
|
||||
# validates_acceptance_of :eula
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Registration do
|
||||
# it { should validate_acceptance_of(:eula) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class RegistrationTest < ActiveSupport::TestCase
|
||||
# should validate_acceptance_of(:eula)
|
||||
# end
|
||||
#
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### with_message
|
||||
#
|
||||
# Use `with_message` if you are using a custom validation message.
|
||||
#
|
||||
# class Registration
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :terms_of_service
|
||||
#
|
||||
# validates_acceptance_of :terms_of_service,
|
||||
# message: 'You must accept the terms of service'
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Registration do
|
||||
# it do
|
||||
# should validate_acceptance_of(:terms_of_service).
|
||||
# with_message('You must accept the terms of service')
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class RegistrationTest < ActiveSupport::TestCase
|
||||
# should validate_acceptance_of(:terms_of_service).
|
||||
# with_message('You must accept the terms of service')
|
||||
# end
|
||||
#
|
||||
# @return [ValidateAcceptanceOfMatcher]
|
||||
#
|
||||
def validate_acceptance_of(attr)
|
||||
ValidateAcceptanceOfMatcher.new(attr)
|
||||
end
|
||||
|
||||
class ValidateAcceptanceOfMatcher < ValidationMatcher # :nodoc:
|
||||
|
||||
# @private
|
||||
class ValidateAcceptanceOfMatcher < ValidationMatcher
|
||||
def with_message(message)
|
||||
if message
|
||||
@expected_message = message
|
||||
|
|
|
@ -1,16 +1,62 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
# Ensures that the model's attribute matches confirmation
|
||||
module ActiveModel
|
||||
# The `validate_confirmation_of` matcher tests usage of the
|
||||
# `validates_confirmation_of` validation.
|
||||
#
|
||||
# Example:
|
||||
# it { should validate_confirmation_of(:password) }
|
||||
# class User
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :email
|
||||
#
|
||||
# validates_confirmation_of :email
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe User do
|
||||
# it { should validate_confirmation_of(:email) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class UserTest < ActiveSupport::TestCase
|
||||
# should validate_confirmation_of(:email)
|
||||
# end
|
||||
#
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### with_message
|
||||
#
|
||||
# Use `with_message` if you are using a custom validation message.
|
||||
#
|
||||
# class User
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :password
|
||||
#
|
||||
# validates_confirmation_of :password,
|
||||
# message: 'Please re-enter your password'
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe User do
|
||||
# it do
|
||||
# should validate_confirmation_of(:password).
|
||||
# with_message('Please re-enter your password')
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class UserTest < ActiveSupport::TestCase
|
||||
# should validate_confirmation_of(:password).
|
||||
# with_message('Please re-enter your password')
|
||||
# end
|
||||
#
|
||||
# @return [ValidateConfirmationOfMatcher]
|
||||
#
|
||||
def validate_confirmation_of(attr)
|
||||
ValidateConfirmationOfMatcher.new(attr)
|
||||
end
|
||||
|
||||
class ValidateConfirmationOfMatcher < ValidationMatcher # :nodoc:
|
||||
# @private
|
||||
class ValidateConfirmationOfMatcher < ValidationMatcher
|
||||
include Helpers
|
||||
|
||||
attr_reader :attribute, :confirmation_attribute
|
||||
|
|
|
@ -1,28 +1,284 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
# Ensure that the attribute is numeric.
|
||||
module ActiveModel
|
||||
# The `validate_numericality_of` matcher tests usage of the
|
||||
# `validates_numericality_of` validation.
|
||||
#
|
||||
# Options:
|
||||
# * <tt>with_message</tt> - value the test expects to find in
|
||||
# <tt>errors.on(:attribute)</tt>. Regexp or string. Defaults to the
|
||||
# translation for <tt>:not_a_number</tt>.
|
||||
# * <tt>only_integer</tt> - allows only integer values
|
||||
# * <tt>odd</tt> - Specifies the value must be an odd number.
|
||||
# * <tt>even</tt> - Specifies the value must be an even number.
|
||||
# * <tt>allow_nil</tt> - allows nil values
|
||||
# class Person
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :gpa
|
||||
#
|
||||
# Examples:
|
||||
# it { should validate_numericality_of(:price) }
|
||||
# it { should validate_numericality_of(:age).only_integer }
|
||||
# it { should validate_numericality_of(:frequency).odd }
|
||||
# it { should validate_numericality_of(:frequency).even }
|
||||
# it { should validate_numericality_of(:rank).is_less_than_or_equal_to(10).allow_nil }
|
||||
# validates_numericality_of :gpa
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should validate_numericality_of(:gpa) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should validate_numericality_of(:gpa)
|
||||
# end
|
||||
#
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### only_integer
|
||||
#
|
||||
# Use `only_integer` to test usage of the `:only_integer` option. This
|
||||
# asserts that your attribute only allows integer numbers and disallows
|
||||
# non-integer ones.
|
||||
#
|
||||
# class Person
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :age
|
||||
#
|
||||
# validates_numericality_of :age, only_integer: true
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should validate_numericality_of(:age).only_integer }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should validate_numericality_of(:age).only_integer
|
||||
# end
|
||||
#
|
||||
# ##### is_less_than
|
||||
#
|
||||
# Use `is_less_than` to test usage of the the `:less_than` option. This
|
||||
# asserts that the attribute can take a number which is less than the
|
||||
# given value and cannot take a number which is greater than or equal to
|
||||
# it.
|
||||
#
|
||||
# class Person
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :number_of_cars
|
||||
#
|
||||
# validates_numericality_of :number_of_cars, less_than: 2
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it do
|
||||
# should validate_numericality_of(:number_of_cars).
|
||||
# is_less_than(2)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should validate_numericality_of(:number_of_cars).
|
||||
# is_less_than(2)
|
||||
# end
|
||||
#
|
||||
# ##### is_less_than_or_equal_to
|
||||
#
|
||||
# Use `is_less_than_or_equal_to` to test usage of the
|
||||
# `:less_than_or_equal_to` option. This asserts that the attribute can
|
||||
# take a number which is less than or equal to the given value and cannot
|
||||
# take a number which is greater than it.
|
||||
#
|
||||
# class Person
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :birth_year
|
||||
#
|
||||
# validates_numericality_of :birth_year, less_than_or_equal_to: 1987
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it do
|
||||
# should validate_numericality_of(:birth_year).
|
||||
# is_less_than_or_equal_to(1987)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should validate_numericality_of(:birth_year).
|
||||
# is_less_than_or_equal_to(1987)
|
||||
# end
|
||||
#
|
||||
# ##### is_equal_to
|
||||
#
|
||||
# Use `is_equal_to` to test usage of the `:equal_to` option. This asserts
|
||||
# that the attribute can take a number which is equal to the given value
|
||||
# and cannot take a number which is not equal.
|
||||
#
|
||||
# class Person
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :weight
|
||||
#
|
||||
# validates_numericality_of :weight, equal_to: 150
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should validate_numericality_of(:weight).is_equal_to(150) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should validate_numericality_of(:weight).is_equal_to(150)
|
||||
# end
|
||||
#
|
||||
# ##### is_greater_than_or_equal_to
|
||||
#
|
||||
# Use `is_greater_than_or_equal_to` to test usage of the
|
||||
# `:greater_than_or_equal_to` option. This asserts that the attribute can
|
||||
# take a number which is greater than or equal to the given value and
|
||||
# cannot take a number which is less than it.
|
||||
#
|
||||
# class Person
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :height
|
||||
#
|
||||
# validates_numericality_of :height, greater_than_or_equal_to: 55
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it do
|
||||
# should validate_numericality_of(:height).
|
||||
# is_greater_than_or_equal_to(55)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should validate_numericality_of(:height).
|
||||
# is_greater_than_or_equal_to(55)
|
||||
# end
|
||||
#
|
||||
# ##### is_greater_than
|
||||
#
|
||||
# Use `is_greater_than` to test usage of tthe `:greater_than` option.
|
||||
# This asserts that the attribute can take a number which is greater than
|
||||
# the given value and cannot take a number less than or equal to it.
|
||||
#
|
||||
# class Person
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :legal_age
|
||||
#
|
||||
# validates_numericality_of :legal_age, greater_than: 21
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it do
|
||||
# should validate_numericality_of(:legal_age).
|
||||
# is_greater_than(21)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should validate_numericality_of(:legal_age).
|
||||
# is_greater_than(21)
|
||||
# end
|
||||
#
|
||||
# ##### even
|
||||
#
|
||||
# Use `even` to test usage of the `:even` option. This asserts that the
|
||||
# attribute can take odd numbers and cannot take even ones.
|
||||
#
|
||||
# class Person
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :birth_month
|
||||
#
|
||||
# validates_numericality_of :birth_month, even: true
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should validate_numericality_of(:birth_month).even }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should validate_numericality_of(:birth_month).even
|
||||
# end
|
||||
#
|
||||
# ##### odd
|
||||
#
|
||||
# Use `odd` to test usage of the `:odd` option. This asserts that the
|
||||
# attribute can take a number which is odd and cannot take a number which
|
||||
# is even.
|
||||
#
|
||||
# class Person
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :birth_day
|
||||
#
|
||||
# validates_numericality_of :birth_day, odd: true
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should validate_numericality_of(:birth_day).odd }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should validate_numericality_of(:birth_day).odd
|
||||
# end
|
||||
#
|
||||
# ##### with_message
|
||||
#
|
||||
# Use `with_message` if you are using a custom validation message.
|
||||
#
|
||||
# class Person
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :number_of_dependents
|
||||
#
|
||||
# validates_numericality_of :number_of_dependents,
|
||||
# message: 'Number of dependents must be a number'
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it do
|
||||
# should validate_numericality_of(:number_of_dependents).
|
||||
# with_message('Number of dependents must be a number')
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should validate_numericality_of(:number_of_dependents).
|
||||
# with_message('Number of dependents must be a number')
|
||||
# end
|
||||
#
|
||||
# ##### allow_nil
|
||||
#
|
||||
# Use `allow_nil` to assert that the attribute allows nil.
|
||||
#
|
||||
# class Age
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :age
|
||||
#
|
||||
# validates_numericality_of :age, allow_nil: true
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Post do
|
||||
# it { should validate_numericality_of(:age).allow_nil }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostTest < ActiveSupport::TestCase
|
||||
# should validate_numericality_of(:age).allow_nil
|
||||
# end
|
||||
#
|
||||
# @return [ValidateNumericalityOfMatcher]
|
||||
#
|
||||
def validate_numericality_of(attr)
|
||||
ValidateNumericalityOfMatcher.new(attr)
|
||||
end
|
||||
|
||||
# @private
|
||||
class ValidateNumericalityOfMatcher
|
||||
NUMERIC_NAME = 'numbers'
|
||||
NON_NUMERIC_VALUE = 'abcd'
|
||||
|
|
|
@ -1,25 +1,95 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
|
||||
# Ensures that the model is not valid if the given attribute is not
|
||||
# present.
|
||||
module ActiveModel
|
||||
# The `validate_presence_of` matcher tests usage of the
|
||||
# `validates_presence_of` validation.
|
||||
#
|
||||
# Options:
|
||||
# * <tt>with_message</tt> - value the test expects to find in
|
||||
# <tt>errors.on(:attribute)</tt>. <tt>Regexp</tt> or <tt>String</tt>.
|
||||
# Defaults to the translation for <tt>:blank</tt>.
|
||||
# class Robot
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :arms
|
||||
#
|
||||
# Examples:
|
||||
# it { should validate_presence_of(:name) }
|
||||
# it { should validate_presence_of(:name).
|
||||
# with_message(/is not optional/) }
|
||||
# validates_presence_of :arms
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Robot do
|
||||
# it { should validate_presence_of(:arms) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class RobotTest < ActiveSupport::TestCase
|
||||
# should validate_presence_of(:arms)
|
||||
# end
|
||||
#
|
||||
# #### Caveats
|
||||
#
|
||||
# Under Rails 4 and greater, if your model `has_secure_password` and you
|
||||
# are validating presence of the password using a record whose password
|
||||
# has already been set prior to calling the matcher, you will be
|
||||
# instructed to use a record whose password is empty instead.
|
||||
#
|
||||
# For example, given this scenario:
|
||||
#
|
||||
# class User < ActiveRecord::Base
|
||||
# has_secure_password validations: false
|
||||
#
|
||||
# validates_presence_of :password
|
||||
# end
|
||||
#
|
||||
# describe User do
|
||||
# subject { User.new(password: '123456') }
|
||||
#
|
||||
# it { should validate_presence_of(:password) }
|
||||
# end
|
||||
#
|
||||
# the above test will raise an error like this:
|
||||
#
|
||||
# The validation failed because your User model declares
|
||||
# `has_secure_password`, and `validate_presence_of` was called on a
|
||||
# user which has `password` already set to a value. Please use a user
|
||||
# with an empty `password` instead.
|
||||
#
|
||||
# This happens because `has_secure_password` itself overrides your model
|
||||
# so that it is impossible to set `password` to nil. This means that it is
|
||||
# impossible to test that setting `password` to nil places your model in
|
||||
# an invalid state (which in turn means that the validation itself is
|
||||
# unnecessary).
|
||||
#
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### with_message
|
||||
#
|
||||
# Use `with_message` if you are using a custom validation message.
|
||||
#
|
||||
# class Robot
|
||||
# include ActiveModel::Model
|
||||
# attr_accessor :legs
|
||||
#
|
||||
# validates_presence_of :legs, message: 'Robot has no legs'
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Robot do
|
||||
# it do
|
||||
# should validate_presence_of(:legs).
|
||||
# with_message('Robot has no legs')
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class RobotTest < ActiveSupport::TestCase
|
||||
# should validate_presence_of(:legs).
|
||||
# with_message('Robot has no legs')
|
||||
# end
|
||||
#
|
||||
# @return [ValidatePresenceOfMatcher]
|
||||
#
|
||||
def validate_presence_of(attr)
|
||||
ValidatePresenceOfMatcher.new(attr)
|
||||
end
|
||||
|
||||
class ValidatePresenceOfMatcher < ValidationMatcher # :nodoc:
|
||||
# @private
|
||||
class ValidatePresenceOfMatcher < ValidationMatcher
|
||||
def with_message(message)
|
||||
@expected_message = message if message
|
||||
self
|
||||
|
|
|
@ -1,38 +1,178 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
# Ensures that the model is invalid if the given attribute is not unique.
|
||||
# It uses the first existing record or creates a new one if no record
|
||||
# exists in the database. It simply uses `validate: false` to get
|
||||
# around validations, so it will probably fail if there are `NOT NULL`
|
||||
# constraints. In that case, you must create a record before calling
|
||||
# `validate_uniqueness_of`.
|
||||
module ActiveModel
|
||||
# The `validate_uniqueness_of` matcher tests usage of the
|
||||
# `validates_uniqueness_of` validation. It first checks for an existing
|
||||
# instance of your model in the database, creating one if necessary. It
|
||||
# then takes a new record and asserts that it fails validation if the
|
||||
# attribute or attributes you've specified in the validation are set to
|
||||
# values which are the same as those of the pre-existing record (thereby
|
||||
# failing the uniqueness check).
|
||||
#
|
||||
# Example:
|
||||
# it { should validate_uniqueness_of(:email) }
|
||||
# class Post < ActiveRecord::Base
|
||||
# validates_uniqueness_of :permalink
|
||||
# end
|
||||
#
|
||||
# Options:
|
||||
# # RSpec
|
||||
# describe Post do
|
||||
# it { should validate_uniqueness_of(:permalink) }
|
||||
# end
|
||||
#
|
||||
# * <tt>with_message</tt> - value the test expects to find in
|
||||
# <tt>errors.on(:attribute)</tt>. <tt>Regexp</tt> or <tt>String</tt>.
|
||||
# Defaults to the translation for <tt>:taken</tt>.
|
||||
# * <tt>scoped_to</tt> - field(s) to scope the uniqueness to.
|
||||
# * <tt>case_insensitive</tt> - ensures that the validation does not
|
||||
# check case. Off by default. Ignored by non-text attributes.
|
||||
# # Test::Unit
|
||||
# class PostTest < ActiveSupport::TestCase
|
||||
# should validate_uniqueness_of(:permalink)
|
||||
# end
|
||||
#
|
||||
# Examples:
|
||||
# it { should validate_uniqueness_of(:keyword) }
|
||||
# it { should validate_uniqueness_of(:keyword).with_message(/dup/) }
|
||||
# it { should validate_uniqueness_of(:email).scoped_to(:name) }
|
||||
# it { should validate_uniqueness_of(:email).
|
||||
# scoped_to(:first_name, :last_name) }
|
||||
# it { should validate_uniqueness_of(:keyword).case_insensitive }
|
||||
# #### Caveat
|
||||
#
|
||||
# This matcher works a bit differently than other matchers. As noted
|
||||
# before, it will create an instance of your model if one doesn't already
|
||||
# exist. Sometimes this step fails, especially if you have database-level
|
||||
# restrictions on any attributes other than the one which is unique. In
|
||||
# this case, the solution is to **create a record manually** before you
|
||||
# call `validate_uniqueness_of`.
|
||||
#
|
||||
# For example, say you have the following migration and model:
|
||||
#
|
||||
# class CreatePosts < ActiveRecord::Migration
|
||||
# def change
|
||||
# create_table :posts do |t|
|
||||
# t.string :title
|
||||
# t.text :content, null: false
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# class Post < ActiveRecord::Base
|
||||
# validates :title, uniqueness: true
|
||||
# end
|
||||
#
|
||||
# You may be tempted to test the model like this:
|
||||
#
|
||||
# describe Post do
|
||||
# it { should validate_uniqueness_of(:title) }
|
||||
# end
|
||||
#
|
||||
# However, running this test will fail with something like:
|
||||
#
|
||||
# Failures:
|
||||
#
|
||||
# 1) Post should require case sensitive unique value for title
|
||||
# Failure/Error: it { should validate_uniqueness_of(:title) }
|
||||
# ActiveRecord::StatementInvalid:
|
||||
# SQLite3::ConstraintException: posts.content may not be NULL: INSERT INTO "posts" ("title") VALUES (?)
|
||||
#
|
||||
# To fix this, you'll need to write this instead:
|
||||
#
|
||||
# describe Post do
|
||||
# it do
|
||||
# Post.create!(content: 'Here is the content')
|
||||
# should validate_uniqueness_of(:title)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# Or, if you're using
|
||||
# [FactoryGirl](http://github.com/thoughtbot/factory_girl) and you have a
|
||||
# `post` factory defined which automatically sets `content`, you can say:
|
||||
#
|
||||
# describe Post do
|
||||
# it do
|
||||
# FactoryGirl.create(:post)
|
||||
# should validate_uniqueness_of(:title)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### with_message
|
||||
#
|
||||
# Use `with_message` if you are using a custom validation message.
|
||||
#
|
||||
# class Post < ActiveRecord::Base
|
||||
# validates_uniqueness_of :title, message: 'Please choose another title'
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Post do
|
||||
# it do
|
||||
# should validate_uniqueness_of(:title).
|
||||
# with_message('Please choose another title')
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostTest < ActiveSupport::TestCase
|
||||
# should validate_uniqueness_of(:title).
|
||||
# with_message('Please choose another title')
|
||||
# end
|
||||
#
|
||||
# ##### scoped_to
|
||||
#
|
||||
# Use `scoped_to` to test usage of the `:scope` option. This asserts that
|
||||
# a new record fails validation if not only the primary attribute is not
|
||||
# unique, but the scoped attributes are not unique either.
|
||||
#
|
||||
# class Post < ActiveRecord::Base
|
||||
# validates_uniqueness_of :slug, scope: :user_id
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Post do
|
||||
# it { should validate_uniqueness_of(:slug).scoped_to(:journal_id) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostTest < ActiveSupport::TestCase
|
||||
# should validate_uniqueness_of(:slug).scoped_to(:journal_id)
|
||||
# end
|
||||
#
|
||||
# ##### case_insensitive
|
||||
#
|
||||
# Use `case_insensitive` to test usage of the `:case_sensitive` option
|
||||
# with a false value. This asserts that the uniquable attributes fail
|
||||
# validation even if their values are a different case than corresponding
|
||||
# attributes in the pre-existing record.
|
||||
#
|
||||
# class Post < ActiveRecord::Base
|
||||
# validates_uniqueness_of :key, case_sensitive: false
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Post do
|
||||
# it { should validate_uniqueness_of(:key).case_insensitive }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostTest < ActiveSupport::TestCase
|
||||
# should validate_uniqueness_of(:key).case_insensitive
|
||||
# end
|
||||
#
|
||||
# ##### allow_nil
|
||||
#
|
||||
# Use `allow_nil` to assert that the attribute allows nil.
|
||||
#
|
||||
# class Post < ActiveRecord::Base
|
||||
# validates_uniqueness_of :author_id, allow_nil: true
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Post do
|
||||
# it { should validate_uniqueness_of(:author_id).allow_nil }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PostTest < ActiveSupport::TestCase
|
||||
# should validate_uniqueness_of(:author_id).allow_nil
|
||||
# end
|
||||
#
|
||||
# @return [ValidateUniquenessOfMatcher]
|
||||
#
|
||||
def validate_uniqueness_of(attr)
|
||||
ValidateUniquenessOfMatcher.new(attr)
|
||||
end
|
||||
|
||||
class ValidateUniquenessOfMatcher < ValidationMatcher # :nodoc:
|
||||
# @private
|
||||
class ValidateUniquenessOfMatcher < ValidationMatcher
|
||||
include Helpers
|
||||
|
||||
def initialize(attribute)
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel # :nodoc:
|
||||
class ValidationMatcher # :nodoc:
|
||||
module ActiveModel
|
||||
# @private
|
||||
class ValidationMatcher
|
||||
attr_reader :failure_message
|
||||
|
||||
alias failure_message_for_should failure_message
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveModel
|
||||
|
||||
# Finds message information from a model's #errors method.
|
||||
# @private
|
||||
class ValidationMessageFinder
|
||||
include Helpers
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
require 'shoulda/matchers/active_record/association_matcher'
|
||||
require 'shoulda/matchers/active_record/association_matchers'
|
||||
require 'shoulda/matchers/active_record/association_matchers/counter_cache_matcher'
|
||||
require 'shoulda/matchers/active_record/association_matchers/inverse_of_matcher'
|
||||
require 'shoulda/matchers/active_record/association_matchers/order_matcher'
|
||||
|
@ -16,18 +17,6 @@ require 'shoulda/matchers/active_record/accept_nested_attributes_for_matcher'
|
|||
|
||||
module Shoulda
|
||||
module Matchers
|
||||
# = Matchers for your active record models
|
||||
#
|
||||
# These matchers will test the associations for your
|
||||
# ActiveRecord models.
|
||||
#
|
||||
# describe User do
|
||||
# it { should have_one(:profile) }
|
||||
# it { should have_many(:dogs) }
|
||||
# it { should have_many(:messes).through(:dogs) }
|
||||
# it { should belong_to(:lover) }
|
||||
# end
|
||||
#
|
||||
module ActiveRecord
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,26 +1,100 @@
|
|||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveRecord
|
||||
# Ensures that the model can accept nested attributes for the specified
|
||||
# association.
|
||||
# The `accept_nested_attributes_for` matcher tests usage of the
|
||||
# `accepts_nested_attributes_for` macro.
|
||||
#
|
||||
# Options:
|
||||
# * <tt>allow_destroy</tt> - Whether or not to allow destroy
|
||||
# * <tt>limit</tt> - Max number of nested attributes
|
||||
# * <tt>update_only</tt> - Only allow updates
|
||||
# class Car < ActiveRecord::Base
|
||||
# accept_nested_attributes_for :doors
|
||||
# end
|
||||
#
|
||||
# Example:
|
||||
# it { should accept_nested_attributes_for(:friends) }
|
||||
# it { should accept_nested_attributes_for(:friends).
|
||||
# allow_destroy(true).
|
||||
# limit(4) }
|
||||
# it { should accept_nested_attributes_for(:friends).
|
||||
# update_only(true) }
|
||||
# # RSpec
|
||||
# describe Car do
|
||||
# it { should accept_nested_attributes_for(:doors) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit (using Shoulda)
|
||||
# class CarTest < ActiveSupport::TestCase
|
||||
# should accept_nested_attributes_for(:doors)
|
||||
# end
|
||||
#
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### allow_destroy
|
||||
#
|
||||
# Use `allow_destroy` to assert that the `:allow_destroy` option was
|
||||
# specified.
|
||||
#
|
||||
# class Car < ActiveRecord::Base
|
||||
# accept_nested_attributes_for :mirrors, allow_destroy: true
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Car do
|
||||
# it do
|
||||
# should accept_nested_attributes_for(:mirrors).
|
||||
# allow_destroy(true)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class CarTest < ActiveSupport::TestCase
|
||||
# should accept_nested_attributes_for(:mirrors).
|
||||
# allow_destroy(true)
|
||||
# end
|
||||
#
|
||||
# ##### limit
|
||||
#
|
||||
# Use `limit` to assert that the `:limit` option was specified.
|
||||
#
|
||||
# class Car < ActiveRecord::Base
|
||||
# accept_nested_attributes_for :windows, limit: 3
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Car do
|
||||
# it do
|
||||
# should accept_nested_attributes_for(:windows).
|
||||
# limit(3)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class CarTest < ActiveSupport::TestCase
|
||||
# should accept_nested_attributes_for(:windows).
|
||||
# limit(3)
|
||||
# end
|
||||
#
|
||||
# ##### update_only
|
||||
#
|
||||
# Use `update_only` to assert that the `:update_only` option was
|
||||
# specified.
|
||||
#
|
||||
# class Car < ActiveRecord::Base
|
||||
# accept_nested_attributes_for :engine, update_only: true
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Car do
|
||||
# it do
|
||||
# should accept_nested_attributes_for(:engine).
|
||||
# update_only(true)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class CarTest < ActiveSupport::TestCase
|
||||
# should accept_nested_attributes_for(:engine).
|
||||
# update_only(true)
|
||||
# end
|
||||
#
|
||||
# @return [AcceptNestedAttributesForMatcher]
|
||||
#
|
||||
def accept_nested_attributes_for(name)
|
||||
AcceptNestedAttributesForMatcher.new(name)
|
||||
end
|
||||
|
||||
# @private
|
||||
class AcceptNestedAttributesForMatcher
|
||||
def initialize(name)
|
||||
@name = name
|
||||
|
|
|
@ -1,95 +1,751 @@
|
|||
require 'active_support/core_ext/module/delegation'
|
||||
|
||||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveRecord # :nodoc:
|
||||
# Ensure that the belongs_to relationship exists.
|
||||
module ActiveRecord
|
||||
# The `belong_to` matcher is used to ensure that a `belong_to` association
|
||||
# exists on your model.
|
||||
#
|
||||
# Options:
|
||||
# * <tt>class_name</tt> - tests that the association resolves to class_name.
|
||||
# * <tt>validate</tt> - tests that the association makes use of the validate
|
||||
# option.
|
||||
# * <tt>touch</tt> - tests that the association makes use of the touch
|
||||
# option.
|
||||
# class Person < ActiveRecord::Base
|
||||
# belongs_to :organization
|
||||
# end
|
||||
#
|
||||
# Example:
|
||||
# it { should belong_to(:parent) }
|
||||
# it { should belong_to(:parent).touch }
|
||||
# it { should belong_to(:parent).validate }
|
||||
# it { should belong_to(:parent).class_name("ModelClassName") }
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should belong_to(:organization) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should belong_to(:organization)
|
||||
# end
|
||||
#
|
||||
# Note that polymorphic associations are automatically detected and do not
|
||||
# need any qualifiers:
|
||||
#
|
||||
# class Comment < ActiveRecord::Base
|
||||
# belongs_to :commentable, polymorphic: true
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Comment do
|
||||
# it { should belong_to(:commentable) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class CommentTest < ActiveSupport::TestCase
|
||||
# should belong_to(:commentable)
|
||||
# end
|
||||
#
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### conditions
|
||||
#
|
||||
# Use `conditions` if your association is defined with a scope that sets
|
||||
# the `where` clause.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# belongs_to :family, -> { where(everyone_is_perfect: false) }
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it do
|
||||
# should belong_to(:family).
|
||||
# conditions(everyone_is_perfect: false)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should belong_to(:family).
|
||||
# conditions(everyone_is_perfect: false)
|
||||
# end
|
||||
#
|
||||
# ##### order
|
||||
#
|
||||
# Use `order` if your association is defined with a scope that sets the
|
||||
# `order` clause.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# belongs_to :previous_company, -> { order('hired_on desc') }
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should belong_to(:previous_company).order('hired_on desc') }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should belong_to(:previous_company).order('hired_on desc')
|
||||
# end
|
||||
#
|
||||
# ##### class_name
|
||||
#
|
||||
# Use `class_name` to test usage of the `:class_name` option. This
|
||||
# asserts that the model you're referring to actually exists.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# belongs_to :ancient_city, class_name: 'City'
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should belong_to(:ancient_city).class_name('City') }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should belong_to(:ancient_city).class_name('City')
|
||||
# end
|
||||
#
|
||||
# ##### with_foreign_key
|
||||
#
|
||||
# Use `with_foreign_key` to test usage of the `:foreign_key` option.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# belongs_to :great_country, foreign_key: 'country_id'
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it do
|
||||
# should belong_to(:great_country).
|
||||
# with_foreign_key('country_id')
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should belong_to(:great_country).
|
||||
# with_foreign_key('country_id')
|
||||
# end
|
||||
#
|
||||
# ##### dependent
|
||||
#
|
||||
# Use `dependent` to assert that the `:dependent` option was specified.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# belongs_to :world, dependent: :destroy
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should belong_to(:world).dependent(:destroy) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should belong_to(:world).dependent(:destroy)
|
||||
# end
|
||||
#
|
||||
# ##### counter_cache
|
||||
#
|
||||
# Use `counter_cache` to assert that the `:counter_cache` option was
|
||||
# specified.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# belongs_to :organization, counter_cache: true
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should belong_to(:organization).counter_cache(true) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should belong_to(:organization).counter_cache(true)
|
||||
# end
|
||||
#
|
||||
# ##### touch
|
||||
#
|
||||
# Use `touch` to assert that the `:touch` option was specified.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# belongs_to :organization, touch: true
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should belong_to(:organization).touch(true) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should belong_to(:organization).touch(true)
|
||||
# end
|
||||
#
|
||||
# #### autosave
|
||||
#
|
||||
# Use `autosave` to assert that the `:autosave` option was specified.
|
||||
#
|
||||
# class Account < ActiveRecord::Base
|
||||
# belongs_to :bank, autosave: true
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Account do
|
||||
# it { should belong_to(:bank).autosave(true) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class AccountTest < ActiveSupport::TestCase
|
||||
# should belong_to(:bank).autosave(true)
|
||||
# end
|
||||
#
|
||||
# ##### inverse_of
|
||||
#
|
||||
# Use `inverse_of` to assert that the `:inverse_of` option was specified.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# belongs_to :organization, inverse_of: :employees
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person
|
||||
# it { should belong_to(:organization).inverse_of(:employees) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should belong_to(:organization).inverse_of(:employees)
|
||||
# end
|
||||
#
|
||||
# @return [AssociationMatcher]
|
||||
#
|
||||
def belong_to(name)
|
||||
AssociationMatcher.new(:belongs_to, name)
|
||||
end
|
||||
|
||||
# Ensures that the has_many relationship exists. Will also test that the
|
||||
# associated table has the required columns. Works with polymorphic
|
||||
# associations.
|
||||
# The `have_many` matcher is used to test that a `has_many` or `has_many
|
||||
# :through` association exists on your model.
|
||||
#
|
||||
# Options:
|
||||
# * <tt>through</tt> - association name for <tt>has_many :through</tt>
|
||||
# * <tt>dependent</tt> - tests that the association makes use of the
|
||||
# dependent option.
|
||||
# * <tt>class_name</tt> - tests that the association resoves to class_name.
|
||||
# * <tt>autosave</tt> - tests that the association makes use of the
|
||||
# autosave option.
|
||||
# * <tt>validate</tt> - tests that the association makes use of the validate
|
||||
# option.
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_many :friends
|
||||
# end
|
||||
#
|
||||
# Example:
|
||||
# it { should have_many(:friends) }
|
||||
# it { should have_many(:enemies).through(:friends) }
|
||||
# it { should have_many(:enemies).dependent(:destroy) }
|
||||
# it { should have_many(:friends).autosave }
|
||||
# it { should have_many(:friends).validate }
|
||||
# it { should have_many(:friends).class_name("Friend") }
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should have_many(:friends) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_many(:friends)
|
||||
# end
|
||||
#
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### conditions
|
||||
#
|
||||
# Use `conditions` if your association is defined with a scope that sets
|
||||
# the `where` clause.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_many :coins, -> { where(quality: 'mint') }
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should have_many(:coins).conditions(quality: 'mint') }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_many(:coins).conditions(quality: 'mint')
|
||||
# end
|
||||
#
|
||||
# ##### order
|
||||
#
|
||||
# Use `order` if your association is defined with a scope that sets the
|
||||
# `order` clause.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_many :shirts, -> { order('color') }
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should have_many(:shirts).order('color') }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_many(:shirts).order('color')
|
||||
# end
|
||||
#
|
||||
# ##### class_name
|
||||
#
|
||||
# Use `class_name` to test usage of the `:class_name` option. This
|
||||
# asserts that the model you're referring to actually exists.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_many :hopes, class_name: 'Dream'
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should have_many(:hopes).class_name('Dream') }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_many(:hopes).class_name('Dream')
|
||||
# end
|
||||
#
|
||||
# ##### with_foreign_key
|
||||
#
|
||||
# Use `with_foreign_key` to test usage of the `:foreign_key` option.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_many :worries, foreign_key: 'worrier_id'
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should have_many(:worries).with_foreign_key('worrier_id') }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_many(:worries).with_foreign_key('worrier_id')
|
||||
# end
|
||||
#
|
||||
# ##### dependent
|
||||
#
|
||||
# Use `dependent` to assert that the `:dependent` option was specified.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_many :secret_documents, dependent: :destroy
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should have_many(:secret_documents).dependent(:destroy) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_many(:secret_documents).dependent(:destroy)
|
||||
# end
|
||||
#
|
||||
# ##### through
|
||||
#
|
||||
# Use `through` to test usage of the `:through` option. This asserts that
|
||||
# the association you are going through actually exists.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_many :acquaintances, through: :friends
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should have_many(:acquaintances).through(:friends) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_many(:acquaintances).through(:friends)
|
||||
# end
|
||||
#
|
||||
# ##### source
|
||||
#
|
||||
# Use `source` to test usage of the `:source` option on a `:through`
|
||||
# association.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_many :job_offers, through: :friends, source: :opportunities
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it do
|
||||
# should have_many(:job_offers).
|
||||
# through(:friends).
|
||||
# source(:opportunities)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_many(:job_offers).
|
||||
# through(:friends).
|
||||
# source(:opportunities)
|
||||
# end
|
||||
#
|
||||
# ##### validate
|
||||
#
|
||||
# Use `validate` to assert that the `:validate` option was specified.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_many :ideas, validate: false
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should have_many(:ideas).validate(false) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_many(:ideas).validate(false)
|
||||
# end
|
||||
#
|
||||
# #### autosave
|
||||
#
|
||||
# Use `autosave` to assert that the `:autosave` option was specified.
|
||||
#
|
||||
# class Player < ActiveRecord::Base
|
||||
# has_many :games, autosave: true
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Player do
|
||||
# it { should have_many(:games).autosave(true) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PlayerTest < ActiveSupport::TestCase
|
||||
# should have_many(:games).autosave(true)
|
||||
# end
|
||||
#
|
||||
# @return [AssociationMatcher]
|
||||
#
|
||||
def have_many(name)
|
||||
AssociationMatcher.new(:has_many, name)
|
||||
end
|
||||
|
||||
# Ensure that the has_one relationship exists. Will also test that the
|
||||
# associated table has the required columns. Works with polymorphic
|
||||
# associations.
|
||||
# The `have_one` matcher is used to test that a `has_one` or `has_one
|
||||
# :through` association exists on your model.
|
||||
#
|
||||
# Options:
|
||||
# * <tt>dependent</tt> - tests that the association makes use of the
|
||||
# dependent option.
|
||||
# * <tt>class_name</tt> - tests that the association resolves to class_name.
|
||||
# * <tt>autosave</tt> - tests that the association makes use of the
|
||||
# autosave option.
|
||||
# * <tt>validate</tt> - tests that the association makes use of the validate
|
||||
# option.
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_one :partner
|
||||
# end
|
||||
#
|
||||
# Example:
|
||||
# it { should have_one(:god) } # unless hindu
|
||||
# it { should have_one(:god).dependent }
|
||||
# it { should have_one(:god).autosave }
|
||||
# it { should have_one(:god).validate }
|
||||
# it { should have_one(:god).class_name("JHVH1") }
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should have_one(:partner) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_one(:partner)
|
||||
# end
|
||||
#
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### conditions
|
||||
#
|
||||
# Use `conditions` if your association is defined with a scope that sets
|
||||
# the `where` clause.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_one :pet, -> { where('weight < 80') }
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should have_one(:pet).conditions('weight < 80') }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_one(:pet).conditions('weight < 80')
|
||||
# end
|
||||
#
|
||||
# ##### order
|
||||
#
|
||||
# Use `order` if your association is defined with a scope that sets the
|
||||
# `order` clause.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_one :focus, -> { order('priority desc') }
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should have_one(:focus).order('priority desc') }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_one(:focus).order('priority desc')
|
||||
# end
|
||||
#
|
||||
# ##### class_name
|
||||
#
|
||||
# Use `class_name` to test usage of the `:class_name` option. This
|
||||
# asserts that the model you're referring to actually exists.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_one :chance, class_name: 'Opportunity'
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should have_one(:chance).class_name('Opportunity') }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_one(:chance).class_name('Opportunity')
|
||||
# end
|
||||
#
|
||||
# ##### dependent
|
||||
#
|
||||
# Use `dependent` to test that the `:dependent` option was specified.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_one :contract, dependent: :nullify
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should have_one(:contract).dependent(:nullify) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_one(:contract).dependent(:nullify)
|
||||
# end
|
||||
#
|
||||
# ##### with_foreign_key
|
||||
#
|
||||
# Use `with_foreign_key` to test usage of the `:foreign_key` option.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_one :job, foreign_key: 'worker_id'
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should have_one(:job).with_foreign_key('worker_id') }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_one(:job).with_foreign_key('worker_id')
|
||||
# end
|
||||
#
|
||||
# ##### through
|
||||
#
|
||||
# Use `through` to test usage of the `:through` option. This asserts that
|
||||
# the association you are going through actually exists.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_one :life, through: :partner
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should have_one(:life).through(:partner) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_one(:life).through(:partner)
|
||||
# end
|
||||
#
|
||||
# ##### source
|
||||
#
|
||||
# Use `source` to test usage of the `:source` option on a `:through`
|
||||
# association.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_one :car, through: :partner, source: :vehicle
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should have_one(:car).through(:partner).source(:vehicle) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_one(:car).through(:partner).source(:vehicle)
|
||||
# end
|
||||
#
|
||||
# ##### validate
|
||||
#
|
||||
# Use `validate` to assert that the the `:validate` option was specified.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_one :parking_card, validate: false
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should have_one(:parking_card).validate(false) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_one(:parking_card).validate(false)
|
||||
# end
|
||||
#
|
||||
# #### autosave
|
||||
#
|
||||
# Use `autosave` to assert that the `:autosave` option was specified.
|
||||
#
|
||||
# class Account < ActiveRecord::Base
|
||||
# has_one :bank, autosave: true
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Account do
|
||||
# it { should have_one(:bank).autosave(true) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class AccountTest < ActiveSupport::TestCase
|
||||
# should have_one(:bank).autosave(true)
|
||||
# end
|
||||
#
|
||||
# @return [AssociationMatcher]
|
||||
#
|
||||
def have_one(name)
|
||||
AssociationMatcher.new(:has_one, name)
|
||||
end
|
||||
|
||||
# Ensures that the has_and_belongs_to_many relationship exists, and that
|
||||
# the join table is in place.
|
||||
# The `have_and_belong_to_many` matcher is used to test that a
|
||||
# `has_and_belongs_to_many` association exists on your model and that the
|
||||
# join table exists in the database.
|
||||
#
|
||||
# Options:
|
||||
# * <tt>class_name</tt> - tests that the association resolves to class_name.
|
||||
# * <tt>validate</tt> - tests that the association makes use of the validate
|
||||
# option.
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_and_belongs_to_many :awards
|
||||
# end
|
||||
#
|
||||
# Example:
|
||||
# it { should have_and_belong_to_many(:posts) }
|
||||
# it { should have_and_belong_to_many(:posts).validate }
|
||||
# it { should have_and_belong_to_many(:posts).class_name("Post") }
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it { should have_and_belong_to_many(:awards) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_and_belong_to_many(:awards)
|
||||
# end
|
||||
#
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### conditions
|
||||
#
|
||||
# Use `conditions` if your association is defined with a scope that sets
|
||||
# the `where` clause.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_and_belongs_to_many :issues, -> { where(difficulty: 'hard') }
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it do
|
||||
# should have_and_belong_to_many(:issues).
|
||||
# conditions(difficulty: 'hard')
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_and_belong_to_many(:issues).
|
||||
# conditions(difficulty: 'hard')
|
||||
# end
|
||||
#
|
||||
# ##### order
|
||||
#
|
||||
# Use `order` if your association is defined with a scope that sets the
|
||||
# `order` clause.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_and_belongs_to_many :projects, -> { order('time_spent') }
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it do
|
||||
# should have_and_belong_to_many(:projects).
|
||||
# order('time_spent')
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_and_belong_to_many(:projects).
|
||||
# order('time_spent')
|
||||
# end
|
||||
#
|
||||
# ##### class_name
|
||||
#
|
||||
# Use `class_name` to test usage of the `:class_name` option. This
|
||||
# asserts that the model you're referring to actually exists.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_and_belongs_to_many :places_visited, class_name: 'City'
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it do
|
||||
# should have_and_belong_to_many(:places_visited).
|
||||
# class_name('City')
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_and_belong_to_many(:places_visited).
|
||||
# class_name('City')
|
||||
# end
|
||||
#
|
||||
# ##### validate
|
||||
#
|
||||
# Use `validate` to test that the `:validate` option was specified.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_and_belongs_to_many :interviews, validate: false
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Person do
|
||||
# it do
|
||||
# should have_and_belong_to_many(:interviews).
|
||||
# validate(false)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PersonTest < ActiveSupport::TestCase
|
||||
# should have_and_belong_to_many(:interviews).
|
||||
# validate(false)
|
||||
# end
|
||||
#
|
||||
# #### autosave
|
||||
#
|
||||
# Use `autosave` to assert that the `:autosave` option was specified.
|
||||
#
|
||||
# class Publisher < ActiveRecord::Base
|
||||
# has_and_belongs_to_many :advertisers, autosave: true
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Publisher do
|
||||
# it { should have_and_belong_to_many(:advertisers).autosave(true) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class AccountTest < ActiveSupport::TestCase
|
||||
# should have_and_belong_to_many(:advertisers).autosave(true)
|
||||
# end
|
||||
#
|
||||
# @return [AssociationMatcher]
|
||||
#
|
||||
def have_and_belong_to_many(name)
|
||||
AssociationMatcher.new(:has_and_belongs_to_many, name)
|
||||
end
|
||||
|
||||
class AssociationMatcher # :nodoc:
|
||||
# @private
|
||||
class AssociationMatcher
|
||||
delegate :reflection, :model_class, :associated_class, :through?,
|
||||
:join_table, :polymorphic?, to: :reflector
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveRecord
|
||||
# @private
|
||||
module AssociationMatchers
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,7 +1,8 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveRecord # :nodoc:
|
||||
module ActiveRecord
|
||||
module AssociationMatchers
|
||||
# @private
|
||||
class CounterCacheMatcher
|
||||
attr_accessor :missing_option
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveRecord # :nodoc:
|
||||
module ActiveRecord
|
||||
module AssociationMatchers
|
||||
# @private
|
||||
class DependentMatcher
|
||||
attr_accessor :missing_option
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveRecord # :nodoc:
|
||||
module ActiveRecord
|
||||
module AssociationMatchers
|
||||
# @private
|
||||
class InverseOfMatcher
|
||||
attr_accessor :missing_option
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ module Shoulda
|
|||
module Matchers
|
||||
module ActiveRecord
|
||||
module AssociationMatchers
|
||||
# @private
|
||||
class ModelReflection < SimpleDelegator
|
||||
def initialize(reflection)
|
||||
super(reflection)
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveRecord # :nodoc:
|
||||
module ActiveRecord
|
||||
module AssociationMatchers
|
||||
# @private
|
||||
class ModelReflector
|
||||
delegate :associated_class, :through?, :join_table,
|
||||
:association_relation, :polymorphic?, to: :reflection
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveRecord # :nodoc:
|
||||
module ActiveRecord
|
||||
module AssociationMatchers
|
||||
# @private
|
||||
class OptionVerifier
|
||||
delegate :reflection, to: :reflector
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveRecord # :nodoc:
|
||||
module ActiveRecord
|
||||
module AssociationMatchers
|
||||
# @private
|
||||
class OrderMatcher
|
||||
attr_accessor :missing_option
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveRecord # :nodoc:
|
||||
module ActiveRecord
|
||||
module AssociationMatchers
|
||||
# @private
|
||||
class SourceMatcher
|
||||
attr_accessor :missing_option
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveRecord # :nodoc:
|
||||
module ActiveRecord
|
||||
module AssociationMatchers
|
||||
# @private
|
||||
class ThroughMatcher
|
||||
attr_accessor :missing_option
|
||||
|
||||
|
|
|
@ -1,25 +1,89 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveRecord # :nodoc:
|
||||
|
||||
# Ensures the database column exists.
|
||||
module ActiveRecord
|
||||
# The `have_db_column` matcher tests that the table that backs your model
|
||||
# has a specific column.
|
||||
#
|
||||
# Options:
|
||||
# * <tt>of_type</tt> - db column type (:integer, :string, etc.)
|
||||
# * <tt>with_options</tt> - same options available in migrations
|
||||
# (:default, :null, :limit, :precision, :scale)
|
||||
# class CreatePhones < ActiveRecord::Migration
|
||||
# def change
|
||||
# create_table :phones do |t|
|
||||
# t.string :supported_ios_version
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# Examples:
|
||||
# it { should_not have_db_column(:admin).of_type(:boolean) }
|
||||
# it { should have_db_column(:salary).
|
||||
# of_type(:decimal).
|
||||
# with_options(precision: 10, scale: 2) }
|
||||
# # RSpec
|
||||
# describe Phone do
|
||||
# it { should have_db_column(:supported_ios_version) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PhoneTest < ActiveSupport::TestCase
|
||||
# should have_db_column(:supported_ios_version)
|
||||
# end
|
||||
#
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### of_type
|
||||
#
|
||||
# Use `of_type` to assert that a column is defined as a certain type.
|
||||
#
|
||||
# class CreatePhones < ActiveRecord::Migration
|
||||
# def change
|
||||
# create_table :phones do |t|
|
||||
# t.decimal :camera_aperture
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Phone do
|
||||
# it do
|
||||
# should have_db_column(:camera_aperture).of_type(:decimal)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PhoneTest < ActiveSupport::TestCase
|
||||
# should have_db_column(:camera_aperture).of_type(:decimal)
|
||||
# end
|
||||
#
|
||||
# ##### with_options
|
||||
#
|
||||
# Use `with_options` to assert that a column has been defined with
|
||||
# certain options (`:precision`, `:limit`, `:default`, `:null`, `:scale`,
|
||||
# or `:primary`).
|
||||
#
|
||||
# class CreatePhones < ActiveRecord::Migration
|
||||
# def change
|
||||
# create_table :phones do |t|
|
||||
# t.decimal :camera_aperture, precision: 1, null: false
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Phone do
|
||||
# it do
|
||||
# should have_db_column(:camera_aperture).
|
||||
# with_options(precision: 1, null: false)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class PhoneTest < ActiveSupport::TestCase
|
||||
# should have_db_column(:camera_aperture).
|
||||
# with_options(precision: 1, null: false)
|
||||
# end
|
||||
#
|
||||
# @return [HaveDbColumnMatcher]
|
||||
#
|
||||
def have_db_column(column)
|
||||
HaveDbColumnMatcher.new(column)
|
||||
end
|
||||
|
||||
class HaveDbColumnMatcher # :nodoc:
|
||||
# @private
|
||||
class HaveDbColumnMatcher
|
||||
def initialize(column)
|
||||
@column = column
|
||||
@options = {}
|
||||
|
|
|
@ -1,27 +1,76 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveRecord # :nodoc:
|
||||
|
||||
# Ensures that there are DB indices on the given columns or tuples of
|
||||
# columns.
|
||||
module ActiveRecord
|
||||
# The `have_db_index` matcher tests that the table that backs your model
|
||||
# has a index on a specific column.
|
||||
#
|
||||
# Options:
|
||||
# * <tt>unique</tt> - whether or not the index has a unique
|
||||
# constraint. Use <tt>true</tt> to explicitly test for a unique
|
||||
# constraint. Use <tt>false</tt> to explicitly test for a non-unique
|
||||
# constraint.
|
||||
# class CreateBlogs < ActiveRecord::Migration
|
||||
# def change
|
||||
# create_table :blogs do |t|
|
||||
# t.integer :user_id
|
||||
# end
|
||||
#
|
||||
# Examples:
|
||||
# add_index :blogs, :user_id
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# it { should have_db_index(:age) }
|
||||
# it { should have_db_index([:commentable_type, :commentable_id]) }
|
||||
# it { should have_db_index(:ssn).unique(true) }
|
||||
# # RSpec
|
||||
# describe Blog do
|
||||
# it { should have_db_index(:user_id) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class BlogTest < ActiveSupport::TestCase
|
||||
# should have_db_index(:user_id)
|
||||
# end
|
||||
#
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### unique
|
||||
#
|
||||
# Use `unique` to assert that the index is unique.
|
||||
#
|
||||
# class CreateBlogs < ActiveRecord::Migration
|
||||
# def change
|
||||
# create_table :blogs do |t|
|
||||
# t.string :name
|
||||
# end
|
||||
#
|
||||
# add_index :blogs, :name, unique: true
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Blog do
|
||||
# it { should have_db_index(:name).unique(true) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class BlogTest < ActiveSupport::TestCase
|
||||
# should have_db_index(:name).unique(true)
|
||||
# end
|
||||
#
|
||||
# Since it only ever makes since for `unique` to be `true`, you can also
|
||||
# leave off the argument to save some keystrokes:
|
||||
#
|
||||
# # RSpec
|
||||
# describe Blog do
|
||||
# it { should have_db_index(:name).unique }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class BlogTest < ActiveSupport::TestCase
|
||||
# should have_db_index(:name).unique
|
||||
# end
|
||||
#
|
||||
# @return [HaveDbIndexMatcher]
|
||||
#
|
||||
def have_db_index(columns)
|
||||
HaveDbIndexMatcher.new(columns)
|
||||
end
|
||||
|
||||
class HaveDbIndexMatcher # :nodoc:
|
||||
# @private
|
||||
class HaveDbIndexMatcher
|
||||
def initialize(columns)
|
||||
@columns = normalize_columns_to_array(columns)
|
||||
@options = {}
|
||||
|
|
|
@ -1,17 +1,31 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveRecord # :nodoc:
|
||||
|
||||
# Ensures that the attribute cannot be changed once the record has been
|
||||
# created.
|
||||
module ActiveRecord
|
||||
# The `have_readonly_attribute` matcher tests usage of the
|
||||
# `attr_readonly` macro.
|
||||
#
|
||||
# it { should have_readonly_attribute(:password) }
|
||||
# class User < ActiveRecord::Base
|
||||
# attr_readonly :password
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe User do
|
||||
# it { should have_readonly_attribute(:password) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class UserTest < ActiveSupport::TestCase
|
||||
# should have_readonly_attribute(:password)
|
||||
# end
|
||||
#
|
||||
# @return [HaveReadonlyAttributeMatcher]
|
||||
#
|
||||
def have_readonly_attribute(value)
|
||||
HaveReadonlyAttributeMatcher.new(value)
|
||||
end
|
||||
|
||||
class HaveReadonlyAttributeMatcher # :nodoc:
|
||||
# @private
|
||||
class HaveReadonlyAttributeMatcher
|
||||
def initialize(attribute)
|
||||
@attribute = attribute.to_s
|
||||
end
|
||||
|
|
|
@ -1,21 +1,96 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module ActiveRecord # :nodoc:
|
||||
# Ensure that the field becomes serialized.
|
||||
module ActiveRecord
|
||||
# The `serialize` matcher tests usage of the `serialize` macro.
|
||||
#
|
||||
# Options:
|
||||
# * <tt>:as</tt> - tests that the serialized attribute makes use of the class_name option.
|
||||
# class Product < ActiveRecord::Base
|
||||
# serialize :customizations
|
||||
# end
|
||||
#
|
||||
# Example:
|
||||
# it { should serialize(:details) }
|
||||
# it { should serialize(:details).as(Hash) }
|
||||
# it { should serialize(:details).as_instance_of(ExampleSerializer) }
|
||||
# # RSpec
|
||||
# describe Product do
|
||||
# it { should serialize(:customizations) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class ProductTest < ActiveSupport::TestCase
|
||||
# should serialize(:customizations)
|
||||
# end
|
||||
#
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### as
|
||||
#
|
||||
# Use `as` if you are using a custom serializer class.
|
||||
#
|
||||
# class ProductSpecsSerializer
|
||||
# def load(string)
|
||||
# # ...
|
||||
# end
|
||||
#
|
||||
# def dump(options)
|
||||
# # ...
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# class Product < ActiveRecord::Base
|
||||
# serialize :specifications, ProductSpecsSerializer
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Product do
|
||||
# it do
|
||||
# should serialize(:specifications).
|
||||
# as(ProductSpecsSerializer)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class ProductTest < ActiveSupport::TestCase
|
||||
# should serialize(:specifications).
|
||||
# as(ProductSpecsSerializer)
|
||||
# end
|
||||
#
|
||||
# ##### as_instance_of
|
||||
#
|
||||
# Use `as_instance_of` if you are using a custom serializer object.
|
||||
#
|
||||
# class ProductOptionsSerializer
|
||||
# def load(string)
|
||||
# # ...
|
||||
# end
|
||||
#
|
||||
# def dump(options)
|
||||
# # ...
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# class Product < ActiveRecord::Base
|
||||
# serialize :options, ProductOptionsSerializer.new
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Product do
|
||||
# it do
|
||||
# should serialize(:options).
|
||||
# as_instance_of(ProductOptionsSerializer)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class ProductTest < ActiveSupport::TestCase
|
||||
# should serialize(:options).
|
||||
# as_instance_of(ProductOptionsSerializer)
|
||||
# end
|
||||
#
|
||||
# @return [SerializeMatcher]
|
||||
#
|
||||
def serialize(name)
|
||||
SerializeMatcher.new(name)
|
||||
end
|
||||
|
||||
class SerializeMatcher # :nodoc:
|
||||
# @private
|
||||
class SerializeMatcher
|
||||
def initialize(name)
|
||||
@name = name.to_s
|
||||
@options = {}
|
||||
|
|
|
@ -2,9 +2,11 @@ module Shoulda
|
|||
module Matchers
|
||||
if Gem.ruby_version >= Gem::Version.new('1.8') && Gem.ruby_version < Gem::Version.new('1.9')
|
||||
require 'test/unit'
|
||||
# @private
|
||||
AssertionError = Test::Unit::AssertionFailedError
|
||||
elsif defined?(Test::Unit::AssertionFailedError)
|
||||
# Test::Unit has been loaded already, so we use it
|
||||
# @private
|
||||
AssertionError = Test::Unit::AssertionFailedError
|
||||
elsif Gem.ruby_version >= Gem::Version.new("1.9")
|
||||
begin
|
||||
|
@ -12,6 +14,7 @@ module Shoulda
|
|||
rescue LoadError
|
||||
require 'minitest/unit'
|
||||
ensure
|
||||
# @private
|
||||
AssertionError = MiniTest::Assertion
|
||||
end
|
||||
else
|
||||
|
|
|
@ -2,6 +2,7 @@ require 'forwardable'
|
|||
|
||||
module Shoulda
|
||||
module Matchers
|
||||
# @private
|
||||
module Doublespeak
|
||||
class << self
|
||||
extend Forwardable
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module Shoulda
|
||||
module Matchers
|
||||
module Doublespeak
|
||||
# @private
|
||||
class Double
|
||||
attr_reader :calls
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module Shoulda
|
||||
module Matchers
|
||||
module Doublespeak
|
||||
# @private
|
||||
class DoubleCollection
|
||||
def initialize(klass)
|
||||
@klass = klass
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module Shoulda
|
||||
module Matchers
|
||||
module Doublespeak
|
||||
# @private
|
||||
module DoubleImplementationRegistry
|
||||
class << self
|
||||
REGISTRY = {}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module Shoulda
|
||||
module Matchers
|
||||
module Doublespeak
|
||||
# @private
|
||||
class ObjectDouble < BasicObject
|
||||
attr_reader :calls
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module Shoulda
|
||||
module Matchers
|
||||
module Doublespeak
|
||||
# @private
|
||||
class ProxyImplementation
|
||||
extend Forwardable
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
module Shoulda
|
||||
module Matchers
|
||||
module Doublespeak
|
||||
# @private
|
||||
MethodCall = Struct.new(:args, :block)
|
||||
# @private
|
||||
MethodCallWithName = Struct.new(:method_name, :args, :block)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module Shoulda
|
||||
module Matchers
|
||||
module Doublespeak
|
||||
# @private
|
||||
class StubImplementation
|
||||
DoubleImplementationRegistry.register(self, :stub)
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module Shoulda
|
||||
module Matchers
|
||||
module Doublespeak
|
||||
# @private
|
||||
class World
|
||||
def register_double_collection(klass)
|
||||
double_collection = DoubleCollection.new(klass)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
module Shoulda
|
||||
module Matchers
|
||||
# @private
|
||||
class Error < StandardError
|
||||
def self.create(attributes)
|
||||
allocate.tap do |error|
|
||||
|
|
|
@ -1,30 +1,117 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module Independent # :nodoc:
|
||||
|
||||
# Ensure that a given method is delegated properly.
|
||||
module Independent
|
||||
# The `delegate_method` matcher tests that an object forwards messages
|
||||
# to other, internal objects by way of delegation.
|
||||
#
|
||||
# Basic Syntax:
|
||||
# it { should delegate_method(method_name).to(delegate_name) }
|
||||
# In this example, we test that Courier forwards a call to #deliver onto
|
||||
# its PostOffice instance:
|
||||
#
|
||||
# Options:
|
||||
# * <tt>:as</tt> - The name of the delegating method. Defaults to
|
||||
# method_name.
|
||||
# * <tt>:with_arguments</tt> - Tests that the delegate method is called
|
||||
# with certain arguments.
|
||||
# require 'forwardable'
|
||||
#
|
||||
# Examples:
|
||||
# it { should delegate_method(:deliver_mail).to(:mailman) }
|
||||
# it { should delegate_method(:deliver_mail).to(:mailman).
|
||||
# as(:deliver_mail_via_mailman) }
|
||||
# it { should delegate_method(:deliver_mail).to(:mailman).
|
||||
# as(:deliver_mail_hastily).
|
||||
# with_arguments('221B Baker St.', hastily: true) }
|
||||
# class Courier
|
||||
# extend Forwardable
|
||||
#
|
||||
# attr_reader :post_office
|
||||
#
|
||||
# def_delegators :post_office, :deliver
|
||||
#
|
||||
# def initialize
|
||||
# @post_office = PostOffice.new
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Courier do
|
||||
# it { should delegate_method(:deliver).to(:post_office) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class CourierTest < Test::Unit::TestCase
|
||||
# should delegate_method(:deliver).to(:post_office)
|
||||
# end
|
||||
#
|
||||
# To employ some terminology, we would say that Courier's #deliver method
|
||||
# is the delegating method, PostOffice is the delegate object, and
|
||||
# PostOffice#deliver is the delegate method.
|
||||
#
|
||||
# #### Qualifiers
|
||||
#
|
||||
# ##### as
|
||||
#
|
||||
# Use `as` if the name of the delegate method is different from the name
|
||||
# of the delegating method.
|
||||
#
|
||||
# Here, Courier has a #deliver method, but instead of calling #deliver on
|
||||
# the PostOffice, it calls #ship:
|
||||
#
|
||||
# class Courier
|
||||
# attr_reader :post_office
|
||||
#
|
||||
# def initialize
|
||||
# @post_office = PostOffice.new
|
||||
# end
|
||||
#
|
||||
# def deliver(package)
|
||||
# post_office.ship(package)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Courier do
|
||||
# it { should delegate_method(:deliver).to(:post_office).as(:ship) }
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class CourierTest < Test::Unit::TestCase
|
||||
# should delegate_method(:deliver).to(:post_office).as(:ship)
|
||||
# end
|
||||
#
|
||||
# ##### with_arguments
|
||||
#
|
||||
# Use `with_arguments` to assert that the delegate method is called with
|
||||
# certain arguments.
|
||||
#
|
||||
# Here, when Courier#deliver calls PostOffice#ship, it adds an options
|
||||
# hash:
|
||||
#
|
||||
# class Courier
|
||||
# attr_reader :post_office
|
||||
#
|
||||
# def initialize
|
||||
# @post_office = PostOffice.new
|
||||
# end
|
||||
#
|
||||
# def deliver(package)
|
||||
# post_office.ship(package, expedited: true)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # RSpec
|
||||
# describe Courier do
|
||||
# it do
|
||||
# should delegate_method(:deliver).
|
||||
# to(:post_office).
|
||||
# as(:ship).
|
||||
# with_arguments(expedited: true)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Test::Unit
|
||||
# class CourierTest < Test::Unit::TestCase
|
||||
# should delegate_method(:deliver).
|
||||
# to(:post_office).
|
||||
# as(:ship).
|
||||
# with_arguments(expedited: true)
|
||||
# end
|
||||
#
|
||||
# @return [DelegateMatcher]
|
||||
#
|
||||
def delegate_method(delegating_method)
|
||||
DelegateMatcher.new(delegating_method)
|
||||
end
|
||||
|
||||
# @private
|
||||
class DelegateMatcher
|
||||
def initialize(delegating_method)
|
||||
@delegating_method = delegating_method
|
||||
|
@ -196,6 +283,7 @@ module Shoulda # :nodoc:
|
|||
string
|
||||
end
|
||||
|
||||
# @private
|
||||
class TargetNotDefinedError < StandardError
|
||||
def message
|
||||
'Delegation needs a target. Use the #to method to define one, e.g.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
module Independent # :nodoc:
|
||||
module Independent
|
||||
# @private
|
||||
class DelegateMatcher::StubbedTarget # :nodoc:
|
||||
def initialize(method)
|
||||
@received_method = false
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
module Shoulda
|
||||
module Matchers
|
||||
# @private
|
||||
module Integrations
|
||||
# @private
|
||||
module NUnitTestCaseDetection
|
||||
def self.possible_test_case_constants
|
||||
[
|
||||
|
@ -29,6 +31,7 @@ module Shoulda
|
|||
end
|
||||
end
|
||||
|
||||
# @private
|
||||
def self.nunit_test_case_constants
|
||||
Integrations::NUnitTestCaseDetection.test_case_constants
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module Shoulda # :nodoc:
|
||||
module Shoulda
|
||||
module Matchers
|
||||
class RailsShim # :nodoc:
|
||||
# @private
|
||||
class RailsShim
|
||||
def self.layouts_ivar
|
||||
if action_pack_major_version >= 4
|
||||
'@_layouts'
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
module Shoulda
|
||||
module Matchers
|
||||
# @private
|
||||
VERSION = '2.6.1'.freeze
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
module Shoulda
|
||||
module Matchers
|
||||
# @private
|
||||
def self.warn(msg)
|
||||
Kernel.warn "Warning from shoulda-matchers:\n\n#{msg}"
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue