Skip to content

Instantly share code, notes, and snippets.

@nepalez
Last active January 15, 2016 11:42
Show Gist options
  • Save nepalez/7a33e39d5fc3162c0ba2 to your computer and use it in GitHub Desktop.
Save nepalez/7a33e39d5fc3162c0ba2 to your computer and use it in GitHub Desktop.
require "rspec"
require "mustermann"
require "delegate"
# Gem-speficic RSpec mocks and expectations
#
# @example
# allow(client)
# .to receive_request(:get, '/users/1')
# .where { |req| req[:query].include? "auth" => "foobar" }
# .and_return status: 200, body: { "id" => 1, "name" => "Andrew" }
#
# expect(client).to receive_request(:get, '/users/1').twice
#
# client.path("/users/1").get auth: "foobar"
# client.path("/users/1").get auth: "foobar"
#
module Evil::Client::RSpec
# Redefines stub to use client.connection instead of a client
#
# @param [Object] subject
#
# @return [undefined]
#
def allow(subject)
super coerce_evil_client(subject)
end
# Redefines stub to use client.connection instead of a client
#
# @param [Object] subject
#
# @return [undefined]
#
def expect(subject = nil, &block)
block ? super(&block) : super(coerce_evil_client(subject))
end
# Provides gem-specific variant of `receive` mock matcher
#
# @param [#to_s] method The method of the request
# @param [#to_s] path The rails pattern for the request path
#
# @return [RSpec::Mocks::Matchers::Receive]
#
def receive_request(method, path = nil)
matcher = receive(:call).tap { |object| object.extend Receive }
matcher = matcher.where(&match_evil_method(method)) unless method == :any
matcher = matcher.where(&match_evil_path(path)) if path
matcher
end
private
def coerce_evil_client(subject)
subject.is_a?(Evil::Client) ? subject.connection : subject
end
def match_evil_method(method)
proc { |req| req[:method] == method.to_s }
end
def match_evil_path(path)
proc { |req| Mustermann.new(path, type: :rails) === req[:path].to_s }
end
# @private
module Receive
def where(&block)
with BlockMatcher.new(lazy_constraints << block)
end
private
def lazy_constraints
@lazy_constraints ||= []
end
# @private
class BlockMatcher < SimpleDelegator
def initialize(procs)
matcher = proc do |req|
procs.inject(true) { |result, item| result && item[req] }
end
super(matcher)
end
def match?(subject)
call(subject)
end
end
end
end
RSpec.configure { |config| config.include(Evil::Client::RSpec) }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment