paid 0.1.0 → 1.0.0
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 +4 -4
- data/.gitignore +5 -1
- data/.travis.yml +16 -0
- data/History.txt +4 -0
- data/README.md +58 -0
- data/Rakefile +9 -29
- data/VERSION +1 -0
- data/bin/paid-console +7 -0
- data/gemfiles/default-with-activesupport.gemfile +10 -0
- data/gemfiles/json.gemfile +12 -0
- data/gemfiles/yajl.gemfile +12 -0
- data/lib/paid.rb +129 -177
- data/lib/paid/account.rb +14 -1
- data/lib/paid/api_class.rb +336 -0
- data/lib/paid/api_list.rb +47 -0
- data/lib/paid/api_resource.rb +8 -25
- data/lib/paid/api_singleton.rb +5 -0
- data/lib/paid/customer.rb +36 -21
- data/lib/paid/errors/api_error.rb +6 -0
- data/lib/paid/event.rb +22 -1
- data/lib/paid/invoice.rb +16 -21
- data/lib/paid/plan.rb +18 -2
- data/lib/paid/subscription.rb +17 -11
- data/lib/paid/transaction.rb +19 -12
- data/lib/paid/util.rb +53 -106
- data/lib/paid/version.rb +1 -1
- data/paid.gemspec +10 -11
- data/tasks/api_test.rb +187 -0
- data/test/mock_resource.rb +69 -0
- data/test/paid/account_test.rb +41 -4
- data/test/paid/api_class_test.rb +412 -0
- data/test/paid/api_list_test.rb +17 -0
- data/test/paid/api_resource_test.rb +13 -343
- data/test/paid/api_singleton_test.rb +12 -0
- data/test/paid/authentication_test.rb +50 -0
- data/test/paid/customer_test.rb +189 -29
- data/test/paid/event_test.rb +74 -0
- data/test/paid/invoice_test.rb +101 -20
- data/test/paid/plan_test.rb +84 -8
- data/test/paid/status_codes_test.rb +63 -0
- data/test/paid/subscription_test.rb +100 -20
- data/test/paid/transaction_test.rb +110 -37
- data/test/paid/util_test.rb +15 -24
- data/test/test_data.rb +144 -93
- data/test/test_helper.rb +6 -4
- metadata +32 -26
- data/Gemfile.lock +0 -54
- data/README.rdoc +0 -35
- data/lib/data/ca-certificates.crt +0 -0
- data/lib/paid/alias.rb +0 -16
- data/lib/paid/api_operations/create.rb +0 -17
- data/lib/paid/api_operations/delete.rb +0 -11
- data/lib/paid/api_operations/list.rb +0 -17
- data/lib/paid/api_operations/update.rb +0 -57
- data/lib/paid/certificate_blacklist.rb +0 -55
- data/lib/paid/list_object.rb +0 -37
- data/lib/paid/paid_object.rb +0 -187
- data/lib/paid/singleton_api_resource.rb +0 -20
- data/lib/tasks/paid_tasks.rake +0 -4
- data/test/paid/alias_test.rb +0 -22
- data/test/paid/certificate_blacklist_test.rb +0 -18
- data/test/paid/list_object_test.rb +0 -16
- data/test/paid/paid_object_test.rb +0 -27
- data/test/paid/properties_test.rb +0 -103
data/paid.gemspec
CHANGED
@@ -1,18 +1,16 @@
|
|
1
1
|
$:.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
2
2
|
|
3
|
-
|
4
|
-
require "paid/version"
|
3
|
+
require 'paid/version'
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
s.
|
9
|
-
s.version = Paid::VERSION
|
10
|
-
s.authors = ['Ryan Jackson']
|
11
|
-
s.email = ['ryan@paidapi.com']
|
12
|
-
s.homepage = 'http://docs.paidapi.com'
|
13
|
-
s.summary = 'Ruby bindings for Paid API'
|
5
|
+
spec = Gem::Specification.new do |s|
|
6
|
+
s.name = 'paid'
|
7
|
+
s.summary = 'Ruby bindings for Paid API'
|
14
8
|
s.description = 'Paid is the programmatic way to manage payments. See https://paidapi.com for details.'
|
15
|
-
s.
|
9
|
+
s.homepage = 'http://docs.paidapi.com'
|
10
|
+
s.authors = ['Jon Calhoun', 'Ryan Jackson']
|
11
|
+
s.email = ['joncalhoun@gmail.com', 'ryan@paidapi.com']
|
12
|
+
s.version = Paid::VERSION
|
13
|
+
s.license = 'MIT'
|
16
14
|
|
17
15
|
s.add_dependency('rest-client', '~> 1.4')
|
18
16
|
s.add_dependency('mime-types', '>= 1.25', '< 3.0')
|
@@ -28,3 +26,4 @@ Gem::Specification.new do |s|
|
|
28
26
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
29
27
|
s.require_paths = ['lib']
|
30
28
|
end
|
29
|
+
|
data/tasks/api_test.rb
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
require 'paid'
|
2
|
+
|
3
|
+
class APITest
|
4
|
+
def initialize(api_key)
|
5
|
+
Paid.api_key = api_key
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
account = run_account_test
|
10
|
+
customer = run_customer_tests
|
11
|
+
plan = run_plan_tests
|
12
|
+
subscription = run_subscription_tests(customer, plan)
|
13
|
+
transaction = run_transaction_tests(customer)
|
14
|
+
invoice = run_invoice_tests(customer)
|
15
|
+
event = run_events_tests
|
16
|
+
run_advanced_tests(transaction, invoice, subscription)
|
17
|
+
end
|
18
|
+
|
19
|
+
def run_advanced_tests(transaction, invoice, subscription)
|
20
|
+
puts "Marking the transaction as paid..."
|
21
|
+
transaction.mark_as_paid
|
22
|
+
puts "Marked transaction=#{transaction.id} as paid."
|
23
|
+
|
24
|
+
puts "Issuing the invoice..."
|
25
|
+
invoice.issue
|
26
|
+
puts "Invoice=#{invoice.id} issued."
|
27
|
+
|
28
|
+
puts "Marking the invoice as paid..."
|
29
|
+
invoice.mark_as_paid(:via => :ach)
|
30
|
+
puts "Marked invoice=#{invoice.id} as paid."
|
31
|
+
|
32
|
+
puts "Cancelling subscription=#{subscription.id}..."
|
33
|
+
subscription.cancel
|
34
|
+
puts "Subscription cancelled."
|
35
|
+
end
|
36
|
+
|
37
|
+
def run_events_tests
|
38
|
+
puts "Looking up all events..."
|
39
|
+
events = Paid::Event.all
|
40
|
+
puts "Found #{events.length} events."
|
41
|
+
|
42
|
+
puts "Retrieving the first event..."
|
43
|
+
event = Paid::Event.retrieve(events.first.id)
|
44
|
+
puts "Retrieved the event with the id=#{event.id}"
|
45
|
+
|
46
|
+
event
|
47
|
+
end
|
48
|
+
|
49
|
+
def run_invoice_tests(customer)
|
50
|
+
puts "Creating an invoice with customer=#{customer.id}"
|
51
|
+
invoice = customer.generate_invoice
|
52
|
+
puts "Created: #{invoice.inspect}"
|
53
|
+
|
54
|
+
puts "Looking up all invoices..."
|
55
|
+
invoices = Paid::Invoice.all
|
56
|
+
puts "Found #{invoices.length} invoices."
|
57
|
+
|
58
|
+
puts "Retrieving the generated invoice..."
|
59
|
+
invoice = Paid::Invoice.retrieve(invoice.id)
|
60
|
+
puts "Retrieved the invoice with the id=#{invoice.id}"
|
61
|
+
|
62
|
+
puts "Retrieving the customer=#{customer.id}'s invoices..."
|
63
|
+
invoices = customer.invoices
|
64
|
+
puts "Retrieved: #{invoices.inspect}"
|
65
|
+
|
66
|
+
invoice
|
67
|
+
end
|
68
|
+
|
69
|
+
def run_transaction_tests(customer)
|
70
|
+
puts "Creating 2 transactions with customer=#{customer.id}"
|
71
|
+
transaction = Paid::Transaction.create({
|
72
|
+
:amount => 100,
|
73
|
+
:description => 'a description',
|
74
|
+
:customer => customer.id,
|
75
|
+
:paid => false
|
76
|
+
})
|
77
|
+
transaction_b = Paid::Transaction.create({
|
78
|
+
:amount => 1000,
|
79
|
+
:description => 'another description',
|
80
|
+
:customer => customer.id,
|
81
|
+
:paid => false
|
82
|
+
})
|
83
|
+
puts "Created: #{transaction.inspect} + 1 other"
|
84
|
+
|
85
|
+
puts "Looking up all transactions..."
|
86
|
+
transactions = Paid::Transaction.all
|
87
|
+
puts "Found #{transactions.length} transactions."
|
88
|
+
|
89
|
+
puts "Retrieving the created transaction..."
|
90
|
+
transaction = Paid::Transaction.retrieve(transaction.id)
|
91
|
+
puts "Retrieved the transaction with the id=#{transaction.id}"
|
92
|
+
|
93
|
+
puts "Updating the transaction's name..."
|
94
|
+
transaction.description = "an updated description..."
|
95
|
+
transaction.save
|
96
|
+
puts "Updated the transaction with id=#{transaction.id} with the new description #{transaction.description.inspect}"
|
97
|
+
|
98
|
+
puts "Looking up customer=#{customer.id}'s transactions..."
|
99
|
+
transactions = customer.transactions
|
100
|
+
puts "Retrieved: #{transactions.inspect}"
|
101
|
+
|
102
|
+
transaction
|
103
|
+
end
|
104
|
+
|
105
|
+
def run_subscription_tests(customer, plan)
|
106
|
+
puts "Creating a subscription for customer=#{customer.id} and plan=#{plan.id}..."
|
107
|
+
subscription = Paid::Subscription.create({
|
108
|
+
:starts_on => (Time.now + 1 * 60 * 60 * 24).strftime("%Y-%m-%d"),
|
109
|
+
:plan => plan.id,
|
110
|
+
:customer => customer.id
|
111
|
+
})
|
112
|
+
puts "Created: #{subscription.inspect}"
|
113
|
+
|
114
|
+
puts "Looking up all subscriptions..."
|
115
|
+
subscriptions = Paid::Subscription.all
|
116
|
+
puts "Found #{subscriptions.length} subscriptions."
|
117
|
+
|
118
|
+
puts "Retrieving the created subscription..."
|
119
|
+
subscription = Paid::Subscription.retrieve(subscription.id)
|
120
|
+
puts "Retrieved the subscription with the id=#{subscription.id}"
|
121
|
+
|
122
|
+
subscription
|
123
|
+
end
|
124
|
+
|
125
|
+
def run_plan_tests
|
126
|
+
puts "Creating a plan..."
|
127
|
+
plan = Paid::Plan.create({
|
128
|
+
:description => "Plan for testing stuff",
|
129
|
+
:name => "Test Plan #{Time.now.to_i}-#{rand(2000)}",
|
130
|
+
:interval => "month",
|
131
|
+
:interval_count => 1,
|
132
|
+
:amount => 5000
|
133
|
+
})
|
134
|
+
puts "Created: #{plan.inspect}"
|
135
|
+
|
136
|
+
puts "Looking up all plans..."
|
137
|
+
plans = Paid::Plan.all
|
138
|
+
puts "Found #{plans.length} plans."
|
139
|
+
|
140
|
+
puts "Retrieving the created plan..."
|
141
|
+
plan = Paid::Plan.retrieve(plan.id)
|
142
|
+
puts "Retrieved the plan with the id=#{plan.id}"
|
143
|
+
|
144
|
+
plan
|
145
|
+
end
|
146
|
+
|
147
|
+
def run_customer_tests
|
148
|
+
puts "Creating a customer..."
|
149
|
+
customer = Paid::Customer.create({
|
150
|
+
:name => "Paid",
|
151
|
+
:email => "hello@paidapi.com",
|
152
|
+
:description => "Obviously this is just a description.",
|
153
|
+
:phone => "4155069330",
|
154
|
+
:address_line1 => "2261 Market Street",
|
155
|
+
:address_line2 => "#567",
|
156
|
+
:address_city => "San Francisco",
|
157
|
+
:address_state => "CA",
|
158
|
+
:address_zip => "94114"
|
159
|
+
})
|
160
|
+
puts "Created: #{customer.inspect}"
|
161
|
+
|
162
|
+
puts "Looking up all customers..."
|
163
|
+
customers = Paid::Customer.all
|
164
|
+
puts "Found #{customers.length} customers"
|
165
|
+
|
166
|
+
puts "Retrieving the created customer..."
|
167
|
+
customer = Paid::Customer.retrieve(customer.id)
|
168
|
+
puts "Retrieved the customer with id=#{customer.id}"
|
169
|
+
|
170
|
+
# TODO(joncalhoun): Add by_external_id lookup test
|
171
|
+
|
172
|
+
puts "Updating the customer's name..."
|
173
|
+
customer.name = "Paid Inc"
|
174
|
+
customer.save
|
175
|
+
puts "Updated the customer with id=#{customer.id} with the new name #{customer.name.inspect}"
|
176
|
+
|
177
|
+
customer
|
178
|
+
end
|
179
|
+
|
180
|
+
def run_account_test
|
181
|
+
puts "Looking up the account..."
|
182
|
+
account = Paid::Account.retrieve
|
183
|
+
puts "Retrieved the account with id=#{account.id}"
|
184
|
+
account
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# Setup a fake resource for testing the APIResource
|
2
|
+
|
3
|
+
class NestedResource < Paid::APIResource
|
4
|
+
attribute :price
|
5
|
+
|
6
|
+
def self.path
|
7
|
+
"/nested_resources"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class MockResource < Paid::APIResource
|
12
|
+
attribute :name
|
13
|
+
attribute :tarray
|
14
|
+
attribute :thash
|
15
|
+
attribute :nested, NestedResource
|
16
|
+
|
17
|
+
api_class_method :retrieve, :get, ":path/:id", :arguments => [:id]
|
18
|
+
api_class_method :all, :get, :constructor => Paid::APIList.constructor(MockResource)
|
19
|
+
api_class_method :create, :post
|
20
|
+
api_class_method :many_args_get, :get, ":path/:b/many", :arguments => [:a, :b, :c]
|
21
|
+
api_class_method :many_args_post, :post, ":path/:b/many", :arguments => [:a, :b, :c]
|
22
|
+
api_class_method :crazy_path, :get, ":crazy"
|
23
|
+
|
24
|
+
api_class_method :with_con_self, :get, :constructor => :self
|
25
|
+
api_class_method :with_con_class, :get, :constructor => MockResource
|
26
|
+
api_class_method :with_con_lambda, :get, :constructor => lambda{ |json| "lamdba result" }
|
27
|
+
api_class_method :with_con_default, :get
|
28
|
+
|
29
|
+
def self.default_lambda
|
30
|
+
lambda do |this|
|
31
|
+
self.default_values
|
32
|
+
end
|
33
|
+
end
|
34
|
+
api_class_method :with_lambda, :post, :default_params => self.default_lambda
|
35
|
+
api_class_method :with_symbol, :post, :default_params => :default_values
|
36
|
+
api_class_method :with_symbol_and_args, :post, :default_params => :default_values, :arguments => [:name]
|
37
|
+
|
38
|
+
api_instance_method :refresh, :get, :constructor => :self
|
39
|
+
api_instance_method :save, :put, :default_params => changed_lambda, :constructor => :self
|
40
|
+
api_instance_method :delete, :delete
|
41
|
+
api_instance_method :custom_path, :get, ":path", :arguments => [:path]
|
42
|
+
api_instance_method :name_path, :get, ":name"
|
43
|
+
api_instance_method :crazy_path, :get, ":crazy"
|
44
|
+
|
45
|
+
api_instance_method :with_con_self, :get, :constructor => :self
|
46
|
+
api_instance_method :with_con_class, :get, :constructor => MockResource
|
47
|
+
api_instance_method :with_con_lambda, :get, :constructor => lambda{ |json| "lamdba result" }
|
48
|
+
api_instance_method :with_con_default, :get
|
49
|
+
|
50
|
+
api_instance_method :with_lambda, :put, :default_params => changed_lambda
|
51
|
+
api_instance_method :with_symbol, :put, :default_params => :changed_attributes
|
52
|
+
api_instance_method :with_symbol_and_args, :put, :default_params => :changed_attributes, :arguments => [:name]
|
53
|
+
|
54
|
+
def self.path
|
55
|
+
"/mocks"
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.crazy
|
59
|
+
"/crazy_path"
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.default_values
|
63
|
+
{
|
64
|
+
:name => "default name",
|
65
|
+
:tarray => [1,2,3]
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
data/test/paid/account_test.rb
CHANGED
@@ -2,11 +2,48 @@ require File.expand_path('../../test_helper', __FILE__)
|
|
2
2
|
|
3
3
|
module Paid
|
4
4
|
class AccountTest < Test::Unit::TestCase
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
setup do
|
6
|
+
@account_url = "#{Paid.api_base}/v0/account"
|
7
|
+
end
|
8
|
+
|
9
|
+
should 'be retrievable' do
|
10
|
+
@mock.expects(:get).once.with(@account_url, anything, anything).returns(test_response(test_account))
|
8
11
|
a = Paid::Account.retrieve
|
9
|
-
|
12
|
+
assert(a.is_a?(Paid::Account))
|
13
|
+
assert_equal(test_account[:id], a.id)
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'Retrieved Paid::Account instance' do
|
17
|
+
setup do
|
18
|
+
@mock.expects(:get).once.returns(test_response(test_account))
|
19
|
+
@account = Paid::Account.retrieve
|
20
|
+
end
|
21
|
+
|
22
|
+
should 'have the id attribute' do
|
23
|
+
assert_equal(test_account[:id], @account.id)
|
24
|
+
end
|
25
|
+
|
26
|
+
should 'have the object attribute' do
|
27
|
+
assert_equal(test_account[:object], @account.object)
|
28
|
+
end
|
29
|
+
|
30
|
+
should 'have the business_name attribute' do
|
31
|
+
assert_equal(test_account[:business_name], @account.business_name)
|
32
|
+
end
|
33
|
+
|
34
|
+
should 'have the business_url attribute' do
|
35
|
+
assert_equal(test_account[:business_url], @account.business_url)
|
36
|
+
end
|
37
|
+
|
38
|
+
should 'have the business_logo attribute' do
|
39
|
+
assert_equal(test_account[:business_logo], @account.business_logo)
|
40
|
+
end
|
10
41
|
end
|
42
|
+
|
43
|
+
should 'be registered' do
|
44
|
+
assert(APIClass.subclasses.include?(Paid::Account))
|
45
|
+
assert_equal(Paid::Account, APIClass.subclass_fetch("account"))
|
46
|
+
end
|
47
|
+
|
11
48
|
end
|
12
49
|
end
|
@@ -0,0 +1,412 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require File.expand_path('../../test_helper', __FILE__)
|
3
|
+
|
4
|
+
module Paid
|
5
|
+
class ApiClassTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
context 'Non-network actions' do
|
8
|
+
setup do
|
9
|
+
@mock.expects(:get).never
|
10
|
+
@mock.expects(:post).never
|
11
|
+
@mock.expects(:put).never
|
12
|
+
@mock.expects(:delete).never
|
13
|
+
end
|
14
|
+
|
15
|
+
should 'not fetch over the network when creating a new APIClass' do
|
16
|
+
MockResource.new('fake_id')
|
17
|
+
end
|
18
|
+
|
19
|
+
should 'not fetch over the network when creating a new APIClass from a hash' do
|
20
|
+
MockResource.construct(test_mock_resource)
|
21
|
+
end
|
22
|
+
|
23
|
+
should 'not fetch over the network when setting an attribute' do
|
24
|
+
c = MockResource.new('fake_id')
|
25
|
+
c.name = 'Another Name'
|
26
|
+
end
|
27
|
+
|
28
|
+
should 'not fetch over the network when accessing an attribute' do
|
29
|
+
c = MockResource.new('fake_id')
|
30
|
+
c.id
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# These GET, POST, etc should really be in a dif test, but this is easier.
|
35
|
+
context 'Making a GET request' do
|
36
|
+
should 'urlencode values in params and have no payload' do
|
37
|
+
response = test_response(test_mock_resource_list)
|
38
|
+
|
39
|
+
# The test is to basically make sure this expectation passes.
|
40
|
+
@mock.expects(:get).with do |url, headers, params|
|
41
|
+
(url == "#{Paid.api_base}#{MockResource.path}?page=1&filter=test%20filter" ||
|
42
|
+
url == "#{Paid.api_base}#{MockResource.path}?filter=test%20filter&page=1") &&
|
43
|
+
params == nil
|
44
|
+
end.returns(response)
|
45
|
+
|
46
|
+
list = MockResource.all({
|
47
|
+
:page => 1,
|
48
|
+
:filter => 'test filter',
|
49
|
+
})
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'Making a DELETE request' do
|
54
|
+
should 'urlencode values in params and have no payload' do
|
55
|
+
@mock.expects(:get).once.returns(test_response(test_mock_resource))
|
56
|
+
mock_resource = MockResource.retrieve("fake_id")
|
57
|
+
|
58
|
+
@mock.expects(:delete).once.with do |url, headers, payload|
|
59
|
+
url == "#{Paid.api_base}#{mock_resource.path}?reason=delinquent%20payments" && payload.nil?
|
60
|
+
end.returns(test_response({}))
|
61
|
+
mock_resource.delete(:reason => "delinquent payments")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'Making a PUT request' do
|
66
|
+
should 'have a payload with no query string' do
|
67
|
+
@mock.expects(:get).once.returns(test_response(test_mock_resource))
|
68
|
+
mock_resource = MockResource.retrieve("fake_id")
|
69
|
+
mock_resource.name = "new name"
|
70
|
+
|
71
|
+
@mock.expects(:put).once.with do |url, header, payload|
|
72
|
+
payload == { :name => "new name" }
|
73
|
+
end.returns(test_response(test_mock_resource))
|
74
|
+
mock_resource.save
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'Making a POST request' do
|
79
|
+
should 'have a payload with no query string' do
|
80
|
+
params = { :name => "some name" }
|
81
|
+
@mock.expects(:post).once.with("#{Paid.api_base}#{MockResource.path}", anything, params).returns(test_response(test_mock_resource))
|
82
|
+
|
83
|
+
MockResource.create(params)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'APIClass :default_params' do
|
88
|
+
context 'api_instance_method' do
|
89
|
+
setup do
|
90
|
+
@response = test_response(test_mock_resource_list)
|
91
|
+
@mr = MockResource.new(test_mock_resource)
|
92
|
+
end
|
93
|
+
|
94
|
+
should 'call any provided lambdas and set the result as params' do
|
95
|
+
@mock.expects(:put).once.with(anything, anything, { :name => "new name" }).returns(@response)
|
96
|
+
|
97
|
+
@mr.name = "new name"
|
98
|
+
@mr.with_lambda
|
99
|
+
end
|
100
|
+
|
101
|
+
should 'call any method defined by a symbol and set the results as params' do
|
102
|
+
@mock.expects(:put).once.with(anything, anything, { :name => "new name" }).returns(@response)
|
103
|
+
|
104
|
+
@mr.name = "new name"
|
105
|
+
@mr.with_symbol
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'order priority' do
|
109
|
+
# Intended order of priority:
|
110
|
+
# 1. Params. eg in mock_resource.save(params, opts), params should take
|
111
|
+
# priority with duplicate keys.
|
112
|
+
# 2. Arguments. These should take priority over default values from :params
|
113
|
+
# method.
|
114
|
+
# 3. Results from method defined by :default_params. This can be a symbol that is
|
115
|
+
# the name of a method to call, or a lambda (though a hash is preferred).
|
116
|
+
should 'prioritize params argument over args and default_params method' do
|
117
|
+
params = {
|
118
|
+
:name => "not arg name",
|
119
|
+
:tarray => ["not method tarray"],
|
120
|
+
:thash => { :val => "custom hash" }
|
121
|
+
}
|
122
|
+
@mock.expects(:put).once.with(anything, anything, params).returns(@response)
|
123
|
+
|
124
|
+
@mr.tarray = ["method array"]
|
125
|
+
@mr.with_symbol_and_args("arg name", params)
|
126
|
+
end
|
127
|
+
|
128
|
+
should 'prioritize arguments over :default_params' do
|
129
|
+
@mock.expects(:put).once.with(anything, anything, { :name => "arg name" }).returns(@response)
|
130
|
+
|
131
|
+
@mr.name = "changed name"
|
132
|
+
@mr.with_symbol_and_args("arg name")
|
133
|
+
end
|
134
|
+
|
135
|
+
should 'use :default_params method as even when args and params are present' do
|
136
|
+
@mock.expects(:put).once.with(anything, anything, {
|
137
|
+
:thash => { :val => "params hash" },
|
138
|
+
:name => "arg name",
|
139
|
+
:tarray => ["change array"],
|
140
|
+
}).returns(@response)
|
141
|
+
|
142
|
+
@mr.tarray = ["change array"]
|
143
|
+
@mr.with_symbol_and_args("arg name", { :thash => { :val => "params hash" } })
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context 'api_class_method' do
|
149
|
+
setup do
|
150
|
+
@response = test_response(test_mock_resource_list)
|
151
|
+
end
|
152
|
+
|
153
|
+
should 'call any provided lambdas and set the result as params' do
|
154
|
+
@mock.expects(:post).once.with(anything, anything, MockResource.default_values).returns(@response)
|
155
|
+
MockResource.with_lambda
|
156
|
+
end
|
157
|
+
|
158
|
+
should 'call any method defined by a symbol and set the results as params' do
|
159
|
+
@mock.expects(:post).once.with(anything, anything, MockResource.default_values).returns(@response)
|
160
|
+
MockResource.with_symbol
|
161
|
+
end
|
162
|
+
|
163
|
+
context 'order priority' do
|
164
|
+
# Intended order of priority:
|
165
|
+
# 1. Params. eg in mock_resource.save(params, opts), params should take
|
166
|
+
# priority with duplicate keys.
|
167
|
+
# 2. Arguments. These should take priority over default values from :params
|
168
|
+
# method.
|
169
|
+
# 3. Results from method defined by :default_params. This can be a symbol that is
|
170
|
+
# the name of a method to call, or a lambda (though a hash is preferred).
|
171
|
+
should 'prioritize params argument over args and default_params method' do
|
172
|
+
params = {
|
173
|
+
:name => "not arg name",
|
174
|
+
:tarray => ["not method tarray"],
|
175
|
+
:thash => { :val => "custom hash" }
|
176
|
+
}
|
177
|
+
@mock.expects(:post).once.with(anything, anything, params).returns(@response)
|
178
|
+
MockResource.with_symbol_and_args("name arg", params)
|
179
|
+
end
|
180
|
+
|
181
|
+
should 'prioritize arguments over :default_params' do
|
182
|
+
params = Util.sorta_deep_clone(MockResource.default_values)
|
183
|
+
params[:name] = "name arg"
|
184
|
+
@mock.expects(:post).once.with(anything, anything, params).returns(@response)
|
185
|
+
MockResource.with_symbol_and_args("name arg", params)
|
186
|
+
end
|
187
|
+
|
188
|
+
should 'use :default_params method as even when args and params are present' do
|
189
|
+
params = {
|
190
|
+
:name => "name arg",
|
191
|
+
:tarray => MockResource.default_values[:tarray].dup,
|
192
|
+
:thash => { :val => "custom hash" }
|
193
|
+
}
|
194
|
+
@mock.expects(:post).once.with(anything, anything, params).returns(@response)
|
195
|
+
MockResource.with_symbol_and_args("name arg", { :thash => { :val => "custom hash" }})
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
|
202
|
+
context 'APIClass#attribute' do
|
203
|
+
should 'create a getter method' do
|
204
|
+
assert(MockResource.method_defined?(:name))
|
205
|
+
end
|
206
|
+
|
207
|
+
should 'create a setter method' do
|
208
|
+
assert(MockResource.method_defined?(:name=))
|
209
|
+
end
|
210
|
+
|
211
|
+
should 'have no changed attributes after init' do
|
212
|
+
mr = MockResource.new(test_mock_resource)
|
213
|
+
assert(mr.changed_attributes.empty?)
|
214
|
+
end
|
215
|
+
|
216
|
+
should 'keep track of changed attributes' do
|
217
|
+
mr = MockResource.new(test_mock_resource)
|
218
|
+
assert(mr.changed_attributes.empty?)
|
219
|
+
mr.name = "new name"
|
220
|
+
assert_equal({:name => "new name"}, mr.changed_attributes)
|
221
|
+
end
|
222
|
+
|
223
|
+
should 'keep track of changed arrays' do
|
224
|
+
mr = MockResource.new(test_mock_resource)
|
225
|
+
assert(mr.changed_attributes.empty?)
|
226
|
+
mr.tarray << "new"
|
227
|
+
assert_equal({:tarray => test_mock_resource[:tarray] + ["new"]}, mr.changed_attributes)
|
228
|
+
end
|
229
|
+
|
230
|
+
should 'keep track of changed hashes' do
|
231
|
+
mr = MockResource.new(test_mock_resource)
|
232
|
+
assert(mr.changed_attributes.empty?)
|
233
|
+
mr.thash[:some_key] = "new value"
|
234
|
+
assert_equal({:thash => { :some_key => "new value" }}, mr.changed_attributes)
|
235
|
+
end
|
236
|
+
|
237
|
+
context 'constructors' do
|
238
|
+
should 'instantiate on #new' do
|
239
|
+
mr = MockResource.new(test_mock_resource)
|
240
|
+
assert(mr.nested.is_a?(NestedResource))
|
241
|
+
end
|
242
|
+
|
243
|
+
should 'instantiate on #construct' do
|
244
|
+
mr = MockResource.construct(test_mock_resource)
|
245
|
+
assert(mr.nested.is_a?(NestedResource))
|
246
|
+
end
|
247
|
+
|
248
|
+
should 'instantiate on #refresh_from' do
|
249
|
+
mr = MockResource.new('fake_id')
|
250
|
+
assert(mr.nested.nil?)
|
251
|
+
|
252
|
+
mr.refresh_from(test_mock_resource)
|
253
|
+
assert(mr.nested.is_a?(NestedResource))
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
context 'APIClass :constructor' do
|
259
|
+
context 'for api_class_method' do
|
260
|
+
setup do
|
261
|
+
@mock.expects(:get).once.returns(test_response(test_mock_resource))
|
262
|
+
end
|
263
|
+
|
264
|
+
should 'create a new MockResource with :constructor => :self' do
|
265
|
+
mr = MockResource.with_con_self
|
266
|
+
assert(mr.is_a?(MockResource))
|
267
|
+
end
|
268
|
+
|
269
|
+
should 'create a new MockResource with :constructor => MockResource' do
|
270
|
+
mr = MockResource.with_con_class
|
271
|
+
assert(mr.is_a?(MockResource))
|
272
|
+
end
|
273
|
+
|
274
|
+
should 'use the lambda with :constructor => lambda{...}' do
|
275
|
+
mr = MockResource.with_con_lambda
|
276
|
+
assert_equal("lamdba result", mr)
|
277
|
+
end
|
278
|
+
|
279
|
+
should 'create a new MockResource with no constructor defined' do
|
280
|
+
mr = MockResource.with_con_default
|
281
|
+
assert(mr.is_a?(MockResource))
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
context 'for api_instance_method' do
|
286
|
+
setup do
|
287
|
+
@mock.expects(:get).once.returns(test_response(test_mock_resource))
|
288
|
+
@mr = MockResource.new('fake_id')
|
289
|
+
end
|
290
|
+
|
291
|
+
should 'update this instance with :constructor => :self' do
|
292
|
+
@mr.with_con_self
|
293
|
+
assert(@mr.is_a?(MockResource))
|
294
|
+
assert_equal(test_mock_resource[:id], @mr.id)
|
295
|
+
end
|
296
|
+
|
297
|
+
should 'create a new instance with :constructor => MockResource' do
|
298
|
+
res = @mr.with_con_class
|
299
|
+
assert(res.is_a?(MockResource))
|
300
|
+
assert_not_equal(@mr.id, res.id)
|
301
|
+
end
|
302
|
+
|
303
|
+
should 'use the lambda with :constructor => lambda{...}' do
|
304
|
+
res = @mr.with_con_lambda
|
305
|
+
assert_equal("lamdba result", res)
|
306
|
+
end
|
307
|
+
|
308
|
+
should 'update this instance with no constructor defined' do
|
309
|
+
@mr.with_con_default
|
310
|
+
assert(@mr.is_a?(MockResource))
|
311
|
+
assert_equal(test_mock_resource[:id], @mr.id)
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
context 'APIClass api_*_method arguments' do
|
317
|
+
should 'throw an ArgumentError if too few arguments are provided' do
|
318
|
+
assert_raises(ArgumentError) { MockResource.retrieve }
|
319
|
+
end
|
320
|
+
|
321
|
+
should 'throw an ArgumentError with the name of missing arguments' do
|
322
|
+
begin
|
323
|
+
MockResource.retrieve
|
324
|
+
assert(false, "ArgumentError was expected.")
|
325
|
+
rescue ArgumentError => e
|
326
|
+
assert(e.message =~ /id/)
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
should 'throw an ArgumentError if too many arguments are provided' do
|
331
|
+
assert_raises(ArgumentError) { MockResource.retrieve(1, 2, {}, {}) }
|
332
|
+
end
|
333
|
+
|
334
|
+
should 'throw an ArgumentError if the param argument is invalid' do
|
335
|
+
assert_raises(ArgumentError) { MockResource.retrieve(1, 2) }
|
336
|
+
end
|
337
|
+
|
338
|
+
should 'throw an ArgumentError if the opts argument is invalid' do
|
339
|
+
assert_raises(ArgumentError) { MockResource.retrieve(1, {}, "abc") }
|
340
|
+
end
|
341
|
+
|
342
|
+
should 'not throw an ArgumentError if the opts or params are nil' do
|
343
|
+
@mock.expects(:get).times(2).returns(test_response(test_mock_resource))
|
344
|
+
MockResource.retrieve(1, nil, {})
|
345
|
+
MockResource.retrieve(1, {}, nil)
|
346
|
+
end
|
347
|
+
|
348
|
+
should 'urlencode unused arguments via GET' do
|
349
|
+
response = test_response(test_mock_resource)
|
350
|
+
@mock.expects(:get).with do |url, headers, params|
|
351
|
+
(url == "#{Paid.api_base}#{MockResource.path}/bval/many?a=aval&c=cval" ||
|
352
|
+
url == "#{Paid.api_base}#{MockResource.path}/bval/many?c=cval&a=aval") &&
|
353
|
+
params.nil?
|
354
|
+
end.returns(response)
|
355
|
+
|
356
|
+
MockResource.many_args_get("aval", "bval", "cval")
|
357
|
+
end
|
358
|
+
|
359
|
+
should 'assign unused arguments to the params payload via POST' do
|
360
|
+
response = test_response(test_mock_resource)
|
361
|
+
@mock.expects(:post).with("#{Paid.api_base}#{MockResource.path}/bval/many", anything, { :a => "aval", :c => "cval" }).returns(response)
|
362
|
+
|
363
|
+
MockResource.many_args_post("aval", "bval", "cval")
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
context 'APIClass api_instance_method paths' do
|
368
|
+
should 'use the provided argument if it is present' do
|
369
|
+
response = test_response(test_mock_resource)
|
370
|
+
@mock.expects(:get).with("#{Paid.api_base}/custom_path", anything, anything).returns(response)
|
371
|
+
|
372
|
+
mr = MockResource.new(test_mock_resource)
|
373
|
+
mr.custom_path("/custom_path")
|
374
|
+
end
|
375
|
+
|
376
|
+
should 'use the instance method for path values' do
|
377
|
+
response = test_response(test_mock_resource)
|
378
|
+
name = "/mock_resource_name"
|
379
|
+
@mock.expects(:get).with("#{Paid.api_base}#{name}", anything, anything).returns(response)
|
380
|
+
|
381
|
+
mr = MockResource.new(test_mock_resource)
|
382
|
+
mr.name = name
|
383
|
+
mr.name_path
|
384
|
+
end
|
385
|
+
|
386
|
+
should 'use the class method for path values' do
|
387
|
+
response = test_response(test_mock_resource)
|
388
|
+
@mock.expects(:get).with("#{Paid.api_base}#{MockResource.crazy}", anything, anything).returns(response)
|
389
|
+
|
390
|
+
mr = MockResource.new(test_mock_resource)
|
391
|
+
mr.crazy_path
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
context 'APIClass api_class_method paths' do
|
396
|
+
should 'use the provided argument if it is present' do
|
397
|
+
response = test_response(test_mock_resource)
|
398
|
+
@mock.expects(:get).with("#{Paid.api_base}#{MockResource.path}/fake_id", anything, anything).returns(response)
|
399
|
+
|
400
|
+
mr = MockResource.retrieve('fake_id')
|
401
|
+
end
|
402
|
+
|
403
|
+
should 'use the class method for path values' do
|
404
|
+
response = test_response(test_mock_resource)
|
405
|
+
@mock.expects(:get).with("#{Paid.api_base}#{MockResource.crazy}", anything, anything).returns(response)
|
406
|
+
|
407
|
+
MockResource.crazy_path
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
end
|
412
|
+
end
|