Skip to content

Commit 1e2e7d5

Browse files
committed
Merge pull request #36 from zipmark/headers
Headers
2 parents b581c70 + ee62f81 commit 1e2e7d5

File tree

9 files changed

+110
-86
lines changed

9 files changed

+110
-86
lines changed

features/headers.feature

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
Feature: Specifying request headers
2+
3+
Background:
4+
Given a file named "app.rb" with:
5+
"""
6+
class App
7+
def self.call(env)
8+
if env["HTTP_ACCEPT"] == "foo"
9+
[200, {}, ["foo"]]
10+
else
11+
[406, {}, ["unknown content type"]]
12+
end
13+
end
14+
end
15+
"""
16+
And a file named "app_spec.rb" with:
17+
"""
18+
require "rspec_api_documentation"
19+
require "rspec_api_documentation/dsl"
20+
21+
RspecApiDocumentation.configure do |config|
22+
config.app = App
23+
end
24+
25+
resource "FooBars" do
26+
get "/foobar" do
27+
header "Accept", "foo"
28+
29+
example "Getting Foo" do
30+
do_request
31+
response_body.should == "foo"
32+
end
33+
end
34+
end
35+
"""
36+
When I run `rspec app_spec.rb --require ./app.rb --format RspecApiDocumentation::ApiFormatter`
37+
38+
Scenario: Sending headers along with the request
39+
Then the output should not contain "unknown content type"

lib/rspec_api_documentation/client_base.rb

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ def delete(*args)
2323

2424
private
2525

26-
def process(method, path, params = {})
27-
do_request(method, path, params)
28-
document_example(method.to_s.upcase, path, params)
26+
def process(method, path, params = {}, headers ={})
27+
do_request(method, path, params, headers)
28+
document_example(method.to_s.upcase, path)
2929
end
3030

31-
def document_example(method, path, params)
31+
def document_example(method, path)
3232
return unless metadata[:document]
3333

3434
input = last_request.env["rack.input"]
@@ -63,12 +63,8 @@ def query_hash
6363
Hash[arrays]
6464
end
6565

66-
def headers(method, path, params)
67-
if options && options[:headers]
68-
options[:headers]
69-
else
70-
{}
71-
end
66+
def headers(headers)
67+
headers || {}
7268
end
7369
end
7470
end

lib/rspec_api_documentation/dsl/endpoint.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def do_request(extra_params = {})
4141
params_or_body = respond_to?(:raw_post) ? raw_post : params
4242
end
4343

44-
client.send(method, path_or_query, params_or_body)
44+
client.send(method, path_or_query, params_or_body, headers)
4545
end
4646

4747
def query_string
@@ -61,6 +61,10 @@ def params
6161
parameters
6262
end
6363

64+
def headers
65+
example.metadata[:headers]
66+
end
67+
6468
def method
6569
example.metadata[:method]
6670
end

lib/rspec_api_documentation/dsl/resource.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ def parameter(name, description, options = {})
3535
parameters.push(options.merge(:name => name.to_s, :description => description))
3636
end
3737

38+
def header(name, value)
39+
headers[name] = value
40+
end
41+
3842
def required_parameters(*names)
3943
names.each do |name|
4044
param = parameters.find { |param| param[:name] == name.to_s }
@@ -67,6 +71,14 @@ def parameters
6771
metadata[:parameters]
6872
end
6973

74+
def headers
75+
metadata[:headers] ||= {}
76+
if superclass_metadata && metadata[:headers].equal?(superclass_metadata[:headers])
77+
metadata[:headers] = Marshal.load(Marshal.dump(superclass_metadata[:headers]))
78+
end
79+
metadata[:headers]
80+
end
81+
7082
def parameter_keys
7183
parameters.map { |param| param[:name] }
7284
end

lib/rspec_api_documentation/headers.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@ def env_to_headers(env)
1414
headers
1515
end
1616

17+
def headers_to_env(headers)
18+
headers.inject({}) do |hsh, (k, v)|
19+
new_key = k.upcase.gsub("-", "_")
20+
new_key = "HTTP_#{new_key}" unless new_key == "CONTENT_TYPE"
21+
hsh[new_key] = v
22+
hsh
23+
end
24+
end
25+
1726
def format_headers(headers)
1827
headers.map do |key, value|
1928
"#{key}: #{value}"

lib/rspec_api_documentation/oauth2_mac_client.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ def response_content_type
4242

4343
protected
4444

45-
def do_request(method, path, params)
46-
self.last_response = access_token.send(method, "http://example.com#{path}", :body => params, :header => headers(method, path, params))
45+
def do_request(method, path, params, request_headers)
46+
self.last_response = access_token.send(method, "http://example.com#{path}", :body => params, :header => headers(request_headers))
4747
end
4848

4949
class ProxyApp < Struct.new(:client, :app)

lib/rspec_api_documentation/rack_test_client.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,12 @@ def response_content_type
3434

3535
protected
3636

37-
def do_request(method, path, params)
38-
rack_test_session.send(method, path, params, headers(method, path, params))
37+
def do_request(method, path, params, request_headers)
38+
rack_test_session.send(method, path, params, headers(request_headers))
39+
end
40+
41+
def headers(*args)
42+
headers_to_env(super)
3943
end
4044

4145
private

spec/dsl_spec.rb

Lines changed: 28 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -139,30 +139,30 @@
139139
let(:raw_post) { { :bill => params }.to_json }
140140

141141
it "should send the raw post body" do
142-
client.should_receive(method).with(path, raw_post)
142+
client.should_receive(method).with(path, raw_post, nil)
143143
do_request
144144
end
145145
end
146146

147147
context "when raw_post is not defined" do
148148
it "should send the params hash" do
149-
client.should_receive(method).with(path, params)
149+
client.should_receive(method).with(path, params, nil)
150150
do_request
151151
end
152152
end
153153

154154
it "should allow extra parameters to be passed in" do
155-
client.should_receive(method).with(path, params.merge("extra" => true))
155+
client.should_receive(method).with(path, params.merge("extra" => true), nil)
156156
do_request(:extra => true)
157157
end
158158

159159
it "should overwrite parameters" do
160-
client.should_receive(method).with(path, params.merge("size" => "large"))
160+
client.should_receive(method).with(path, params.merge("size" => "large"), nil)
161161
do_request(:size => "large")
162162
end
163163

164164
it "should overwrite path variables" do
165-
client.should_receive(method).with("/orders/2", params)
165+
client.should_receive(method).with("/orders/2", params, nil)
166166
do_request(:id => 2)
167167
end
168168
end
@@ -203,32 +203,6 @@
203203
end
204204
end
205205

206-
# parameter :type, "The type of drink you want."
207-
# parameter :size, "The size of drink you want."
208-
# parameter :note, "Any additional notes about your order."
209-
210-
# required_parameters :type, :size
211-
212-
# raw_post { { :bill => params }.to_json }
213-
214-
# example_request "Ordering a cup of coffee" do
215-
# param(:type) { "coffee" }
216-
# param(:size) { "cup" }
217-
218-
# should_respond_with_status eq(200)
219-
# should_respond_with_body eq("Order created")
220-
# end
221-
222-
# example_request "An invalid order" do
223-
# param(:type) { "caramel macchiato" }
224-
# param(:note) { "whipped cream" }
225-
226-
# should_respond_with_status eq(400)
227-
# should_respond_with_body json_eql({:errors => {:size => ["can't be blank"]}}.to_json)
228-
# end
229-
#end
230-
#
231-
232206
describe "nested parameters" do
233207
parameter :per_page, "Number of results on a page"
234208

@@ -309,18 +283,19 @@
309283

310284
get "/users/:id/orders" do
311285
example "Page should be in the query string" do
312-
client.should_receive(method).with do |path, data|
286+
client.should_receive(method).with do |path, data, headers|
313287
path.should =~ /^\/users\/1\/orders\?/
314288
path.split("?")[1].split("&").sort.should == "page=2&message=Thank+you".split("&").sort
315289
data.should be_nil
290+
headers.should be_nil
316291
end
317292
do_request
318293
end
319294
end
320295

321296
post "/users/:id/orders" do
322297
example "Page should be in the post body" do
323-
client.should_receive(method).with("/users/1/orders", {"page" => 2, "message" => "Thank you"})
298+
client.should_receive(method).with("/users/1/orders", {"page" => 2, "message" => "Thank you"}, nil)
324299
do_request
325300
end
326301
end
@@ -411,7 +386,7 @@
411386

412387
context "no extra params" do
413388
before do
414-
client.should_receive(:post).with("/orders", {})
389+
client.should_receive(:post).with("/orders", {}, nil)
415390
end
416391

417392
example_request "Creating an order"
@@ -423,7 +398,7 @@
423398

424399
context "extra options for do_request" do
425400
before do
426-
client.should_receive(:post).with("/orders", {"order_type" => "big"})
401+
client.should_receive(:post).with("/orders", {"order_type" => "big"}, nil)
427402
end
428403

429404
example_request "should take an optional parameter hash", :order_type => "big"
@@ -444,6 +419,24 @@
444419
end
445420
end
446421
end
422+
423+
context "headers" do
424+
put "/orders" do
425+
header "Accept", "application/json"
426+
427+
it "should be sent with the request" do
428+
example.metadata[:headers].should == { "Accept" => "application/json" }
429+
end
430+
431+
context "nested headers" do
432+
header "Content-Type", "application/json"
433+
434+
it "does not affect the outer context's assertions" do
435+
# pass
436+
end
437+
end
438+
end
439+
end
447440
end
448441

449442
resource "top level parameters" do

spec/rack_test_client_spec.rb

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,7 @@ class StubApp < Sinatra::Base
6767

6868
describe "#request_headers" do
6969
before do
70-
test_client.options[:headers] = {
71-
"HTTP_ACCEPT" => "application/json",
72-
"CONTENT_TYPE" => "application/json"
73-
}
74-
test_client.get "/"
70+
test_client.get "/", {}, { "Accept" => "application/json", "Content-Type" => "application/json" }
7571
end
7672

7773
it "should contain all the headers" do
@@ -84,42 +80,13 @@ class StubApp < Sinatra::Base
8480
end
8581
end
8682

87-
describe "#headers" do
88-
before do
89-
test_client.options[:headers] = { "HTTP_X_CUSTOM_HEADER" => "custom header value" }
90-
test_client.get "/"
91-
end
92-
93-
it "can be overridden to add headers to the request" do
94-
test_client.request_headers["X-Custom-Header"].should eq("custom header value")
95-
end
96-
end
97-
98-
describe "setup default headers" do
99-
it "should let you set default headers when creating a new RackTestClient" do
100-
test_client = RspecApiDocumentation::RackTestClient.new(context, :headers => { "HTTP_MY_HEADER" => "hello" })
101-
test_client.get "/"
102-
test_client.request_headers["My-Header"].should == "hello"
103-
test_client.request_headers.should have(3).headers
104-
end
105-
106-
it "should be blank if not set" do
107-
test_client = RspecApiDocumentation::RackTestClient.new(context)
108-
test_client.get "/"
109-
test_client.request_headers.should have(2).headers
110-
end
111-
end
112-
11383
context "after a request is made" do
11484
before do
115-
test_client.options[:headers] = {
116-
"CONTENT_TYPE" => "application/json;charset=utf-8",
117-
"HTTP_X_CUSTOM_HEADER" => "custom header value"
118-
}
119-
test_client.post "/greet?query=test+query", post_data
85+
test_client.post "/greet?query=test+query", post_data, headers
12086
end
12187

12288
let(:post_data) { { :target => "nurse" }.to_json }
89+
let(:headers) { { "Content-Type" => "application/json;charset=utf-8", "X-Custom-Header" => "custom header value" } }
12390

12491
context "when examples should be documented", :document => true do
12592
it "should augment the metadata with information about the request" do

0 commit comments

Comments
 (0)