Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

1.0 release

  • Loading branch information...
commit f7f190111961af4caa7d3658b0dcee8d0f29f175 1 parent 6d09fe3
Pat Allan authored
5 .document
... ... @@ -1,5 +0,0 @@
1   -README.rdoc
2   -lib/**/*.rb
3   -bin/*
4   -features/**/*.feature
5   -LICENSE
3  .gitignore
@@ -3,3 +3,6 @@
3 3 coverage
4 4 rdoc
5 5 pkg
  6 +coverage
  7 +doc
  8 +.yardoc
7 README.rdoc
Source Rendered
... ... @@ -1,7 +0,0 @@
1   -= fakeweb-matcher
2   -
3   -Description goes here.
4   -
5   -== Copyright
6   -
7   -Copyright (c) 2009 Pat Allan. See LICENSE for details.
30 README.textile
Source Rendered
... ... @@ -0,0 +1,30 @@
  1 +h1. FakeWeb Matcher
  2 +
  3 +An RSpec matcher for the Fakeweb HTTP stubbing library, allowing you to use RSpec syntax to check if requests to particular URIs have been made.
  4 +
  5 +h2. Installing
  6 +
  7 +First, install the gem
  8 +<pre><code>gem install freelancing-god-fakeweb-matcher --source http://gems.github.com</code></pre>
  9 +
  10 +Then, in your @spec/spec_helper.rb@ file, you'll need to require the library _after_ you have required "FakeWeb":http://fakeweb.rubyforge.org and "RSpec":http://rspec.info, to look something like this:
  11 +
  12 +<pre><code>require 'spec'
  13 +require 'fakeweb'
  14 +require 'fakeweb_matcher'</code></pre>
  15 +
  16 +This ensures that the matcher is automatically loaded into RSpec for you.
  17 +
  18 +h2. Usage
  19 +
  20 +<pre><code>FakeWeb.should have_requested(:get, 'http://example.com')
  21 +FakeWeb.should have_requested(:any, 'http://example.com')
  22 +FakeWeb.should_not have_requested(:put, 'http://example.com')</code></pre>
  23 +
  24 +h2. Contribution
  25 +
  26 +Unsurprisingly, this library is tested using RSpec, and relies upon FakeWeb. It also uses "YARD":http://yard.soen.ca/ for documentation, so if you're submitting patches (which are most definitely welcome!) please use YARD syntax and have valid specs.
  27 +
  28 +h2. Copyright
  29 +
  30 +Copyright (c) 2009 Pat Allan, released under an MIT Licence
48 Rakefile
... ... @@ -1,48 +1,4 @@
1   -require 'rubygems'
2   -require 'rake'
3   -
4   -begin
5   - require 'jeweler'
6   - Jeweler::Tasks.new do |gem|
7   - gem.name = "fakeweb-matcher"
8   - gem.summary = %Q{TODO}
9   - gem.email = "pat@freelancing-gods.com"
10   - gem.homepage = "http://github.com/freelancing-god/fakeweb-matcher"
11   - gem.authors = ["Pat Allan"]
12   - # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
13   - end
14   -
15   -rescue LoadError
16   - puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
17   -end
18   -
19   -require 'spec/rake/spectask'
20   -Spec::Rake::SpecTask.new(:spec) do |spec|
21   - spec.libs << 'lib' << 'spec'
22   - spec.spec_files = FileList['spec/**/*_spec.rb']
23   -end
24   -
25   -Spec::Rake::SpecTask.new(:rcov) do |spec|
26   - spec.libs << 'lib' << 'spec'
27   - spec.pattern = 'spec/**/*_spec.rb'
28   - spec.rcov = true
29   -end
30   -
  1 +require 'tasks/distribution'
  2 +require 'tasks/testing'
31 3
32 4 task :default => :spec
33   -
34   -require 'rake/rdoctask'
35   -Rake::RDocTask.new do |rdoc|
36   - if File.exist?('VERSION.yml')
37   - config = YAML.load(File.read('VERSION.yml'))
38   - version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
39   - else
40   - version = ""
41   - end
42   -
43   - rdoc.rdoc_dir = 'rdoc'
44   - rdoc.title = "fakeweb-matcher #{version}"
45   - rdoc.rdoc_files.include('README*')
46   - rdoc.rdoc_files.include('lib/**/*.rb')
47   -end
48   -
4 VERSION.yml
... ... @@ -0,0 +1,4 @@
  1 +---
  2 +:major: 1
  3 +:minor: 0
  4 +:patch: 0
55 fakeweb-matcher.gemspec
... ... @@ -0,0 +1,55 @@
  1 +# -*- encoding: utf-8 -*-
  2 +
  3 +Gem::Specification.new do |s|
  4 + s.name = %q{fakeweb-matcher}
  5 + s.version = "1.0.0"
  6 +
  7 + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
  8 + s.authors = ["Pat Allan"]
  9 + s.date = %q{2009-07-29}
  10 + s.email = %q{pat@freelancing-gods.com}
  11 + s.extra_rdoc_files = [
  12 + "LICENSE",
  13 + "README.textile"
  14 + ]
  15 + s.files = [
  16 + "LICENSE",
  17 + "README.textile",
  18 + "Rakefile",
  19 + "VERSION.yml",
  20 + "lib/fake_web_matcher.rb",
  21 + "lib/fake_web_matcher/extension.rb",
  22 + "lib/fake_web_matcher/matchers.rb",
  23 + "lib/fake_web_matcher/request_matcher.rb",
  24 + "lib/fakeweb_matcher.rb"
  25 + ]
  26 + s.has_rdoc = true
  27 + s.homepage = %q{http://github.com/freelancing-god/fakeweb-matcher}
  28 + s.rdoc_options = ["--charset=UTF-8"]
  29 + s.require_paths = ["lib"]
  30 + s.rubygems_version = %q{1.3.1}
  31 + s.summary = %q{RSpec matcher for the FakeWeb library}
  32 + s.test_files = [
  33 + "spec/lib/fake_web_matcher/extension_spec.rb",
  34 + "spec/lib/fake_web_matcher/matchers_spec.rb",
  35 + "spec/lib/fake_web_matcher/request_matcher_spec.rb",
  36 + "spec/lib/fake_web_matcher_spec.rb",
  37 + "spec/spec_helper.rb"
  38 + ]
  39 +
  40 + if s.respond_to? :specification_version then
  41 + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
  42 + s.specification_version = 2
  43 +
  44 + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
  45 + s.add_runtime_dependency(%q<fakeweb>, [">= 1.2.5"])
  46 + s.add_runtime_dependency(%q<rspec>, [">= 1.2.0"])
  47 + else
  48 + s.add_dependency(%q<fakeweb>, [">= 1.2.5"])
  49 + s.add_dependency(%q<rspec>, [">= 1.2.0"])
  50 + end
  51 + else
  52 + s.add_dependency(%q<fakeweb>, [">= 1.2.5"])
  53 + s.add_dependency(%q<rspec>, [">= 1.2.0"])
  54 + end
  55 +end
37 lib/fake_web_matcher.rb
... ... @@ -0,0 +1,37 @@
  1 +require 'fake_web_matcher/extension'
  2 +require 'fake_web_matcher/matchers'
  3 +require 'fake_web_matcher/request_matcher'
  4 +
  5 +# An RSpec matcher for the Fakeweb HTTP stubbing library, allowing you to use
  6 +# RSpec syntax to check if requests to particular URIs have been made.
  7 +#
  8 +# The matcher is automatically included into RSpec's set, and can be used as
  9 +# follows:
  10 +#
  11 +# @example
  12 +# FakeWeb.should have_requested(:get, 'http://example.com')
  13 +# FakeWeb.should have_requested(:any, 'http://example.com')
  14 +# FakeWeb.should_not have_requested(:put, 'http://example.com')
  15 +#
  16 +# @see FakeWebMatcher::Matchers
  17 +# @see http://fakeweb.rubyforge.org
  18 +# @author Pat Allan
  19 +#
  20 +module FakeWebMatcher
  21 + #
  22 +end
  23 +
  24 +FakeWeb::Registry.class_eval do
  25 + # Don't like doing this, but need some way to track the requests
  26 + include FakeWebMatcher::Extension
  27 +end
  28 +
  29 +Spec::Runner.configure { |config|
  30 + # Adding the custom matcher to the default set
  31 + config.include FakeWebMatcher::Matchers
  32 +
  33 + # Ensuring the request list gets cleared after each spec
  34 + config.before :each do
  35 + FakeWeb::Registry.instance.clear_requests
  36 + end
  37 +}
43 lib/fake_web_matcher/extension.rb
... ... @@ -0,0 +1,43 @@
  1 +module FakeWebMatcher
  2 + # Extension for FakeWeb::Registry, to track requests made for given URIs. The
  3 + # code that includes this into FakeWeb is in the base FakeWebMatcher module.
  4 + #
  5 + # @see http://fakeweb.rubyforge.org
  6 + #
  7 + module Extension
  8 + def self.included(base)
  9 + base.class_eval do
  10 + # Keep the original response_for method
  11 + alias_method :response_without_request_tracking, :response_for
  12 +
  13 + # Overwrites the existing FakeWeb::Registry#response method, to ensure
  14 + # requests are tracked. Returns the usual stubbed response.
  15 + #
  16 + # @param [Symbol] method HTTP method
  17 + # @param [String] uri URI requested
  18 + # @param [Proc] block The block passed into Net::HTTP requests
  19 + # @return [String] The stubbed page response
  20 + #
  21 + def response_for(method, uri, &block)
  22 + requests << [method, uri]
  23 + response_without_request_tracking(method, uri, &block)
  24 + end
  25 + end
  26 + end
  27 +
  28 + # A list of the requests, kept as an array of arrays, where each child array
  29 + # has two values - the method and the URI.
  30 + #
  31 + # @return [Array] Recorded requests
  32 + #
  33 + def requests
  34 + @requests ||= []
  35 + end
  36 +
  37 + # Clears the stored request list
  38 + #
  39 + def clear_requests
  40 + requests.clear
  41 + end
  42 + end
  43 +end
22 lib/fake_web_matcher/matchers.rb
... ... @@ -0,0 +1,22 @@
  1 +# An RSpec matcher for the Fakeweb HTTP stubbing library, allowing you to use
  2 +# RSpec syntax to check if requests to particular URIs have been made.
  3 +#
  4 +# @see FakeWebMatcher::Matchers
  5 +# @see http://fakeweb.rubyforge.org
  6 +# @author Pat Allan
  7 +#
  8 +module FakeWebMatcher
  9 + # Custom matcher holder for RSpec
  10 + #
  11 + module Matchers
  12 + # Returns a new matcher instance.
  13 + #
  14 + # @param [Symbol] method The HTTP method
  15 + # @param [String] uri The URI to check for
  16 + # @return [FakeWebMatcher::RequestMatcher]
  17 + #
  18 + def have_requested(method, uri)
  19 + FakeWebMatcher::RequestMatcher.new(method, uri)
  20 + end
  21 + end
  22 +end
94 lib/fake_web_matcher/request_matcher.rb
... ... @@ -0,0 +1,94 @@
  1 +module FakeWebMatcher
  2 + # Matcher class, following RSpec's expectations. Used to confirm whether a
  3 + # request has been made on a given method and URI.
  4 + #
  5 + class RequestMatcher
  6 + attr_reader :url, :method
  7 +
  8 + # Create a new matcher.
  9 + #
  10 + # @param [Symbol] method The HTTP method
  11 + # @param [String] uri The URI to check for
  12 + #
  13 + def initialize(method, url)
  14 + @method, @url = method, url
  15 + end
  16 +
  17 + # Indication of whether there's a match on the URI from given requests.
  18 + #
  19 + # @param [Module] FakeWeb Module, necessary for RSpec, although not
  20 + # required internally.
  21 + # @return [Boolean] true if the URI was requested, otherwise false.
  22 + #
  23 + def matches?(fakeweb)
  24 + !FakeWeb::Registry.instance.requests.detect { |req|
  25 + method, url = args_split(*req)
  26 + match_method(method) && url == @url
  27 + }.nil?
  28 + end
  29 +
  30 + # Failure message if the URI should have been requested.
  31 + #
  32 + # @return [String] failure message
  33 + #
  34 + def failure_message
  35 + if @method == :any
  36 + "The URL #{@url} was not requested."
  37 + else
  38 + "The URL #{@url} was not requested using #{formatted_method}."
  39 + end
  40 + end
  41 +
  42 + # Failure message if the URI should not have been requested.
  43 + #
  44 + # @return [String] failure message
  45 + #
  46 + def negative_failure_message
  47 + if @method == :any
  48 + "The URL #{@url} was requested and should not have been."
  49 + else
  50 + "The URL #{@url} was requested using #{formatted_method} and should not have been."
  51 + end
  52 + end
  53 +
  54 + private
  55 +
  56 + # Compares methods, or ignores if either side of the comparison is :any.
  57 + #
  58 + # @param [Symbol] method HTTP method
  59 + # @return [Boolean] true if methods match or either is :any.
  60 + #
  61 + def match_method(method)
  62 + @method == :any || method == :any || method == @method
  63 + end
  64 +
  65 + # Expected method formatted to be an uppercase string. Example: :get becomes
  66 + # "GET".
  67 + #
  68 + # @return [String] uppercase method
  69 + #
  70 + def formatted_method
  71 + @method.to_s.upcase
  72 + end
  73 +
  74 + # Interprets given arguments to a method and URI instance. The URI, as a
  75 + # string, is required, but the method is not (will default to :any).
  76 + #
  77 + # @param [Array] args
  78 + # @return [Array] Two items: method and URI instance
  79 + #
  80 + def args_split(*args)
  81 + method = :any
  82 + uri = nil
  83 +
  84 + case args.length
  85 + when 1 then uri = URI.parse(args[0])
  86 + when 2 then method, uri = args[0], URI.parse(args[1])
  87 + else
  88 + raise ArgumentError.new("wrong number of arguments")
  89 + end
  90 +
  91 + return method, uri
  92 + end
  93 + end
  94 +end
0  lib/fakeweb-matcher.rb
No changes.
1  lib/fakeweb_matcher.rb
... ... @@ -0,0 +1 @@
  1 +require 'fake_web_matcher'
7 spec/fakeweb-matcher_spec.rb
... ... @@ -1,7 +0,0 @@
1   -require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2   -
3   -describe "FakewebMatcher" do
4   - it "fails" do
5   - fail "hey buddy, you should probably rename this file and start specing for real"
6   - end
7   -end
42 spec/lib/fake_web_matcher/extension_spec.rb
... ... @@ -0,0 +1,42 @@
  1 +require 'spec/spec_helper'
  2 +
  3 +describe FakeWebMatcher::Extension do
  4 + it "should be included into the FakeWeb::Registry class" do
  5 + FakeWeb::Registry.included_modules.should include(FakeWebMatcher::Extension)
  6 + end
  7 +
  8 + describe '#requests' do
  9 + it "should return an empty Array by default" do
  10 + FakeWeb::Registry.instance.requests.should == []
  11 + end
  12 + end
  13 +
  14 + describe '#clear_requests' do
  15 + it "should clear the requests array" do
  16 + registry = FakeWeb::Registry.instance
  17 + registry.requests << :something
  18 + registry.requests.should == [:something]
  19 +
  20 + registry.clear_requests
  21 + registry.requests.should == []
  22 + end
  23 + end
  24 +
  25 + describe '#response_for' do
  26 + before :each do
  27 + @registry = FakeWeb::Registry.instance
  28 + end
  29 +
  30 + it "should track request" do
  31 + @registry.response_for(:any, 'http://uri.com')
  32 +
  33 + @registry.requests.should == [[:any, 'http://uri.com']]
  34 + end
  35 +
  36 + it "should return the underlying response from response_without_request_tracking" do
  37 + @registry.stub!(:response_without_request_tracking => :response)
  38 +
  39 + @registry.response_for(:any, 'http://uri.com').should == :response
  40 + end
  41 + end
  42 +end
35 spec/lib/fake_web_matcher/matchers_spec.rb
... ... @@ -0,0 +1,35 @@
  1 +require 'spec/spec_helper'
  2 +
  3 +describe FakeWebMatcher::Matchers do
  4 + describe '#have_requested' do
  5 + before :each do
  6 + class Matchbox
  7 + include FakeWebMatcher::Matchers
  8 + end
  9 +
  10 + @matcher = Matchbox.new.have_requested(:put, 'http://url.com')
  11 + end
  12 +
  13 + it "should return an instance of RequestMatcher" do
  14 + @matcher.should be_a(FakeWebMatcher::RequestMatcher)
  15 + end
  16 +
  17 + it "should set the url and method using the matcher arguments" do
  18 + @matcher.url.to_s.should == 'http://url.com'
  19 + @matcher.method.should == :put
  20 + end
  21 + end
  22 +
  23 + it "should pass if the request has been made" do
  24 + FakeWeb.register_uri(:get, 'http://example.com/', :body => 'foo')
  25 + open('http://example.com/')
  26 +
  27 + FakeWeb.should have_requested(:get, 'http://example.com')
  28 + end
  29 +
  30 + it "should pass if the request has not been made" do
  31 + FakeWeb.register_uri(:get, 'http://example.com/', :body => 'foo')
  32 +
  33 + FakeWeb.should_not have_requested(:get, 'http://example.com')
  34 + end
  35 +end
85 spec/lib/fake_web_matcher/request_matcher_spec.rb
... ... @@ -0,0 +1,85 @@
  1 +require 'spec/spec_helper'
  2 +
  3 +describe FakeWebMatcher::RequestMatcher do
  4 + describe '#initialize' do
  5 + it "should set the url if no method is supplied" do
  6 + matcher = FakeWebMatcher::RequestMatcher.new('http://example.com')
  7 + matcher.url.to_s.should == 'http://example.com'
  8 + end
  9 +
  10 + it "set the url if a method is explicitly supplied" do
  11 + matcher = FakeWebMatcher::RequestMatcher.new(:get, 'http://example.com')
  12 + matcher.url.to_s.should == 'http://example.com'
  13 + end
  14 +
  15 + it "should set the method to any if not supplied" do
  16 + matcher = FakeWebMatcher::RequestMatcher.new('http://example.com')
  17 + matcher.method.should == :any
  18 + end
  19 +
  20 + it "set the method if explicitly supplied" do
  21 + matcher = FakeWebMatcher::RequestMatcher.new(:get, 'http://example.com')
  22 + matcher.method.should == :get
  23 + end
  24 + end
  25 +
  26 + describe '#matches?' do
  27 + before :each do
  28 + FakeWeb.register_uri(:get, 'http://example.com/', :body => 'foo')
  29 + open('http://example.com/')
  30 + end
  31 +
  32 + it "should return true if same url and any method" do
  33 + matcher = FakeWebMatcher::RequestMatcher.new('http://example.com')
  34 + matcher.matches?(FakeWeb).should be_true
  35 + end
  36 +
  37 + it "should return true if same url and same explicit method" do
  38 + matcher = FakeWebMatcher::RequestMatcher.new(:get, 'http://example.com')
  39 + matcher.matches?(FakeWeb).should be_true
  40 + end
  41 +
  42 + it "should return false if same url and different explicit method" do
  43 + matcher = FakeWebMatcher::RequestMatcher.new(:post, 'http://example.com')
  44 + matcher.matches?(FakeWeb).should be_false
  45 + end
  46 +
  47 + it "should return false if different url and same method" do
  48 + matcher = FakeWebMatcher::RequestMatcher.new(:get, 'http://domain.com')
  49 + matcher.matches?(FakeWeb).should be_false
  50 + end
  51 +
  52 + it "should return false if different url and different explicit method" do
  53 + matcher = FakeWebMatcher::RequestMatcher.new(:post, 'http://domain.com')
  54 + matcher.matches?(FakeWeb).should be_false
  55 + end
  56 + end
  57 +
  58 + describe '#failure_message' do
  59 + it "should mention the method if explicitly set" do
  60 + matcher = FakeWebMatcher::RequestMatcher.new(:get, 'http://example.com')
  61 + matcher.failure_message.
  62 + should == 'The URL http://example.com was not requested using GET.'
  63 + end
  64 +
  65 + it "should not mention the method if not explicitly set" do
  66 + matcher = FakeWebMatcher::RequestMatcher.new('http://example.com')
  67 + matcher.failure_message.
  68 + should == 'The URL http://example.com was not requested.'
  69 + end
  70 + end
  71 +
  72 + describe '#negative_failure_message' do
  73 + it "should mention the method if explicitly set" do
  74 + matcher = FakeWebMatcher::RequestMatcher.new(:get, 'http://example.com')
  75 + matcher.negative_failure_message.
  76 + should == 'The URL http://example.com was requested using GET and should not have been.'
  77 + end
  78 +
  79 + it "should not mention the method if not explicitly set" do
  80 + matcher = FakeWebMatcher::RequestMatcher.new('http://example.com')
  81 + matcher.negative_failure_message.
  82 + should == 'The URL http://example.com was requested and should not have been.'
  83 + end
  84 + end
  85 +end
5 spec/lib/fake_web_matcher_spec.rb
... ... @@ -0,0 +1,5 @@
  1 +require 'spec/spec_helper'
  2 +
  3 +describe FakeWebMatcher do
  4 + #
  5 +end
12 spec/spec_helper.rb
... ... @@ -1,9 +1,11 @@
1   -require 'spec'
  1 +$:.unshift File.dirname(__FILE__) + '/../lib'
2 2
3   -$LOAD_PATH.unshift(File.dirname(__FILE__))
4   -$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5   -require 'fakeweb-matcher'
  3 +require 'rubygems'
  4 +require 'open-uri'
  5 +require 'spec'
  6 +require 'fake_web'
  7 +require 'fake_web_matcher'
6 8
7 9 Spec::Runner.configure do |config|
8   -
  10 + #
9 11 end
28 tasks/distribution.rb
... ... @@ -0,0 +1,28 @@
  1 +require 'yard'
  2 +require 'jeweler'
  3 +
  4 +desc 'Generate documentation'
  5 +YARD::Rake::YardocTask.new
  6 +
  7 +task :rdoc => :yardoc
  8 +
  9 +Jeweler::Tasks.new do |gem|
  10 + gem.name = "fakeweb-matcher"
  11 + gem.summary = "RSpec matcher for the FakeWeb library"
  12 + gem.homepage = "http://github.com/freelancing-god/fakeweb-matcher"
  13 + gem.author = "Pat Allan"
  14 + gem.email = "pat@freelancing-gods.com"
  15 +
  16 + gem.files = FileList[
  17 + 'lib/**/*.rb',
  18 + 'LICENSE',
  19 + 'Rakefile',
  20 + 'README.textile',
  21 + 'tasks',
  22 + 'VERSION.yml'
  23 + ]
  24 + gem.test_files = FileList['spec/**/*.rb']
  25 +
  26 + gem.add_dependency 'fakeweb', '>= 1.2.5'
  27 + gem.add_dependency 'rspec', '>= 1.2.0'
  28 +end
14 tasks/testing.rb
... ... @@ -0,0 +1,14 @@
  1 +require 'spec/rake/spectask'
  2 +
  3 +Spec::Rake::SpecTask.new(:spec) do |t|
  4 + t.spec_files = FileList['spec/**/*_spec.rb']
  5 + t.spec_opts << "-c"
  6 +end
  7 +
  8 +Spec::Rake::SpecTask.new(:rcov) do |t|
  9 + t.pattern = 'spec/**/*_spec.rb'
  10 + t.spec_opts << "-c"
  11 +
  12 + t.rcov_opts = ['--exclude', 'spec', '--exclude', 'gems']
  13 + t.rcov = true
  14 +end

0 comments on commit f7f1901

Please sign in to comment.
Something went wrong with that request. Please try again.