Permalink
Browse files

Actually initialize categories collection from Shoeboxed

  • Loading branch information...
1 parent c41f188 commit 7b3397eaae2a4c003a606c43be34c60ae42dce82 @ffmike committed Dec 4, 2011
View
@@ -1,4 +1,5 @@
pkg/*
*.gem
-.bundle
+.bundle
.rvmrc
+test/shoehorn_credentials.yml
View
@@ -2,6 +2,7 @@ PATH
remote: .
specs:
shoehorn (0.1.0)
+ builder
GEM
remote: http://rubygems.org/
View
@@ -39,6 +39,10 @@ GetUserStatisticsCall
RegisterDiyUserCall
GetLoginCall
+## Testing Shoehorn
+
+Some of the tests depend on a live connection to Shoeboxed. To set this up, you must make a copy of test/shoehorn\_credentials.sample.yml to test/shoehorn\_credentials.yml and fill in the required information.
+
## Footnotes
Mike Gunderloy, MikeG1@larkfarm.com
View
@@ -1,3 +1,4 @@
# TODO
-Support authentication credentials in YAML file in /config
+Support authentication credentials in YAML file in /config
+Test on persistent connection to Shoeboxed
View
@@ -1,7 +1,10 @@
+require 'rexml/document'
+require 'builder'
+
module Shoehorn
class Categories
- include Enumerable
-
+ include Enumerable
+
attr_accessor :connection
def initialize(connection)
@@ -23,6 +26,32 @@ def [](i)
private
def get_categories
+ @categories = Array.new
+ request = build_category_request
+ response = connection.post_xml(request)
+
+ @categories = parse(response)
+ end
+
+ def build_category_request
+ xml = Builder::XmlMarkup.new
+ xml.instruct!
+ xml.Request(:xmlns => "urn:sbx:apis:SbxBaseComponents") do |xml|
+ connection.requester_credentials_block(xml)
+ xml.GetCategoryCall
+ end
+ end
+
+ def parse(xml)
+ document = REXML::Document.new(xml)
+ document.elements.collect("//Category") do |category_element|
+ begin
+ category = Category.new(category_element.attributes["id"], category_element.attributes["name"])
+ rescue => e
+ raise Shoehorn::ParseError.new(e, category_element.to_s, "Error parsing category.")
+ end
+ @categories << category
+ end
end
end
View
@@ -1,11 +1,15 @@
require 'cgi'
+require 'iconv'
require 'logger'
+require "net/https"
module Shoehorn
class Connection
- API_VERSION = 1
- API_ENDPOINT = "https://api.shoeboxed.com/v#{API_VERSION}/ws/api.htm"
+ API_SERVER = "api.shoeboxed.com"
+ API_VERSION = 1
+ API_PATH = "/v#{API_VERSION}/ws/api.htm"
+ API_ENDPOINT = "https://#{API_SERVER}#{API_PATH}"
attr_accessor :application_name, :return_url, :return_parameters, :application_token, :user_token
@@ -66,7 +70,60 @@ def receipts
end
@receipts
end
+
+ def requester_credentials_block(xml)
+ xml.RequesterCredentials do |xml|
+ xml.ApiUserToken(@application_token)
+ xml.SbxUserToken(@user_token)
+ end
+ end
+
+ def post_xml(body)
+ connection = Net::HTTP.new(API_SERVER, 443)
+ connection.use_ssl = true
+ connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
+
+ request = Net::HTTP::Post.new(API_PATH)
+ request.set_form_data({'xml'=>body})
+
+ result = connection.start { |http| http.request(request) }
+
+ # Convert to UTF-8, shoeboxed encodes with ISO-8859-1
+ result_body = Iconv.conv('UTF-8', 'ISO-8859-1', result.body)
+ if logger.debug?
+ logger.debug "Request:"
+ logger.debug body
+ logger.debug "Response:"
+ logger.debug result_body
+ end
+
+ check_for_api_error(result_body)
+ end
+
+ def check_for_api_error(body)
+ document = REXML::Document.new(body)
+ root = document.root
+ puts root.inspect
+ if root && root.name == "Error"
+ description = root.attributes["description"]
+
+ case root.attributes["code"]
+ when "1"
+ raise AuthenticationError.new(description)
+ when "2"
+ raise UnknownAPICallError.new(description)
+ when "3"
+ raise RestrictedIPError.new(description)
+ when "4"
+ raise XMLValidationError.new(description)
+ when "5"
+ raise InternalError.new(description)
+ end
+ end
+
+ body
+ end
def logger
@@logger
end
View
@@ -1,3 +1,9 @@
module Shoehorn
- class ParameterError < StandardError; end
+ class AuthenticationError < StandardError; end;
+ class InternalError < StandardError; end;
+ class ParameterError < StandardError; end
+ class ParseError < StandardError; end
+ class RestrictedIPError < StandardError; end;
+ class UnknownAPICallError < StandardError; end;
+ class XMLValidationError < StandardError; end;
end
View
@@ -13,7 +13,9 @@ Gem::Specification.new do |s|
s.description = %q{Ruby implementation of the API for Shoeboxed, http://developer.shoeboxed.com/overview}
s.rubyforge_project = "shoehorn"
-
+
+ s.add_dependency 'builder'
+
s.add_development_dependency 'rake'
s.add_development_dependency 'test-unit'
s.add_development_dependency 'shoulda'
View
@@ -4,7 +4,7 @@ class CategoriesTest < ShoehornTest
context "initialization" do
setup do
- @connection = Shoehorn::Connection.new
+ @connection = live_connection
@categories = @connection.categories
end
View
@@ -124,7 +124,7 @@ class ConnectionTest <ShoehornTest
context "collections" do
setup do
- @connection = Shoehorn::Connection.new('GreatApp', 'http://greatapp.example.com')
+ @connection = live_connection
end
should "initialize bills when first accessed" do
@@ -0,0 +1,11 @@
+# You need to supply valid credentials in a copy of this file named test/shoehorn_credentials.yml to test shoehorn
+# The application token and application name are found in your Account & Settings under 'API Keys and Info'
+# Shoeboxed calls them 'App token' and 'App name
+# The user token and user name must be obtained by making an authentication call - Set up a connection with your application name,
+# application token, and return URL, then visit connection.authentication_url in your browser. Shoeboxed will return the user name
+# and user token to the URL you specified.
+credentials:
+ application_token: my_application_token
+ application_name: my_application_name
+ user_name: my_user_name
+ user_token: my_user_token
View
@@ -1,10 +1,24 @@
require File.dirname(__FILE__) + '/../lib/shoehorn'
-require 'test/unit'
+require 'test/unit'
require 'shoulda'
-require 'mocha'
+require 'mocha'
+require 'yaml'
class ShoehornTest < Test::Unit::TestCase
include Shoehorn
+
+ def live_connection
+ config = YAML.load_file(File.dirname(__FILE__) + '/shoehorn_credentials.yml')
+ application_token = config["credentials"]["application_token"]
+ application_name = config["credentials"]["application_name"]
+ user_name = config["credentials"]["user_name"]
+ user_token = config["credentials"]["user_token"]
+
+ connection = Shoehorn::Connection.new(application_name, application_token)
+ connection.user_token = user_token
+ connection
+ end
+
end

0 comments on commit 7b3397e

Please sign in to comment.