finapps 0.0.14.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.rspec +3 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +22 -0
- data/README.md +64 -0
- data/Rakefile +2 -0
- data/bin/finapps +6 -0
- data/finapps.gemspec +35 -0
- data/lib/finapps/cli/common.rb +40 -0
- data/lib/finapps/cli/institutions.rb +34 -0
- data/lib/finapps/cli/users.rb +87 -0
- data/lib/finapps/middleware/api_token.rb +25 -0
- data/lib/finapps/middleware/raise_http_exceptions.rb +91 -0
- data/lib/finapps/middleware/response_logger.rb +40 -0
- data/lib/finapps/rest/accounts.rb +13 -0
- data/lib/finapps/rest/client.rb +154 -0
- data/lib/finapps/rest/connection.rb +77 -0
- data/lib/finapps/rest/defaults.rb +36 -0
- data/lib/finapps/rest/errors.rb +110 -0
- data/lib/finapps/rest/institutions.rb +32 -0
- data/lib/finapps/rest/resource.rb +13 -0
- data/lib/finapps/rest/resources.rb +17 -0
- data/lib/finapps/rest/users.rb +45 -0
- data/lib/finapps/utils/logging.rb +78 -0
- data/lib/finapps/utils/utils.rb +51 -0
- data/lib/finapps/version.rb +3 -0
- data/lib/finapps.rb +25 -0
- data/spec/rest/client_spec.rb +61 -0
- data/spec/spec_helper.rb +84 -0
- metadata +246 -0
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'pp'
|
2
|
+
|
3
|
+
module FinApps
|
4
|
+
module REST
|
5
|
+
module Connection
|
6
|
+
include FinApps::REST::Defaults
|
7
|
+
|
8
|
+
# @param [Hash] company_credentials
|
9
|
+
# @param [Hash] config
|
10
|
+
# @return [Faraday::Connection]
|
11
|
+
def set_up_connection(company_credentials, config)
|
12
|
+
logger.debug "##{__method__.to_s} => Started"
|
13
|
+
|
14
|
+
company_credentials.validate_required_strings!
|
15
|
+
logger.debug "##{__method__.to_s} => company_credentials passed validation."
|
16
|
+
|
17
|
+
host = config[:host]
|
18
|
+
validate_host_url! host
|
19
|
+
|
20
|
+
base_url = "#{host}/v#{API_VERSION}"
|
21
|
+
logger.debug " base_url: #{base_url}"
|
22
|
+
|
23
|
+
timeout = config[:timeout].blank? ? DEFAULTS[:timeout] : config[:timeout]
|
24
|
+
logger.debug " timeout: #{timeout}"
|
25
|
+
|
26
|
+
user_identifier = config[:user_identifier]
|
27
|
+
logger.debug " user_identifier: #{user_identifier}" if user_identifier.present?
|
28
|
+
|
29
|
+
user_token = config[:user_token]
|
30
|
+
logger.debug ' user_token: [REDACTED]' if user_token.present?
|
31
|
+
|
32
|
+
connection = Faraday.new(:url => base_url,
|
33
|
+
:request => {
|
34
|
+
:open_timeout => timeout,
|
35
|
+
:timeout => timeout},
|
36
|
+
:headers => {
|
37
|
+
:accept => HEADERS[:accept],
|
38
|
+
:user_agent => HEADERS[:user_agent]}) do |conn|
|
39
|
+
|
40
|
+
# Request Middleware
|
41
|
+
conn.use FinApps::Middleware::ApiToken, company_credentials
|
42
|
+
conn.request :json
|
43
|
+
conn.request :retry
|
44
|
+
conn.request :multipart
|
45
|
+
conn.request :url_encoded
|
46
|
+
if user_identifier.blank? || user_token.blank?
|
47
|
+
logger.debug "##{__method__.to_s} => User credentials were not provided. Authentication header not set."
|
48
|
+
else
|
49
|
+
conn.request :basic_auth, user_identifier, user_token
|
50
|
+
logger.debug "##{__method__.to_s} => Basic Authentication header set for provided user credentials."
|
51
|
+
end
|
52
|
+
|
53
|
+
# Response Middleware
|
54
|
+
conn.use FinApps::Middleware::RaiseHttpExceptions
|
55
|
+
conn.response :rashify
|
56
|
+
conn.response :json, :content_type => /\bjson$/
|
57
|
+
conn.use FinApps::Middleware::ResponseLogger
|
58
|
+
|
59
|
+
# Adapter (ensure that the adapter is always last.)
|
60
|
+
conn.adapter :typhoeus
|
61
|
+
end
|
62
|
+
|
63
|
+
logger.debug "##{__method__.to_s} => Completed"
|
64
|
+
connection
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
def validate_host_url!(host_url)
|
69
|
+
raise MissingArgumentsError.new 'Missing argument: host_url.' if host_url.blank?
|
70
|
+
raise InvalidArgumentsError.new 'Invalid argument: host_url does not specify a valid protocol (http/https).' unless host_url.start_with?('http://', 'https://')
|
71
|
+
|
72
|
+
logger.debug "##{__method__.to_s} => host [#{host_url}] passed validation."
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module FinApps
|
2
|
+
module REST
|
3
|
+
module Defaults
|
4
|
+
|
5
|
+
API_VERSION = '1'
|
6
|
+
|
7
|
+
HEADERS = {
|
8
|
+
:accept => 'application/json',
|
9
|
+
:user_agent => "finapps-ruby/#{FinApps::VERSION} (#{RUBY_ENGINE}/#{RUBY_PLATFORM} #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL})"
|
10
|
+
}
|
11
|
+
|
12
|
+
# noinspection SpellCheckingInspection
|
13
|
+
DEFAULTS = {
|
14
|
+
:host => 'https://www.financialapps.com',
|
15
|
+
:timeout => 30,
|
16
|
+
:proxy_addr => nil,
|
17
|
+
:proxy_port => nil,
|
18
|
+
:proxy_user => nil,
|
19
|
+
:proxy_pass => nil,
|
20
|
+
:retry_limit => 1,
|
21
|
+
:log_level => Logger::INFO
|
22
|
+
}
|
23
|
+
|
24
|
+
|
25
|
+
END_POINTS = {
|
26
|
+
:users_create => 'users/new',
|
27
|
+
:users_login => 'users/login',
|
28
|
+
:users_delete => 'users/:public_id/delete',
|
29
|
+
:institutions_search => 'institutions/:search_term/search',
|
30
|
+
:institutions_form => 'institutions/:site_id/form',
|
31
|
+
:institutions_add => 'institutions/:site_id/add',
|
32
|
+
}
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module FinApps
|
2
|
+
module REST
|
3
|
+
|
4
|
+
# Custom error class for rescuing from all FinApps errors
|
5
|
+
class Error < StandardError;
|
6
|
+
attr_reader :response
|
7
|
+
|
8
|
+
def initialize(ex, response = nil)
|
9
|
+
@wrapped_exception = nil
|
10
|
+
@response = response
|
11
|
+
|
12
|
+
if ex.respond_to?(:backtrace)
|
13
|
+
super(ex.message)
|
14
|
+
@wrapped_exception = ex
|
15
|
+
elsif ex.respond_to?(:each_key)
|
16
|
+
super("the server responded with status #{ex[:status]}")
|
17
|
+
@response = ex
|
18
|
+
else
|
19
|
+
super(ex.to_s)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def backtrace
|
24
|
+
if @wrapped_exception
|
25
|
+
@wrapped_exception.backtrace
|
26
|
+
else
|
27
|
+
super
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def inspect
|
32
|
+
%(#<#{self.class}>)
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [Array<String>]
|
36
|
+
def error_messages
|
37
|
+
@response.present? ? @response[:error_messages] : []
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
# Raised when required arguments are missing
|
43
|
+
class MissingArgumentsError < Error
|
44
|
+
def initialize(message)
|
45
|
+
super(message)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Raised when invalid arguments are detected
|
50
|
+
class InvalidArgumentsError < Error
|
51
|
+
def initialize(message)
|
52
|
+
super(message)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
# Client Error 4xx
|
58
|
+
# The 4xx class of status code is intended for cases in which the client seems to have erred.
|
59
|
+
class ClientError < Error
|
60
|
+
end
|
61
|
+
|
62
|
+
class BadRequest < ClientError
|
63
|
+
end
|
64
|
+
|
65
|
+
class Unauthorized < ClientError
|
66
|
+
end
|
67
|
+
|
68
|
+
class Forbidden < ClientError
|
69
|
+
end
|
70
|
+
|
71
|
+
class NotFound < ClientError
|
72
|
+
end
|
73
|
+
|
74
|
+
class MethodNotAllowed < ClientError
|
75
|
+
end
|
76
|
+
|
77
|
+
class NotAcceptable < ClientError
|
78
|
+
end
|
79
|
+
|
80
|
+
class ConnectionFailed < ClientError
|
81
|
+
end
|
82
|
+
|
83
|
+
class Conflict < ClientError
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
# Server Error 5xx
|
88
|
+
#
|
89
|
+
# Response status codes beginning with the digit "5" indicate cases in which the server is aware
|
90
|
+
# that it has erred or is incapable of performing the request.
|
91
|
+
class ServerError < Error
|
92
|
+
end
|
93
|
+
|
94
|
+
class InternalServerError < ServerError
|
95
|
+
end
|
96
|
+
|
97
|
+
class BadGateway < ServerError
|
98
|
+
end
|
99
|
+
|
100
|
+
class ServiceUnavailable < ServerError
|
101
|
+
end
|
102
|
+
|
103
|
+
class GatewayTimeout < ServerError
|
104
|
+
end
|
105
|
+
|
106
|
+
class VersionNotSupported < ServerError
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module FinApps
|
2
|
+
module REST
|
3
|
+
|
4
|
+
class Institutions < FinApps::REST::Resources
|
5
|
+
|
6
|
+
# @param [String] term
|
7
|
+
# @return [Array<FinApps::REST::Institution>, Array<String>]
|
8
|
+
def search(term)
|
9
|
+
logger.debug "##{__method__.to_s} => Started"
|
10
|
+
|
11
|
+
raise MissingArgumentsError.new 'Missing argument: term.' if term.blank?
|
12
|
+
logger.debug "##{__method__.to_s} => term: #{term}"
|
13
|
+
|
14
|
+
path = END_POINTS[:institutions_search].sub! ':search_term', term.to_s
|
15
|
+
|
16
|
+
institutions, error_messages = @client.get(path) do |r|
|
17
|
+
r.body.each { |i| Institution.new(i) }
|
18
|
+
end
|
19
|
+
|
20
|
+
logger.debug "##{__method__.to_s} => Completed"
|
21
|
+
return institutions, error_messages
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
class Institution < FinApps::REST::Resource
|
28
|
+
attr_accessor :base_url, :display_name, :site_id, :org_display_name
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module FinApps
|
2
|
+
module REST
|
3
|
+
class Resources
|
4
|
+
|
5
|
+
include FinApps::REST::Defaults
|
6
|
+
include FinApps::Logging
|
7
|
+
|
8
|
+
# @param [FinApps::REST::Client] client
|
9
|
+
# @return [FinApps::REST::Resources]
|
10
|
+
def initialize(client)
|
11
|
+
@client = client
|
12
|
+
logger.debug "##{__method__.to_s} => #{self.class.name} initialized."
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module FinApps
|
2
|
+
module REST
|
3
|
+
|
4
|
+
class Users < FinApps::REST::Resources
|
5
|
+
include FinApps::Logging
|
6
|
+
|
7
|
+
# @param [Hash] params
|
8
|
+
# @return [FinApps::REST::User, Array<String>]
|
9
|
+
def create(params = {})
|
10
|
+
logger.debug "##{__method__.to_s} => Started"
|
11
|
+
user, error_messages = @client.post(END_POINTS[:users_create], params) { |r| User.new(r.body) }
|
12
|
+
logger.debug "##{__method__.to_s} => Completed"
|
13
|
+
|
14
|
+
return user, error_messages
|
15
|
+
end
|
16
|
+
|
17
|
+
# @param [Hash] params
|
18
|
+
# @return [FinApps::REST::User, Array<String>]
|
19
|
+
def login(params = {})
|
20
|
+
logger.debug "##{__method__.to_s} => Started"
|
21
|
+
user, error_messages = @client.post(END_POINTS[:users_login], params) { |r| User.new(r.body) }
|
22
|
+
logger.debug "##{__method__.to_s} => Completed"
|
23
|
+
|
24
|
+
return user, error_messages
|
25
|
+
end
|
26
|
+
|
27
|
+
# @param [String] public_id
|
28
|
+
# @return [Array<String>]
|
29
|
+
def delete(public_id)
|
30
|
+
logger.debug "##{__method__.to_s} => Started"
|
31
|
+
raise MissingArgumentsError.new 'Missing argument: public_id.' if public_id.blank?
|
32
|
+
_, error_messages = @client.delete(END_POINTS[:users_delete].sub! ':public_id', public_id.to_s)
|
33
|
+
logger.debug "##{__method__.to_s} => Completed"
|
34
|
+
|
35
|
+
error_messages
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
class User < FinApps::REST::Resource
|
41
|
+
attr_accessor :public_id, :token, :email, :first_name, :last_name, :postal_code
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module FinApps
|
2
|
+
module Logging
|
3
|
+
|
4
|
+
SEVERITY_LABEL = %w(DEBUG INFO WARN ERROR FATAL UNKNOWN)
|
5
|
+
PROTECTED_KEYS = [:password, :password_confirm]
|
6
|
+
|
7
|
+
class << self;
|
8
|
+
attr_accessor :tag;
|
9
|
+
end
|
10
|
+
|
11
|
+
def logger=(logger)
|
12
|
+
@logger = logger
|
13
|
+
end
|
14
|
+
|
15
|
+
# noinspection SpellCheckingInspection
|
16
|
+
def logger
|
17
|
+
|
18
|
+
@logger ||= begin
|
19
|
+
require 'logger' unless defined?(::Logger)
|
20
|
+
::Logger.new(STDOUT).tap do |log|
|
21
|
+
log.progname = "#{self.class.to_s}"
|
22
|
+
log.formatter = proc do |severity, time, progname, msg|
|
23
|
+
Logging.tag.present? ?
|
24
|
+
"[%s#%d] %5s -- %s: %s %s\n" % [format_datetime(time), $$, severity, progname, Logging.tag.to_s, msg2str(msg)] :
|
25
|
+
"[%s#%d] %5s -- %s: %s\n" % [format_datetime(time), $$, severity, progname, msg2str(msg)]
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
def set_up_logger_level(logger_level)
|
34
|
+
unless logger_level.blank? || @logger.level == logger_level
|
35
|
+
@logger.info "##{__method__.to_s} => Setting logger level to #{SEVERITY_LABEL[logger_level]}"
|
36
|
+
@logger.level = logger_level
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# noinspection SpellCheckingInspection
|
41
|
+
def set_up_logger_session_params(uuid, session_id)
|
42
|
+
if uuid.present? || session_id.present?
|
43
|
+
uuid ||= '-'
|
44
|
+
session_id ||= '-'
|
45
|
+
logger.formatter = proc do |severity, time, progname, msg|
|
46
|
+
"[%s#%d] %5s -- %s: [#{uuid}] [#{session_id}] %s\n" % [format_datetime(time), $$, severity, progname, msg2str(msg)]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# @param [Hash] hash
|
52
|
+
def skip_sensitive_data(hash)
|
53
|
+
if hash.is_a? Hash
|
54
|
+
redacted = hash.clone
|
55
|
+
redacted.update(redacted) { |key, v1| (PROTECTED_KEYS.include? key) ? '[REDACTED]' : v1 }
|
56
|
+
else
|
57
|
+
hash
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
def format_datetime(time)
|
63
|
+
time.strftime('%Y-%m-%dT%H:%M:%S.') << '%06d ' % time.usec
|
64
|
+
end
|
65
|
+
|
66
|
+
def msg2str(msg)
|
67
|
+
case msg
|
68
|
+
when ::String
|
69
|
+
msg
|
70
|
+
when ::Exception
|
71
|
+
"#{ msg.message } (#{ msg.class })\n" << (msg.backtrace || []).join("\n")
|
72
|
+
else
|
73
|
+
msg.inspect
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class Object
|
2
|
+
# An object is blank if it's false, empty, or a whitespace string.
|
3
|
+
# For example, "", " ", +nil+, [], and {} are all blank.
|
4
|
+
#
|
5
|
+
# This simplifies:
|
6
|
+
#
|
7
|
+
# if address.nil? || address.empty?
|
8
|
+
#
|
9
|
+
# ...to:
|
10
|
+
#
|
11
|
+
# if address.blank?
|
12
|
+
def blank?
|
13
|
+
respond_to?(:empty?) ? empty? : !self
|
14
|
+
end
|
15
|
+
|
16
|
+
# An object is present if it's not <tt>blank?</tt>.
|
17
|
+
def present?
|
18
|
+
!blank?
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns object if it's <tt>present?</tt> otherwise returns +nil+.
|
22
|
+
# <tt>object.presence</tt> is equivalent to <tt>object.present? ? object : nil</tt>.
|
23
|
+
#
|
24
|
+
# This is handy for any representation of objects where blank is the same
|
25
|
+
# as not present at all. For example, this simplifies a common check for
|
26
|
+
# HTTP POST/query parameters:
|
27
|
+
#
|
28
|
+
# state = params[:state] if params[:state].present?
|
29
|
+
# country = params[:country] if params[:country].present?
|
30
|
+
# region = state || country || 'US'
|
31
|
+
#
|
32
|
+
# ...becomes:
|
33
|
+
#
|
34
|
+
# region = params[:state].presence || params[:country].presence || 'US'
|
35
|
+
def presence
|
36
|
+
self if present?
|
37
|
+
end
|
38
|
+
|
39
|
+
def trim
|
40
|
+
respond_to?(:strip) ? self.strip : self
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Hash
|
45
|
+
def validate_required_strings!
|
46
|
+
self.each do |key, value|
|
47
|
+
raise MissingArgumentsError.new "Missing argument: #{key}." if value.blank?
|
48
|
+
raise InvalidArgumentsError.new "Invalid #{key} specified: #{value.inspect} must be a string or symbol." unless value.is_a?(String) || value.is_a?(Symbol)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/finapps.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'finapps/version' unless defined?(FinApps::VERSION)
|
2
|
+
require 'logger' unless defined?(::Logger)
|
3
|
+
require 'pp'
|
4
|
+
|
5
|
+
require 'faraday'
|
6
|
+
require 'faraday_middleware'
|
7
|
+
require 'typhoeus'
|
8
|
+
require 'typhoeus/adapters/faraday'
|
9
|
+
|
10
|
+
require 'finapps/rest/defaults'
|
11
|
+
require 'finapps/rest/errors'
|
12
|
+
require 'finapps/utils/logging'
|
13
|
+
require 'finapps/utils/utils'
|
14
|
+
|
15
|
+
require 'finapps/rest/resource'
|
16
|
+
require 'finapps/rest/resources'
|
17
|
+
require 'finapps/rest/users'
|
18
|
+
require 'finapps/rest/institutions'
|
19
|
+
|
20
|
+
require 'finapps/middleware/api_token'
|
21
|
+
require 'finapps/middleware/raise_http_exceptions'
|
22
|
+
require 'finapps/middleware/response_logger'
|
23
|
+
|
24
|
+
require 'finapps/rest/connection'
|
25
|
+
require 'finapps/rest/client'
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'finapps'
|
3
|
+
|
4
|
+
module FinApps
|
5
|
+
|
6
|
+
describe FinApps::REST::Client do
|
7
|
+
|
8
|
+
before do
|
9
|
+
@client = FinApps::REST::Client.new :company_identifier, :company_token
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#new' do
|
13
|
+
context 'when company credentials are NOT provided' do
|
14
|
+
it 'should raise a MissingArgumentsError exception' do
|
15
|
+
expect { FinApps::REST::Client.new nil, nil }.to raise_error(FinApps::REST::MissingArgumentsError)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'when company credentials are of invalid type' do
|
20
|
+
it 'should raise an InvalidArgumentsError exception' do
|
21
|
+
expect{FinApps::REST::Client.new 1, 2}.to raise_error(FinApps::REST::InvalidArgumentsError)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when company credentials are provided' do
|
26
|
+
it 'returns a client object' do
|
27
|
+
expect(@client).to be_an_instance_of(FinApps::REST::Client)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#get' do
|
33
|
+
it 'responds to get' do
|
34
|
+
expect(@client).to respond_to(:get)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#post' do
|
39
|
+
it 'responds to post' do
|
40
|
+
expect(@client).to respond_to(:post)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '.users' do
|
45
|
+
it 'returns a Users object' do
|
46
|
+
expect(@client.users).to be_an_instance_of(FinApps::REST::Users)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#connection' do
|
51
|
+
it 'looks like Faraday connection' do
|
52
|
+
expect(@client.send(:connection)).to respond_to(:run_request)
|
53
|
+
end
|
54
|
+
it 'memoizes the connection' do
|
55
|
+
c1, c2 = @client.send(:connection), @client.send(:connection)
|
56
|
+
expect(c1.object_id).to eq(c2.object_id)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'finapps'
|
2
|
+
|
3
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
4
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
5
|
+
# The generated `.rspec` file contains `--require spec_helper` which will cause this
|
6
|
+
# file to always be loaded, without a need to explicitly require it in any files.
|
7
|
+
#
|
8
|
+
# Given that it is always loaded, you are encouraged to keep this file as
|
9
|
+
# light-weight as possible. Requiring heavyweight dependencies from this file
|
10
|
+
# will add to the boot time of your test suite on EVERY test run, even for an
|
11
|
+
# individual file that may not need all of that loaded. Instead, make a
|
12
|
+
# separate helper file that requires this one and then use it only in the specs
|
13
|
+
# that actually need it.
|
14
|
+
#
|
15
|
+
# The `.rspec` file also contains a few flags that are not defaults but that
|
16
|
+
# users commonly want.
|
17
|
+
#
|
18
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
19
|
+
RSpec.configure do |config|
|
20
|
+
|
21
|
+
# These two settings work together to allow you to limit a spec run
|
22
|
+
# to individual examples or groups you care about by tagging them with
|
23
|
+
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
24
|
+
# get run.
|
25
|
+
config.filter_run :focus
|
26
|
+
config.run_all_when_everything_filtered = true
|
27
|
+
|
28
|
+
# Many RSpec users commonly either run the entire suite or an individual
|
29
|
+
# file, and it's useful to allow more verbose output when running an
|
30
|
+
# individual spec file.
|
31
|
+
if config.files_to_run.one?
|
32
|
+
# Use the documentation formatter for detailed output,
|
33
|
+
# unless a formatter has already been configured
|
34
|
+
# (e.g. via a command-line flag).
|
35
|
+
config.default_formatter = 'doc'
|
36
|
+
end
|
37
|
+
|
38
|
+
# Run specs in random order to surface order dependencies. If you find an
|
39
|
+
# order dependency and want to debug it, you can fix the order by providing
|
40
|
+
# the seed, which is printed after each run.
|
41
|
+
# --seed 1234
|
42
|
+
config.order = :random
|
43
|
+
|
44
|
+
# The settings below are suggested to provide a good initial experience
|
45
|
+
# with RSpec, but feel free to customize to your heart's content.
|
46
|
+
=begin
|
47
|
+
|
48
|
+
# Print the 10 slowest examples and example groups at the
|
49
|
+
# end of the spec run, to help surface which specs are running
|
50
|
+
# particularly slow.
|
51
|
+
config.profile_examples = 10
|
52
|
+
|
53
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
54
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
55
|
+
# test failures related to randomization by passing the same `--seed` value
|
56
|
+
# as the one that triggered the failure.
|
57
|
+
Kernel.srand config.seed
|
58
|
+
|
59
|
+
# rspec-expectations config goes here. You can use an alternate
|
60
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
61
|
+
# assertions if you prefer.
|
62
|
+
config.expect_with :rspec do |expectations|
|
63
|
+
# Enable only the newer, non-monkey-patching expect syntax.
|
64
|
+
# For more details, see:
|
65
|
+
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
66
|
+
expectations.syntax = :expect
|
67
|
+
end
|
68
|
+
|
69
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
70
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
71
|
+
config.mock_with :rspec do |mocks|
|
72
|
+
# Enable only the newer, non-monkey-patching expect syntax.
|
73
|
+
# For more details, see:
|
74
|
+
# - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
75
|
+
mocks.syntax = :expect
|
76
|
+
|
77
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
78
|
+
# a real object. This is generally recommended.
|
79
|
+
mocks.verify_partial_doubles = true
|
80
|
+
end
|
81
|
+
=end
|
82
|
+
|
83
|
+
|
84
|
+
end
|