Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Move into the Matchers namespace

  • Loading branch information...
commit 56b0a0439e17d53e1cd9429cdcfbbe8fc278d4e4 1 parent ecb01a2
@jferris jferris authored
Showing with 2,577 additions and 2,518 deletions.
  1. +2 −2 Rakefile
  2. +2 −2 features/rails_integration.feature
  3. +8 −0 lib/shoulda-matchers.rb
  4. +0 −8 lib/shoulda.rb
  5. +0 −36 lib/shoulda/action_controller.rb
  6. +0 −112 lib/shoulda/action_controller/assign_to_matcher.rb
  7. +0 −48 lib/shoulda/action_controller/filter_param_matcher.rb
  8. +0 −60 lib/shoulda/action_controller/redirect_to_matcher.rb
  9. +0 −52 lib/shoulda/action_controller/render_template_matcher.rb
  10. +0 −97 lib/shoulda/action_controller/render_with_layout_matcher.rb
  11. +0 −72 lib/shoulda/action_controller/respond_with_content_type_matcher.rb
  12. +0 −83 lib/shoulda/action_controller/respond_with_matcher.rb
  13. +0 −91 lib/shoulda/action_controller/route_matcher.rb
  14. +0 −96 lib/shoulda/action_controller/set_session_matcher.rb
  15. +0 −92 lib/shoulda/action_controller/set_the_flash_matcher.rb
  16. +0 −20 lib/shoulda/action_mailer.rb
  17. +0 −108 lib/shoulda/action_mailer/have_sent_email.rb
  18. +0 −40 lib/shoulda/active_record.rb
  19. +0 −81 lib/shoulda/active_record/allow_mass_assignment_of_matcher.rb
  20. +0 −108 lib/shoulda/active_record/allow_value_matcher.rb
  21. +0 −224 lib/shoulda/active_record/association_matcher.rb
  22. +0 −85 lib/shoulda/active_record/ensure_inclusion_of_matcher.rb
  23. +0 −139 lib/shoulda/active_record/ensure_length_of_matcher.rb
  24. +0 −167 lib/shoulda/active_record/have_db_column_matcher.rb
  25. +0 −110 lib/shoulda/active_record/have_db_index_matcher.rb
  26. +0 −57 lib/shoulda/active_record/have_readonly_attribute_matcher.rb
  27. +0 −32 lib/shoulda/active_record/helpers.rb
  28. +0 −39 lib/shoulda/active_record/validate_acceptance_of_matcher.rb
  29. +0 −63 lib/shoulda/active_record/validate_format_of_matcher.rb
  30. +0 −37 lib/shoulda/active_record/validate_numericality_of_matcher.rb
  31. +0 −58 lib/shoulda/active_record/validate_presence_of_matcher.rb
  32. +0 −146 lib/shoulda/active_record/validate_uniqueness_of_matcher.rb
  33. +0 −54 lib/shoulda/active_record/validation_matcher.rb
  34. +0 −23 lib/shoulda/integrations/rspec.rb
  35. +0 −41 lib/shoulda/integrations/test_unit.rb
  36. +38 −0 lib/shoulda/matchers/action_controller.rb
  37. +114 −0 lib/shoulda/matchers/action_controller/assign_to_matcher.rb
  38. +50 −0 lib/shoulda/matchers/action_controller/filter_param_matcher.rb
  39. +62 −0 lib/shoulda/matchers/action_controller/redirect_to_matcher.rb
  40. +54 −0 lib/shoulda/matchers/action_controller/render_template_matcher.rb
  41. +99 −0 lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb
  42. +74 −0 lib/shoulda/matchers/action_controller/respond_with_content_type_matcher.rb
  43. +85 −0 lib/shoulda/matchers/action_controller/respond_with_matcher.rb
  44. +93 −0 lib/shoulda/matchers/action_controller/route_matcher.rb
  45. +98 −0 lib/shoulda/matchers/action_controller/set_session_matcher.rb
  46. +94 −0 lib/shoulda/matchers/action_controller/set_the_flash_matcher.rb
  47. +22 −0 lib/shoulda/matchers/action_mailer.rb
  48. +110 −0 lib/shoulda/matchers/action_mailer/have_sent_email.rb
  49. +42 −0 lib/shoulda/matchers/active_record.rb
  50. +83 −0 lib/shoulda/matchers/active_record/allow_mass_assignment_of_matcher.rb
  51. +110 −0 lib/shoulda/matchers/active_record/allow_value_matcher.rb
  52. +226 −0 lib/shoulda/matchers/active_record/association_matcher.rb
  53. +87 −0 lib/shoulda/matchers/active_record/ensure_inclusion_of_matcher.rb
  54. +141 −0 lib/shoulda/matchers/active_record/ensure_length_of_matcher.rb
  55. +169 −0 lib/shoulda/matchers/active_record/have_db_column_matcher.rb
  56. +112 −0 lib/shoulda/matchers/active_record/have_db_index_matcher.rb
  57. +59 −0 lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb
  58. +34 −0 lib/shoulda/matchers/active_record/helpers.rb
  59. +41 −0 lib/shoulda/matchers/active_record/validate_acceptance_of_matcher.rb
  60. +65 −0 lib/shoulda/matchers/active_record/validate_format_of_matcher.rb
  61. +39 −0 lib/shoulda/matchers/active_record/validate_numericality_of_matcher.rb
  62. +60 −0 lib/shoulda/matchers/active_record/validate_presence_of_matcher.rb
  63. +148 −0 lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb
  64. +56 −0 lib/shoulda/matchers/active_record/validation_matcher.rb
  65. +23 −0 lib/shoulda/matchers/integrations/rspec.rb
  66. +41 −0 lib/shoulda/matchers/integrations/test_unit.rb
  67. +6 −0 lib/shoulda/matchers/version.rb
  68. +0 −4 lib/shoulda/version.rb
  69. +3 −4 shoulda.gemspec → shoulda-matchers.gemspec
  70. +1 −1  spec/shoulda/action_controller/assign_to_matcher_spec.rb
  71. +1 −1  spec/shoulda/action_controller/filter_param_matcher_spec.rb
  72. +1 −1  spec/shoulda/action_controller/redirect_to_matcher_spec.rb
  73. +1 −1  spec/shoulda/action_controller/render_template_matcher_spec.rb
  74. +1 −1  spec/shoulda/action_controller/render_with_layout_matcher_spec.rb
  75. +1 −1  spec/shoulda/action_controller/respond_with_content_type_matcher_spec.rb
  76. +1 −1  spec/shoulda/action_controller/respond_with_matcher_spec.rb
  77. +1 −1  spec/shoulda/action_controller/route_matcher_spec.rb
  78. +1 −1  spec/shoulda/action_controller/set_session_matcher_spec.rb
  79. +1 −1  spec/shoulda/action_controller/set_the_flash_matcher_spec.rb
  80. +1 −1  spec/shoulda/action_mailer/have_sent_email_spec.rb
  81. +1 −1  spec/shoulda/active_record/allow_mass_assignment_of_matcher_spec.rb
  82. +1 −1  spec/shoulda/active_record/allow_value_matcher_spec.rb
  83. +1 −1  spec/shoulda/active_record/association_matcher_spec.rb
  84. +1 −1  spec/shoulda/active_record/ensure_inclusion_of_matcher_spec.rb
  85. +1 −1  spec/shoulda/active_record/ensure_length_of_matcher_spec.rb
  86. +1 −1  spec/shoulda/active_record/have_db_column_matcher_spec.rb
  87. +1 −1  spec/shoulda/active_record/have_db_index_matcher_spec.rb
  88. +1 −1  spec/shoulda/active_record/have_readonly_attributes_matcher_spec.rb
  89. +1 −1  spec/shoulda/active_record/validate_acceptance_of_matcher_spec.rb
  90. +1 −1  spec/shoulda/active_record/validate_format_of_matcher_spec.rb
  91. +1 −1  spec/shoulda/active_record/validate_numericality_of_matcher_spec.rb
  92. +1 −1  spec/shoulda/active_record/validate_presence_of_matcher_spec.rb
  93. +1 −1  spec/shoulda/active_record/validate_uniqueness_of_matcher_spec.rb
  94. +3 −3 spec/spec_helper.rb
View
4 Rakefile
@@ -7,7 +7,7 @@ require 'rspec/core/rake_task'
require 'cucumber/rake/task'
$LOAD_PATH.unshift("lib")
-require 'shoulda/version'
+require 'shoulda/matchers/version'
Rake::RDocTask.new { |rdoc|
rdoc.rdoc_dir = 'doc'
@@ -31,7 +31,7 @@ RSpec::Core::RakeTask.new(:coverage) do |t|
t.pattern = "spec/**/*_spec.rb"
end
-eval("$specification = begin; #{IO.read('shoulda.gemspec')}; end")
+eval("$specification = begin; #{IO.read('shoulda-matchers.gemspec')}; end")
Rake::GemPackageTask.new $specification do |pkg|
pkg.need_tar = true
pkg.need_zip = true
View
4 features/rails_integration.feature
@@ -33,7 +33,7 @@ Feature: integrate with Rails
Scenario: generate a rails application and use matchers in Test::Unit
When I configure the application to use shoulda-context
- And I configure the application to use "shoulda" from this project
+ And I configure the application to use "shoulda-matchers" from this project
And I write to "test/unit/user_test.rb" with:
"""
require 'test_helper'
@@ -63,7 +63,7 @@ Feature: integrate with Rails
Scenario: generate a rails application and use matchers in Rspec
When I configure the application to use rspec-rails
- And I configure the application to use "shoulda" from this project
+ And I configure the application to use "shoulda-matchers" from this project
And I run the rspec generator
And I write to "spec/models/user_spec.rb" with:
"""
View
8 lib/shoulda-matchers.rb
@@ -0,0 +1,8 @@
+require 'shoulda/matchers/version'
+
+if defined?(RSpec)
+ require 'shoulda/matchers/integrations/rspec'
+else
+ require 'shoulda/matchers/integrations/test_unit'
+end
+
View
8 lib/shoulda.rb
@@ -1,8 +0,0 @@
-require 'shoulda/version'
-
-if defined?(RSpec)
- require 'shoulda/integrations/rspec'
-else
- require 'shoulda/integrations/test_unit'
-end
-
View
36 lib/shoulda/action_controller.rb
@@ -1,36 +0,0 @@
-require 'shoulda/action_controller/assign_to_matcher'
-require 'shoulda/action_controller/filter_param_matcher'
-require 'shoulda/action_controller/set_the_flash_matcher'
-require 'shoulda/action_controller/render_with_layout_matcher'
-require 'shoulda/action_controller/respond_with_matcher'
-require 'shoulda/action_controller/respond_with_content_type_matcher'
-require 'shoulda/action_controller/set_session_matcher'
-require 'shoulda/action_controller/route_matcher'
-require 'shoulda/action_controller/redirect_to_matcher'
-require 'shoulda/action_controller/render_template_matcher'
-
-module Shoulda
- # 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 assign_to(:user) }
- # it { should respond_with(:success) }
- # it { should render_template(:show) }
- # it { should not_set_the_flash) }
- #
- # it "should do something else really cool" do
- # assigns[:user].id.should == 1
- # end
- # end
- #
- # Would produce 5 tests for the show action
- module ActionController
- end
-end
View
112 lib/shoulda/action_controller/assign_to_matcher.rb
@@ -1,112 +0,0 @@
-module Shoulda # :nodoc:
- module ActionController # :nodoc:
-
- # Ensures that the controller assigned to the named instance variable.
- #
- # Options:
- # * <tt>with_kind_of</tt> - The expected class of the instance variable
- # being checked.
- # * <tt>with</tt> - The value that should be assigned.
- #
- # Example:
- #
- # it { should assign_to(:user) }
- # it { should_not assign_to(:user) }
- # it { should assign_to(:user).with_kind_of(User) }
- # it { should assign_to(:user).with(@user) }
- def assign_to(variable)
- AssignToMatcher.new(variable)
- end
-
- class AssignToMatcher # :nodoc:
-
- def initialize(variable)
- @variable = variable.to_s
- @check_value = false
- end
-
- def with_kind_of(expected_class)
- @expected_class = expected_class
- self
- end
-
- def with(expected_value = nil, &block)
- @check_value = true
- @expected_value = expected_value
- @expectation_block = block
- self
- end
-
- def matches?(controller)
- @controller = controller
- @expected_value = @context.instance_eval(&@expectation_block) if @expectation_block
- assigned_value? && kind_of_expected_class? && equal_to_expected_value?
- end
-
- attr_reader :failure_message, :negative_failure_message
-
- def description
- description = "assign @#{@variable}"
- description << " with a kind of #{@expected_class}" if @expected_class
- description
- end
-
- def in_context(context)
- @context = context
- self
- end
-
- private
-
- def assigned_value?
- if !@controller.instance_variables.include?("@#{@variable}")
- @failure_message =
- "Expected action to assign a value for @#{@variable}"
- false
- else
- @negative_failure_message =
- "Didn't expect action to assign a value for @#{@variable}, " <<
- "but it was assigned to #{assigned_value.inspect}"
- true
- end
- end
-
- def kind_of_expected_class?
- return true unless @expected_class
- if assigned_value.kind_of?(@expected_class)
- @negative_failure_message =
- "Didn't expect action to assign a kind of #{@expected_class} " <<
- "for #{@variable}, but got one anyway"
- true
- else
- @failure_message =
- "Expected action to assign a kind of #{@expected_class} " <<
- "for #{@variable}, but got #{@variable.inspect} " <<
- "(#{@variable.class.name})"
- false
- end
- end
-
- def equal_to_expected_value?
- return true unless @check_value
- if @expected_value == assigned_value
- @negative_failure_message =
- "Didn't expect action to assign #{@expected_value.inspect} " <<
- "for #{@variable}, but got it anyway"
- true
- else
- @failure_message =
- "Expected action to assign #{@expected_value.inspect} " <<
- "for #{@variable}, but got #{assigned_value.inspect}"
- false
- end
- end
-
- def assigned_value
- @controller.instance_variable_get("@#{@variable}")
- end
-
- end
-
- end
-end
View
48 lib/shoulda/action_controller/filter_param_matcher.rb
@@ -1,48 +0,0 @@
-module Shoulda # :nodoc:
- module ActionController # :nodoc:
-
- # Ensures that filter_parameter_logging is set for the specified key.
- #
- # Example:
- #
- # it { should filter_param(:password) }
- def filter_param(key)
- FilterParamMatcher.new(key)
- end
-
- class FilterParamMatcher # :nodoc:
-
- def initialize(key)
- @key = key.to_s
- end
-
- def matches?(controller)
- @controller = controller
- filters_key?
- end
-
- def failure_message
- "Expected #{@key} to be filtered; filtered keys: #{filtered_keys.join(', ')}"
- end
-
- def negative_failure_message
- "Did not expect #{@key} to be filtered"
- end
-
- def description
- "filter #{@key}"
- end
-
- private
-
- def filters_key?
- filtered_keys.include?(@key)
- end
-
- def filtered_keys
- Rails.application.config.filter_parameters.map { |filter| filter.to_s }
- end
- end
-
- end
-end
View
60 lib/shoulda/action_controller/redirect_to_matcher.rb
@@ -1,60 +0,0 @@
-module Shoulda # :nodoc:
- module ActionController # :nodoc:
-
- # Ensures a controller redirected to the given url.
- #
- # Example:
- #
- # 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:
-
- def initialize(url_or_description, context, &block)
- if block
- @url_block = block
- @location = @url_or_description
- else
- @url = url_or_description
- @location = @url
- end
- @context = context
- end
-
- def in_context(context)
- @context = context
- self
- end
-
- def matches?(controller)
- @controller = controller
- redirects_to_url?
- end
-
- attr_reader :failure_message, :negative_failure_message
-
- def description
- "redirect to #{@location}"
- end
-
- private
-
- def redirects_to_url?
- @url = @context.instance_eval(&@url_block) if @url_block
- begin
- @context.send(:assert_redirected_to, @url)
- @negative_failure_message = "Didn't expect to redirect to #{@url}"
- true
- rescue Test::Unit::AssertionFailedError => error
- @failure_message = error.message
- false
- end
- end
-
- end
-
- end
-end
View
52 lib/shoulda/action_controller/render_template_matcher.rb
@@ -1,52 +0,0 @@
-module Shoulda # :nodoc:
- module ActionController # :nodoc:
-
- # Ensures a controller rendered the given template.
- #
- # Example:
- #
- # it { should render_template(:show) }
- def render_template(template)
- RenderTemplateMatcher.new(template, self)
- end
-
- class RenderTemplateMatcher # :nodoc:
-
- def initialize(template, context)
- @template = template.to_s
- @context = context
- end
-
- def matches?(controller)
- @controller = controller
- renders_template?
- end
-
- attr_reader :failure_message, :negative_failure_message
-
- def description
- "render template #{@template}"
- end
-
- def in_context(context)
- @context = context
- self
- end
-
- private
-
- def renders_template?
- begin
- @context.send(:assert_template, @template)
- @negative_failure_message = "Didn't expect to render #{@template}"
- true
- rescue Test::Unit::AssertionFailedError => error
- @failure_message = error.message
- false
- end
- end
-
- end
-
- end
-end
View
97 lib/shoulda/action_controller/render_with_layout_matcher.rb
@@ -1,97 +0,0 @@
-module Shoulda # :nodoc:
- module ActionController # :nodoc:
-
- # Ensures that the controller rendered with the given layout.
- #
- # Example:
- #
- # 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:
-
- def initialize(expected_layout)
- @expected_layout = expected_layout.to_s unless expected_layout.nil?
- end
-
- # Used to provide access to layouts recorded by
- # ActionController::TemplateAssertions in Rails 3
- def in_context(context)
- @context = context
- self
- end
-
- def matches?(controller)
- @controller = controller
- rendered_with_layout? && rendered_with_expected_layout?
- end
-
- def failure_message
- "Expected #{expectation}, but #{result}"
- end
-
- def negative_failure_message
- "Did not expect #{expectation}, but #{result}"
- end
-
- def description
- description = "render with "
- if @expected_layout.nil?
- description << "a layout"
- else
- description << "the #{@expected_layout.inspect} layout"
- end
- description
- end
-
- private
-
- def rendered_with_layout?
- !rendered_layouts.empty?
- end
-
- def rendered_with_expected_layout?
- return true if @expected_layout.nil?
- rendered_layouts.include?(@expected_layout)
- end
-
- def rendered_layouts
- if recorded_layouts
- recorded_layouts.keys.compact.map { |layout| layout.sub(%r{^layouts/}, '') }
- else
- layout = @controller.response.layout
- if layout.nil?
- []
- else
- [layout.split('/').last]
- end
- end
- end
-
- def recorded_layouts
- if @context
- @context.instance_variable_get('@layouts')
- end
- end
-
- def expectation
- "to #{description}"
- end
-
- def result
- if rendered_with_layout?
- "rendered with " <<
- rendered_layouts.map { |layout| layout.inspect }.join(", ")
- else
- "rendered without a layout"
- end
- end
-
- end
-
- end
-end
View
72 lib/shoulda/action_controller/respond_with_content_type_matcher.rb
@@ -1,72 +0,0 @@
-module Shoulda # :nodoc:
- module ActionController # :nodoc:
-
- # Ensures a controller responded with expected 'response' content type.
- #
- # You can pass an explicit content type such as 'application/rss+xml'
- # or its symbolic equivalent :rss
- # or a regular expression such as /rss/
- #
- # Example:
- #
- # it { should respond_with_content_type(:xml) }
- # it { should respond_with_content_type(:csv) }
- # it { should respond_with_content_type(:atom) }
- # it { should respond_with_content_type(:yaml) }
- # it { should respond_with_content_type(:text) }
- # it { should respond_with_content_type('application/rss+xml') }
- # it { should respond_with_content_type(/json/) }
- def respond_with_content_type(content_type)
- RespondWithContentTypeMatcher.new(content_type)
- end
-
- class RespondWithContentTypeMatcher # :nodoc:
-
- def initialize(content_type)
- @content_type = if content_type.is_a?(Symbol)
- lookup_by_extension(content_type)
- else
- content_type
- end
- end
-
- def description
- "respond with content type of #{@content_type}"
- end
-
- def matches?(controller)
- @controller = controller
- if @content_type.is_a?(Regexp)
- response_content_type =~ @content_type
- else
- response_content_type == @content_type
- end
- end
-
- def failure_message
- "Expected #{expectation}"
- end
-
- def negative_failure_message
- "Did not expect #{expectation}"
- end
-
- protected
-
- def response_content_type
- @controller.response.content_type.to_s
- end
-
- def lookup_by_extension(extension)
- Mime::Type.lookup_by_extension(extension.to_s).to_s
- end
-
- def expectation
- "content type to be #{@content_type}, " <<
- "but was #{response_content_type}"
- end
-
- end
-
- end
-end
View
83 lib/shoulda/action_controller/respond_with_matcher.rb
@@ -1,83 +0,0 @@
-module Shoulda # :nodoc:
- module ActionController # :nodoc:
-
- # Ensures a controller responded with expected 'response' 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.
- #
- # Example:
- #
- # 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:
-
- def initialize(status)
- @status = symbol_to_status_code(status)
- end
-
- def matches?(controller)
- @controller = controller
- correct_status_code? || correct_status_code_range?
- end
-
- def failure_message
- "Expected #{expectation}"
- end
-
- def negative_failure_message
- "Did not expect #{expectation}"
- end
-
- def description
- "respond with #{@status}"
- end
-
- protected
-
- def correct_status_code?
- response_code == @status
- end
-
- def correct_status_code_range?
- @status.is_a?(Range) &&
- @status.include?(response_code)
- end
-
- def response_code
- @controller.response.response_code
- end
-
- def symbol_to_status_code(potential_symbol)
- case potential_symbol
- when :success then 200
- when :redirect then 300..399
- when :missing then 404
- when :error then 500..599
- when Symbol
- if defined?(::Rack::Utils::SYMBOL_TO_STATUS_CODE)
- ::Rack::Utils::SYMBOL_TO_STATUS_CODE[potential_symbol]
- else
- ::ActionController::Base::SYMBOL_TO_STATUS_CODE[potential_symbol]
- end
- else
- potential_symbol
- end
- end
-
- def expectation
- "response to be a #{@status}, but was #{response_code}"
- end
-
- end
-
- end
-end
View
91 lib/shoulda/action_controller/route_matcher.rb
@@ -1,91 +0,0 @@
-module Shoulda # :nodoc:
- module ActionController # :nodoc:
-
- # Ensures that requesting +path+ using +method+ routes to +options+.
- #
- # If you don't specify a controller, it will use the controller from the
- # example group.
- #
- # +to_param+ is called on the +options+ given.
- #
- # Examples:
- #
- # it { should route(:get, "/posts").
- # to(:controller => :posts, :action => :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(:edit, "/posts/1").to(:action => :show, :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) }
- def route(method, path)
- RouteMatcher.new(method, path, self)
- end
-
- class RouteMatcher # :nodoc:
-
- def initialize(method, path, context)
- @method = method
- @path = path
- @context = context
- end
-
- def to(params)
- @params = params
- stringify_params!
- self
- end
-
- def in_context(context)
- @context = context
- self
- end
-
- def matches?(controller)
- @controller = controller
- guess_controller!
- route_recognized?
- end
-
- attr_reader :failure_message, :negative_failure_message
-
- def description
- "route #{@method.to_s.upcase} #{@path} to/from #{@params.inspect}"
- end
-
- private
-
- def guess_controller!
- @params[:controller] ||= @controller.controller_path
- end
-
- def stringify_params!
- @params.each do |key, value|
- @params[key] = value.is_a?(Array) ? value.collect {|v| v.to_param } : value.to_param
- end
- end
-
- def route_recognized?
- begin
- @context.send(:assert_routing,
- { :method => @method, :path => @path },
- @params)
-
- @negative_failure_message = "Didn't expect to #{description}"
- true
- rescue ::ActionController::RoutingError => error
- @failure_message = error.message
- false
- rescue Test::Unit::AssertionFailedError => error
- @failure_message = error.message
- false
- end
- end
-
- end
-
- end
-end
View
96 lib/shoulda/action_controller/set_session_matcher.rb
@@ -1,96 +0,0 @@
-module Shoulda # :nodoc:
- module ActionController # :nodoc:
-
- # Ensures that a session key was set to the expected value.
- #
- # Example:
- #
- # 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:
-
- def initialize(key)
- @key = key.to_s
- end
-
- def to(value = nil, &block)
- @value = value
- @value_block = block
- self
- end
-
- def matches?(controller)
- @controller = controller
- @value = @context.instance_eval(&@value_block) if @value_block
- (assigned_value? && assigned_correct_value?) || cleared_value?
- end
-
- def failure_message
- "Expected #{expectation}, but #{result}"
- end
-
- def negative_failure_message
- "Didn't expect #{expectation}, but #{result}"
- end
-
- def description
- description = "set session variable #{@key.inspect}"
- description << " to #{@value.inspect}" if defined?(@value)
- description
- end
-
- def in_context(context)
- @context = context
- self
- end
-
- private
-
- def assigned_value?
- !assigned_value.nil?
- end
-
- def cleared_value?
- defined?(@value) && @value.nil? && assigned_value.nil?
- end
-
- def assigned_correct_value?
- return true if @value.nil?
- assigned_value == @value
- end
-
- def assigned_value
- session[@key]
- end
-
- def session
- if @controller.request.respond_to?(:session)
- @controller.request.session.to_hash
- else
- @controller.response.session.data
- end
- end
-
- def expectation
- expectation = "session variable #{@key} to be set"
- expectation << " to #{@value.inspect}" if @value
- expectation
- end
-
- def result
- if session.empty?
- "no session variables were set"
- else
- "the session was #{session.inspect}"
- end
- end
-
- end
-
- end
-end
View
92 lib/shoulda/action_controller/set_the_flash_matcher.rb
@@ -1,92 +0,0 @@
-module Shoulda # :nodoc:
- 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).
- #
- # Example:
- #
- # 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.to(/logged in/i).now }
- # it { should_not set_the_flash }
- def set_the_flash
- SetTheFlashMatcher.new
- end
-
- class SetTheFlashMatcher # :nodoc:
-
- def to(value)
- @value = value
- self
- end
-
- def now
- @now = true
- self
- end
-
- def matches?(controller)
- @controller = controller
- sets_the_flash? && string_value_matches? && regexp_value_matches?
- end
-
- attr_reader :failure_message, :negative_failure_message
-
- def description
- description = "set the flash"
- description << " to #{@value.inspect}" unless @value.nil?
- description
- end
-
- def failure_message
- "Expected #{expectation}"
- end
-
- def negative_failure_message
- "Did not expect #{expectation}"
- end
-
- private
-
- def sets_the_flash?
- !flash.blank?
- end
-
- def string_value_matches?
- return true unless String === @value
- flash.values.any? {|value| value == @value }
- end
-
- def regexp_value_matches?
- return true unless Regexp === @value
- flash.values.any? {|value| value =~ @value }
- end
-
- def flash
- return @flash if @flash
- @flash = @controller.flash.dup
- @flash.sweep unless @now
- @flash
- end
-
- def expectation
- expectation = "the flash#{".now" if @now} to be set"
- expectation << " to #{@value.inspect}" unless @value.nil?
- expectation << ", but #{flash_description}"
- expectation
- end
-
- def flash_description
- if flash.blank?
- "no flash was set"
- else
- "was #{flash.inspect}"
- end
- end
-
- end
-
- end
-end
View
20 lib/shoulda/action_mailer.rb
@@ -1,20 +0,0 @@
-require 'shoulda/action_mailer/have_sent_email'
-
-module Shoulda
- # = Matchers for your mailers
- #
- # This matcher will test that email is sent properly
- #
- # describe User do
- # it { should have_sent_email.with_subject(/is spam$/) }
- # it { should have_sent_email.from('do-not-reply@example.com') }
- # it { should have_sent_email.with_body(/is spam\./) }
- # it { should have_sent_email.to('myself@me.com') }
- # it { should have_sent_email.with_subject(/spam/).
- # from('do-not-reply@example.com').
- # with_body(/spam/).
- # to('myself@me.com') }
- # end
- module ActionMailer
- end
-end
View
108 lib/shoulda/action_mailer/have_sent_email.rb
@@ -1,108 +0,0 @@
-module Shoulda # :nodoc:
- module ActionMailer # :nodoc:
-
- # The right email is sent.
- #
- # it { should have_sent_email.with_subject(/is spam$/) }
- # it { should have_sent_email.from('do-not-reply@example.com') }
- # it { should have_sent_email.with_body(/is spam\./) }
- # it { should have_sent_email.to('myself@me.com') }
- # it { should have_sent_email.with_subject(/spam/).
- # from('do-not-reply@example.com').
- # with_body(/spam/).
- # to('myself@me.com') }
- def have_sent_email
- HaveSentEmailMatcher.new
- end
-
- class HaveSentEmailMatcher # :nodoc:
-
- def initialize
- end
-
- def with_subject(email_subject)
- @email_subject = email_subject
- self
- end
-
- def from(sender)
- @sender = sender
- self
- end
-
- def with_body(body)
- @body = body
- self
- end
-
- def to(recipient)
- @recipient = recipient
- self
- end
-
- def matches?(subject)
- ::ActionMailer::Base.deliveries.each do |mail|
- @subject_failed = !regexp_or_string_match(mail.subject, @email_subject) if @email_subject
- @body_failed = !regexp_or_string_match(mail.body, @body) if @body
- @sender_failed = !regexp_or_string_match_in_array(mail.from, @sender) if @sender
- @recipient_failed = !regexp_or_string_match_in_array(mail.to, @recipient) if @recipient
- return true unless anything_failed?
- end
-
- false
- end
-
- def failure_message
- "Expected #{expectation}"
- end
-
- def negative_failure_message
- "Did not expect #{expectation}"
- end
-
- def description
- "send an email"
- end
-
- private
-
- def expectation
- expectation = "sent email"
- expectation << " with subject #{@email_subject.inspect}" if @subject_failed
- expectation << " with body #{@body.inspect}" if @body_failed
- expectation << " from #{@sender.inspect}" if @sender_failed
- expectation << " to #{@recipient.inspect}" if @recipient_failed
- expectation << "\nDeliveries:\n#{inspect_deliveries}"
- end
-
- def inspect_deliveries
- ::ActionMailer::Base.deliveries.map do |delivery|
- "#{delivery.subject.inspect} to #{delivery.to.inspect}"
- end.join("\n")
- end
-
- def anything_failed?
- @subject_failed || @body_failed || @sender_failed || @recipient_failed
- end
-
- def regexp_or_string_match(a_string, a_regexp_or_string)
- case a_regexp_or_string
- when Regexp
- a_string =~ a_regexp_or_string
- when String
- a_string == a_regexp_or_string
- end
- end
-
- def regexp_or_string_match_in_array(an_array, a_regexp_or_string)
- case a_regexp_or_string
- when Regexp
- an_array.any? { |string| string =~ a_regexp_or_string }
- when String
- an_array.include?(a_regexp_or_string)
- end
- end
- end
- end
-end
-
View
40 lib/shoulda/active_record.rb
@@ -1,40 +0,0 @@
-require 'shoulda/active_record/helpers'
-require 'shoulda/active_record/validation_matcher'
-require 'shoulda/active_record/allow_value_matcher'
-require 'shoulda/active_record/ensure_length_of_matcher'
-require 'shoulda/active_record/ensure_inclusion_of_matcher'
-require 'shoulda/active_record/validate_presence_of_matcher'
-require 'shoulda/active_record/validate_format_of_matcher'
-require 'shoulda/active_record/validate_uniqueness_of_matcher'
-require 'shoulda/active_record/validate_acceptance_of_matcher'
-require 'shoulda/active_record/validate_numericality_of_matcher'
-require 'shoulda/active_record/association_matcher'
-require 'shoulda/active_record/have_db_column_matcher'
-require 'shoulda/active_record/have_db_index_matcher'
-require 'shoulda/active_record/have_readonly_attribute_matcher'
-require 'shoulda/active_record/allow_mass_assignment_of_matcher'
-
-
-module Shoulda
- # = Matchers for your active record models
- #
- # These matchers will test most of the validations and associations for your
- # ActiveRecord models.
- #
- # 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 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
View
81 lib/shoulda/active_record/allow_mass_assignment_of_matcher.rb
@@ -1,81 +0,0 @@
-module Shoulda # :nodoc:
- module ActiveRecord # :nodoc:
-
- # Ensures that the attribute can be set on mass update.
- #
- # it { should_not allow_mass_assignment_of(:password) }
- # it { should allow_mass_assignment_of(:first_name) }
- #
- def allow_mass_assignment_of(value)
- AllowMassAssignmentOfMatcher.new(value)
- end
-
- class AllowMassAssignmentOfMatcher # :nodoc:
-
- def initialize(attribute)
- @attribute = attribute.to_s
- end
-
- def matches?(subject)
- @subject = subject
- if attr_mass_assignable?
- if whitelisting?
- @negative_failure_message = "#{@attribute} was made accessible"
- else
- if protected_attributes.empty?
- @negative_failure_message = "no attributes were protected"
- else
- @negative_failure_message = "#{class_name} is protecting " <<
- "#{protected_attributes.to_a.to_sentence}, " <<
- "but not #{@attribute}."
- end
- end
- true
- else
- if whitelisting?
- @failure_message =
- "Expected #{@attribute} to be accessible"
- else
- @failure_message =
- "Did not expect #{@attribute} to be protected"
- end
- false
- end
- end
-
- attr_reader :failure_message, :negative_failure_message
-
- def description
- "allow mass assignment of #{@attribute}"
- end
-
- private
-
- def protected_attributes
- @protected_attributes ||= (@subject.class.protected_attributes || [])
- end
-
- def accessible_attributes
- @accessible_attributes ||= (@subject.class.accessible_attributes || [])
- end
-
- def whitelisting?
- !accessible_attributes.empty?
- end
-
- def attr_mass_assignable?
- if whitelisting?
- accessible_attributes.include?(@attribute)
- else
- !protected_attributes.include?(@attribute)
- end
- end
-
- def class_name
- @subject.class.name
- end
-
- end
-
- end
-end
View
108 lib/shoulda/active_record/allow_value_matcher.rb
@@ -1,108 +0,0 @@
-module Shoulda # :nodoc:
- module ActiveRecord # :nodoc:
-
- # Ensures that the attribute can be set to the given value.
- #
- # 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>.
- #
- # Example:
- # it { should_not allow_value('bad').for(:isbn) }
- # it { should allow_value("isbn 1 2345 6789 0").for(:isbn) }
- #
- def allow_value(value)
- AllowValueMatcher.new(value)
- end
-
- class AllowValueMatcher # :nodoc:
- include Helpers
-
- def initialize(value)
- @value = value
- end
-
- def for(attribute)
- @attribute = attribute
- self
- end
-
- def with_message(message)
- @expected_message = message if message
- self
- end
-
- def matches?(instance)
- @instance = instance
- if Symbol === @expected_message
- @expected_message = default_error_message(@expected_message)
- end
- @instance.send("#{@attribute}=", @value)
- !errors_match?
- end
-
- def failure_message
- "Did not expect #{expectation}, got error: #{@matched_error}"
- end
-
- def negative_failure_message
- "Expected #{expectation}, got #{error_description}"
- end
-
- def description
- "allow #{@attribute} to be set to #{@value.inspect}"
- end
-
- private
-
- def errors_match?
- @instance.valid?
- @errors = errors_for_attribute(@instance, @attribute)
- @errors = [@errors] unless @errors.is_a?(Array)
- @expected_message ? (errors_match_regexp? || errors_match_string?) : (@errors.compact.any?)
- end
-
- def errors_for_attribute(instance, attribute)
- if instance.errors.respond_to?(:[])
- instance.errors[attribute]
- else
- instance.errors.on(attribute)
- end
- end
-
- def errors_match_regexp?
- if Regexp === @expected_message
- @matched_error = @errors.detect { |e| e =~ @expected_message }
- !@matched_error.nil?
- else
- false
- end
- end
-
- def errors_match_string?
- if @errors.include?(@expected_message)
- @matched_error = @expected_message
- true
- else
- false
- end
- end
-
- def expectation
- "errors " <<
- (@expected_message ? "to include #{@expected_message.inspect} " : "") <<
- "when #{@attribute} is set to #{@value.inspect}"
- end
-
- def error_description
- if @instance.errors.empty?
- "no errors"
- else
- "errors: #{pretty_error_messages(@instance)}"
- end
- end
- end
-
- end
-end
View
224 lib/shoulda/active_record/association_matcher.rb
@@ -1,224 +0,0 @@
-module Shoulda # :nodoc:
- module ActiveRecord # :nodoc:
-
- # Ensure that the belongs_to relationship exists.
- #
- # it { should belong_to(:parent) }
- #
- 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.
- #
- # 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.
- #
- # Example:
- # it { should have_many(:friends) }
- # it { should have_many(:enemies).through(:friends) }
- # it { should have_many(:enemies).dependent(:destroy) }
- #
- 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.
- #
- # Options:
- # * <tt>:dependent</tt> - tests that the association makes use of the
- # dependent option.
- #
- # Example:
- # it { should have_one(:god) } # unless hindu
- #
- 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.
- #
- # it { should have_and_belong_to_many(:posts) }
- #
- def have_and_belong_to_many(name)
- AssociationMatcher.new(:has_and_belongs_to_many, name)
- end
-
- class AssociationMatcher # :nodoc:
- def initialize(macro, name)
- @macro = macro
- @name = name
- end
-
- def through(through)
- @through = through
- self
- end
-
- def dependent(dependent)
- @dependent = dependent
- self
- end
-
- def matches?(subject)
- @subject = subject
- association_exists? &&
- macro_correct? &&
- foreign_key_exists? &&
- through_association_valid? &&
- dependent_correct? &&
- join_table_exists?
- end
-
- def failure_message
- "Expected #{expectation} (#{@missing})"
- end
-
- def negative_failure_message
- "Did not expect #{expectation}"
- end
-
- def description
- description = "#{macro_description} #{@name}"
- description += " through #{@through}" if @through
- description += " dependent => #{@dependent}" if @dependent
- description
- end
-
- protected
-
- def association_exists?
- if reflection.nil?
- @missing = "no association called #{@name}"
- false
- else
- true
- end
- end
-
- def macro_correct?
- if reflection.macro == @macro
- true
- else
- @missing = "actual association type was #{reflection.macro}"
- false
- end
- end
-
- def foreign_key_exists?
- !(belongs_foreign_key_missing? || has_foreign_key_missing?)
- end
-
- def belongs_foreign_key_missing?
- @macro == :belongs_to && !class_has_foreign_key?(model_class)
- end
-
- def has_foreign_key_missing?
- [:has_many, :has_one].include?(@macro) &&
- !through? &&
- !class_has_foreign_key?(associated_class)
- end
-
- def through_association_valid?
- @through.nil? || (through_association_exists? && through_association_correct?)
- end
-
- def through_association_exists?
- if through_reflection.nil?
- @missing = "#{model_class.name} does not have any relationship to #{@through}"
- false
- else
- true
- end
- end
-
- def through_association_correct?
- if @through == reflection.options[:through]
- true
- else
- @missing = "Expected #{model_class.name} to have #{@name} through #{@through}, " <<
- "but got it through #{reflection.options[:through]}"
- false
- end
- end
-
- def dependent_correct?
- if @dependent.nil? || @dependent.to_s == reflection.options[:dependent].to_s
- true
- else
- @missing = "#{@name} should have #{@dependent} dependency"
- false
- end
- end
-
- def join_table_exists?
- if @macro != :has_and_belongs_to_many ||
- ::ActiveRecord::Base.connection.tables.include?(join_table.to_s)
- true
- else
- @missing = "join table #{join_table} doesn't exist"
- false
- end
- end
-
- def class_has_foreign_key?(klass)
- if klass.column_names.include?(foreign_key.to_s)
- true
- else
- @missing = "#{klass} does not have a #{foreign_key} foreign key."
- false
- end
- end
-
- def model_class
- @subject.class
- end
-
- def join_table
- reflection.options[:join_table]
- end
-
- def associated_class
- reflection.klass
- end
-
- def foreign_key
- reflection.primary_key_name
- end
-
- def through?
- reflection.options[:through]
- end
-
- def reflection
- @reflection ||= model_class.reflect_on_association(@name)
- end
-
- def through_reflection
- @through_reflection ||= model_class.reflect_on_association(@through)
- end
-
- def expectation
- "#{model_class.name} to have a #{@macro} association called #{@name}"
- end
-
- def macro_description
- case @macro.to_s
- when 'belongs_to' then 'belong to'
- when 'has_many' then 'have many'
- when 'has_one' then 'have one'
- when 'has_and_belongs_to_many' then
- 'have and belong to many'
- end
- end
- end
-
- end
-end
View
85 lib/shoulda/active_record/ensure_inclusion_of_matcher.rb
@@ -1,85 +0,0 @@
-module Shoulda # :nodoc:
- module ActiveRecord # :nodoc:
-
- # Ensure that the attribute's value is in the range specified
- #
- # Options:
- # * <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.
- #
- # Example:
- # it { should ensure_inclusion_of(:age).in_range(0..100) }
- #
- def ensure_inclusion_of(attr)
- EnsureInclusionOfMatcher.new(attr)
- end
-
- class EnsureInclusionOfMatcher < ValidationMatcher # :nodoc:
-
- def in_range(range)
- @range = range
- @minimum = range.first
- @maximum = range.last
- self
- end
-
- def with_message(message)
- if message
- @low_message = message
- @high_message = message
- end
- self
- end
-
- def with_low_message(message)
- @low_message = message if message
- self
- end
-
- def with_high_message(message)
- @high_message = message if message
- self
- end
-
- def description
- "ensure inclusion of #{@attribute} in #{@range.inspect}"
- end
-
- def matches?(subject)
- super(subject)
-
- @low_message ||= :inclusion
- @high_message ||= :inclusion
-
- disallows_lower_value &&
- allows_minimum_value &&
- disallows_higher_value &&
- allows_maximum_value
- end
-
- private
-
- def disallows_lower_value
- @minimum == 0 || disallows_value_of(@minimum - 1, @low_message)
- end
-
- def disallows_higher_value
- disallows_value_of(@maximum + 1, @high_message)
- end
-
- def allows_minimum_value
- allows_value_of(@minimum, @low_message)
- end
-
- def allows_maximum_value
- allows_value_of(@maximum, @high_message)
- end
- end
-
- end
-end
View
139 lib/shoulda/active_record/ensure_length_of_matcher.rb
@@ -1,139 +0,0 @@
-module Shoulda # :nodoc:
- module ActiveRecord # :nodoc:
-
- # Ensures that the length of the attribute is validated.
- #
- # 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>.
- #
- # 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:
- include Helpers
-
- def is_at_least(length)
- @minimum = length
- @short_message ||= :too_short
- self
- end
-
- def is_at_most(length)
- @maximum = length
- @long_message ||= :too_long
- self
- end
-
- def is_equal_to(length)
- @minimum = length
- @maximum = length
- @short_message ||= :wrong_length
- self
- end
-
- def with_short_message(message)
- @short_message = message if message
- self
- end
- alias_method :with_message, :with_short_message
-
- def with_long_message(message)
- @long_message = message if message
- self
- end
-
- def description
- description = "ensure #{@attribute} has a length "
- if @minimum && @maximum
- if @minimum == @maximum
- description << "of exactly #{@minimum}"
- else
- description << "between #{@minimum} and #{@maximum}"
- end
- else
- description << "of at least #{@minimum}" if @minimum
- description << "of at most #{@maximum}" if @maximum
- end
- description
- end
-
- def matches?(subject)
- super(subject)
- translate_messages!
- disallows_lower_length &&
- allows_minimum_length &&
- ((@minimum == @maximum) ||
- (disallows_higher_length &&
- allows_maximum_length))
- end
-
- private
-
- def translate_messages!
- if Symbol === @short_message
- @short_message = default_error_message(@short_message,
- :count => @minimum)
- end
-
- if Symbol === @long_message
- @long_message = default_error_message(@long_message,
- :count => @maximum)
- end
- end
-
- def disallows_lower_length
- @minimum == 0 ||
- @minimum.nil? ||
- disallows_length_of(@minimum - 1, @short_message)
- end
-
- def disallows_higher_length
- @maximum.nil? || disallows_length_of(@maximum + 1, @long_message)
- end
-
- def allows_minimum_length
- allows_length_of(@minimum, @short_message)
- end
-
- def allows_maximum_length
- allows_length_of(@maximum, @long_message)
- end
-
- def allows_length_of(length, message)
- length.nil? || allows_value_of(string_of_length(length), message)
- end
-
- def disallows_length_of(length, message)
- length.nil? || disallows_value_of(string_of_length(length), message)
- end
-
- def string_of_length(length)
- 'x' * length
- end
- end
-
- end
-end
View
167 lib/shoulda/active_record/have_db_column_matcher.rb
@@ -1,167 +0,0 @@
-module Shoulda # :nodoc:
- module ActiveRecord # :nodoc:
-
- # Ensures the database column exists.
- #
- # 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)
- #
- # 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) }
- #
- def have_db_column(column)
- HaveDbColumnMatcher.new(:have_db_column, column)
- end
-
- class HaveDbColumnMatcher # :nodoc:
- def initialize(macro, column)
- @macro = macro
- @column = column
- end
-
- def of_type(column_type)
- @column_type = column_type
- self
- end
-
- def with_options(opts = {})
- @precision = opts[:precision]
- @limit = opts[:limit]
- @default = opts[:default]
- @null = opts[:null]
- @scale = opts[:scale]
- self
- end
-
- def matches?(subject)
- @subject = subject
- column_exists? &&
- correct_column_type? &&
- correct_precision? &&
- correct_limit? &&
- correct_default? &&
- correct_null? &&
- correct_scale?
- end
-
- def failure_message
- "Expected #{expectation} (#{@missing})"
- end
-
- def negative_failure_message
- "Did not expect #{expectation}"
- end
-
- def description
- desc = "have db column named #{@column}"
- desc << " of type #{@column_type}" unless @column_type.nil?
- desc << " of precision #{@precision}" unless @precision.nil?
- desc << " of limit #{@limit}" unless @limit.nil?
- desc << " of default #{@default}" unless @default.nil?
- desc << " of null #{@null}" unless @null.nil?
- desc << " of primary #{@primary}" unless @primary.nil?
- desc << " of scale #{@scale}" unless @scale.nil?
- desc
- end
-
- protected
-
- def column_exists?
- if model_class.column_names.include?(@column.to_s)
- true
- else
- @missing = "#{model_class} does not have a db column named #{@column}."
- false
- end
- end
-
- def correct_column_type?
- return true if @column_type.nil?
- if matched_column.type.to_s == @column_type.to_s
- true
- else
- @missing = "#{model_class} has a db column named #{@column} " <<
- "of type #{matched_column.type}, not #{@column_type}."
- false
- end
- end
-
- def correct_precision?
- return true if @precision.nil?
- if matched_column.precision.to_s == @precision.to_s
- true
- else
- @missing = "#{model_class} has a db column named #{@column} " <<
- "of precision #{matched_column.precision}, " <<
- "not #{@precision}."
- false
- end
- end
-
- def correct_limit?
- return true if @limit.nil?
- if matched_column.limit.to_s == @limit.to_s
- true
- else
- @missing = "#{model_class} has a db column named #{@column} " <<
- "of limit #{matched_column.limit}, " <<
- "not #{@limit}."
- false
- end
- end
-
- def correct_default?
- return true if @default.nil?
- if matched_column.default.to_s == @default.to_s
- true
- else
- @missing = "#{model_class} has a db column named #{@column} " <<
- "of default #{matched_column.default}, " <<
- "not #{@default}."
- false
- end
- end
-
- def correct_null?
- return true if @null.nil?
- if matched_column.null.to_s == @null.to_s
- true
- else
- @missing = "#{model_class} has a db column named #{@column} " <<
- "of null #{matched_column.null}, " <<
- "not #{@null}."
- false
- end
- end
-
- def correct_scale?
- return true if @scale.nil?
- if matched_column.scale.to_s == @scale.to_s
- true
- else
- @missing = "#{model_class} has a db column named #{@column} " <<
- "of scale #{matched_column.scale}, not #{@scale}."
- false
- end
- end
-
- def matched_column
- model_class.columns.detect { |each| each.name == @column.to_s }
- end
-
- def model_class
- @subject.class
- end
-
- def expectation
- expected = "#{model_class.name} to #{description}"
- end
- end
-
- end
-end
View
110 lib/shoulda/active_record/have_db_index_matcher.rb
@@ -1,110 +0,0 @@
-module Shoulda # :nodoc:
- module ActiveRecord # :nodoc:
-
- # Ensures that there are DB indices on the given columns or tuples of
- # columns.
- #
- # 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. Use <tt>nil</tt> if you don't care whether the index is
- # unique or not. Default = <tt>nil</tt>
- #
- # Examples:
- #
- # it { should have_db_index(:age) }
- # it { should have_db_index([:commentable_type, :commentable_id]) }
- # it { should have_db_index(:ssn).unique(true) }
- #
- def have_db_index(columns)
- HaveDbIndexMatcher.new(:have_index, columns)
- end
-
- class HaveDbIndexMatcher # :nodoc:
- def initialize(macro, columns)
- @macro = macro
- @columns = normalize_columns_to_array(columns)
- end
-
- def unique(unique)
- @unique = unique
- self
- end
-
- def matches?(subject)
- @subject = subject
- index_exists? && correct_unique?
- end
-
- def failure_message
- "Expected #{expectation} (#{@missing})"
- end
-
- def negative_failure_message
- "Did not expect #{expectation}"
- end
-
- def description
- "have a #{index_type} index on columns #{@columns.join(' and ')}"
- end
-
- protected
-
- def index_exists?
- ! matched_index.nil?
- end
-
- def correct_unique?
- return true if @unique.nil?
- if matched_index.unique == @unique
- true
- else
- @missing = "#{table_name} has an index named #{matched_index.name} " <<
- "of unique #{matched_index.unique}, not #{@unique}."
- false
- end
- end
-
- def matched_index
- indexes.detect { |each| each.columns == @columns }
- end
-
- def model_class
- @subject.class
- end
-
- def table_name
- model_class.table_name
- end
-
- def indexes
- ::ActiveRecord::Base.connection.indexes(table_name)
- end
-
- def expectation
- expected = "#{model_class.name} to #{description}"
- end
-
- def index_type
- case @unique
- when nil
- ''
- when false
- 'non-unique'
- else
- 'unique'
- end
- end
-
- def normalize_columns_to_array(columns)
- if columns.class == Array
- columns.collect { |each| each.to_s }
- else
- [columns.to_s]
- end
- end
- end
-
- end
-end
View
57 lib/shoulda/active_record/have_readonly_attribute_matcher.rb
@@ -1,57 +0,0 @@
-module Shoulda # :nodoc:
- module ActiveRecord # :nodoc:
-
- # Ensures that the attribute cannot be changed once the record has been
- # created.
- #
- # it { should have_readonly_attributes(:password) }
- #
- def have_readonly_attribute(value)
- HaveReadonlyAttributeMatcher.new(value)
- end
-
- class HaveReadonlyAttributeMatcher # :nodoc:
-
- def initialize(attribute)
- @attribute = attribute.to_s
- end
-
- def matches?(subject)
- @subject = subject
- if readonly_attributes.include?(@attribute)
- @negative_failure_message =
- "Did not expect #{@attribute} to be read-only"
- true
- else
- if readonly_attributes.empty?
- @failure_message = "#{class_name} attribute #{@attribute} " <<
- "is not read-only"
- else
- @failure_message = "#{class_name} is making " <<
- "#{readonly_attributes.to_sentence} " <<
- "read-only, but not #{@attribute}."
- end
- false
- end
- end
-
- attr_reader :failure_message, :negative_failure_message
-
- def description
- "make #{@attribute} read-only"
- end
-
- private
-
- def readonly_attributes
- @readonly_attributes ||= (@subject.class.readonly_attributes || [])
- end
-
- def class_name
- @subject.class.name
- end
-
- end
-
- end
-end
View
32 lib/shoulda/active_record/helpers.rb
@@ -1,32 +0,0 @@
-module Shoulda # :nodoc:
- module ActiveRecord # :nodoc:
- module Helpers
- def pretty_error_messages(obj) # :nodoc:
- obj.errors.map do |a, m|
- msg = "#{a} #{m}"
- msg << " (#{obj.send(a).inspect})" unless a.to_sym == :base
- end
- end
-
- # Helper method that determines the default error message used by Active
- # Record. Works for both existing Rails 2.1 and Rails 2.2 with the newly
- # introduced I18n module used for localization.
- #
- # default_error_message(:blank)
- # default_error_message(:too_short, :count => 5)
- # default_error_message(:too_long, :count => 60)
- def default_error_message(key, values = {})
- if Object.const_defined?(:I18n) # Rails >= 2.2
- result = I18n.translate("activerecord.errors.messages.#{key}", values)
- if result =~ /^translation missing/
- I18n.translate("errors.messages.#{key}", values)
- else
- result
- end
- else # Rails <= 2.1.x
- ::ActiveRecord::Errors.default_error_messages[key] % values[:count]
- end
- end
- end
- end
-end
View
39 lib/shoulda/active_record/validate_acceptance_of_matcher.rb
@@ -1,39 +0,0 @@
-module Shoulda # :nodoc:
- module ActiveRecord # :nodoc:
-
- # Ensures that the model cannot be saved the given attribute is not
- # accepted.
- #
- # 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>.
- #
- # Example:
- # it { should validate_acceptance_of(:eula) }
- #
- def validate_acceptance_of(attr)
- ValidateAcceptanceOfMatcher.new(attr)
- end
-
- class ValidateAcceptanceOfMatcher < ValidationMatcher # :nodoc:
-
- def with_message(message)
- @expected_message = message if message
- self
- end
-
- def matches?(subject)
- super(subject)
- @expected_message ||= :accepted
- disallows_value_of(false, @expected_message)
- end
-
- def description
- "require #{@attribute} to be accepted"
- end
-
- end
-
- end
-end
View
63 lib/shoulda/active_record/validate_format_of_matcher.rb
@@ -1,63 +0,0 @@
-module Shoulda # :nodoc:
- module ActiveRecord # :nodoc:
-
- # Ensures that the model is not valid if the given attribute is not
- # formatted correctly.
- #
- # 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>.
- # * <tt>with(string to test against)</tt>
- # * <tt>not_with(string to test against)</tt>
- #
- # Examples:
- # it { should validate_format_of(:name).
- # with('12345').
- # with_message(/is not optional/) }
- # it { should validate_format_of(:name).
- # not_with('12D45').
- # with_message(/is not optional/) }
- #
- def validate_format_of(attr)
- ValidateFormatOfMatcher.new(attr)
- end
-
- class ValidateFormatOfMatcher < ValidationMatcher # :nodoc:
-
- def initialize(attribute)
- super
- end
-
- def with_message(message)
- @expected_message = message if message
- self
- end
-
- def with(value)
- raise "You may not call both with and not_with" if @value_to_fail
- @value_to_pass = value
- self
- end
-
- def not_with(value)
- raise "You may not call both with and not_with" if @value_to_pass
- @value_to_fail = value
- self
- end
-
- def matches?(subject)
- super(subject)
- @expected_message ||= :blank
- return disallows_value_of(@value_to_fail, @expected_message) if @value_to_fail
- allows_value_of(@value_to_pass, @expected_message) if @value_to_pass
- end
-
- def description
- "#{@attribute} have a valid format"
- end
-
- end
-
- end
-end