Extract ValidationMessageFinder from AllowValueMatcher

This commit is contained in:
Joe Ferris 2012-09-12 20:23:18 -04:00
parent 96d32c289c
commit 3dbf5d4f0d
4 changed files with 192 additions and 34 deletions

View File

@ -1,5 +1,6 @@
require 'shoulda/matchers/active_model/helpers'
require 'shoulda/matchers/active_model/validation_matcher'
require 'shoulda/matchers/active_model/validation_message_finder'
require 'shoulda/matchers/active_model/allow_value_matcher'
require 'shoulda/matchers/active_model/ensure_length_of_matcher'
require 'shoulda/matchers/active_model/ensure_inclusion_of_matcher'

View File

@ -71,34 +71,30 @@ module Shoulda # :nodoc:
if strict?
"strictly #{base}"
else
base
message_finder.allow_description(allowed_values)
end
end
private
def errors_match?
has_messages? && errors_for_attribute_match?
end
def has_messages?
if strict?
exception_message_matches?
has_exception_message?
else
validation_messages_match?
message_finder.has_messages?
end
end
def exception_message_matches?
def has_exception_message?
@instance.valid?
false
rescue ::ActiveModel::StrictValidationFailed => exception
@strict_exception = exception
errors_for_attribute_match?
end
def validation_messages_match?
if @instance.valid?
false
else
errors_for_attribute_match?
end
true
end
def errors_for_attribute_match?
@ -113,7 +109,7 @@ module Shoulda # :nodoc:
if strict?
[strict_exception_message]
else
validation_messages_for_attribute
message_finder.messages
end
end
@ -121,15 +117,6 @@ module Shoulda # :nodoc:
@strict_exception.message
end
def validation_messages_for_attribute
if @instance.errors.respond_to?(:[])
errors = @instance.errors[@attribute]
else
errors = @instance.errors.on(@attribute)
end
Array.wrap(errors)
end
def strict?
@strict
end
@ -155,7 +142,7 @@ module Shoulda # :nodoc:
if strict?
'exception'
else
'errors'
message_finder.source_description
end
end
@ -163,7 +150,7 @@ module Shoulda # :nodoc:
if strict?
exception_description
else
validation_error_description
message_finder.messages_description
end
end
@ -175,14 +162,6 @@ module Shoulda # :nodoc:
end
end
def validation_error_description
if @instance.errors.empty?
"no errors"
else
"errors: #{pretty_error_messages(@instance)}"
end
end
def allowed_values
if @values_to_match.length > 1
"any of [#{@values_to_match.map(&:inspect).join(', ')}]"
@ -205,7 +184,7 @@ module Shoulda # :nodoc:
if strict?
default_full_message
else
default_attribute_message
message_finder.expected_message_from(default_attribute_message)
end
end
@ -228,6 +207,10 @@ module Shoulda # :nodoc:
def model_name
@instance.class.to_s.underscore
end
def message_finder
@message_finder ||= ValidationMessageFinder.new(@instance, @attribute)
end
end
end
end

View File

@ -0,0 +1,69 @@
module Shoulda
module Matchers
module ActiveModel
# Finds message information from a model's #errors method.
class ValidationMessageFinder
include Helpers
def initialize(instance, attribute)
@instance = instance
@attribute = attribute
end
def allow_description(allowed_values)
"allow #{@attribute} to be set to #{allowed_values}"
end
def expected_message_from(attribute_message)
attribute_message
end
def has_messages?
errors.present?
end
def source_description
'errors'
end
def messages_description
if errors.empty?
"no errors"
else
"errors: #{pretty_error_messages(validated_instance)}"
end
end
def messages
Array.wrap(messages_for_attribute)
end
private
def messages_for_attribute
if errors.respond_to?(:[])
errors[@attribute]
else
errors.on(@attribute)
end
end
def errors
validated_instance.errors
end
def validated_instance
@validated_instance ||= validate_instance
end
def validate_instance
@instance.valid?
@instance
end
end
end
end
end

View File

@ -0,0 +1,105 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveModel::ValidationMessageFinder do
context '#allow_description' do
it 'describes its attribute' do
finder = build_finder(:attribute => :attr)
description = finder.allow_description('allowed values')
description.should == 'allow attr to be set to allowed values'
end
end
context '#expected_message_from' do
it 'returns the message as-is' do
finder = build_finder
message = finder.expected_message_from('some message')
message.should == 'some message'
end
end
context '#has_messages?' do
it 'has messages when some validations fail' do
finder = build_finder(:format => /abc/, :value => 'xyz')
result = finder.has_messages?
result.should be_true
end
it 'has no messages when all validations pass' do
finder = build_finder(:format => /abc/, :value => 'abc')
result = finder.has_messages?
result.should be_false
end
end
context '#messages' do
it 'returns errors for the given attribute' do
finder = build_finder(:format => /abc/, :value => 'xyz')
messages = finder.messages
messages.should == ['is invalid']
end
end
context '#messages_description' do
it 'describes errors for the given attribute' do
finder = build_finder(
:attribute => :attr,
:format => /abc/,
:value => 'xyz'
)
description = finder.messages_description
description.should == 'errors: ["attr is invalid (\"xyz\")"]'
end
it 'describes errors when there are none' do
finder = build_finder(:format => /abc/, :value => 'abc')
description = finder.messages_description
description.should == 'no errors'
end
end
context '#source_description' do
it 'describes the source of its messages' do
finder = build_finder
description = finder.source_description
description.should == 'errors'
end
end
def build_finder(arguments = {})
arguments[:attribute] ||= :attr
instance = build_instance_validating(
arguments[:attribute],
arguments[:format] || /abc/,
arguments[:value] || 'abc'
)
Shoulda::Matchers::ActiveModel::ValidationMessageFinder.new(
instance,
arguments[:attribute]
)
end
def build_instance_validating(attribute, format, value)
model_class = define_model(:example, attribute => :string) do
attr_accessible attribute
validates_format_of attribute, :with => format
end
model_class.new(attribute => value)
end
end