Skip to content

Instantly share code, notes, and snippets.

@mikespokefire
Created April 5, 2013 14:13
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 mikespokefire/5319565 to your computer and use it in GitHub Desktop.
Save mikespokefire/5319565 to your computer and use it in GitHub Desktop.
# The actual matcher class
class VirtusAttributeMatcher
# initialize is called with the expected outcome
# => expect(described_class).to have_attribute(:token)
def initialize(attribute_name)
@attribute_name = attribute_name
@options = {}
end
# When RSpec will call matches? on the expectation class, this needs to
# return true if everything is good, or false if there are errors
def matches?(subject)
@subject = subject
attribute_exists? && type_correct?
end
# Extra methods must return self in order for RSpec to call matches? on the final object
def of_type(type)
@options[:type] = type
self
end
# The message that is given to failures (expect(described_class).to)
# Make this helpful so people know why it failed.
def failure_message
"expected #{@attribute_name} to be defined"
end
# The message that is given to negative failures (expect(described_class).to_not)
# Make this helpful so people know why it failed.
def negative_failure_message
"expected #{@attribute_name} not to be defined"
end
private
def attribute
@subject.attribute_set[@attribute_name]
end
def attribute_exists?
attribute != nil
end
def type_correct?
if @options[:type]
attribute.options[:primitive] == @options[:type]
else
true
end
end
end
# The module with methods that will be mixed into RSpec, this will provide the interface
# from RSpec to your matcher class
module VirtusRspecMatchers
def have_attribute(attribute_name)
VirtusAttributeMatcher.new(attribute_name)
end
end
# Mix in the matchers
RSpec.configure do |config|
config.include VirtusRspecMatchers
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment