Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save khalilgharbaoui/5357e5d23826b65960b6a6763a0fd62a to your computer and use it in GitHub Desktop.
Save khalilgharbaoui/5357e5d23826b65960b6a6763a0fd62a to your computer and use it in GitHub Desktop.
RSpec matcher for validates_with
# RSpec matcher for validates_with.
# https://gist.github.com/2032846
# Usage:
#
# describe User do
# it { should validate_with CustomValidator }
# end
#
# describe User do
# it do
# should validate_with(CustomValidator)
# .with_options(foo: 'foo', bar: 'bar')
# end
RSpec::Matchers.define :validate_with do |expected_validator_class, options|
match do |subject|
# allow Class to call same Validator multiple times w/ different options
@matching_validators = subject.class.validators.select do |validator|
validator.class == expected_validator_class
end
@matching_validators.present? && options_matching?
end
# exact because they should be exactly as specified in the validation in the model.
chain :with_exact_options do |options|
@options = options
end
description do
'validates_with'
end
failure_message do |text|
"expected to validate with #{expected_validator_class}" + options_failure_message
end
failure_message_when_negated do |text|
"expected to not validate with #{expected_validator_class}" + options_failure_message
end
private
def options_matching?
if @options.present?
@matching_validators.any? do |validator|
@options.all? { |key, value| validator.options[key] == value }
end
else
true
end
end
# TODO - add ", instead received options: #{actual_options}" to message
# - how should it output multiple matching validators?
def options_failure_message
return '' unless @matching_validators.present? && @options.present?
" with options: #{@options}"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment