freshtrack 0.2.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.
- data/History.txt +4 -0
- data/License.txt +20 -0
- data/Manifest.txt +37 -0
- data/README.txt +30 -0
- data/Rakefile +4 -0
- data/bin/freshtrack +23 -0
- data/config/hoe.rb +74 -0
- data/config/requirements.rb +17 -0
- data/lib/freshbooks/extensions/base_object.rb +31 -0
- data/lib/freshbooks/extensions/project.rb +58 -0
- data/lib/freshbooks/extensions/task.rb +50 -0
- data/lib/freshbooks/extensions/time_entry.rb +53 -0
- data/lib/freshbooks/extensions.rb +5 -0
- data/lib/freshtrack/core_ext/array.rb +11 -0
- data/lib/freshtrack/core_ext/numeric.rb +5 -0
- data/lib/freshtrack/core_ext/time.rb +3 -0
- data/lib/freshtrack/core_ext.rb +3 -0
- data/lib/freshtrack/version.rb +9 -0
- data/lib/freshtrack.rb +107 -0
- data/log/debug.log +0 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/setup.rb +1585 -0
- data/spec/array_spec.rb +35 -0
- data/spec/base_object_spec.rb +51 -0
- data/spec/freshtrack_spec.rb +566 -0
- data/spec/numeric_spec.rb +21 -0
- data/spec/project_spec.rb +400 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/task_spec.rb +350 -0
- data/spec/time_entry_spec.rb +351 -0
- data/spec/time_spec.rb +37 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/rspec.rake +21 -0
- data/tasks/website.rake +9 -0
- metadata +110 -0
@@ -0,0 +1,400 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe FreshBooks::Project do
|
4
|
+
before :each do
|
5
|
+
@project = FreshBooks::Project.new
|
6
|
+
end
|
7
|
+
|
8
|
+
describe 'attributes' do
|
9
|
+
it 'should have a project_id' do
|
10
|
+
@project.should respond_to(:project_id)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should have a name' do
|
14
|
+
@project.should respond_to(:name)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should have a bill_method' do
|
18
|
+
@project.should respond_to(:bill_method)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should have a client_id' do
|
22
|
+
@project.should respond_to(:client_id)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should have a rate' do
|
26
|
+
@project.should respond_to(:rate)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should have a description' do
|
30
|
+
@project.should respond_to(:description)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe 'type mappings' do
|
35
|
+
before :each do
|
36
|
+
@mapping = FreshBooks::Project::TYPE_MAPPINGS
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should map project_id to Fixnum' do
|
40
|
+
@mapping['project_id'].should == Fixnum
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should map client_id to Fixnum' do
|
44
|
+
@mapping['client_id'].should == Fixnum
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should map rate to Float' do
|
48
|
+
@mapping['rate'].should == Float
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'creating an instance' do
|
53
|
+
before :each do
|
54
|
+
@response = stub('response', :success? => nil)
|
55
|
+
FreshBooks.stubs(:call_api).returns(@response)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should issue a request with the instance' do
|
59
|
+
FreshBooks.expects(:call_api).with('project.create', 'project' => @project).returns(@response)
|
60
|
+
@project.create
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'with a successful request' do
|
64
|
+
before :each do
|
65
|
+
@project_id = 5
|
66
|
+
@response.stubs(:elements).returns([stub('pre element'), stub('element', :text => @project_id.to_s), stub('post element')])
|
67
|
+
@response.stubs(:success?).returns(true)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should set the ID from the response' do
|
71
|
+
@project.expects(:project_id=).with(@project_id)
|
72
|
+
@project.create
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should return the ID' do
|
76
|
+
@project.create.should == @project_id
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe 'with an unsuccessful request' do
|
81
|
+
before :each do
|
82
|
+
@response.stubs(:success?).returns(false)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should not set the ID' do
|
86
|
+
@project.expects(:project_id=).never
|
87
|
+
@project.create
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should return nil' do
|
91
|
+
@project.create.should be_nil
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe 'updating an instance' do
|
97
|
+
before :each do
|
98
|
+
@response = stub('response', :success? => nil)
|
99
|
+
FreshBooks.stubs(:call_api).returns(@response)
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'should issue a request with the instance' do
|
103
|
+
FreshBooks.expects(:call_api).with('project.update', 'project' => @project).returns(@response)
|
104
|
+
@project.update
|
105
|
+
end
|
106
|
+
|
107
|
+
describe 'with a successful request' do
|
108
|
+
before :each do
|
109
|
+
@response.stubs(:success?).returns(true)
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should return true' do
|
113
|
+
@project.update.should be(true)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe 'with an unsuccessful request' do
|
118
|
+
before :each do
|
119
|
+
@response.stubs(:success?).returns(false)
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'should return false' do
|
123
|
+
@project.update.should be(false)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe 'deleting an instance' do
|
129
|
+
before :each do
|
130
|
+
@project_id = '5'
|
131
|
+
@response = stub('response', :success? => nil)
|
132
|
+
FreshBooks.stubs(:call_api).returns(@response)
|
133
|
+
end
|
134
|
+
|
135
|
+
describe 'from the class' do
|
136
|
+
it 'should require an argument' do
|
137
|
+
lambda { FreshBooks::Project.delete }.should raise_error(ArgumentError)
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'should accept an argument' do
|
141
|
+
lambda { FreshBooks::Project.delete('arg') }.should_not raise_error(ArgumentError)
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'should issue a request with the supplied ID' do
|
145
|
+
FreshBooks.expects(:call_api).with('project.delete', 'project_id' => @project_id).returns(@response)
|
146
|
+
FreshBooks::Project.delete(@project_id)
|
147
|
+
end
|
148
|
+
|
149
|
+
describe 'with a successful request' do
|
150
|
+
before :each do
|
151
|
+
@response.stubs(:success?).returns(true)
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'should return true' do
|
155
|
+
FreshBooks::Project.delete(@project_id).should be(true)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe 'with an unsuccessful request' do
|
160
|
+
before :each do
|
161
|
+
@response.stubs(:success?).returns(false)
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'should return false' do
|
165
|
+
FreshBooks::Project.delete(@project_id).should be(false)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
describe 'from the instance' do
|
171
|
+
before :each do
|
172
|
+
@project.stubs(:project_id).returns(@project_id)
|
173
|
+
FreshBooks::Project.stubs(:delete)
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'should delegate to the class' do
|
177
|
+
FreshBooks::Project.expects(:delete)
|
178
|
+
@project.delete
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'should pass its ID to the class method' do
|
182
|
+
FreshBooks::Project.expects(:delete).with(@project_id)
|
183
|
+
@project.delete
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'should return the result from the class method' do
|
187
|
+
val = stub('return val')
|
188
|
+
FreshBooks::Project.stubs(:delete).returns(val)
|
189
|
+
@project.delete.should == val
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
describe 'getting an instance' do
|
195
|
+
before :each do
|
196
|
+
@project_id = 1
|
197
|
+
@element = stub('element')
|
198
|
+
@response = stub('response', :elements => [stub('pre element'), @element, stub('post element')], :success? => nil)
|
199
|
+
FreshBooks.stubs(:call_api).returns(@response)
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'should require an argument' do
|
203
|
+
lambda { FreshBooks::Project.get }.should raise_error(ArgumentError)
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'should accept an argument' do
|
207
|
+
lambda { FreshBooks::Project.get(@project_id) }.should_not raise_error(ArgumentError)
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'should issue a request for the supplied ID' do
|
211
|
+
FreshBooks.expects(:call_api).with('project.get', 'project_id' => @project_id).returns(@response)
|
212
|
+
FreshBooks::Project.get(@project_id)
|
213
|
+
end
|
214
|
+
|
215
|
+
describe 'with a successful request' do
|
216
|
+
before :each do
|
217
|
+
@response.stubs(:success?).returns(true)
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'should instantiate a new project instance from the request' do
|
221
|
+
FreshBooks::Project.expects(:new_from_xml).with(@element)
|
222
|
+
FreshBooks::Project.get(@project_id)
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'should return the project instance' do
|
226
|
+
val = stub('return val')
|
227
|
+
FreshBooks::Project.stubs(:new_from_xml).returns(val)
|
228
|
+
FreshBooks::Project.get(@project_id).should == val
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
describe 'with an unsuccessful request' do
|
233
|
+
before :each do
|
234
|
+
@response.stubs(:success?).returns(false)
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'should return nil' do
|
238
|
+
FreshBooks::Project.get(@project_id).should be_nil
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
describe 'getting a list' do
|
244
|
+
before :each do
|
245
|
+
@project_id = 1
|
246
|
+
@elements = Array.new(3) { stub('element') }
|
247
|
+
@response = stub('response', :elements => @elements, :success? => nil)
|
248
|
+
FreshBooks.stubs(:call_api).returns(@response)
|
249
|
+
end
|
250
|
+
|
251
|
+
it 'should not require an argument' do
|
252
|
+
lambda { FreshBooks::Project.list }.should_not raise_error(ArgumentError)
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'should accept an argument' do
|
256
|
+
lambda { FreshBooks::Project.list('arg') }.should_not raise_error(ArgumentError)
|
257
|
+
end
|
258
|
+
|
259
|
+
it 'should issue a request for the time_entry list' do
|
260
|
+
FreshBooks.expects(:call_api).with('project.list', {}).returns(@response)
|
261
|
+
FreshBooks::Project.list
|
262
|
+
end
|
263
|
+
|
264
|
+
it 'should pass the argument to the request' do
|
265
|
+
arg = stub('arg')
|
266
|
+
FreshBooks.expects(:call_api).with('project.list', arg).returns(@response)
|
267
|
+
FreshBooks::Project.list(arg)
|
268
|
+
end
|
269
|
+
|
270
|
+
describe 'with a successful request' do
|
271
|
+
before :each do
|
272
|
+
@response.stubs(:success?).returns(true)
|
273
|
+
end
|
274
|
+
|
275
|
+
it 'should instantiate new project instances from the request' do
|
276
|
+
@elements.each do |element|
|
277
|
+
FreshBooks::Project.expects(:new_from_xml).with(element)
|
278
|
+
end
|
279
|
+
FreshBooks::Project.list
|
280
|
+
end
|
281
|
+
|
282
|
+
it 'should return the project instances' do
|
283
|
+
vals = Array.new(@elements.length) { stub('return val') }
|
284
|
+
@elements.each_with_index do |element, i|
|
285
|
+
FreshBooks::Project.stubs(:new_from_xml).with(element).returns(vals[i])
|
286
|
+
end
|
287
|
+
FreshBooks::Project.list.should == vals
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
describe 'with an unsuccessful request' do
|
292
|
+
before :each do
|
293
|
+
@response.stubs(:success?).returns(false)
|
294
|
+
end
|
295
|
+
|
296
|
+
it 'should return nil' do
|
297
|
+
FreshBooks::Project.list.should be_nil
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
describe 'getting by name' do
|
303
|
+
before :each do
|
304
|
+
@name = 'projname'
|
305
|
+
FreshBooks::Project.stubs(:list).returns([])
|
306
|
+
end
|
307
|
+
|
308
|
+
it 'should require an argument' do
|
309
|
+
lambda { FreshBooks::Project.find_by_name }.should raise_error(ArgumentError)
|
310
|
+
end
|
311
|
+
|
312
|
+
it 'should accept an argument' do
|
313
|
+
lambda { FreshBooks::Project.find_by_name(@name) }.should_not raise_error(ArgumentError)
|
314
|
+
end
|
315
|
+
|
316
|
+
it 'should return the project with a matching name' do
|
317
|
+
projects = Array.new(3) { |i| stub('project', :name => "project #{i}" ) }
|
318
|
+
projects[1,0] = expected = stub('project', :name => @name)
|
319
|
+
FreshBooks::Project.stubs(:list).returns(projects)
|
320
|
+
FreshBooks::Project.find_by_name(@name).should == expected
|
321
|
+
end
|
322
|
+
|
323
|
+
it 'should return the first project found whose name matches' do
|
324
|
+
projects = Array.new(3) { |i| stub('project', :name => "project #{i}" ) }
|
325
|
+
projects[1,0] = expected = stub('project', :name => @name)
|
326
|
+
projects[3,0] = stub('project', :name => @name)
|
327
|
+
FreshBooks::Project.stubs(:list).returns(projects)
|
328
|
+
FreshBooks::Project.find_by_name(@name).should == expected
|
329
|
+
end
|
330
|
+
|
331
|
+
it 'should return nil if no project with matching name found' do
|
332
|
+
projects = Array.new(3) { |i| stub('project', :name => "project #{i}" ) }
|
333
|
+
FreshBooks::Project.stubs(:list).returns(projects)
|
334
|
+
FreshBooks::Project.find_by_name(@name).should be_nil
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
it 'should have a client' do
|
339
|
+
@project.should respond_to(:client)
|
340
|
+
end
|
341
|
+
|
342
|
+
describe 'client' do
|
343
|
+
it 'should find client based on client_id' do
|
344
|
+
client_id = stub('client ID')
|
345
|
+
@project.stubs(:client_id).returns(client_id)
|
346
|
+
FreshBooks::Client.expects(:get).with(client_id)
|
347
|
+
@project.client
|
348
|
+
end
|
349
|
+
|
350
|
+
it 'should return found client' do
|
351
|
+
client = stub('client')
|
352
|
+
client_id = stub('client ID')
|
353
|
+
@project.stubs(:client_id).returns(client_id)
|
354
|
+
FreshBooks::Client.stubs(:get).with(client_id).returns(client)
|
355
|
+
@project.client.should == client
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
it 'should have tasks' do
|
360
|
+
@project.should respond_to(:tasks)
|
361
|
+
end
|
362
|
+
|
363
|
+
describe 'tasks' do
|
364
|
+
it 'should list tasks based on project ID' do
|
365
|
+
project_id = stub('project ID')
|
366
|
+
@project.stubs(:project_id).returns(project_id)
|
367
|
+
FreshBooks::Task.expects(:list).with('project_id' => project_id)
|
368
|
+
@project.tasks
|
369
|
+
end
|
370
|
+
|
371
|
+
it 'should return found tasks' do
|
372
|
+
tasks = stub('tasks')
|
373
|
+
project_id = stub('project ID')
|
374
|
+
@project.stubs(:project_id).returns(project_id)
|
375
|
+
FreshBooks::Task.stubs(:list).with('project_id' => project_id).returns(tasks)
|
376
|
+
@project.tasks.should == tasks
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
it 'should have time entries' do
|
381
|
+
@project.should respond_to(:time_entries)
|
382
|
+
end
|
383
|
+
|
384
|
+
describe 'time entries' do
|
385
|
+
it 'should list time entries based on project ID' do
|
386
|
+
project_id = stub('project ID')
|
387
|
+
@project.stubs(:project_id).returns(project_id)
|
388
|
+
FreshBooks::TimeEntry.expects(:list).with('project_id' => project_id)
|
389
|
+
@project.time_entries
|
390
|
+
end
|
391
|
+
|
392
|
+
it 'should return found time entries' do
|
393
|
+
time_entries = stub('time entries')
|
394
|
+
project_id = stub('project ID')
|
395
|
+
@project.stubs(:project_id).returns(project_id)
|
396
|
+
FreshBooks::TimeEntry.stubs(:list).with('project_id' => project_id).returns(time_entries)
|
397
|
+
@project.time_entries.should == time_entries
|
398
|
+
end
|
399
|
+
end
|
400
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
begin
|
2
|
+
require 'spec'
|
3
|
+
rescue LoadError
|
4
|
+
require 'rubygems'
|
5
|
+
gem 'rspec'
|
6
|
+
require 'spec'
|
7
|
+
end
|
8
|
+
|
9
|
+
# this is my favorite way to require ever
|
10
|
+
begin
|
11
|
+
require 'mocha'
|
12
|
+
rescue LoadError
|
13
|
+
require 'rubygems'
|
14
|
+
gem 'mocha'
|
15
|
+
require 'mocha'
|
16
|
+
end
|
17
|
+
|
18
|
+
Spec::Runner.configure do |config|
|
19
|
+
config.mock_with :mocha
|
20
|
+
end
|
21
|
+
|
22
|
+
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
23
|
+
|
24
|
+
require 'freshtrack'
|