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