require File.dirname(__FILE__) + '/../spec_helper'
describe Sfn::Loader do
# ==== GET ==========================================================================================================
shared_examples_for "#get" do
before(:each) do
@response = nil
@status_code = '200'
@loader = Sfn::Loader.new
@get = lambda do
FakeWeb.register_uri(
:get,
"http://#{@api_host}:#{@api_port}",
:body => @response_body,
:status => [@status_code]
)
stub(@loader).add_authentication {}
@response = @loader.get(@api_url)
end
end
describe "when the status is successful (2xx)" do
before(:each) do
@status_code.should == '200'
@response_body = {:id => "123", :domain => "foo.bar"}.to_json
@get.call
end
it "should return a status of :ok and the response body" do
@response.should == [:ok, @response_body]
end
end
describe "when the status is not modified (304)" do
before(:each) do
@status_code = '304'
@cached_body = {:id => "123", :domain => "foo.bar"}.to_json
@response_body = nil
stub(@loader.cache).get(anything) { Sfn::Loader::CacheRecord.new('http://test', 'etag-foo', @cached_body) }
@get.call
end
it "should return a status of :ok and the cached response body" do
@response.should == [:ok, @cached_body]
end
end
describe "when the status is 400 (Bad Request)" do
before(:each) do
@status_code = '400'
@response_body = {:message => "You've already me-too'd this topic."}.to_json
end
it "should return a status of :bad_request and the response body" do
@get.should raise_error(Sfn::BadRequest, "Bad request. Response body:\n" + @response_body)
end
end
describe "when there is an authentication error" do
describe "when the status is 401 (Unauthorized)" do
before(:each) do
@status_code = '401'
end
it "should raise an Sfn::AuthorizationError" do
@get.should raise_error(Sfn::AuthorizationError, "Not authorized")
end
end
describe "when the status is 403 (Forbidden)" do
before(:each) do
@status_code = '403'
end
it "should raise an Sfn::AuthorizationError" do
@get.should raise_error(Sfn::AuthorizationError, "Not authorized")
end
end
end
# ---- MAINTENANCE --------------------------------------------------------------------------------------------------
describe "when the status is 404 (Not Found)" do
before(:each) do
@status_code = '404'
end
it "should raise an Sfn::NotFound error" do
@get.should raise_error(Sfn::NotFound, "Not found")
end
end
describe "when the site is in maintenance mode (503)" do
before(:each) do
@status_code = '503'
@response_body = "blah blah maintenance blah"
end
describe "and there is not an element with a class of error_message_summary in the HTML" do
it "should raise an error and include the default maintenance message" do
@get.should raise_error(Sfn::SiteMaintenance, "The site is down for maintenance. Please try again later.")
end
end
describe "and there is an element with a class of error_message_summary in the HTML" do
before(:each) do
@custom_error = "Something crazy is going down!"
@response_body = "
#{@custom_error}
"
end
it "should raise an error and include the contents of the element" do
@get.should raise_error(Sfn::SiteMaintenance, @custom_error)
end
end
end
describe "when the error is not one we explicitly check for" do
before(:each) do
@status_code = '505' # HTTP Version Not Supported
@response_body = "it'd be a little weird if our app responded with this error"
end
it "should raise an Sfn::Error and include the response body" do
begin
@get.call
rescue Sfn::Error => e
e.class.should == Sfn::Error
e.message.should == "Encountered error. Body of response:\n" + @response_body
end
end
end
# ---- GATEWAY -----------------------------------------------------------------------------------------------
describe "when the status is 502 (Bad Gateway, returned when a Unicorn worker is killed)" do
before(:each) do
@status_code = '502'
end
it "should raise an Sfn::BadGateway error" do
@get.should raise_error(Sfn::BadGateway, "Bad Gateway")
end
end
describe "when the status is 504 (GatewayTimeOut)" do
before(:each) do
@status_code = '504'
end
it "should raise an Sfn::GatewayTimeOut error" do
@get.should raise_error(Sfn::GatewayTimeOut, "Gateway TimeOut")
end
end
end
# ==== POST ==================================================================================================
shared_examples_for "#post" do
before(:each) do
@response = nil
@status_code = '200'
@post = lambda do
FakeWeb.register_uri(
:post,
"http://#{@api_host}:#{@api_port}",
:body => @response_body,
:status => [@status_code]
)
loader = Sfn::Loader.new
stub(loader).add_authentication {}
@response = loader.post(@api_url, "a=b")
end
end
describe "when the status is successful (2xx)" do
before(:each) do
@status_code.should == '200'
@response_body = {:id => "123", :domain => "foo.bar"}.to_json
@post.call
end
it "should return a status of :ok and the response body" do
@response.should == [:ok, @response_body]
end
end
describe "when the status is 400 (bad request)" do
before(:each) do
@status_code = '400'
@response_body = 'some error message'.to_json
end
it "should return raise an Sfn::BadRequest error and the response body" do
@post.should raise_error(Sfn::BadRequest, "Bad request. Response body:\n" + @response_body)
end
end
describe "when there is an authentication error" do
describe "when the status is 401 (Unauthorized)" do
before(:each) do
@status_code = '401'
end
it "should raise an Sfn::AuthorizationError" do
@post.should raise_error(Sfn::AuthorizationError, "Not authorized")
end
end
describe "when the status is 403 (Forbidden)" do
before(:each) do
@status_code = '403'
end
it "should raise an Sfn::AuthorizationError" do
@post.should raise_error(Sfn::AuthorizationError, "Not authorized")
end
end
end
describe "when the status is 404 (Not Found)" do
before(:each) do
@status_code = '404'
end
it "should raise an Sfn::NotFound error" do
@post.should raise_error(Sfn::NotFound, "Not found")
end
end
# ---- GATEWAY -----------------------------------------------------------------------------------------------
describe "when the status is 502 (Bad Gateway, returned when a Unicorn worker is killed)" do
before(:each) do
@status_code = '502'
end
it "should raise an Sfn::BadGateway error" do
@post.should raise_error(Sfn::BadGateway, "Bad Gateway")
end
end
describe "when the status is 504 (GatewayTimeOut)" do
before(:each) do
@status_code = '504'
end
it "should raise an Sfn::GatewayTimeOut error" do
@post.should raise_error(Sfn::GatewayTimeOut, "Gateway TimeOut")
end
end
end
context 'over ssl' do
before do
@api_host = 'test'
@api_url = "https://#{@api_host}"
@api_port = "443"
any_instance_of(Net::HTTP) do |n|
mock(n).use_ssl=(true)
end
end
it_should_behave_like '#get'
it_should_behave_like '#post'
end
context 'not over ssl' do
before do
@api_host = 'test'
@api_url = "http://#{@api_host}"
@api_port = ""
end
it_should_behave_like '#get'
it_should_behave_like '#post'
describe "when we are in a redirect loop" do
attr_reader :loader
before(:each) do
@url = @api_url
@loader = Sfn::Loader.new
stub(loader).add_authentication {}
end
describe "and the status is 301" do
before(:each) do
@get = lambda {
FakeWeb.register_uri(:get, "http://#{@api_host}:#{@api_port}", :status => 301, :location => @url)
@response = loader.get(@url)
}
end
it "should raise a TooManyRedirects exception with an appropriate message" do
@get.should raise_error(Sfn::TooManyRedirects, "Too many redirects")
end
end
describe "and the status is 302" do
before(:each) do
@get = lambda {
FakeWeb.register_uri(:get, "http://#{@api_host}:#{@api_port}", :status => 302, :location => @url)
@response = loader.get(@url)
}
end
it "should raise a TooManyRedirects exception with an appropriate message" do
@get.should raise_error(Sfn::TooManyRedirects, "Too many redirects")
end
end
end
end
# ---- MAINTENANCE --------------------------------------------------------------------------------------------------
describe 'MAINTENANCE' do
before(:each) do
@api_url = "http://test"
@response = nil
@status_code = '200'
@post = lambda do
FakeWeb.register_uri(
:post,
@api_url,
:body => @response_body,
:status => [@status_code]
)
loader = Sfn::Loader.new
stub(loader).add_authentication {}
@response = loader.post(@api_url, "a=b")
end
end
shared_examples_for "the site is in maintenance mode" do
describe "and there is not an element with a class of error_message_summary in the HTML" do
before(:each) do
FakeWeb.register_uri(:get, @api_url, :body => "blah", :status => "503")
end
it "should raise an error and include the default maintenance message" do
@post.should raise_error(Sfn::SiteMaintenance, "The site is down for maintenance. Please try again later.")
end
end
describe "and there is an element with a class of error_message_summary in the HTML" do
before(:each) do
@custom_error = "Something crazy is going down!"
@response_body = "#{@custom_error}
"
FakeWeb.register_uri(:get, @api_url, :body => @response_body, :status => "503")
end
it "should raise an error and include the contents of the element" do
@post.should raise_error(Sfn::SiteMaintenance, @custom_error)
end
end
end
describe "when the status is 405 (Method Not Allowed)" do
before(:each) do
@status_code = '405'
@response_body = "blah blah maintenance blah"
end
it_should_behave_like "the site is in maintenance mode"
describe "when the site is not in maintenance mode" do
before(:each) do
FakeWeb.register_uri(:get, @api_url, :body => "blah", :status => "200")
end
it "should raise an error and include the reponse body" do
@post.should raise_error(Sfn::MethodNotAllowed, "Method not allowed")
end
end
end
describe "when the status is 503 (Service Unavailable)" do
before :each do
@status_code = '503'
@response_body = "blah blah maintenance mode"
end
it_should_behave_like "the site is in maintenance mode"
end
describe "when the error is not one we explicitly check for" do
before(:each) do
@status_code = '505' # HTTP Version Not Supported
@response_body = "it'd be a little weird if our app responded with this error"
end
it "should raise an Sfn::Error and include the response body" do
begin
@post.call
rescue Sfn::Error => e
e.class.should == Sfn::Error
e.message.should == "Encountered error. Body of response:\n" + @response_body
end
end
end
end
end