Created
June 22, 2014 06:00
-
-
Save morhekil/16c57ea5d9a2a0f25547 to your computer and use it in GitHub Desktop.
custom RSpec 3 matcher for Grape Entities
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Custom RSpec 3 matcher to easily test validity of Grape API responses based on Grape::Entity serializers. | |
# It is assumed that all entities are defined as nested classes, which is the recommended approach, see | |
# the last example at https://github.com/intridea/grape#grape-entities | |
# | |
# HOW TO USE | |
# ---------- | |
# | |
# 1. Require this file in your test environment. | |
# | |
# 2. To verify that a given JSON hash is the correct representation of a single model: | |
# expect(json['user']).to represent_entity_of(user) | |
# | |
# 3. To verify that a given JSON array of hashes is the correct representation of an array of models: | |
# expect(json['users']).to represent_array_of(users) | |
# | |
class GrapeEntityMatcher < Struct.new(:target) | |
def represents?(actual) | |
klass = target.class | |
if !klass.const_defined?('Entity') | |
raise ArgumentError, "#{klass} does not have nested Entity" | |
end | |
entity = klass.const_get('Entity').new(target) | |
actual == entity.serializable_hash.stringify_keys | |
end | |
end | |
RSpec::Matchers.define :represent_entity_of do |target| | |
match do |actual| | |
GrapeEntityMatcher.new(target).represents? actual | |
end | |
end | |
RSpec::Matchers.define :represent_array_of do |targets| | |
match do |actual_orig| | |
return false if actual.size != targets.size | |
actual = actual_orig.clone | |
targets.all? do |item| | |
match = actual.find { |t| GrapeEntityMatcher.new(item).represents? t } | |
match ? (actual.delete(match) && true) : false | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment