rspec-cramp 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +40 -7
- data/lib/rspec/cramp/matchers/respond_with.rb +2 -0
- data/lib/rspec/cramp/mock_response.rb +13 -4
- data/spec/examples/basic_spec.rb +32 -3
- data/spec/rspec_cramp_spec.rb +32 -10
- data/spec/spec_helper.rb +2 -2
- data/spec/tests.log +3621 -0
- metadata +40 -15
    
        data/README.md
    CHANGED
    
    | @@ -3,19 +3,22 @@ A set of rspec matchers and helpers that make it easier to write specs for [cram | |
| 3 3 | 
             
            Quick start
         | 
| 4 4 | 
             
            -----------
         | 
| 5 5 |  | 
| 6 | 
            -
            	gem install rspec-cramp
         | 
| 6 | 
            +
            	> gem install rspec-cramp
         | 
| 7 7 |  | 
| 8 8 |  | 
| 9 9 |  | 
| 10 10 | 
             
            	require 'rspec/cramp'
         | 
| 11 11 |  | 
| 12 | 
            +
            	# Decorate your spec with :cramp => true
         | 
| 12 13 | 
             
            	describe HelloWorld, :cramp => true do
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            	  # You need to define this method
         | 
| 13 16 | 
             
            	  def app
         | 
| 14 | 
            -
            	    HelloWorld
         | 
| 17 | 
            +
            	    HelloWorld # Here goes your cramp application, action or http routes.
         | 
| 15 18 | 
             
            	  end
         | 
| 16 19 |  | 
| 20 | 
            +
            	  # Matching on status code.
         | 
| 17 21 | 
             
            	  it "should respond to a GET request" do
         | 
| 18 | 
            -
            	    # Various ways to match a response code.
         | 
| 19 22 | 
             
            	    get("/").should respond_with :status => :ok         # Matches responses from 200 to 299.
         | 
| 20 23 | 
             
            	    get("/").should respond_with :status => 200         # Matches only 200.
         | 
| 21 24 | 
             
            	    get("/").should respond_with :status => "200"       # Same as above.
         | 
| @@ -23,19 +26,45 @@ Quick start | |
| 23 26 | 
             
            	    get("/").should_not respond_with :status => :error  # Matches any HTTP error.
         | 
| 24 27 | 
             
            	  end
         | 
| 25 28 |  | 
| 29 | 
            +
            	  # Matching on response body.
         | 
| 26 30 | 
             
            	  it "should respond with text starting with 'Hello'" do
         | 
| 27 31 | 
             
            	    get("/").should respond_with :body => /^Hello.*/
         | 
| 28 32 | 
             
            	  end
         | 
| 29 | 
            -
             | 
| 30 33 | 
             
            	  it "should respond with 'Hello, world!'" do
         | 
| 31 34 | 
             
            	    get("/").should respond_with :body => "Hello, world!"
         | 
| 32 35 | 
             
            	  end
         | 
| 33 | 
            -
             | 
| 36 | 
            +
             | 
| 37 | 
            +
            	  # Matching on response headers.
         | 
| 34 38 | 
             
            	  it "should respond with html" do
         | 
| 35 39 | 
             
            	    get("/").should respond_with :headers => {"Content-Type" => "text/html"}
         | 
| 36 40 | 
             
            	    get("/").should_not respond_with :headers => {"Content-Type" => "text/plain"}
         | 
| 37 41 | 
             
            	    get("/").should_not respond_with :headers => {"Unexpected-Header" => /.*/}
         | 
| 38 42 | 
             
            	  end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            	  # Matching using lambdas.
         | 
| 45 | 
            +
            	  it "should match my sophisticated custom matchers" do
         | 
| 46 | 
            +
            	    # Entire headers.
         | 
| 47 | 
            +
            	    status_check = lambda {|status| status.between?(200, 299)}
         | 
| 48 | 
            +
            	    body_check = lambda {|body| body =~ /.*el.*/}
         | 
| 49 | 
            +
            	    headers_check = lambda {|headers| true} # Any headers will do.
         | 
| 50 | 
            +
            	    get("/").should respond_with :status => status_check, :body => body_check, :headers => headers_check
         | 
| 51 | 
            +
            	    # Header value.
         | 
| 52 | 
            +
            	    get("/").should respond_with :headers => {"Content-Type" => lambda {|value| value == "text/html"}}
         | 
| 53 | 
            +
            	    get("/").should_not respond_with :headers => {"Content-Type" => lambda {|value| value == "text/plain"}}
         | 
| 54 | 
            +
            	  end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            	  # Supports POST/GET/PUT/DELETE and you don't have to use the matcher.
         | 
| 57 | 
            +
            	  it "should work without a matcher" do
         | 
| 58 | 
            +
            	    get "/"
         | 
| 59 | 
            +
            	    post "/"
         | 
| 60 | 
            +
            	    put "/"
         | 
| 61 | 
            +
            	    delete "/"
         | 
| 62 | 
            +
            	  end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
            	  # Request params & custom headers.
         | 
| 65 | 
            +
            	  it "should accept my params" do
         | 
| 66 | 
            +
            	    post("/", :params => {:text => "whatever"}, :headers => {"Custom-Header" => "blah"})
         | 
| 67 | 
            +
            	  end
         | 
| 39 68 | 
             
            	end
         | 
| 40 69 |  | 
| 41 70 | 
             
            The matcher is fairly flexible, supports regular expressions and also works with multipart responses (more than one `Cramp::Action.render`), SSE and so on. I'll create more examples and docs but for the time being, pls. take a look at the code and [examples](https://github.com/bilus/rspec-cramp/tree/master/spec/examples).
         | 
| @@ -47,11 +76,15 @@ Project status | |
| 47 76 |  | 
| 48 77 | 
             
            **IMPORTANT:** This is work in progress. 
         | 
| 49 78 |  | 
| 50 | 
            -
             | 
| 51 | 
            -
            2. I extracted the code from one of my projects and rewrote the matchers from scratch test-first. Still, after the weekend I plan to actually use it to replace the 'legacy' matchers in my project; this will probably uncover some bugs and may make me add more functionality. *UPDATE: I'm working on it right now.*
         | 
| 79 | 
            +
            There are still some things I'll take care of soon (esp. better failure messages).
         | 
| 52 80 |  | 
| 53 81 | 
             
            If you have any comments regarding the code as it is now (I know it's a bit messy), please feel free to tweet [@MartinBilski](http://twitter.com/#!/MartinBilski)
         | 
| 54 82 |  | 
| 83 | 
            +
            Contributors
         | 
| 84 | 
            +
            ------------
         | 
| 85 | 
            +
             | 
| 86 | 
            +
            [Ivan Fomichev](https://github.com/codeholic)
         | 
| 87 | 
            +
             | 
| 55 88 | 
             
            Notes
         | 
| 56 89 | 
             
            ----
         | 
| 57 90 |  | 
| @@ -7,6 +7,8 @@ RSpec::Matchers.define :respond_with do |options = {}| | |
| 7 7 | 
             
                response.matching?(options)
         | 
| 8 8 | 
             
              end
         | 
| 9 9 |  | 
| 10 | 
            +
              # TODO Better message for cases such as: specify { get("/").should respond_with :status => :ok }.
         | 
| 11 | 
            +
              
         | 
| 10 12 | 
             
              failure_message_for_should do
         | 
| 11 13 | 
             
                @actual_response.last_failure_message_for_should
         | 
| 12 14 | 
             
              end
         | 
| @@ -14,8 +14,7 @@ module RSpec | |
| 14 14 | 
             
                      stopping = false
         | 
| 15 15 | 
             
                      deferred_body = @body
         | 
| 16 16 | 
             
                      chunks = []
         | 
| 17 | 
            -
                       | 
| 18 | 
            -
                        chunks << chunk unless stopping
         | 
| 17 | 
            +
                      check = lambda do
         | 
| 19 18 | 
             
                        if chunks.count >= max_chunks
         | 
| 20 19 | 
             
                          @body = chunks
         | 
| 21 20 | 
             
                          stopping = true
         | 
| @@ -23,6 +22,11 @@ module RSpec | |
| 23 22 | 
             
                          EM.next_tick { EM.stop }
         | 
| 24 23 | 
             
                        end            
         | 
| 25 24 | 
             
                      end
         | 
| 25 | 
            +
                      check.call
         | 
| 26 | 
            +
                      deferred_body.each do |chunk|
         | 
| 27 | 
            +
                        chunks << chunk unless stopping
         | 
| 28 | 
            +
                        check.call
         | 
| 29 | 
            +
                      end
         | 
| 26 30 | 
             
                    end
         | 
| 27 31 | 
             
                  end
         | 
| 28 32 |  | 
| @@ -117,8 +121,13 @@ module RSpec | |
| 117 121 | 
             
                  end
         | 
| 118 122 |  | 
| 119 123 | 
             
                  def matching_headers?(expected_header)
         | 
| 120 | 
            -
                    expected_header.nil? | 
| 121 | 
            -
             | 
| 124 | 
            +
                    if expected_header.nil?
         | 
| 125 | 
            +
                      true
         | 
| 126 | 
            +
                    elsif expected_header.is_a? Proc
         | 
| 127 | 
            +
                      matching_response_element?(:headers, @headers, expected_header)
         | 
| 128 | 
            +
                    else
         | 
| 129 | 
            +
                      matching_header_keys?(expected_header) && matching_header_values?(expected_header)
         | 
| 130 | 
            +
                    end
         | 
| 122 131 | 
             
                  end
         | 
| 123 132 |  | 
| 124 133 | 
             
                  def matching_body?(expected_body)
         | 
    
        data/spec/examples/basic_spec.rb
    CHANGED
    
    | @@ -1,13 +1,16 @@ | |
| 1 1 | 
             
            require File.join(File.dirname(__FILE__), "../spec_helper")
         | 
| 2 2 | 
             
            require File.join(File.dirname(__FILE__), "sample_actions")
         | 
| 3 3 |  | 
| 4 | 
            +
            # Decorate your spec with :cramp => true
         | 
| 4 5 | 
             
            describe HelloWorld, :cramp => true do
         | 
| 6 | 
            +
              
         | 
| 7 | 
            +
              # You need to define this method
         | 
| 5 8 | 
             
              def app
         | 
| 6 | 
            -
                HelloWorld
         | 
| 9 | 
            +
                HelloWorld # Here goes your cramp application, action or http routes.
         | 
| 7 10 | 
             
              end
         | 
| 8 11 |  | 
| 12 | 
            +
              # Matching on status code.
         | 
| 9 13 | 
             
              it "should respond to a GET request" do
         | 
| 10 | 
            -
                # Variaus ways to match a response code.
         | 
| 11 14 | 
             
                get("/").should respond_with :status => :ok         # Matches responses from 200 to 299.
         | 
| 12 15 | 
             
                get("/").should respond_with :status => 200         # Matches only 200.
         | 
| 13 16 | 
             
                get("/").should respond_with :status => "200"       # Same as above.
         | 
| @@ -15,17 +18,43 @@ describe HelloWorld, :cramp => true do | |
| 15 18 | 
             
                get("/").should_not respond_with :status => :error  # Matches any HTTP error.
         | 
| 16 19 | 
             
              end
         | 
| 17 20 |  | 
| 21 | 
            +
              # Matching on response body.
         | 
| 18 22 | 
             
              it "should respond with text starting with 'Hello'" do
         | 
| 19 23 | 
             
                get("/").should respond_with :body => /^Hello.*/
         | 
| 20 24 | 
             
              end
         | 
| 21 | 
            -
             | 
| 22 25 | 
             
              it "should respond with 'Hello, world!'" do
         | 
| 23 26 | 
             
                get("/").should respond_with :body => "Hello, world!"
         | 
| 24 27 | 
             
              end
         | 
| 25 28 |  | 
| 29 | 
            +
              # Matching on response headers.
         | 
| 26 30 | 
             
              it "should respond with html" do
         | 
| 27 31 | 
             
                get("/").should respond_with :headers => {"Content-Type" => "text/html"}
         | 
| 28 32 | 
             
                get("/").should_not respond_with :headers => {"Content-Type" => "text/plain"}
         | 
| 29 33 | 
             
                get("/").should_not respond_with :headers => {"Unexpected-Header" => /.*/}
         | 
| 30 34 | 
             
              end
         | 
| 35 | 
            +
              
         | 
| 36 | 
            +
              # Matching using lambdas.
         | 
| 37 | 
            +
              it "should match my sophisticated custom matchers" do
         | 
| 38 | 
            +
                # Entire headers.
         | 
| 39 | 
            +
                status_check = lambda {|status| status.between?(200, 299)}
         | 
| 40 | 
            +
                body_check = lambda {|body| body =~ /.*el.*/}
         | 
| 41 | 
            +
                headers_check = lambda {|headers| true} # Any headers will do.
         | 
| 42 | 
            +
                get("/").should respond_with :status => status_check, :body => body_check, :headers => headers_check
         | 
| 43 | 
            +
                # Header value.
         | 
| 44 | 
            +
                get("/").should respond_with :headers => {"Content-Type" => lambda {|value| value == "text/html"}}
         | 
| 45 | 
            +
                get("/").should_not respond_with :headers => {"Content-Type" => lambda {|value| value == "text/plain"}}
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
              
         | 
| 48 | 
            +
              # Supports POST/GET/PUT/DELETE and you don't have to use the matcher.
         | 
| 49 | 
            +
              it "should work without a matcher" do
         | 
| 50 | 
            +
                get "/"
         | 
| 51 | 
            +
                post "/"
         | 
| 52 | 
            +
                put "/"
         | 
| 53 | 
            +
                delete "/"
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
              
         | 
| 56 | 
            +
              # Request params & custom headers.
         | 
| 57 | 
            +
              it "should accept my params" do
         | 
| 58 | 
            +
                post("/", :params => {:text => "whatever"}, :headers => {"Custom-Header" => "blah"})
         | 
| 59 | 
            +
              end
         | 
| 31 60 | 
             
            end
         | 
    
        data/spec/rspec_cramp_spec.rb
    CHANGED
    
    | @@ -91,6 +91,10 @@ module Cramp | |
| 91 91 | 
             
                  end
         | 
| 92 92 | 
             
                end
         | 
| 93 93 |  | 
| 94 | 
            +
                class SseNoRenderAction < Cramp::Action
         | 
| 95 | 
            +
                  self.transport = :sse
         | 
| 96 | 
            +
                end
         | 
| 97 | 
            +
             | 
| 94 98 | 
             
                class RequestHeaders < Cramp::Action
         | 
| 95 99 | 
             
                  on_start :render_request_headers
         | 
| 96 100 | 
             
                  def render_request_headers
         | 
| @@ -127,10 +131,11 @@ module Cramp | |
| 127 131 | 
             
                    add('/raise_on_start').to RaiseOnStart
         | 
| 128 132 | 
             
                    add('/raise_on_finish').to RaiseOnFinish
         | 
| 129 133 | 
             
                    add('/sse').to SseAction
         | 
| 130 | 
            -
                    add('/ | 
| 131 | 
            -
                     | 
| 132 | 
            -
                     | 
| 133 | 
            -
                     | 
| 134 | 
            +
                    add('/sse_no_render').to SseNoRenderAction
         | 
| 135 | 
            +
                    get('/get_only').to SuccessfulResponse
         | 
| 136 | 
            +
                    post('/post_only').to SuccessfulResponse
         | 
| 137 | 
            +
                    put('/put_only').to SuccessfulResponse
         | 
| 138 | 
            +
                    delete('/delete_only').to SuccessfulResponse
         | 
| 134 139 | 
             
                    add('/request_headers').to RequestHeaders
         | 
| 135 140 | 
             
                    add('/request_params').to RequestParams
         | 
| 136 141 | 
             
                  end
         | 
| @@ -160,7 +165,6 @@ module Cramp | |
| 160 165 | 
             
                      end
         | 
| 161 166 | 
             
                    end
         | 
| 162 167 |  | 
| 163 | 
            -
                    # TODO Rewrite the repetitive code below using data-based spec generation.
         | 
| 164 168 | 
             
                    describe "exact match on response status" do
         | 
| 165 169 | 
             
                      it "should match successful response" do
         | 
| 166 170 | 
             
                        send(method, "/200").should respond_with :status => 200
         | 
| @@ -255,6 +259,21 @@ module Cramp | |
| 255 259 | 
             
                      it "should not match iff the header isn't there" do
         | 
| 256 260 | 
             
                        send(method, "/custom_header").should_not respond_with :headers => {/Non\-Existent\-One/i => /^QWERTY$/}
         | 
| 257 261 | 
             
                      end
         | 
| 262 | 
            +
                    end  
         | 
| 263 | 
            +
                    
         | 
| 264 | 
            +
                    describe "lambda match on entire header " do
         | 
| 265 | 
            +
                      it "should match when true" do
         | 
| 266 | 
            +
                        match_headers = lambda do |headers|
         | 
| 267 | 
            +
                          headers.find {|(k, v)| k == "Extra-Header" && v == "ABCD"}
         | 
| 268 | 
            +
                        end
         | 
| 269 | 
            +
                        send(method, "/custom_header").should respond_with :headers => match_headers
         | 
| 270 | 
            +
                      end
         | 
| 271 | 
            +
                      it "should not match when false" do
         | 
| 272 | 
            +
                        match_headers = lambda do |headers|
         | 
| 273 | 
            +
                          headers.find {|(k, v)| k == "Non-Existent-One" && v == "QWERTY"}
         | 
| 274 | 
            +
                        end
         | 
| 275 | 
            +
                        send(method, "/custom_header").should_not respond_with :headers => match_headers
         | 
| 276 | 
            +
                      end
         | 
| 258 277 | 
             
                    end
         | 
| 259 278 |  | 
| 260 279 | 
             
                    # FIXME How to handle a situation where nothing is rendered? get reads the body...
         | 
| @@ -345,6 +364,11 @@ module Cramp | |
| 345 364 | 
             
                        send(method, "/sse", :max_chunks => 2).should respond_with :chunks => [/^data: Hello 1.*/, /^data: Hello 2.*/]
         | 
| 346 365 | 
             
                        send(method, "/sse", :max_chunks => 2).should_not respond_with :chunks => [/.*Incorrect 1.*/, /.*Incorrect 2.*/]
         | 
| 347 366 | 
             
                      end
         | 
| 367 | 
            +
             | 
| 368 | 
            +
                      it "should not wait for body if it is skipped explicitly" do
         | 
| 369 | 
            +
                        lambda { send(method, "/sse_no_render", :max_chunks => 0) }.should_not raise_error Timeout::Error
         | 
| 370 | 
            +
                        send(method, "/sse_no_render", :max_chunks => 0).should respond_with :status => 200, :body => ""
         | 
| 371 | 
            +
                      end
         | 
| 348 372 | 
             
                    end
         | 
| 349 373 |  | 
| 350 374 | 
             
                    it "should correctly handle exception in the callbacks" do
         | 
| @@ -385,7 +409,6 @@ module Cramp | |
| 385 409 | 
             
                    end
         | 
| 386 410 | 
             
                  end
         | 
| 387 411 |  | 
| 388 | 
            -
                  # TODO Add method-specific paths to http routes and write specs.
         | 
| 389 412 | 
             
                  describe "GET request" do
         | 
| 390 413 | 
             
                    it_should_behave_like "async_request", :get 
         | 
| 391 414 |  | 
| @@ -437,9 +460,8 @@ module Cramp | |
| 437 460 | 
             
                    routes
         | 
| 438 461 | 
             
                  end
         | 
| 439 462 |  | 
| 440 | 
            -
                  #  | 
| 441 | 
            -
             | 
| 442 | 
            -
                  # Anyway, we need more tests here.
         | 
| 463 | 
            +
                  # Note: Only basic specs here because respond_with matcher uses the same code and is extensively tested.
         | 
| 464 | 
            +
                   
         | 
| 443 465 | 
             
                  it "should support expectations on response status" do
         | 
| 444 466 | 
             
                    get("/200") do |response|
         | 
| 445 467 | 
             
                      response.should be_matching :status => 200
         | 
| @@ -488,4 +510,4 @@ module Cramp | |
| 488 510 | 
             
                   end
         | 
| 489 511 | 
             
                end
         | 
| 490 512 | 
             
              end
         | 
| 491 | 
            -
            end
         | 
| 513 | 
            +
            end
         | 
    
        data/spec/spec_helper.rb
    CHANGED