rspec-cramp 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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