active_utils 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,63 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module PostsData #:nodoc:
3
+
4
+ def self.included(base)
5
+ base.superclass_delegating_accessor :ssl_strict
6
+ base.ssl_strict = true
7
+
8
+ base.class_attribute :retry_safe
9
+ base.retry_safe = false
10
+
11
+ base.superclass_delegating_accessor :open_timeout
12
+ base.open_timeout = 60
13
+
14
+ base.superclass_delegating_accessor :read_timeout
15
+ base.read_timeout = 60
16
+
17
+ base.superclass_delegating_accessor :logger
18
+ base.superclass_delegating_accessor :wiredump_device
19
+ end
20
+
21
+ def ssl_get(endpoint, headers={})
22
+ ssl_request(:get, endpoint, nil, headers)
23
+ end
24
+
25
+ def ssl_post(endpoint, data, headers = {})
26
+ ssl_request(:post, endpoint, data, headers)
27
+ end
28
+
29
+ def ssl_request(method, endpoint, data, headers)
30
+ handle_response(raw_ssl_request(method, endpoint, data, headers))
31
+ end
32
+
33
+ def raw_ssl_request(method, endpoint, data, headers = {})
34
+ connection = Connection.new(endpoint)
35
+ connection.open_timeout = open_timeout
36
+ connection.read_timeout = read_timeout
37
+ connection.retry_safe = retry_safe
38
+ connection.verify_peer = ssl_strict
39
+ connection.logger = logger
40
+ connection.tag = self.class.name
41
+ connection.wiredump_device = wiredump_device
42
+
43
+ connection.pem = @options[:pem] if @options
44
+ connection.pem_password = @options[:pem_password] if @options
45
+
46
+ connection.ignore_http_status = @options[:ignore_http_status] if @options
47
+
48
+ connection.request(method, data, headers)
49
+ end
50
+
51
+ private
52
+
53
+ def handle_response(response)
54
+ case response.code.to_i
55
+ when 200...300
56
+ response.body
57
+ else
58
+ raise ResponseError.new(response)
59
+ end
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,16 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module RequiresParameters #:nodoc:
3
+ def requires!(hash, *params)
4
+ params.each do |param|
5
+ if param.is_a?(Array)
6
+ raise ArgumentError.new("Missing required parameter: #{param.first}") unless hash.has_key?(param.first)
7
+
8
+ valid_options = param[1..-1]
9
+ raise ArgumentError.new("Parameter: #{param.first} must be one of #{valid_options.to_sentence(:words_connector => 'or')}") unless valid_options.include?(hash[param.first])
10
+ else
11
+ raise ArgumentError.new("Missing required parameter: #{param}") unless hash.has_key?(param)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ require 'digest/md5'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Utils #:nodoc:
5
+ def generate_unique_id
6
+ md5 = Digest::MD5.new
7
+ now = Time.now
8
+ md5 << now.to_s
9
+ md5 << String(now.usec)
10
+ md5 << String(rand(0))
11
+ md5 << String($$)
12
+ md5 << self.class.name
13
+ md5.hexdigest
14
+ end
15
+
16
+ module_function :generate_unique_id
17
+
18
+ def deprecated(message)
19
+ warn(Kernel.caller[1] + message)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,81 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Validateable #:nodoc:
3
+ def valid?
4
+ errors.clear
5
+
6
+ before_validate if respond_to?(:before_validate, true)
7
+ validate if respond_to?(:validate, true)
8
+
9
+ errors.empty?
10
+ end
11
+
12
+ def initialize(attributes = {})
13
+ self.attributes = attributes
14
+ end
15
+
16
+ def errors
17
+ @errors ||= Errors.new(self)
18
+ end
19
+
20
+ private
21
+
22
+ def attributes=(attributes)
23
+ unless attributes.nil?
24
+ for key, value in attributes
25
+ send("#{key}=", value )
26
+ end
27
+ end
28
+ end
29
+
30
+ # This hash keeps the errors of the object
31
+ class Errors < HashWithIndifferentAccess
32
+
33
+ def initialize(base)
34
+ super() { |h, k| h[k] = [] ; h[k] }
35
+ @base = base
36
+ end
37
+
38
+ def count
39
+ size
40
+ end
41
+
42
+ def empty?
43
+ all? { |k, v| v && v.empty? }
44
+ end
45
+
46
+ # returns a specific fields error message.
47
+ # if more than one error is available we will only return the first. If no error is available
48
+ # we return an empty string
49
+ def on(field)
50
+ self[field].to_a.first
51
+ end
52
+
53
+ def add(field, error)
54
+ self[field] << error
55
+ end
56
+
57
+ def add_to_base(error)
58
+ add(:base, error)
59
+ end
60
+
61
+ def each_full
62
+ full_messages.each { |msg| yield msg }
63
+ end
64
+
65
+ def full_messages
66
+ result = []
67
+
68
+ self.each do |key, messages|
69
+ next if messages.blank?
70
+ if key == 'base'
71
+ result << "#{messages.first}"
72
+ else
73
+ result << "#{key.to_s.humanize} #{messages.first}"
74
+ end
75
+ end
76
+
77
+ result
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,3 @@
1
+ module ActiveUtils
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,19 @@
1
+ require 'active_support/core_ext/hash/indifferent_access'
2
+ require 'active_support/core_ext/hash/conversions'
3
+ require 'active_support/core_ext/class/attribute'
4
+
5
+ module ActiveMerchant
6
+ autoload :Connection, 'active_utils/common/connection'
7
+ autoload :Country, 'active_utils/common/country'
8
+ autoload :CountryCode, 'active_utils/common/country'
9
+ autoload :ActiveMerchantError, 'active_utils/common/error'
10
+ autoload :ConnectionError, 'active_utils/common/error'
11
+ autoload :RetriableConnectionError, 'active_utils/common/error'
12
+ autoload :ResponseError, 'active_utils/common/error'
13
+ autoload :ClientCertificateError, 'active_utils/common/error'
14
+ autoload :PostData, 'active_utils/common/post_data'
15
+ autoload :PostsData, 'active_utils/common/posts_data'
16
+ autoload :RequiresParameters, 'active_utils/common/requires_parameters'
17
+ autoload :Utils, 'active_utils/common/utils'
18
+ autoload :Validateable, 'active_utils/common/validateable'
19
+ end
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
3
+
4
+ require 'rubygems'
5
+ require 'bundler'
6
+ Bundler.setup
7
+
8
+ require 'test/unit'
9
+ require 'active_utils'
10
+ require 'mocha'
11
+
12
+ include ActiveMerchant
@@ -0,0 +1,131 @@
1
+ require 'test_helper'
2
+
3
+ class ConnectionTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @ok = stub(:code => 200, :message => 'OK', :body => 'success')
7
+
8
+ @endpoint = 'https://example.com/tx.php'
9
+ @connection = ActiveMerchant::Connection.new(@endpoint)
10
+ end
11
+
12
+ def test_connection_endpoint_parses_string_to_uri
13
+ assert_equal URI.parse(@endpoint), @connection.endpoint
14
+ end
15
+
16
+ def test_connection_endpoint_accepts_uri
17
+ endpoint = URI.parse(@endpoint)
18
+ connection = ActiveMerchant::Connection.new(endpoint)
19
+ assert_equal endpoint, connection.endpoint
20
+ end
21
+
22
+ def test_connection_endpoint_raises_uri_error
23
+ assert_raises URI::InvalidURIError do
24
+ ActiveMerchant::Connection.new("not a URI")
25
+ end
26
+ end
27
+
28
+ def test_successful_get_request
29
+ Net::HTTP.any_instance.expects(:get).with('/tx.php', {}).returns(@ok)
30
+ response = @connection.request(:get, nil, {})
31
+ assert_equal 'success', response.body
32
+ end
33
+
34
+ def test_successful_post_request
35
+ Net::HTTP.any_instance.expects(:post).with('/tx.php', 'data', ActiveMerchant::Connection::RUBY_184_POST_HEADERS).returns(@ok)
36
+ response = @connection.request(:post, 'data', {})
37
+ assert_equal 'success', response.body
38
+ end
39
+
40
+ def test_get_raises_argument_error_if_passed_data
41
+ assert_raise(ArgumentError) do
42
+ @connection.request(:get, 'data', {})
43
+ end
44
+ end
45
+
46
+ def test_request_raises_when_request_method_not_supported
47
+ assert_raise(ArgumentError) do
48
+ @connection.request(:delete, nil, {})
49
+ end
50
+ end
51
+
52
+
53
+
54
+ def test_default_read_timeout
55
+ assert_equal ActiveMerchant::Connection::READ_TIMEOUT, @connection.read_timeout
56
+ end
57
+
58
+ def test_override_read_timeout
59
+ @connection.read_timeout = 20
60
+ assert_equal 20, @connection.read_timeout
61
+ end
62
+
63
+ def test_default_open_timeout
64
+ @connection.open_timeout = 20
65
+ assert_equal 20, @connection.open_timeout
66
+ end
67
+
68
+ def test_default_verify_peer
69
+ assert_equal ActiveMerchant::Connection::VERIFY_PEER, @connection.verify_peer
70
+ end
71
+
72
+ def test_override_verify_peer
73
+ @connection.verify_peer = false
74
+ assert_equal false, @connection.verify_peer
75
+ end
76
+
77
+ def test_unrecoverable_exception
78
+ Net::HTTP.any_instance.expects(:post).raises(EOFError)
79
+
80
+ assert_raises(ActiveMerchant::ConnectionError) do
81
+ @connection.request(:post, '')
82
+ end
83
+ end
84
+
85
+ def test_failure_then_success_with_recoverable_exception
86
+ Net::HTTP.any_instance.expects(:post).times(2).raises(Errno::ECONNREFUSED).then.returns(@ok)
87
+
88
+ assert_nothing_raised do
89
+ @connection.request(:post, '')
90
+ end
91
+ end
92
+
93
+ def test_failure_limit_reached
94
+ Net::HTTP.any_instance.expects(:post).times(ActiveMerchant::Connection::MAX_RETRIES).raises(Errno::ECONNREFUSED)
95
+
96
+ assert_raises(ActiveMerchant::ConnectionError) do
97
+ @connection.request(:post, '')
98
+ end
99
+ end
100
+
101
+ def test_failure_then_success_with_retry_safe_enabled
102
+ Net::HTTP.any_instance.expects(:post).times(2).raises(EOFError).then.returns(@ok)
103
+
104
+ @connection.retry_safe = true
105
+
106
+ assert_nothing_raised do
107
+ @connection.request(:post, '')
108
+ end
109
+ end
110
+
111
+ def test_mixture_of_failures_with_retry_safe_enabled
112
+ Net::HTTP.any_instance.expects(:post).times(3).raises(Errno::ECONNRESET).
113
+ raises(Errno::ECONNREFUSED).
114
+ raises(EOFError)
115
+
116
+ @connection.retry_safe = true
117
+
118
+ assert_raises(ActiveMerchant::ConnectionError) do
119
+ @connection.request(:post, '')
120
+ end
121
+ end
122
+
123
+ def test_failure_with_ssl_certificate
124
+ Net::HTTP.any_instance.expects(:post).raises(OpenSSL::X509::CertificateError)
125
+
126
+ assert_raises(ActiveMerchant::ClientCertificateError) do
127
+ @connection.request(:post, '')
128
+ end
129
+ end
130
+
131
+ end
@@ -0,0 +1,31 @@
1
+ require 'test_helper'
2
+
3
+ class CountryCodeTest < Test::Unit::TestCase
4
+ def test_alpha2_country_code
5
+ code = CountryCode.new('CA')
6
+ assert_equal 'CA', code.value
7
+ assert_equal 'CA', code.to_s
8
+ assert_equal :alpha2, code.format
9
+ end
10
+
11
+ def test_lower_alpha2_country_code
12
+ code = CountryCode.new('ca')
13
+ assert_equal 'CA', code.value
14
+ assert_equal 'CA', code.to_s
15
+ assert_equal :alpha2, code.format
16
+ end
17
+
18
+ def test_alpha2_country_code
19
+ code = CountryCode.new('CAN')
20
+ assert_equal :alpha3, code.format
21
+ end
22
+
23
+ def test_numeric_code
24
+ code = CountryCode.new('004')
25
+ assert_equal :numeric, code.format
26
+ end
27
+
28
+ def test_invalid_code_format
29
+ assert_raise(CountryCodeFormatError){ CountryCode.new('Canada') }
30
+ end
31
+ end
@@ -0,0 +1,68 @@
1
+ require 'test_helper'
2
+
3
+ class CountryTest < Test::Unit::TestCase
4
+ def test_country_from_hash
5
+ country = Country.new(:name => 'Canada', :alpha2 => 'CA', :alpha3 => 'CAN', :numeric => '124')
6
+ assert_equal 'CA', country.code(:alpha2).value
7
+ assert_equal 'CAN', country.code(:alpha3).value
8
+ assert_equal '124', country.code(:numeric).value
9
+ assert_equal 'Canada', country.to_s
10
+ end
11
+
12
+ def test_country_for_alpha2_code
13
+ country = Country.find('CA')
14
+ assert_equal 'CA', country.code(:alpha2).value
15
+ assert_equal 'CAN', country.code(:alpha3).value
16
+ assert_equal '124', country.code(:numeric).value
17
+ assert_equal 'Canada', country.to_s
18
+ end
19
+
20
+ def test_country_for_alpha3_code
21
+ country = Country.find('CAN')
22
+ assert_equal 'Canada', country.to_s
23
+ end
24
+
25
+ def test_country_for_numeric_code
26
+ country = Country.find('124')
27
+ assert_equal 'Canada', country.to_s
28
+ end
29
+
30
+ def test_find_country_by_name
31
+ country = Country.find('Canada')
32
+ assert_equal 'Canada', country.to_s
33
+ end
34
+
35
+ def test_find_unknown_country_name
36
+ assert_raise(InvalidCountryCodeError) do
37
+ Country.find('Asskickistan')
38
+ end
39
+ end
40
+
41
+ def test_find_australia
42
+ country = Country.find('AU')
43
+ assert_equal 'AU', country.code(:alpha2).value
44
+
45
+ country = Country.find('Australia')
46
+ assert_equal 'AU', country.code(:alpha2).value
47
+ end
48
+
49
+ def test_find_united_kingdom
50
+ country = Country.find('GB')
51
+ assert_equal 'GB', country.code(:alpha2).value
52
+
53
+ country = Country.find('United Kingdom')
54
+ assert_equal 'GB', country.code(:alpha2).value
55
+ end
56
+
57
+ def test_raise_on_nil_name
58
+ assert_raise(InvalidCountryCodeError) do
59
+ Country.find(nil)
60
+ end
61
+ end
62
+
63
+ def test_country_names_are_alphabetized
64
+ country_names = Country::COUNTRIES.map { | each | each[:name] }
65
+ assert_equal(country_names.sort, country_names)
66
+ end
67
+
68
+ end
@@ -0,0 +1,50 @@
1
+ require 'test_helper'
2
+
3
+ class MyPost < ActiveMerchant::PostData
4
+ self.required_fields = [ :ccnumber, :ccexp, :firstname, :lastname, :username, :password, :order_id, :key, :time ]
5
+ end
6
+
7
+ class PostDataTest < Test::Unit::TestCase
8
+ def teardown
9
+ ActiveMerchant::PostData.required_fields = []
10
+ end
11
+
12
+ def test_element_assignment
13
+ name = 'Cody Fauser'
14
+ post = ActiveMerchant::PostData.new
15
+
16
+ post[:name] = name
17
+ assert_equal name, post[:name]
18
+ end
19
+
20
+ def test_ignore_blank_fields
21
+ post = ActiveMerchant::PostData.new
22
+ assert_equal 0, post.keys.size
23
+
24
+ post[:name] = ''
25
+ assert_equal 0, post.keys.size
26
+
27
+ post[:name] = nil
28
+ assert_equal 0, post.keys.size
29
+ end
30
+
31
+ def test_dont_ignore_required_blank_fields
32
+ ActiveMerchant::PostData.required_fields = [ :name ]
33
+ post = ActiveMerchant::PostData.new
34
+
35
+ assert_equal 0, post.keys.size
36
+
37
+ post[:name] = ''
38
+ assert_equal 1, post.keys.size
39
+ assert_equal '', post[:name]
40
+
41
+ post[:name] = nil
42
+ assert_equal 1, post.keys.size
43
+ assert_nil post[:name]
44
+ end
45
+
46
+ def test_subclass
47
+ post = MyPost.new
48
+ assert_equal [ :ccnumber, :ccexp, :firstname, :lastname, :username, :password, :order_id, :key, :time ], post.required_fields
49
+ end
50
+ end
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class UtilsTest < Test::Unit::TestCase
4
+ def test_unique_id_should_be_32_chars_and_alphanumeric
5
+ assert_match /^\w{32}$/, ActiveMerchant::Utils.generate_unique_id
6
+ end
7
+ end
@@ -0,0 +1,59 @@
1
+ require 'test_helper'
2
+
3
+ class Dood
4
+ include ActiveMerchant::Validateable
5
+
6
+ attr_accessor :name, :email, :country
7
+
8
+ def validate
9
+ errors.add "name", "cannot be empty" if name.blank?
10
+ errors.add "email", "cannot be empty" if email.blank?
11
+ errors.add_to_base "The country cannot be blank" if country.blank?
12
+ end
13
+
14
+ end
15
+
16
+ class ValidateableTest < Test::Unit::TestCase
17
+
18
+ def setup
19
+ @dood = Dood.new
20
+ end
21
+
22
+ def test_validation
23
+ assert ! @dood.valid?
24
+ assert ! @dood.errors.empty?
25
+ end
26
+
27
+ def test_assigns
28
+ @dood = Dood.new(:name => "tobi", :email => "tobi@neech.de", :country => 'DE')
29
+
30
+ assert_equal "tobi", @dood.name
31
+ assert_equal "tobi@neech.de", @dood.email
32
+ assert @dood.valid?
33
+ end
34
+
35
+ def test_multiple_calls
36
+ @dood.name = "tobi"
37
+ assert !@dood.valid?
38
+
39
+ @dood.email = "tobi@neech.de"
40
+ assert !@dood.valid?
41
+
42
+ @dood.country = 'DE'
43
+ assert @dood.valid?
44
+ end
45
+
46
+ def test_messages
47
+ @dood.valid?
48
+ assert_equal "cannot be empty", @dood.errors.on('name')
49
+ assert_equal "cannot be empty", @dood.errors.on('email')
50
+ assert_equal nil, @dood.errors.on('doesnt_exist')
51
+
52
+ end
53
+
54
+ def test_full_messages
55
+ @dood.valid?
56
+ assert_equal ["Email cannot be empty", "Name cannot be empty", "The country cannot be blank"], @dood.errors.full_messages.sort
57
+ end
58
+
59
+ end