turingstudio-freshbooks-rb 3.0.1
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.
- data/History.txt +4 -0
- data/README.rdoc +65 -0
- data/Rakefile +20 -0
- data/lib/freshbooks.rb +41 -0
- data/lib/freshbooks/base.rb +286 -0
- data/lib/freshbooks/category.rb +11 -0
- data/lib/freshbooks/client.rb +32 -0
- data/lib/freshbooks/estimate.rb +30 -0
- data/lib/freshbooks/expense.rb +16 -0
- data/lib/freshbooks/invoice.rb +34 -0
- data/lib/freshbooks/item.rb +12 -0
- data/lib/freshbooks/line.rb +13 -0
- data/lib/freshbooks/payment.rb +22 -0
- data/lib/freshbooks/project.rb +39 -0
- data/lib/freshbooks/recurring.rb +51 -0
- data/lib/freshbooks/response.rb +25 -0
- data/lib/freshbooks/staff.rb +24 -0
- data/lib/freshbooks/task.rb +11 -0
- data/lib/freshbooks/time_entry.rb +13 -0
- data/lib/freshbooks/version.rb +6 -0
- data/spec/lib/freshbooks/base_spec.rb +385 -0
- data/spec/lib/freshbooks/category_spec.rb +64 -0
- data/spec/lib/freshbooks/client_spec.rb +91 -0
- data/spec/lib/freshbooks/estimate_spec.rb +80 -0
- data/spec/lib/freshbooks/expense_spec.rb +86 -0
- data/spec/lib/freshbooks/invoice_spec.rb +89 -0
- data/spec/lib/freshbooks/item_spec.rb +75 -0
- data/spec/lib/freshbooks/payment_spec.rb +77 -0
- data/spec/lib/freshbooks/project_spec.rb +83 -0
- data/spec/lib/freshbooks/recurring_spec.rb +82 -0
- data/spec/lib/freshbooks/staff_spec.rb +21 -0
- data/spec/lib/freshbooks/task_spec.rb +61 -0
- data/spec/lib/freshbooks/time_entry_spec.rb +94 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +11 -0
- data/tasks/rspec.rake +33 -0
- metadata +109 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
module FreshBooks
|
2
|
+
class Estimate < Base
|
3
|
+
attribute :estimate_id, :integer
|
4
|
+
attribute :client_id, :integer
|
5
|
+
attribute :status, :string
|
6
|
+
attribute :date, :string
|
7
|
+
attribute :po_number, :integer
|
8
|
+
attribute :discount, :float
|
9
|
+
attribute :notes, :string
|
10
|
+
attribute :terms, :string
|
11
|
+
attribute :first_name, :string
|
12
|
+
attribute :last_name, :string
|
13
|
+
attribute :organization, :string
|
14
|
+
attribute :p_street1, :string
|
15
|
+
attribute :p_street2, :string
|
16
|
+
attribute :p_city, :string
|
17
|
+
attribute :p_state, :string
|
18
|
+
attribute :p_country, :string
|
19
|
+
attribute :p_code, :string
|
20
|
+
attribute :lines, :array
|
21
|
+
|
22
|
+
belongs_to :client
|
23
|
+
method :list, :get, :create, :update, :delete, :send_by_email
|
24
|
+
|
25
|
+
def initialize(data = {})
|
26
|
+
super
|
27
|
+
self.lines ||= []
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module FreshBooks
|
2
|
+
class Expense < Base
|
3
|
+
attribute :expense_id, :integer
|
4
|
+
attribute :staff_id, :integer
|
5
|
+
attribute :category_id, :integer
|
6
|
+
attribute :project_id, :integer
|
7
|
+
attribute :client_id, :integer
|
8
|
+
attribute :amount, :float
|
9
|
+
attribute :date, :string
|
10
|
+
attribute :notes, :string
|
11
|
+
attribute :status, :string
|
12
|
+
|
13
|
+
belongs_to :staff, :category, :project, :client
|
14
|
+
method :list, :get, :create, :update, :delete, :send_by_email
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module FreshBooks
|
2
|
+
class Invoice < Base
|
3
|
+
attribute :invoice_id, :integer
|
4
|
+
attribute :client_id, :integer
|
5
|
+
attribute :number, :string
|
6
|
+
attribute :date, :string
|
7
|
+
attribute :po_number, :integer
|
8
|
+
attribute :terms, :string
|
9
|
+
attribute :first_name, :string
|
10
|
+
attribute :last_name, :string
|
11
|
+
attribute :organization, :string
|
12
|
+
attribute :p_street1, :string
|
13
|
+
attribute :p_street2, :string
|
14
|
+
attribute :p_city, :string
|
15
|
+
attribute :p_state, :string
|
16
|
+
attribute :p_country, :string
|
17
|
+
attribute :p_code, :string
|
18
|
+
attribute :amount, :float
|
19
|
+
attribute :lines, :array
|
20
|
+
attribute :discount, :float
|
21
|
+
attribute :status, :string
|
22
|
+
attribute :notes, :string
|
23
|
+
attribute :url, :string, :read_only => true
|
24
|
+
|
25
|
+
belongs_to :client
|
26
|
+
has_many :payments
|
27
|
+
method :list, :get, :create, :update, :delete, :send_by_email, :send_by_snail_mail
|
28
|
+
|
29
|
+
def initialize(data = {})
|
30
|
+
super
|
31
|
+
self.lines ||= []
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module FreshBooks
|
2
|
+
class Item < Base
|
3
|
+
attribute :item_id, :integer
|
4
|
+
attribute :name, :string
|
5
|
+
attribute :description, :string
|
6
|
+
attribute :unit_cost, :float
|
7
|
+
attribute :quantity, :integer
|
8
|
+
attribute :inventory, :integer
|
9
|
+
|
10
|
+
method :list, :get, :create, :update, :delete
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module FreshBooks
|
2
|
+
class Line < Base
|
3
|
+
attribute :name, :string
|
4
|
+
attribute :description, :string
|
5
|
+
attribute :unit_cost, :float
|
6
|
+
attribute :quantity, :integer
|
7
|
+
attribute :tax1_name, :string
|
8
|
+
attribute :tax2_name, :string
|
9
|
+
attribute :tax1_percent, :float
|
10
|
+
attribute :tax2_percent, :float
|
11
|
+
attribute :amount, :float
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module FreshBooks
|
2
|
+
# * If you specify an invoice_id only, the payment will be recorded as an invoice payment.
|
3
|
+
# * If you specify a client_id only, the payment will be recorded as a client credit.
|
4
|
+
# * If you specify both an invoice_id and client_id, the payment will be recorded
|
5
|
+
# as an invoice payment, and the amount will be subtracted from the client’s credit.
|
6
|
+
#
|
7
|
+
# Payment type must be one of: ‘Check’, ‘Credit’, ‘Bank Transfer’, ‘PayPal’, ‘2Checkout’,
|
8
|
+
# ‘VISA’, ‘MASTERCARD’, ‘DISCOVER’, ‘NOVA’, ‘AMEX’, ‘DINERS’, ‘EUROCARD’, ‘JCB’ or ‘ACH’.
|
9
|
+
|
10
|
+
class Payment < Base
|
11
|
+
attribute :payment_id, :integer
|
12
|
+
attribute :client_id, :integer
|
13
|
+
attribute :invoice_id, :integer
|
14
|
+
attribute :date, :string
|
15
|
+
attribute :amount, :float
|
16
|
+
attribute :type, :string
|
17
|
+
attribute :notes, :string
|
18
|
+
|
19
|
+
belongs_to :client, :invoice
|
20
|
+
method :list, :get, :create, :update
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module FreshBooks
|
2
|
+
# If you specify project-rate or flat-rate for
|
3
|
+
# billing_method when creating a new project, you must supply a rate.
|
4
|
+
#
|
5
|
+
# Billing Method Types
|
6
|
+
# * task-rate
|
7
|
+
# * flat-rate
|
8
|
+
# * project-rate
|
9
|
+
# * staff-rate
|
10
|
+
|
11
|
+
class Project < Base
|
12
|
+
attribute :project_id, :integer
|
13
|
+
attribute :client_id, :integer
|
14
|
+
attribute :name, :string
|
15
|
+
attribute :bill_method, :string
|
16
|
+
attribute :rate, :float
|
17
|
+
attribute :description, :string
|
18
|
+
attribute :tasks, :array
|
19
|
+
|
20
|
+
belongs_to :client
|
21
|
+
has_many :expenses
|
22
|
+
method :list, :get, :create, :update, :delete
|
23
|
+
|
24
|
+
def initialize(data = {})
|
25
|
+
super
|
26
|
+
self.tasks ||= []
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def tasks_to_xml(root)
|
32
|
+
return if tasks.empty?
|
33
|
+
node = root.add_element('tasks')
|
34
|
+
tasks.each do |task|
|
35
|
+
node.add_element('task_id').text = task.task_id
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module FreshBooks
|
2
|
+
# Create a new recurring profile.
|
3
|
+
#
|
4
|
+
# The method arguments are nearly identical to invoice.create, but include four new fields:
|
5
|
+
#
|
6
|
+
# * occurrences
|
7
|
+
# Number of invoices to generate, with zero (0) being infinite
|
8
|
+
# * frequency
|
9
|
+
# Rate at which to generate invoices - can be one of ‘weekly’, ‘2 weeks’, ‘4 weeks’,
|
10
|
+
# ‘monthly’, ‘2 months’, ‘3 months’, ‘6 months’, ‘yearly’, ‘2 years’
|
11
|
+
# * stopped
|
12
|
+
# This profile is no longer generating invoices (1 - stopped, 0 - active)
|
13
|
+
# * send_email
|
14
|
+
# Notify client by email each time a new invoice is generated (1 or 0)
|
15
|
+
# * send_snail_mail
|
16
|
+
# Send a copy of your invoice by snail mail, each time it’s generated (1 or 0)
|
17
|
+
|
18
|
+
class Recurring < Base
|
19
|
+
attribute :recurring_id, :integer
|
20
|
+
attribute :client_id, :integer
|
21
|
+
attribute :date, :string
|
22
|
+
attribute :po_number, :integer
|
23
|
+
attribute :terms, :string
|
24
|
+
attribute :first_name, :string
|
25
|
+
attribute :last_name, :string
|
26
|
+
attribute :organization, :string
|
27
|
+
attribute :p_street1, :string
|
28
|
+
attribute :p_street2, :string
|
29
|
+
attribute :p_city, :string
|
30
|
+
attribute :p_state, :string
|
31
|
+
attribute :p_country, :string
|
32
|
+
attribute :p_code, :string
|
33
|
+
attribute :amount, :float
|
34
|
+
attribute :lines, :array
|
35
|
+
attribute :discount, :float
|
36
|
+
attribute :status, :string
|
37
|
+
attribute :notes, :string
|
38
|
+
attribute :occurrences, :integer
|
39
|
+
attribute :frequency, :string
|
40
|
+
attribute :send_email, :integer
|
41
|
+
attribute :send_snail_mail, :integer
|
42
|
+
|
43
|
+
belongs_to :client
|
44
|
+
method :list, :get, :create, :update, :delete
|
45
|
+
|
46
|
+
def initialize(data = {})
|
47
|
+
super
|
48
|
+
self.lines ||= []
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module FreshBooks
|
2
|
+
class Response
|
3
|
+
attr_accessor :doc
|
4
|
+
|
5
|
+
def initialize(xml_raw)
|
6
|
+
@doc = REXML::Document.new(xml_raw)
|
7
|
+
end
|
8
|
+
|
9
|
+
def elements
|
10
|
+
@doc.root.elements
|
11
|
+
end
|
12
|
+
|
13
|
+
def success?
|
14
|
+
@doc.root.attributes['status'] == 'ok'
|
15
|
+
end
|
16
|
+
|
17
|
+
def fail?
|
18
|
+
!success?
|
19
|
+
end
|
20
|
+
|
21
|
+
def error_msg
|
22
|
+
return @doc.root.elements['error'].text
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module FreshBooks
|
2
|
+
class Staff < Base
|
3
|
+
attribute :staff_id, :integer
|
4
|
+
attribute :username, :string
|
5
|
+
attribute :first_name, :string
|
6
|
+
attribute :last_name, :string
|
7
|
+
attribute :email, :string
|
8
|
+
attribute :business_phone, :string
|
9
|
+
attribute :mobile_phone, :string
|
10
|
+
attribute :rate, :string
|
11
|
+
attribute :last_login, :string
|
12
|
+
attribute :number_of_logins,:string
|
13
|
+
attribute :signup_date, :string
|
14
|
+
attribute :street1, :string
|
15
|
+
attribute :street2, :string
|
16
|
+
attribute :city, :string
|
17
|
+
attribute :state, :string
|
18
|
+
attribute :country, :string
|
19
|
+
attribute :code, :string
|
20
|
+
|
21
|
+
has_many :expenses
|
22
|
+
method :list, :get
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module FreshBooks
|
2
|
+
class TimeEntry < Base
|
3
|
+
attribute :time_entry_id, :integer
|
4
|
+
attribute :project_id, :integer
|
5
|
+
attribute :task_id, :integer
|
6
|
+
attribute :hours, :float
|
7
|
+
attribute :notes, :string
|
8
|
+
attribute :date, :string
|
9
|
+
|
10
|
+
belongs_to :project, :task
|
11
|
+
method :list, :get, :create, :update, :delete
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,385 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe FreshBooks::Base do
|
4
|
+
class First < FreshBooks::Base
|
5
|
+
attribute :first_id, :integer
|
6
|
+
attribute :name, :string
|
7
|
+
attribute :amount, :float
|
8
|
+
attribute :url, :string, :read_only => true
|
9
|
+
attribute :seconds, :array
|
10
|
+
end
|
11
|
+
|
12
|
+
class Second < FreshBooks::Base
|
13
|
+
attribute :second_id, :integer
|
14
|
+
attribute :first_id, :integer
|
15
|
+
belongs_to :first
|
16
|
+
has_many :tests
|
17
|
+
end
|
18
|
+
|
19
|
+
class Test < FreshBooks::Base
|
20
|
+
attribute :test_id, :integer
|
21
|
+
method :list, :get, :create, :update, :delete, :send_by_email, :send_by_snail_mail
|
22
|
+
end
|
23
|
+
|
24
|
+
class TestWithoutMethods < FreshBooks::Base
|
25
|
+
attribute :test_id, :integer
|
26
|
+
end
|
27
|
+
|
28
|
+
before(:each) do
|
29
|
+
@object = Test.new
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should return corrent node name" do
|
33
|
+
FreshBooks::Base.node_name.should == 'base'
|
34
|
+
First.node_name.should == 'first'
|
35
|
+
Second.node_name.should == 'second'
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should has correct attributes" do
|
39
|
+
First.attributes[:first_id].should == { :type => :integer }
|
40
|
+
First.attributes[:name].should == { :type => :string }
|
41
|
+
First.attributes[:amount].should == { :type => :float }
|
42
|
+
First.attributes[:url].should == { :type => :string, :read_only => true }
|
43
|
+
First.attributes[:seconds].should == { :type => :array }
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should has attribure accessors for decalred attributes" do
|
47
|
+
first = First.new
|
48
|
+
lambda { first.first_id }.should_not raise_error
|
49
|
+
lambda { first.first_id = 1 }.should_not raise_error
|
50
|
+
first.first_id.should == 1
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should provide changed detector for decalred attributes" do
|
54
|
+
first = First.new
|
55
|
+
lambda { first.first_id_changed? }.should_not raise_error
|
56
|
+
first.first_id_changed?.should be_false
|
57
|
+
first.first_id = 1
|
58
|
+
first.first_id_changed?.should be_true
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "belongs_to association" do
|
62
|
+
before(:each) do
|
63
|
+
First.stub!(:get)
|
64
|
+
@second = Second.new(:first_id => 1)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should has method" do
|
68
|
+
lambda { @second.first }.should_not raise_error
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should find associated object" do
|
72
|
+
First.should_receive(:get).with(1)
|
73
|
+
@second.first
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "belongs_to association" do
|
78
|
+
before(:each) do
|
79
|
+
Test.stub!(:list)
|
80
|
+
@second = Second.new(:second_id => 1)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should has method" do
|
84
|
+
lambda { @second.tests }.should_not raise_error
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should find associated object" do
|
88
|
+
Test.should_receive(:list).with({'second_id' => 1, 'name' => 'value'})
|
89
|
+
@second.tests('name' => 'value')
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "xml conversion" do
|
94
|
+
before(:each) do
|
95
|
+
@second1 = Second.new(:second_id => 1)
|
96
|
+
@second2 = Second.new(:second_id => 2)
|
97
|
+
@first = First.new(
|
98
|
+
:first_id => 1,
|
99
|
+
:name => 'name',
|
100
|
+
:url => 'url',
|
101
|
+
:seconds => [@second1, @second2]
|
102
|
+
)
|
103
|
+
@xml = @first.to_xml
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should return correct xml" do
|
107
|
+
@xml.to_s.should =~ Regexp.new(Regexp.escape('<first_id>1</first_id>'))
|
108
|
+
@xml.to_s.should =~ Regexp.new(Regexp.escape('<name>name</name>'))
|
109
|
+
@xml.to_s.should =~ Regexp.new(Regexp.escape('<seconds><second><second_id>1</second_id></second><second><second_id>2</second_id></second></seconds>'))
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should not include read_only attributes in xml" do
|
113
|
+
@xml.to_s.should_not =~ Regexp.new(Regexp.escape('<url>url</url>'))
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should not include unchanged attributes in xml" do
|
117
|
+
@xml.to_s.should_not =~ Regexp.new(Regexp.escape('<amount>'))
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should return correct xml and initialize correctly from xml" do
|
121
|
+
first = First.new_from_xml(@xml)
|
122
|
+
first.first_id.should == 1
|
123
|
+
first.seconds.size.should == 2
|
124
|
+
first.seconds[0].second_id.should == 1
|
125
|
+
first.seconds[1].second_id.should == 2
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should raise an exception when unknown method is being called" do
|
130
|
+
lambda { TestWithoutMethods.list }.should raise_error
|
131
|
+
lambda { TestWithoutMethods.new.create }.should raise_error
|
132
|
+
end
|
133
|
+
|
134
|
+
describe "create method" do
|
135
|
+
before(:each) do
|
136
|
+
@elem = mock('XmlObj', :text => '123')
|
137
|
+
@resp = mock('XmlResp', :elements => [nil, @elem])
|
138
|
+
@resp.stub!(:success?).and_return(true)
|
139
|
+
FreshBooks::Base.stub!(:call_api).and_return(@resp)
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should call api method" do
|
143
|
+
FreshBooks::Base.should_receive(:call_api).with('test.create', 'test' => @object).and_return(@resp)
|
144
|
+
@object.create
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should assign id returned by api if call succeeded" do
|
148
|
+
@object.create
|
149
|
+
@object.test_id.should == 123
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should not assign id returned by api if call failed" do
|
153
|
+
@resp.stub!(:success?).and_return(false)
|
154
|
+
@object.create
|
155
|
+
@object.test_id.should be_nil
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should return id if call succeeded" do
|
159
|
+
@object.create.should == 123
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should return nil if call failed" do
|
163
|
+
@resp.stub!(:success?).and_return(false)
|
164
|
+
@object.create.should be_nil
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe "update method" do
|
169
|
+
before(:each) do
|
170
|
+
@resp = mock('XmlResp')
|
171
|
+
@resp.stub!(:success?).and_return(true)
|
172
|
+
FreshBooks::Base.stub!(:call_api).and_return(@resp)
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should call api method" do
|
176
|
+
FreshBooks::Base.should_receive(:call_api).with('test.update', 'test' => @object).and_return(@resp)
|
177
|
+
@object.update
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should return true if request succeeded" do
|
181
|
+
@resp.stub!(:success?).and_return(true)
|
182
|
+
@object.update.should be_true
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should return false if request failed" do
|
186
|
+
@resp.stub!(:success?).and_return(false)
|
187
|
+
@object.update.should be_false
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
describe "delete method" do
|
192
|
+
before(:each) do
|
193
|
+
@object.test_id = 1
|
194
|
+
@resp = mock('XmlResp')
|
195
|
+
@resp.stub!(:success?).and_return(true)
|
196
|
+
FreshBooks::Base.stub!(:call_api).and_return(@resp)
|
197
|
+
end
|
198
|
+
|
199
|
+
it "should call api method" do
|
200
|
+
FreshBooks::Base.should_receive(:call_api).with('test.delete', 'test_id' => 1).and_return(@resp)
|
201
|
+
@object.delete
|
202
|
+
end
|
203
|
+
|
204
|
+
it "should return true if request succeeded" do
|
205
|
+
@resp.stub!(:success?).and_return(true)
|
206
|
+
@object.delete.should be_true
|
207
|
+
end
|
208
|
+
|
209
|
+
it "should return false if request failed" do
|
210
|
+
@resp.stub!(:success?).and_return(false)
|
211
|
+
@object.delete.should be_false
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
describe "delete class method" do
|
216
|
+
before(:each) do
|
217
|
+
@resp = mock('XmlResp')
|
218
|
+
@resp.stub!(:success?).and_return(true)
|
219
|
+
FreshBooks::Base.stub!(:call_api).and_return(@resp)
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should call api method" do
|
223
|
+
FreshBooks::Base.should_receive(:call_api).with('test.delete', 'test_id' => 1).and_return(@resp)
|
224
|
+
Test.delete(1)
|
225
|
+
end
|
226
|
+
|
227
|
+
it "should return true if request succeeded" do
|
228
|
+
@resp.stub!(:success?).and_return(true)
|
229
|
+
Test.delete(1).should be_true
|
230
|
+
end
|
231
|
+
|
232
|
+
it "should return false if request failed" do
|
233
|
+
@resp.stub!(:success?).and_return(false)
|
234
|
+
Test.delete(1).should be_false
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
describe "get class method" do
|
239
|
+
before(:each) do
|
240
|
+
@resp = mock('XmlResp', :elements => [])
|
241
|
+
@resp.stub!(:success?).and_return(true)
|
242
|
+
FreshBooks::Base.stub!(:call_api).and_return(@resp)
|
243
|
+
Test.stub!(:new_from_xml).and_return(true)
|
244
|
+
end
|
245
|
+
|
246
|
+
it "should call api method" do
|
247
|
+
FreshBooks::Base.should_receive(:call_api).with('test.get', 'test_id' => 1).and_return(@resp)
|
248
|
+
Test.get(1)
|
249
|
+
end
|
250
|
+
|
251
|
+
it "should build and return instance from xml if request succeeded" do
|
252
|
+
@resp.stub!(:success?).and_return(true)
|
253
|
+
Test.should_receive(:new_from_xml).and_return(true)
|
254
|
+
Test.get(1).should be_true
|
255
|
+
end
|
256
|
+
|
257
|
+
it "should return false if request failed" do
|
258
|
+
@resp.stub!(:success?).and_return(false)
|
259
|
+
Test.get(1).should be_nil
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
describe "list class method" do
|
264
|
+
before(:each) do
|
265
|
+
@elem1 = mock('XmlElement')
|
266
|
+
@elem2 = mock('XmlElement')
|
267
|
+
@elems = mock('XmlElements', :elements => [@elem1, @elem2])
|
268
|
+
@resp = mock('XmlResp', :elements => [nil, @elems])
|
269
|
+
@resp.stub!(:success?).and_return(true)
|
270
|
+
FreshBooks::Base.stub!(:call_api).and_return(@resp)
|
271
|
+
Test.stub!(:new_from_xml).and_return(true)
|
272
|
+
end
|
273
|
+
|
274
|
+
it "should call api method" do
|
275
|
+
FreshBooks::Base.should_receive(:call_api).with('test.list', :name => 'value').and_return(@resp)
|
276
|
+
Test.list(:name => 'value')
|
277
|
+
end
|
278
|
+
|
279
|
+
it "should return nil if request failed" do
|
280
|
+
@resp.stub!(:success?).and_return(false)
|
281
|
+
Test.list.should be_nil
|
282
|
+
end
|
283
|
+
|
284
|
+
it "should build instances from response records if request succeeded" do
|
285
|
+
@resp.stub!(:success?).and_return(true)
|
286
|
+
Test.should_receive(:new_from_xml).with(@elem1).and_return(1)
|
287
|
+
Test.should_receive(:new_from_xml).with(@elem2).and_return(2)
|
288
|
+
Test.list.should == [1, 2]
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
describe "send_by_email method" do
|
293
|
+
before(:each) do
|
294
|
+
@object.test_id = 1
|
295
|
+
@resp = mock('XmlResp')
|
296
|
+
@resp.stub!(:success?).and_return(true)
|
297
|
+
FreshBooks::Base.stub!(:call_api).and_return(@resp)
|
298
|
+
end
|
299
|
+
|
300
|
+
it "should call api method" do
|
301
|
+
FreshBooks::Base.should_receive(:call_api).with('test.sendByEmail', 'test_id' => 1).and_return(@resp)
|
302
|
+
@object.send_by_email
|
303
|
+
end
|
304
|
+
|
305
|
+
it "should return true if request succeeded" do
|
306
|
+
@resp.stub!(:success?).and_return(true)
|
307
|
+
@object.send_by_email.should be_true
|
308
|
+
end
|
309
|
+
|
310
|
+
it "should return false if request failed" do
|
311
|
+
@resp.stub!(:success?).and_return(false)
|
312
|
+
@object.send_by_email.should be_false
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
describe "send_by_email class method" do
|
317
|
+
before(:each) do
|
318
|
+
@resp = mock('XmlResp')
|
319
|
+
@resp.stub!(:success?).and_return(true)
|
320
|
+
FreshBooks::Base.stub!(:call_api).and_return(@resp)
|
321
|
+
end
|
322
|
+
|
323
|
+
it "should call api method" do
|
324
|
+
FreshBooks::Base.should_receive(:call_api).with('test.sendByEmail', 'test_id' => 1).and_return(@resp)
|
325
|
+
Test.send_by_email(1)
|
326
|
+
end
|
327
|
+
|
328
|
+
it "should return true if request succeeded" do
|
329
|
+
@resp.stub!(:success?).and_return(true)
|
330
|
+
Test.send_by_email(1).should be_true
|
331
|
+
end
|
332
|
+
|
333
|
+
it "should return false if request failed" do
|
334
|
+
@resp.stub!(:success?).and_return(false)
|
335
|
+
Test.send_by_email(1).should be_false
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
describe "send_by_snail_mail method" do
|
340
|
+
before(:each) do
|
341
|
+
@object.test_id = 1
|
342
|
+
@resp = mock('XmlResp')
|
343
|
+
@resp.stub!(:success?).and_return(true)
|
344
|
+
FreshBooks::Base.stub!(:call_api).and_return(@resp)
|
345
|
+
end
|
346
|
+
|
347
|
+
it "should call api method" do
|
348
|
+
FreshBooks::Base.should_receive(:call_api).with('test.sendBySnailMail', 'test_id' => 1).and_return(@resp)
|
349
|
+
@object.send_by_snail_mail
|
350
|
+
end
|
351
|
+
|
352
|
+
it "should return true if request succeeded" do
|
353
|
+
@resp.stub!(:success?).and_return(true)
|
354
|
+
@object.send_by_snail_mail.should be_true
|
355
|
+
end
|
356
|
+
|
357
|
+
it "should return false if request failed" do
|
358
|
+
@resp.stub!(:success?).and_return(false)
|
359
|
+
@object.send_by_snail_mail.should be_false
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
describe "send_by_snail_mail class method" do
|
364
|
+
before(:each) do
|
365
|
+
@resp = mock('XmlResp')
|
366
|
+
@resp.stub!(:success?).and_return(true)
|
367
|
+
FreshBooks::Base.stub!(:call_api).and_return(@resp)
|
368
|
+
end
|
369
|
+
|
370
|
+
it "should call api method" do
|
371
|
+
FreshBooks::Base.should_receive(:call_api).with('test.sendBySnailMail', 'test_id' => 1).and_return(@resp)
|
372
|
+
Test.send_by_snail_mail(1)
|
373
|
+
end
|
374
|
+
|
375
|
+
it "should return true if request succeeded" do
|
376
|
+
@resp.stub!(:success?).and_return(true)
|
377
|
+
Test.send_by_snail_mail(1).should be_true
|
378
|
+
end
|
379
|
+
|
380
|
+
it "should return false if request failed" do
|
381
|
+
@resp.stub!(:success?).and_return(false)
|
382
|
+
Test.send_by_snail_mail(1).should be_false
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|