lib/rspec/hal/matchers.rb
require 'json'
require 'hal-client'
module RSpec
module Hal
module Matchers
autoload :HalMatcherHelpers, "rspec/hal/matchers/hal_matcher_helpers"
require "rspec/hal/matchers/relation_matcher"
require "rspec/hal/matchers/templated_relation_matcher"
require "rspec/hal/matchers/have_property_matcher"
require "rspec/hal/matchers/uri_template_has_variables_matcher"
# Examples
#
# expect(doc).to have_templated_relation("search")
# expect(doc).to have_templated_relation("search", matching("{?q}"))
#
def have_templated_relation(*args)
TemplatedRelationMatcher.new(*args)
end
# Signature
#
# expect(doc).to have_relation(link_rel)
# expect(doc).to have_relation(link_rel, href_matcher)
# expect(doc).to have_relation(link_rel, template_variables)
# expect(doc).to have_relation(link_rel, template_variables, href_matcher)
#
# Examples
#
# expect(authors_doc).to have_relation("search",
# {q: "Alice"},
# match(%r|users/42|))
def have_relation(*args)
RelationMatcher.new(*args)
end
# Signature
#
# expect(a_doc).to have_property "name"
# expect(a_doc).to have_property "name, matching(/alice/i)
#
# expect(a_doc).to have_property("name").matching(/alice/i)
# expect(a_doc).to have_property("hobbies").including(matching("golf"))
# expect(a_doc).to have_property("name").that_is("Bob")
# expect(a_doc).to have_property("age").that_is kind_of Numeric
def have_property(*args)
HavePropertyMatcher.new(*args)
end
# Signature
#
# expect(a_uri_template_str).to have_variables "q", "limit"
# expect(a_uri_template_str).to has_variable "q"
def have_variables(*args)
UriTemplateHasVariablesMatcher.new(*args)
end
alias_method :has_variable, :have_variables
alias_method :with_variables, :have_variables
alias_method :with_variable, :have_variables
module DocumentMatchers
extend RSpec::Matchers::DSL
# Provide a 3.0 compatible DSL methods for 2.x RSpec.
module ForwardCompat
def failure_message(&blk)
failure_message_for_should(&blk)
end
end
# Install 3.0 compatibility layer if needed.
class << self
def matcher(name, &blk)
super name do |*args|
extend ForwardCompat unless respond_to? :failure_message
self.instance_exec *args, &blk
end
end
end
# Check that the document provided is a valid HAL document.
#
# Signature
#
# expect(a_user_doc).to be_hal
matcher :be_hal do
match do |a_json_doc|
!!(JSON.load(a_json_doc) rescue false)
end
failure_message do |a_json_doc|
message = begin
JSON.load(a_json_doc)
rescue => err
err.message
end
"Expected a HAL document but it wasn't because #{message} in:\n" +
a_json_doc
end
end
# Check that the document is both a valid HAL document and is
# a page of an RFC 6573 collection
#
# Signature
#
# expect(first_users_page).to be_hal_collection
matcher :be_hal_collection do
match do |a_doc|
a_doc = JSON.load(a_doc) rescue a_doc
a_doc.fetch("_embedded").has_key?("item") rescue false
end
failure_message do |a_doc|
"Expected `$._embedded.item` to exist in:\n" + a_doc
end
end
end
include DocumentMatchers
end
end
end