mirror of
https://github.com/jnunemaker/httparty
synced 2023-03-27 23:23:07 -04:00
Cucumber features and steps for most functionality as of the 0.2.8
version. No features for the CLI yet. Signed-off-by: John Nunemaker <nunemaker@gmail.com>
This commit is contained in:
parent
5704725703
commit
2febfe3c83
13 changed files with 285 additions and 1 deletions
11
Manifest
11
Manifest
|
@ -1,4 +1,5 @@
|
|||
bin/httparty
|
||||
cucumber.yml
|
||||
examples/aaws.rb
|
||||
examples/basic.rb
|
||||
examples/delicious.rb
|
||||
|
@ -6,6 +7,16 @@ examples/google.rb
|
|||
examples/rubyurl.rb
|
||||
examples/twitter.rb
|
||||
examples/whoismyrep.rb
|
||||
features/basic_authentication.feature
|
||||
features/command_line.feature
|
||||
features/deals_with_http_error_codes.feature
|
||||
features/handles_multiple_formats.feature
|
||||
features/steps/env.rb
|
||||
features/steps/httparty_response_steps.rb
|
||||
features/steps/httparty_steps.rb
|
||||
features/steps/mongrel_helper.rb
|
||||
features/steps/remote_service_steps.rb
|
||||
features/supports_redirection.feature
|
||||
History
|
||||
httparty.gemspec
|
||||
lib/core_extensions.rb
|
||||
|
|
5
Rakefile
5
Rakefile
|
@ -6,6 +6,7 @@ require 'rake'
|
|||
require 'echoe'
|
||||
require 'spec/rake/spectask'
|
||||
require "lib/#{ProjectName}/version"
|
||||
require 'cucumber/rake/task'
|
||||
|
||||
Echoe.new(ProjectName, HTTParty::Version) do |p|
|
||||
p.description = "Makes http fun! Also, makes consuming restful web services dead easy."
|
||||
|
@ -41,3 +42,7 @@ task :default => :spec
|
|||
Spec::Rake::SpecTask.new do |t|
|
||||
t.spec_files = FileList["spec/**/*_spec.rb"]
|
||||
end
|
||||
|
||||
Cucumber::Rake::Task.new(:features) do |t|
|
||||
t.cucumber_opts = "--format pretty"
|
||||
end
|
||||
|
|
1
cucumber.yml
Normal file
1
cucumber.yml
Normal file
|
@ -0,0 +1 @@
|
|||
default: features
|
20
features/basic_authentication.feature
Normal file
20
features/basic_authentication.feature
Normal file
|
@ -0,0 +1,20 @@
|
|||
Feature: Basic Authentication
|
||||
|
||||
As a developer
|
||||
I want to be able to use a service that requires Basic Authentication
|
||||
Because that is not an uncommon requirement
|
||||
|
||||
Scenario: Passing no credentials to a page requiring Basic Authentication
|
||||
Given a restricted page at '/protected.html'
|
||||
When I call HTTParty#get with '/protected.html'
|
||||
Then it should return a response with a 401 response code
|
||||
|
||||
Scenario: Passing proper credentials to a page requiring Basic Authentication
|
||||
Given a remote service that returns 'Authenticated Page'
|
||||
And that service is accessed at the path '/protected.html'
|
||||
And that service is protected by Basic Authentication
|
||||
And that service requires the username 'jcash' with the password 'maninblack'
|
||||
When I call HTTParty#get with '/protected.html' and a basic_auth hash:
|
||||
| username | password |
|
||||
| jcash | maninblack |
|
||||
Then the return value should match 'Authenticated Page'
|
7
features/command_line.feature
Normal file
7
features/command_line.feature
Normal file
|
@ -0,0 +1,7 @@
|
|||
Feature: Command Line
|
||||
|
||||
As a developer
|
||||
I want to be able to harness the power of HTTParty from the command line
|
||||
Because that would make quick testing and debugging easy
|
||||
And 'easy' is my middle name
|
||||
And I'm kidding it's actually 'Danger'!
|
26
features/deals_with_http_error_codes.feature
Normal file
26
features/deals_with_http_error_codes.feature
Normal file
|
@ -0,0 +1,26 @@
|
|||
Feature: Deals with HTTP error codes
|
||||
|
||||
As a developer
|
||||
I want to be informed of non-successful responses
|
||||
Because sometimes thing explode
|
||||
And I should probably know what happened
|
||||
|
||||
Scenario: A response of '404 - Not Found'
|
||||
Given a remote service that returns a 404 status code
|
||||
And that service is accessed at the path '/service.html'
|
||||
When I call HTTParty#get with '/service.html'
|
||||
Then it should return a response with a 404 response code
|
||||
|
||||
Scenario: A response of '500 - Internal Server Error'
|
||||
Given a remote service that returns a 500 status code
|
||||
And that service is accessed at the path '/service.html'
|
||||
When I call HTTParty#get with '/service.html'
|
||||
Then it should return a response with a 500 response code
|
||||
|
||||
Scenario: A non-successful response where I need the body
|
||||
Given a remote service that returns a 400 status code
|
||||
And the response from the service has a body of 'Bad response'
|
||||
And that service is accessed at the path '/service.html'
|
||||
When I call HTTParty#get with '/service.html'
|
||||
Then it should return a response with a 400 response code
|
||||
And the return value should match 'Bad response'
|
34
features/handles_multiple_formats.feature
Normal file
34
features/handles_multiple_formats.feature
Normal file
|
@ -0,0 +1,34 @@
|
|||
Feature: Handles Multiple Formats
|
||||
|
||||
As a developer
|
||||
I want to be able to consume remote services of many different formats
|
||||
And I want those formats to be automatically detected and handled
|
||||
Because web services take many forms
|
||||
And I don't want to have to do any extra work
|
||||
|
||||
Scenario: An HTML service
|
||||
Given a remote service that returns '<h1>Some HTML</h1>'
|
||||
And that service is accessed at the path '/service.html'
|
||||
And the response from the service has a Content-Type of 'text/html'
|
||||
When I call HTTParty#get with '/service.html'
|
||||
Then it should return a String
|
||||
And the return value should match '<h1>Some HTML</h1>'
|
||||
|
||||
Scenario: A JSON service
|
||||
Given a remote service that returns '{ "jennings": "waylon", "cash": "johnny" }'
|
||||
And that service is accessed at the path '/service.json'
|
||||
And the response from the service has a Content-Type of 'application/json'
|
||||
When I call HTTParty#get with '/service.json'
|
||||
Then it should return a Hash equaling:
|
||||
| key | value |
|
||||
| jennings | waylon |
|
||||
| cash | johnny |
|
||||
|
||||
Scenario: An XML Service
|
||||
Given a remote service that returns '<singer>waylon jennings</singer>'
|
||||
And that service is accessed at the path '/service.xml'
|
||||
And the response from the service has a Content-Type of 'text/xml'
|
||||
When I call HTTParty#get with '/service.xml'
|
||||
Then it should return a Hash equaling:
|
||||
| key | value |
|
||||
| singer | waylon jennings |
|
15
features/steps/env.rb
Normal file
15
features/steps/env.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
require 'mongrel'
|
||||
require 'activesupport'
|
||||
require 'lib/httparty'
|
||||
require 'spec/expectations'
|
||||
|
||||
Before do
|
||||
port = ENV["HTTPARTY_PORT"] || 31981
|
||||
@host_and_port = "0.0.0.0:#{port}"
|
||||
@server = Mongrel::HttpServer.new("0.0.0.0", port)
|
||||
@server.run
|
||||
end
|
||||
|
||||
After do
|
||||
@server.stop
|
||||
end
|
26
features/steps/httparty_response_steps.rb
Normal file
26
features/steps/httparty_response_steps.rb
Normal file
|
@ -0,0 +1,26 @@
|
|||
Then /it should return an? (\w+)$/ do |class_string|
|
||||
@response_from_httparty.should be_an_instance_of(class_string.constantize)
|
||||
end
|
||||
|
||||
Then /the return value should match '(.*)'/ do |expected_text|
|
||||
@response_from_httparty.should eql(expected_text)
|
||||
end
|
||||
|
||||
Then /it should return a Hash equaling:/ do |hash_table|
|
||||
@response_from_httparty.should be_an_instance_of(Hash)
|
||||
@response_from_httparty.keys.length.should eql(hash_table.rows.length)
|
||||
hash_table.hashes.each do |pair|
|
||||
key, value = pair["key"], pair["value"]
|
||||
@response_from_httparty.keys.should include(key)
|
||||
@response_from_httparty[key].should eql(value)
|
||||
end
|
||||
end
|
||||
|
||||
Then /it should return a response with a (\d+) response code/ do |code|
|
||||
@response_from_httparty.code.should eql(code)
|
||||
end
|
||||
|
||||
Then /it should raise an HTTParty::RedirectionTooDeep exception/ do
|
||||
@exception_from_httparty.should_not be_nil
|
||||
@exception_from_httparty.class.should eql(HTTParty::RedirectionTooDeep)
|
||||
end
|
15
features/steps/httparty_steps.rb
Normal file
15
features/steps/httparty_steps.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
When /I call HTTParty#get with '(.*)'$/ do |url|
|
||||
begin
|
||||
@response_from_httparty = HTTParty.get("http://#{@host_and_port}#{url}")
|
||||
rescue HTTParty::RedirectionTooDeep => e
|
||||
@exception_from_httparty = e
|
||||
end
|
||||
end
|
||||
|
||||
When /I call HTTParty#get with '(.*)' and a basic_auth hash:/ do |url, auth_table|
|
||||
h = auth_table.hashes.first
|
||||
@response_from_httparty = HTTParty.get(
|
||||
"http://#{@host_and_port}#{url}",
|
||||
:basic_auth => { :username => h["username"], :password => h["password"] }
|
||||
)
|
||||
end
|
55
features/steps/mongrel_helper.rb
Normal file
55
features/steps/mongrel_helper.rb
Normal file
|
@ -0,0 +1,55 @@
|
|||
def basic_mongrel_handler
|
||||
Class.new(Mongrel::HttpHandler) do
|
||||
attr_writer :content_type, :response_body, :response_code
|
||||
|
||||
def initialize
|
||||
@content_type = "text/html"
|
||||
@response_body = ""
|
||||
@response_code = 200
|
||||
@custom_headers = {}
|
||||
end
|
||||
|
||||
def process(request, response)
|
||||
reply_with(response, @response_code, @response_body)
|
||||
end
|
||||
|
||||
def reply_with(response, code, response_body)
|
||||
response.start(code) do |head, body|
|
||||
head["Content-Type"] = @content_type
|
||||
@custom_headers.each { |k,v| head[k] = v }
|
||||
body.write(response_body)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def new_mongrel_handler
|
||||
basic_mongrel_handler.new
|
||||
end
|
||||
|
||||
def add_basic_authentication_to(handler)
|
||||
m = Module.new do
|
||||
attr_writer :username, :password
|
||||
|
||||
def self.extended(base)
|
||||
base.instance_eval { @custom_headers["WWW-Authenticate"] = 'Basic Realm="Super Secret Page"' }
|
||||
base.class_eval { alias_method_chain :process, :basic_authentication }
|
||||
end
|
||||
|
||||
def process_with_basic_authentication(request, response)
|
||||
if authorized?(request) then process_without_basic_authentication(request, response)
|
||||
else reply_with(response, 401, "Incorrect. You have 20 seconds to comply.")
|
||||
end
|
||||
end
|
||||
|
||||
def authorized?(request)
|
||||
request.params["HTTP_AUTHORIZATION"] == "Basic " + Base64.encode64("#{@username}:#{@password}").strip
|
||||
end
|
||||
end
|
||||
handler.extend(m)
|
||||
end
|
||||
|
||||
def new_mongrel_redirector(target_url, relative_path = false)
|
||||
target_url = "http://#{@host_and_port}#{target_url}" unless relative_path
|
||||
Mongrel::RedirectHandler.new(target_url)
|
||||
end
|
47
features/steps/remote_service_steps.rb
Normal file
47
features/steps/remote_service_steps.rb
Normal file
|
@ -0,0 +1,47 @@
|
|||
Given /a remote service that returns '(.*)'/ do |response_body|
|
||||
@handler = new_mongrel_handler
|
||||
Given "the response from the service has a body of '#{response_body}'"
|
||||
end
|
||||
|
||||
Given /a remote service that returns a (\d+) status code/ do |code|
|
||||
@handler = new_mongrel_handler
|
||||
@handler.response_code = code
|
||||
end
|
||||
|
||||
Given /that service is accessed at the path '(.*)'/ do |path|
|
||||
@server.register(path, @handler)
|
||||
end
|
||||
|
||||
Given /the response from the service has a Content-Type of '(.*)'/ do |content_type|
|
||||
@handler.content_type = content_type
|
||||
end
|
||||
|
||||
Given /the response from the service has a body of '(.*)'/ do |response_body|
|
||||
@handler.response_body = response_body
|
||||
end
|
||||
|
||||
Given /the url '(.*)' redirects to '(.*)'/ do |redirection_url, target_url|
|
||||
@server.register redirection_url, new_mongrel_redirector(target_url)
|
||||
end
|
||||
|
||||
Given /that service is protected by Basic Authentication/ do
|
||||
add_basic_authentication_to @handler
|
||||
end
|
||||
|
||||
Given /that service requires the username '(.*)' with the password '(.*)'/ do |username, password|
|
||||
@handler.username = username
|
||||
@handler.password = password
|
||||
end
|
||||
|
||||
Given /a restricted page at '(.*)'/ do |url|
|
||||
Given "a remote service that returns 'A response I will never see'"
|
||||
And "that service is accessed at the path '#{url}'"
|
||||
And "that service is protected by Basic Authentication"
|
||||
And "that service requires the username 'something' with the password 'secret'"
|
||||
end
|
||||
|
||||
# This joins the server thread, and halts cucumber, so you can actually hit the
|
||||
# server with a browser. Runs until you kill it with Ctrl-c
|
||||
Given /I want to hit this in a browser/ do
|
||||
@server.acceptor.join
|
||||
end
|
22
features/supports_redirection.feature
Normal file
22
features/supports_redirection.feature
Normal file
|
@ -0,0 +1,22 @@
|
|||
Feature: Supports Redirection
|
||||
|
||||
As a developer
|
||||
I want to work with services that may redirect me
|
||||
And I want it to follow a reasonable number of redirects
|
||||
Because sometimes web services do that
|
||||
|
||||
Scenario: A service that redirects once
|
||||
Given a remote service that returns 'Service Response'
|
||||
And that service is accessed at the path '/service.html'
|
||||
And the url '/redirector.html' redirects to '/service.html'
|
||||
When I call HTTParty#get with '/redirector.html'
|
||||
Then the return value should match 'Service Response'
|
||||
|
||||
# TODO: Look in to why this actually fails...
|
||||
Scenario: A service that redirects to a relative URL
|
||||
|
||||
Scenario: A service that redirects infinitely
|
||||
Given the url '/first.html' redirects to '/second.html'
|
||||
And the url '/second.html' redirects to '/first.html'
|
||||
When I call HTTParty#get with '/first.html'
|
||||
Then it should raise an HTTParty::RedirectionTooDeep exception
|
Loading…
Add table
Reference in a new issue