Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Headers #36

Merged
merged 3 commits into from
May 22, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions features/headers.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
Feature: Specifying request headers

Background:
Given a file named "app.rb" with:
"""
class App
def self.call(env)
if env["HTTP_ACCEPT"] == "foo"
[200, {}, ["foo"]]
else
[406, {}, ["unknown content type"]]
end
end
end
"""
And a file named "app_spec.rb" with:
"""
require "rspec_api_documentation"
require "rspec_api_documentation/dsl"

RspecApiDocumentation.configure do |config|
config.app = App
end

resource "FooBars" do
get "/foobar" do
header "Accept", "foo"

example "Getting Foo" do
do_request
response_body.should == "foo"
end
end
end
"""
When I run `rspec app_spec.rb --require ./app.rb --format RspecApiDocumentation::ApiFormatter`

Scenario: Sending headers along with the request
Then the output should not contain "unknown content type"
16 changes: 6 additions & 10 deletions lib/rspec_api_documentation/client_base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ def delete(*args)

private

def process(method, path, params = {})
do_request(method, path, params)
document_example(method.to_s.upcase, path, params)
def process(method, path, params = {}, headers ={})
do_request(method, path, params, headers)
document_example(method.to_s.upcase, path)
end

def document_example(method, path, params)
def document_example(method, path)
return unless metadata[:document]

input = last_request.env["rack.input"]
Expand Down Expand Up @@ -63,12 +63,8 @@ def query_hash
Hash[arrays]
end

def headers(method, path, params)
if options && options[:headers]
options[:headers]
else
{}
end
def headers(headers)
headers || {}
end
end
end
6 changes: 5 additions & 1 deletion lib/rspec_api_documentation/dsl/endpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def do_request(extra_params = {})
params_or_body = respond_to?(:raw_post) ? raw_post : params
end

client.send(method, path_or_query, params_or_body)
client.send(method, path_or_query, params_or_body, headers)
end

def query_string
Expand All @@ -61,6 +61,10 @@ def params
parameters
end

def headers
example.metadata[:headers]
end

def method
example.metadata[:method]
end
Expand Down
12 changes: 12 additions & 0 deletions lib/rspec_api_documentation/dsl/resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ def parameter(name, description, options = {})
parameters.push(options.merge(:name => name.to_s, :description => description))
end

def header(name, value)
headers[name] = value
end

def required_parameters(*names)
names.each do |name|
param = parameters.find { |param| param[:name] == name.to_s }
Expand Down Expand Up @@ -67,6 +71,14 @@ def parameters
metadata[:parameters]
end

def headers
metadata[:headers] ||= {}
if superclass_metadata && metadata[:headers].equal?(superclass_metadata[:headers])
metadata[:headers] = Marshal.load(Marshal.dump(superclass_metadata[:headers]))
end
metadata[:headers]
end

def parameter_keys
parameters.map { |param| param[:name] }
end
Expand Down
9 changes: 9 additions & 0 deletions lib/rspec_api_documentation/headers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ def env_to_headers(env)
headers
end

def headers_to_env(headers)
headers.inject({}) do |hsh, (k, v)|
new_key = k.upcase.gsub("-", "_")
new_key = "HTTP_#{new_key}" unless new_key == "CONTENT_TYPE"
hsh[new_key] = v
hsh
end
end

def format_headers(headers)
headers.map do |key, value|
"#{key}: #{value}"
Expand Down
4 changes: 2 additions & 2 deletions lib/rspec_api_documentation/oauth2_mac_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ def response_content_type

protected

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

class ProxyApp < Struct.new(:client, :app)
Expand Down
8 changes: 6 additions & 2 deletions lib/rspec_api_documentation/rack_test_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,12 @@ def response_content_type

protected

def do_request(method, path, params)
rack_test_session.send(method, path, params, headers(method, path, params))
def do_request(method, path, params, request_headers)
rack_test_session.send(method, path, params, headers(request_headers))
end

def headers(*args)
headers_to_env(super)
end

private
Expand Down
63 changes: 28 additions & 35 deletions spec/dsl_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -139,30 +139,30 @@
let(:raw_post) { { :bill => params }.to_json }

it "should send the raw post body" do
client.should_receive(method).with(path, raw_post)
client.should_receive(method).with(path, raw_post, nil)
do_request
end
end

context "when raw_post is not defined" do
it "should send the params hash" do
client.should_receive(method).with(path, params)
client.should_receive(method).with(path, params, nil)
do_request
end
end

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

it "should overwrite parameters" do
client.should_receive(method).with(path, params.merge("size" => "large"))
client.should_receive(method).with(path, params.merge("size" => "large"), nil)
do_request(:size => "large")
end

it "should overwrite path variables" do
client.should_receive(method).with("/orders/2", params)
client.should_receive(method).with("/orders/2", params, nil)
do_request(:id => 2)
end
end
Expand Down Expand Up @@ -203,32 +203,6 @@
end
end

# parameter :type, "The type of drink you want."
# parameter :size, "The size of drink you want."
# parameter :note, "Any additional notes about your order."

# required_parameters :type, :size

# raw_post { { :bill => params }.to_json }

# example_request "Ordering a cup of coffee" do
# param(:type) { "coffee" }
# param(:size) { "cup" }

# should_respond_with_status eq(200)
# should_respond_with_body eq("Order created")
# end

# example_request "An invalid order" do
# param(:type) { "caramel macchiato" }
# param(:note) { "whipped cream" }

# should_respond_with_status eq(400)
# should_respond_with_body json_eql({:errors => {:size => ["can't be blank"]}}.to_json)
# end
#end
#

describe "nested parameters" do
parameter :per_page, "Number of results on a page"

Expand Down Expand Up @@ -309,18 +283,19 @@

get "/users/:id/orders" do
example "Page should be in the query string" do
client.should_receive(method).with do |path, data|
client.should_receive(method).with do |path, data, headers|
path.should =~ /^\/users\/1\/orders\?/
path.split("?")[1].split("&").sort.should == "page=2&message=Thank+you".split("&").sort
data.should be_nil
headers.should be_nil
end
do_request
end
end

post "/users/:id/orders" do
example "Page should be in the post body" do
client.should_receive(method).with("/users/1/orders", {"page" => 2, "message" => "Thank you"})
client.should_receive(method).with("/users/1/orders", {"page" => 2, "message" => "Thank you"}, nil)
do_request
end
end
Expand Down Expand Up @@ -411,7 +386,7 @@

context "no extra params" do
before do
client.should_receive(:post).with("/orders", {})
client.should_receive(:post).with("/orders", {}, nil)
end

example_request "Creating an order"
Expand All @@ -423,7 +398,7 @@

context "extra options for do_request" do
before do
client.should_receive(:post).with("/orders", {"order_type" => "big"})
client.should_receive(:post).with("/orders", {"order_type" => "big"}, nil)
end

example_request "should take an optional parameter hash", :order_type => "big"
Expand All @@ -444,6 +419,24 @@
end
end
end

context "headers" do
put "/orders" do
header "Accept", "application/json"

it "should be sent with the request" do
example.metadata[:headers].should == { "Accept" => "application/json" }
end

context "nested headers" do
header "Content-Type", "application/json"

it "does not affect the outer context's assertions" do
# pass
end
end
end
end
end

resource "top level parameters" do
Expand Down
39 changes: 3 additions & 36 deletions spec/rack_test_client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,7 @@ class StubApp < Sinatra::Base

describe "#request_headers" do
before do
test_client.options[:headers] = {
"HTTP_ACCEPT" => "application/json",
"CONTENT_TYPE" => "application/json"
}
test_client.get "/"
test_client.get "/", {}, { "Accept" => "application/json", "Content-Type" => "application/json" }
end

it "should contain all the headers" do
Expand All @@ -84,42 +80,13 @@ class StubApp < Sinatra::Base
end
end

describe "#headers" do
before do
test_client.options[:headers] = { "HTTP_X_CUSTOM_HEADER" => "custom header value" }
test_client.get "/"
end

it "can be overridden to add headers to the request" do
test_client.request_headers["X-Custom-Header"].should eq("custom header value")
end
end

describe "setup default headers" do
it "should let you set default headers when creating a new RackTestClient" do
test_client = RspecApiDocumentation::RackTestClient.new(context, :headers => { "HTTP_MY_HEADER" => "hello" })
test_client.get "/"
test_client.request_headers["My-Header"].should == "hello"
test_client.request_headers.should have(3).headers
end

it "should be blank if not set" do
test_client = RspecApiDocumentation::RackTestClient.new(context)
test_client.get "/"
test_client.request_headers.should have(2).headers
end
end

context "after a request is made" do
before do
test_client.options[:headers] = {
"CONTENT_TYPE" => "application/json;charset=utf-8",
"HTTP_X_CUSTOM_HEADER" => "custom header value"
}
test_client.post "/greet?query=test+query", post_data
test_client.post "/greet?query=test+query", post_data, headers
end

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

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