Skip to content

Commit 2be36b9

Browse files
committed
Refactor RackTestClient. Introduce ClientBase for new, awesome clients.
1 parent 8de9ded commit 2be36b9

File tree

8 files changed

+93
-84
lines changed

8 files changed

+93
-84
lines changed

features/html_documentation.feature

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,7 @@ Feature: Generate HTML documentation from test examples
6969
| Host | example.org |
7070
| Cookie | |
7171
And I should see the following query parameters:
72-
"""
73-
target: rspec_api_documentation
74-
"""
72+
| target | rspec_api_documentation |
7573

7674
Scenario: Example HTML documentation includes the response information
7775
When I open the index

features/step_definitions/html_steps.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@
2727
page.should have_css(".request.route", :text => route)
2828
end
2929

30-
Then /^I should see the following query parameters:$/ do |query_parameters|
31-
page.should have_css("pre.request.query_parameters"), :text => query_parameters
30+
Then /^I should see the following query parameters:$/ do |table|
31+
text = page.find("pre.request.query_parameters").text
32+
actual = text.split("\n")
33+
expected = table.raw.map { |row| row.join(": ") }
34+
actual.should =~ expected
3235
end
3336

3437
Then /^I should see the response status is "([^"]*)"$/ do |status|

lib/rspec_api_documentation.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ module RspecApiDocumentation
1616
autoload :Example
1717
autoload :ExampleGroup
1818
autoload :Index
19-
autoload :TestClient
19+
autoload :ClientBase
20+
autoload :RackTestClient
2021
autoload :Headers
2122
autoload :Syntax
2223
end

lib/rspec_api_documentation/test_client.rb renamed to lib/rspec_api_documentation/client_base.rb

Lines changed: 17 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,10 @@
1-
require "coderay"
2-
31
module RspecApiDocumentation
4-
class TestClient < Struct.new(:context, :options)
2+
class ClientBase < Struct.new(:context, :options)
53
include Headers
64
include Syntax
75

86
delegate :example, :app, :to => :context
97
delegate :metadata, :to => :example
10-
delegate :last_request, :last_response, :to => :rack_test_session
11-
private :last_request, :last_response
12-
13-
def rack_test_session
14-
@rack_test_session ||= Struct.new(:app) do
15-
begin
16-
include Rack::Test::Methods
17-
rescue LoadError
18-
raise "#{self.class.name} requires Rack::Test >= 0.5.5. Please add it to your test dependencies."
19-
end
20-
end.new(app)
21-
end
228

239
def get(*args)
2410
process :get, *args
@@ -36,50 +22,14 @@ def delete(*args)
3622
process :delete, *args
3723
end
3824

39-
def request_headers
40-
env_to_headers(last_request.env)
41-
end
42-
43-
def response_headers
44-
last_response.headers
45-
end
46-
47-
def query_string
48-
last_request.env["QUERY_STRING"]
49-
end
50-
51-
def query_hash
52-
strings = query_string.split("&")
53-
arrays = strings.map do |segment|
54-
segment.split("=")
55-
end
56-
Hash[arrays]
57-
end
58-
59-
def headers(method, action, params)
60-
if options && options[:headers]
61-
options[:headers]
62-
else
63-
{}
64-
end
65-
end
66-
67-
def status
68-
last_response.status
69-
end
70-
71-
def response_body
72-
last_response.body
73-
end
74-
7525
private
76-
def process(method, action, params = {})
77-
rack_test_session.send(method, action, params, headers(method, action, params))
7826

79-
document_example(method, action, params)
27+
def process(method, path, params = {})
28+
do_request(method, path, params)
29+
document_example(method.to_s.upcase, path, params)
8030
end
8131

82-
def document_example(method, action, params)
32+
def document_example(method, path, params)
8333
return unless metadata[:document]
8434

8535
input = last_request.env["rack.input"]
@@ -88,21 +38,29 @@ def document_example(method, action, params)
8838

8939
request_metadata = {}
9040

91-
request_metadata[:request_method] = method.to_s.upcase
92-
request_metadata[:request_path] = action
93-
request_metadata[:request_body] = highlight_syntax(request_body, last_request.content_type, true)
41+
request_metadata[:request_method] = method
42+
request_metadata[:request_path] = path
43+
request_metadata[:request_body] = highlight_syntax(request_body, content_type, true)
9444
request_metadata[:request_headers] = format_headers(request_headers)
9545
request_metadata[:request_query_parameters] = format_query_hash(query_hash)
9646
request_metadata[:response_status] = status
9747
request_metadata[:response_status_text] = Rack::Utils::HTTP_STATUS_CODES[status]
9848
request_metadata[:response_body] = highlight_syntax(response_body, response_headers['Content-Type'])
9949
request_metadata[:response_headers] = format_headers(response_headers)
100-
request_metadata[:curl] = Curl.new(method.to_s, action, request_body, request_headers)
50+
request_metadata[:curl] = Curl.new(method, path, request_body, request_headers)
10151

10252
metadata[:requests] ||= []
10353
metadata[:requests] << request_metadata
10454
end
10555

56+
def query_hash
57+
strings = query_string.split("&")
58+
arrays = strings.map do |segment|
59+
segment.split("=")
60+
end
61+
Hash[arrays]
62+
end
63+
10664
def format_query_hash(query_hash)
10765
return if query_hash.blank?
10866
query_hash.map do |key, value|

lib/rspec_api_documentation/dsl.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def parameter_keys
9292
end
9393

9494
def client
95-
@client ||= TestClient.new(self)
95+
@client ||= RackTestClient.new(self)
9696
end
9797

9898
def destination
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
require "coderay"
2+
3+
module RspecApiDocumentation
4+
class RackTestClient < ClientBase
5+
6+
delegate :last_request, :last_response, :to => :rack_test_session
7+
private :last_request, :last_response
8+
9+
def request_headers
10+
env_to_headers(last_request.env)
11+
end
12+
13+
def response_headers
14+
last_response.headers
15+
end
16+
17+
def query_string
18+
last_request.env["QUERY_STRING"]
19+
end
20+
21+
def status
22+
last_response.status
23+
end
24+
25+
def response_body
26+
last_response.body
27+
end
28+
29+
def content_type
30+
last_request.content_type
31+
end
32+
33+
protected
34+
35+
def do_request(method, path, params)
36+
rack_test_session.send(method, path, params, headers(method, path, params))
37+
end
38+
39+
private
40+
41+
def rack_test_session
42+
@rack_test_session ||= Struct.new(:app) do
43+
begin
44+
include Rack::Test::Methods
45+
rescue LoadError
46+
raise "#{self.class.name} requires Rack::Test >= 0.5.5. Please add it to your test dependencies."
47+
end
48+
end.new(app)
49+
end
50+
51+
def headers(method, path, params)
52+
if options && options[:headers]
53+
options[:headers]
54+
else
55+
{}
56+
end
57+
end
58+
end
59+
end

spec/dsl_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
describe "example context" do
2020
it "should provide a client" do
21-
client.should be_a(RspecApiDocumentation::TestClient)
21+
client.should be_a(RspecApiDocumentation::RackTestClient)
2222
end
2323

2424
it "should return the same client every time" do

spec/test_client_spec.rb renamed to spec/rack_test_client_spec.rb

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ class StubApp < Sinatra::Base
2929
end
3030
end
3131

32-
describe RspecApiDocumentation::TestClient do
32+
describe RspecApiDocumentation::RackTestClient do
3333
let(:context) { stub(:app => StubApp, :example => example) }
34-
let(:test_client) { RspecApiDocumentation::TestClient.new(context, {}) }
34+
let(:test_client) { RspecApiDocumentation::RackTestClient.new(context, {}) }
3535

3636
subject { test_client }
3737

38-
it { should be_a(RspecApiDocumentation::TestClient) }
38+
it { should be_a(RspecApiDocumentation::RackTestClient) }
3939

4040
its(:context) { should equal(context) }
4141
its(:example) { should equal(example) }
@@ -65,16 +65,6 @@ class StubApp < Sinatra::Base
6565
end
6666
end
6767

68-
describe "#query_hash" do
69-
before do
70-
test_client.get "/?query_hash=true"
71-
end
72-
73-
it 'should contain the query_hash' do
74-
test_client.query_hash.should == { "query_hash" => "true" }
75-
end
76-
end
77-
7868
describe "#request_headers" do
7969
before do
8070
test_client.options[:headers] = {
@@ -106,15 +96,15 @@ class StubApp < Sinatra::Base
10696
end
10797

10898
describe "setup default headers" do
109-
it "should let you set default headers when creating a new TestClient" do
110-
test_client = RspecApiDocumentation::TestClient.new(context, :headers => { "HTTP_MY_HEADER" => "hello" })
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" })
111101
test_client.get "/"
112102
test_client.request_headers["My-Header"].should == "hello"
113103
test_client.request_headers.should have(3).headers
114104
end
115105

116106
it "should be blank if not set" do
117-
test_client = RspecApiDocumentation::TestClient.new(context)
107+
test_client = RspecApiDocumentation::RackTestClient.new(context)
118108
test_client.get "/"
119109
test_client.request_headers.should have(2).headers
120110
end
@@ -145,7 +135,7 @@ class StubApp < Sinatra::Base
145135
metadata[:response_body].should be_present
146136
metadata[:response_headers].should match(/^Content-Type: application\/json/)
147137
metadata[:response_headers].should match(/^Content-Length: 17$/)
148-
metadata[:curl].should eq(RspecApiDocumentation::Curl.new("post", "/greet?query=test+query", post_data, {"Content-Type" => "application/json;charset=utf-8", "X-Custom-Header" => "custom header value", "Host" => "example.org", "Cookie" => ""}))
138+
metadata[:curl].should eq(RspecApiDocumentation::Curl.new("POST", "/greet?query=test+query", post_data, {"Content-Type" => "application/json;charset=utf-8", "X-Custom-Header" => "custom header value", "Host" => "example.org", "Cookie" => ""}))
149139
end
150140

151141
context "when post data is not json" do

0 commit comments

Comments
 (0)