freshtrack 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,35 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe Array do
4
+ it 'should be groupable' do
5
+ Array.new.should respond_to(:group_by)
6
+ end
7
+
8
+ describe 'when grouping' do
9
+ before :each do
10
+ @array = (1..10).to_a
11
+ end
12
+
13
+ it 'should require a block' do
14
+ lambda { @array.group_by }.should raise_error(ArgumentError)
15
+ end
16
+
17
+ it 'should accept a block' do
18
+ lambda { @array.group_by {} }.should_not raise_error(ArgumentError)
19
+ end
20
+
21
+ it 'should return a hash' do
22
+ @array.group_by {}.should be_kind_of(Hash)
23
+ end
24
+
25
+ it 'should group the elements by the return value of the block' do
26
+ [1,2,3,4,5,6,7,8,9,10]
27
+ expected = {
28
+ 0 => [3,6,9],
29
+ 1 => [1,4,7,10],
30
+ 2 => [2,5,8]
31
+ }
32
+ @array.group_by { |x| x % 3 }.should == expected
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,51 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ Thing = FreshBooks::BaseObject.new(:attr)
4
+ ThingDeal = FreshBooks::BaseObject.new(:attr)
5
+
6
+ describe FreshBooks::BaseObject do
7
+ it 'should have a mapping function for Date' do
8
+ FreshBooks::BaseObject::MAPPING_FNS[Date].should respond_to(:call)
9
+ end
10
+
11
+ describe 'Date mapping function' do
12
+ before :each do
13
+ @func = FreshBooks::BaseObject::MAPPING_FNS[Date]
14
+ @date = stub('date arg', :text => '2008-01-29')
15
+ end
16
+
17
+ it 'should return a date' do
18
+ @func.call(@date).should be_kind_of(Date)
19
+ end
20
+
21
+ it 'should return a date matching the text of its argument' do
22
+ @func.call(@date).to_s.should == @date.text
23
+ end
24
+ end
25
+
26
+ describe 'converting an instance to XML' do
27
+ before :each do
28
+ @thing = Thing.new
29
+ end
30
+
31
+ it 'should use the elem name' do
32
+ @thing.expects(:elem_name)
33
+ @thing.to_xml
34
+ end
35
+ end
36
+
37
+ describe 'getting the elem name' do
38
+ before :each do
39
+ @thing = Thing.new
40
+ @thing_deal = ThingDeal.new
41
+ end
42
+
43
+ it 'should be the class name, downcased' do
44
+ @thing.elem_name.should == 'thing'
45
+ end
46
+
47
+ it 'should be underscored if the class name has CamelCase' do
48
+ @thing_deal.elem_name.should == 'thing_deal'
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,566 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe Freshtrack do
4
+ describe 'loading configuration' do
5
+ before :each do
6
+ File.stubs(:read).returns('')
7
+ end
8
+
9
+ it 'should load the contents of the .freshtrack.yml file' do
10
+ File.stubs(:expand_path).with('~/.freshtrack.yml').returns('~/.freshtrack.yml')
11
+ File.expects(:read).with('~/.freshtrack.yml').returns('')
12
+ Freshtrack.load_config
13
+ end
14
+
15
+ it 'should turn the file contents into data' do
16
+ file_contents = stub('lorem ipsum')
17
+ File.stubs(:read).returns(file_contents)
18
+ YAML.expects(:load).with(file_contents)
19
+ Freshtrack.load_config
20
+ end
21
+
22
+ it 'should store the configuration data' do
23
+ config = stub('config data')
24
+ YAML.stubs(:load).returns(config)
25
+ Freshtrack.load_config
26
+ Freshtrack.config.should == config
27
+ end
28
+ end
29
+
30
+ describe 'getting configuration data' do
31
+ before :each do
32
+ @config = {}
33
+ Freshtrack.stubs(:config).returns(@config)
34
+ end
35
+
36
+ it 'should provide easy access to the company name' do
37
+ @config['company'] = company = stub('company name')
38
+ Freshtrack.company.should == company
39
+ end
40
+
41
+ it 'should provide easy access to the token' do
42
+ @config['token'] = token = stub('token')
43
+ Freshtrack.token.should == token
44
+ end
45
+
46
+ it 'should provide easy access to the project/task mapping' do
47
+ @config['project_task_mapping'] = project_task_mapping = stub('project/task mapping')
48
+ Freshtrack.project_task_mapping.should == project_task_mapping
49
+ end
50
+ end
51
+
52
+ describe 'initialization' do
53
+ before :each do
54
+ @company = 'zee_company_boss'
55
+ @token = 'token goes here'
56
+ Freshtrack.stubs(:load_config)
57
+ Freshtrack.stubs(:config).returns({ 'company' => @company, 'token' => @token })
58
+ end
59
+
60
+ it 'should load the configuration' do
61
+ Freshtrack.expects(:load_config)
62
+ Freshtrack.init
63
+ end
64
+
65
+ it 'should use the config data to set up FreshBooks' do
66
+ FreshBooks.expects(:setup).with("#{@company}.freshbooks.com", @token)
67
+ Freshtrack.init
68
+ end
69
+ end
70
+
71
+ describe 'getting project data' do
72
+ before :each do
73
+ @project_name = :proj
74
+ @project_task_mapping = { @project_name => { :project => 'fb proj', :task => 'fb task' } }
75
+ Freshtrack.stubs(:project_task_mapping).returns(@project_task_mapping)
76
+ @project = stub('project')
77
+ @task = stub('task')
78
+ FreshBooks::Project.stubs(:find_by_name).returns(@project)
79
+ FreshBooks::Task.stubs(:find_by_name).returns(@task)
80
+ end
81
+
82
+ it 'should require an argument' do
83
+ lambda { Freshtrack.get_project_data }.should raise_error(ArgumentError)
84
+ end
85
+ it 'should accept an argument' do
86
+ lambda { Freshtrack.get_project_data(@project_name) }.should_not raise_error(ArgumentError)
87
+ end
88
+
89
+ it 'should require the argument to be a valid project identifier' do
90
+ @project_task_mapping.delete(@project_name)
91
+ lambda { Freshtrack.get_project_data(@project_name) }.should raise_error
92
+ end
93
+
94
+ it 'should accept an argument that is a valid project identifier' do
95
+ lambda { Freshtrack.get_project_data(@project_name) }.should_not raise_error
96
+ end
97
+
98
+ it 'should get the indicated FreshBooks project' do
99
+ FreshBooks::Project.expects(:find_by_name).with(@project_task_mapping[@project_name][:project]).returns(@project)
100
+ Freshtrack.get_project_data(@project_name)
101
+ end
102
+
103
+ it 'should abort if no FreshBooks project found' do
104
+ FreshBooks::Project.stubs(:find_by_name).returns(nil)
105
+ lambda { Freshtrack.get_project_data(@project_name) }.should raise_error
106
+ end
107
+
108
+ it 'should provide easy access to the project' do
109
+ FreshBooks::Project.stubs(:find_by_name).returns(@project)
110
+ Freshtrack.get_project_data(@project_name)
111
+ Freshtrack.project.should == @project
112
+ end
113
+
114
+ it 'should get the indicated FreshBooks task' do
115
+ FreshBooks::Task.expects(:find_by_name).with(@project_task_mapping[@project_name][:task]).returns(@task)
116
+ Freshtrack.get_project_data(@project_name)
117
+ end
118
+
119
+ it 'should abort if no FreshBooks task found' do
120
+ FreshBooks::Task.stubs(:find_by_name).returns(nil)
121
+ lambda { Freshtrack.get_project_data(@project_name) }.should raise_error
122
+ end
123
+
124
+ it 'should provide easy access to the task' do
125
+ FreshBooks::Task.stubs(:find_by_name).returns(@task)
126
+ Freshtrack.get_project_data(@project_name)
127
+ Freshtrack.task.should == @task
128
+ end
129
+ end
130
+
131
+ describe 'getting time data' do
132
+ before :each do
133
+ @project_name = :proj
134
+ @time_data = stub('time data')
135
+ IO.stubs(:read).returns(@time_data)
136
+ Freshtrack.stubs(:convert_time_data)
137
+ end
138
+
139
+ it 'should require an argument' do
140
+ lambda { Freshtrack.get_time_data }.should raise_error(ArgumentError)
141
+ end
142
+
143
+ it 'should accept an argument' do
144
+ lambda { Freshtrack.get_time_data(@project_name) }.should_not raise_error(ArgumentError)
145
+ end
146
+
147
+ it 'should accept an option string' do
148
+ lambda { Freshtrack.get_time_data(@project_name, 'option string') }.should_not raise_error(ArgumentError)
149
+ end
150
+
151
+ it 'should get the time data (from punch)' do
152
+ IO.expects(:read).with(regexp_matches(/^\| punch list\b/))
153
+ Freshtrack.get_time_data(@project_name)
154
+ end
155
+
156
+ it 'should pass the supplied project when getting the time data' do
157
+ IO.expects(:read).with(regexp_matches(/\b#{@project_name}\b/))
158
+ Freshtrack.get_time_data(@project_name)
159
+ end
160
+
161
+ it 'should pass the supplied option string on when getting the time data' do
162
+ options = 'options go here'
163
+ IO.expects(:read).with(regexp_matches(/\b#{@project_name} #{options}\b/))
164
+ Freshtrack.get_time_data(@project_name, options)
165
+ end
166
+
167
+ it 'should default option string to empty string' do
168
+ IO.expects(:read).with(regexp_matches(/\b#{@project_name} $/))
169
+ Freshtrack.get_time_data(@project_name)
170
+ end
171
+
172
+ it 'should convert the time data' do
173
+ Freshtrack.expects(:convert_time_data).with(@time_data)
174
+ Freshtrack.get_time_data(@project_name)
175
+ end
176
+
177
+ it 'should return the converted data' do
178
+ converted = stub('converted time data')
179
+ Freshtrack.stubs(:convert_time_data).returns(converted)
180
+ Freshtrack.get_time_data(@project_name).should == converted
181
+ end
182
+ end
183
+
184
+ describe 'converting time data' do
185
+ before :each do
186
+ @time_data = stub('time data')
187
+ YAML.stubs(:load)
188
+ Freshtrack.stubs(:condense_time_data)
189
+ end
190
+
191
+ it 'should require an argument' do
192
+ lambda { Freshtrack.convert_time_data }.should raise_error(ArgumentError)
193
+ end
194
+
195
+ it 'should accept an argument' do
196
+ lambda { Freshtrack.convert_time_data(@time_data) }.should_not raise_error(ArgumentError)
197
+ end
198
+
199
+ it 'should convert the time data from YAML' do
200
+ YAML.expects(:load).with(@time_data)
201
+ Freshtrack.convert_time_data(@time_data)
202
+ end
203
+
204
+ it 'should condense the raw data' do
205
+ raw = stub('raw time data')
206
+ YAML.stubs(:load).returns(raw)
207
+ Freshtrack.expects(:condense_time_data).with(raw)
208
+ Freshtrack.convert_time_data(@project_name)
209
+ end
210
+
211
+ it 'should return the condensed data' do
212
+ condensed = stub('condensed time data')
213
+ Freshtrack.stubs(:condense_time_data).returns(condensed)
214
+ Freshtrack.convert_time_data(@time_data).should == condensed
215
+ end
216
+ end
217
+
218
+ describe 'condensing time data' do
219
+ before :each do
220
+ @time_data = stub('time data')
221
+ Freshtrack.stubs(:times_to_dates)
222
+ Freshtrack.stubs(:group_date_data)
223
+ end
224
+
225
+ it 'should require an argument' do
226
+ lambda { Freshtrack.condense_time_data }.should raise_error(ArgumentError)
227
+ end
228
+
229
+ it 'should accept an argument' do
230
+ lambda { Freshtrack.condense_time_data(@time_data) }.should_not raise_error(ArgumentError)
231
+ end
232
+
233
+ it 'should convert times to dates and hour differences' do
234
+ Freshtrack.expects(:times_to_dates).with(@time_data)
235
+ Freshtrack.condense_time_data(@time_data)
236
+ end
237
+
238
+ it 'should group date and hour differences' do
239
+ date_hour_data = stub('date/hour data')
240
+ Freshtrack.stubs(:times_to_dates).returns(date_hour_data)
241
+ Freshtrack.expects(:group_date_data).with(date_hour_data)
242
+ Freshtrack.condense_time_data(@time_data)
243
+ end
244
+
245
+ it 'should return the grouped date/hour data' do
246
+ grouped_dates = stub('grouped date/hour data')
247
+ Freshtrack.stubs(:group_date_data).returns(grouped_dates)
248
+ Freshtrack.condense_time_data(@time_data).should == grouped_dates
249
+ end
250
+ end
251
+
252
+ describe 'converting times to dates and hour differences' do
253
+ before :each do
254
+ @time_data = []
255
+ end
256
+
257
+ it 'should require an argument' do
258
+ lambda { Freshtrack.times_to_dates }.should raise_error(ArgumentError)
259
+ end
260
+
261
+ it 'should accept an argument' do
262
+ lambda { Freshtrack.times_to_dates(@time_data) }.should_not raise_error(ArgumentError)
263
+ end
264
+
265
+ it 'should return an array' do
266
+ Freshtrack.times_to_dates(@time_data).should be_kind_of(Array)
267
+ end
268
+
269
+ it 'should replace the in/out time data with a single date' do
270
+ @time_data.push({ 'in' => Time.local(2008, 1, 25, 6, 25, 0), 'out' => Time.local(2008, 1, 25, 7, 25, 0) })
271
+ result = Freshtrack.times_to_dates(@time_data)
272
+ result = result.first
273
+
274
+ result.should have_key('date')
275
+ result.should_not have_key('in')
276
+ result.should_not have_key('out')
277
+ end
278
+
279
+ it 'should make the date appopriate to the time' do
280
+ @time_data.push({ 'in' => Time.local(2008, 1, 25, 6, 25, 0), 'out' => Time.local(2008, 1, 25, 7, 25, 0) })
281
+ result = Freshtrack.times_to_dates(@time_data)
282
+ result = result.first
283
+ result['date'].should == Date.civil(2008, 1, 25)
284
+ end
285
+
286
+ it 'should use the in time date' do
287
+ @time_data.push({ 'in' => Time.local(2008, 1, 25, 6, 25, 0), 'out' => Time.local(2008, 1, 26, 7, 25, 0) })
288
+ result = Freshtrack.times_to_dates(@time_data)
289
+ result = result.first
290
+ result['date'].should == Date.civil(2008, 1, 25)
291
+ end
292
+
293
+ it 'should add hour data' do
294
+ @time_data.push({ 'in' => Time.local(2008, 1, 25, 6, 25, 0), 'out' => Time.local(2008, 1, 25, 7, 25, 0) })
295
+ result = Freshtrack.times_to_dates(@time_data)
296
+ result = result.first
297
+ result.should have_key('hours')
298
+ end
299
+
300
+ it 'should make the hour data appropriate to the in/out difference' do
301
+ @time_data.push({ 'in' => Time.local(2008, 1, 25, 6, 25, 0), 'out' => Time.local(2008, 1, 25, 7, 55, 0) })
302
+ result = Freshtrack.times_to_dates(@time_data)
303
+ result = result.first
304
+ result['hours'].should == 1.5
305
+ end
306
+ end
307
+
308
+ describe 'grouping date data' do
309
+ before :each do
310
+ @date_data = []
311
+ end
312
+
313
+ it 'should require an argument' do
314
+ lambda { Freshtrack.group_date_data }.should raise_error(ArgumentError)
315
+ end
316
+
317
+ it 'should accept an argument' do
318
+ lambda { Freshtrack.group_date_data(@date_data) }.should_not raise_error(ArgumentError)
319
+ end
320
+
321
+ it 'should return an array' do
322
+ Freshtrack.group_date_data(@date_data).should be_kind_of(Array)
323
+ end
324
+
325
+ it 'should group the data by date' do
326
+ today = Date.today
327
+ @date_data.push({ 'date' => today, 'hours' => 0, 'log' => [] })
328
+ @date_data.push({ 'date' => today, 'hours' => 0, 'log' => [] })
329
+ @date_data.push({ 'date' => today + 1, 'hours' => 0, 'log' => [] })
330
+ Freshtrack.group_date_data(@date_data).collect { |x| x['date'] }.should == [today, today + 1]
331
+ end
332
+
333
+ it 'should return the array sorted by date' do
334
+ today = Date.today
335
+ @date_data.push({ 'date' => today + 1, 'hours' => 0, 'log' => [] })
336
+ @date_data.push({ 'date' => today - 1, 'hours' => 0, 'log' => [] })
337
+ @date_data.push({ 'date' => today, 'hours' => 0, 'log' => [] })
338
+ @date_data.push({ 'date' => today + 1, 'hours' => 0, 'log' => [] })
339
+ Freshtrack.group_date_data(@date_data).collect { |x| x['date'] }.should == [today - 1, today, today + 1]
340
+ end
341
+
342
+ it 'should add the hours for a particular date' do
343
+ today = Date.today
344
+ @date_data.push({ 'date' => today, 'hours' => 1, 'log' => [] })
345
+ @date_data.push({ 'date' => today, 'hours' => 3, 'log' => [] })
346
+ @date_data.push({ 'date' => today + 1, 'hours' => 2, 'log' => [] })
347
+ result = Freshtrack.group_date_data(@date_data)
348
+
349
+ result[0]['date'].should == today
350
+ result[0]['hours'].should == 4
351
+
352
+ result[1]['date'].should == today + 1
353
+ result[1]['hours'].should == 2
354
+ end
355
+
356
+ it 'should round the hours to two decimal places' do
357
+ today = Date.today
358
+ @date_data.push({ 'date' => today, 'hours' => 1.666666666, 'log' => [] })
359
+ result = Freshtrack.group_date_data(@date_data)
360
+
361
+ result[0]['date'].should == today
362
+ result[0]['hours'].should == 1.67
363
+ end
364
+
365
+ it 'should join the log into notes' do
366
+ today = Date.today
367
+ @date_data.push({ 'date' => today, 'hours' => 0, 'log' => ['punch in 1', 'punch out 1'] })
368
+ @date_data.push({ 'date' => today, 'hours' => 0, 'log' => ['punch in 2', 'punch out 2'] })
369
+ @date_data.push({ 'date' => today + 1, 'hours' => 0, 'log' => ['punch in 3', 'punch out 3'] })
370
+ result = Freshtrack.group_date_data(@date_data)
371
+
372
+ result[0]['date'].should == today
373
+ result[0]['notes'].should == "punch in 1\npunch out 1\n--------------------\npunch in 2\npunch out 2"
374
+ result[0].should_not have_key('log')
375
+
376
+ result[1]['date'].should == today + 1
377
+ result[1]['notes'].should == "punch in 3\npunch out 3"
378
+ result[1].should_not have_key('log')
379
+ end
380
+ end
381
+
382
+ describe 'getting data' do
383
+ before :each do
384
+ @project_name = :proj
385
+ Freshtrack.stubs(:get_project_data)
386
+ Freshtrack.stubs(:get_time_data)
387
+ end
388
+
389
+ it 'should require an argument' do
390
+ lambda { Freshtrack.get_data }.should raise_error(ArgumentError)
391
+ end
392
+
393
+ it 'should accept an argument' do
394
+ lambda { Freshtrack.get_data(@project_name) }.should_not raise_error(ArgumentError)
395
+ end
396
+
397
+ it 'should accept an option string' do
398
+ lambda { Freshtrack.get_data(@project_name, 'option string') }.should_not raise_error(ArgumentError)
399
+ end
400
+
401
+ it 'should get project data for supplied project' do
402
+ Freshtrack.expects(:get_project_data).with(@project_name)
403
+ Freshtrack.get_data(@project_name)
404
+ end
405
+
406
+ it 'should get time data for supplied project' do
407
+ Freshtrack.expects(:get_time_data).with(@project_name, anything)
408
+ Freshtrack.get_data(@project_name)
409
+ end
410
+
411
+ it 'should pass option string on when getting time data' do
412
+ options = 'here be options'
413
+ Freshtrack.expects(:get_time_data).with(@project_name, options)
414
+ Freshtrack.get_data(@project_name, options)
415
+ end
416
+
417
+ it 'should default option string to empty string' do
418
+ Freshtrack.expects(:get_time_data).with(@project_name, '')
419
+ Freshtrack.get_data(@project_name)
420
+ end
421
+
422
+ it 'should return time data' do
423
+ time_data = stub('time data')
424
+ Freshtrack.stubs(:get_time_data).returns(time_data)
425
+ Freshtrack.get_data(@project_name).should == time_data
426
+ end
427
+ end
428
+
429
+ describe 'tracking time' do
430
+ before :each do
431
+ @project_name = :proj
432
+ @data = []
433
+ Freshtrack.stubs(:get_data).returns(@data)
434
+ end
435
+
436
+ it 'should require an argument' do
437
+ lambda { Freshtrack.track }.should raise_error(ArgumentError)
438
+ end
439
+
440
+ it 'should accept an argument' do
441
+ lambda { Freshtrack.track(@project_name) }.should_not raise_error(ArgumentError)
442
+ end
443
+
444
+ it 'should accept an option string' do
445
+ lambda { Freshtrack.track(@project_name, 'option string') }.should_not raise_error(ArgumentError)
446
+ end
447
+
448
+ it 'should get data for supplied project' do
449
+ Freshtrack.expects(:get_data).with(@project_name, anything).returns(@data)
450
+ Freshtrack.track(@project_name)
451
+ end
452
+
453
+ it 'should pass option string on when getting data' do
454
+ options = 'here be options'
455
+ Freshtrack.expects(:get_data).with(@project_name, options).returns(@data)
456
+ Freshtrack.track(@project_name, options)
457
+ end
458
+
459
+ it 'should default option string to empty string' do
460
+ Freshtrack.expects(:get_data).with(@project_name, '').returns(@data)
461
+ Freshtrack.track(@project_name)
462
+ end
463
+
464
+ it 'should create entries for project data' do
465
+ 2.times do
466
+ ent = stub('entry data')
467
+ @data.push(ent)
468
+ Freshtrack.expects(:create_entry).with(ent)
469
+ end
470
+ Freshtrack.track(@project_name)
471
+ end
472
+ end
473
+
474
+ describe 'creating an entry' do
475
+ before :each do
476
+ @date = Date.today - 3
477
+ @hours = 5.67
478
+ @notes = 'notes for the time entry'
479
+ @entry_data = { 'date' => @date, 'hours' => @hours, 'notes' => @notes }
480
+ @time_entry = stub('time entry', :project_id= => nil, :task_id= => nil, :date= => nil, :hours= => nil, :notes= => nil, :create => true)
481
+ FreshBooks::TimeEntry.stubs(:new).returns(@time_entry)
482
+
483
+ @project = stub('project', :project_id => stub('project id'))
484
+ @task = stub('task', :task_id => stub('task id'))
485
+ Freshtrack.stubs(:project).returns(@project)
486
+ Freshtrack.stubs(:task).returns(@task)
487
+
488
+ STDERR.stubs(:puts)
489
+ end
490
+
491
+ it 'should require an argument' do
492
+ lambda { Freshtrack.create_entry }.should raise_error(ArgumentError)
493
+ end
494
+
495
+ it 'should accept an argument' do
496
+ lambda { Freshtrack.create_entry(@entry_data) }.should_not raise_error(ArgumentError)
497
+ end
498
+
499
+ it 'should instantiate a new time entry' do
500
+ FreshBooks::TimeEntry.expects(:new).returns(@time_entry)
501
+ Freshtrack.create_entry(@entry_data)
502
+ end
503
+
504
+ describe 'with the time entry instance' do
505
+ it 'should set the project' do
506
+ @time_entry.expects(:project_id=).with(@project.project_id)
507
+ Freshtrack.create_entry(@entry_data)
508
+ end
509
+
510
+ it 'should set the task' do
511
+ @time_entry.expects(:task_id=).with(@task.task_id)
512
+ Freshtrack.create_entry(@entry_data)
513
+ end
514
+
515
+ it 'should set the date' do
516
+ @time_entry.expects(:date=).with(@date)
517
+ Freshtrack.create_entry(@entry_data)
518
+ end
519
+
520
+ it 'should set the hours' do
521
+ @time_entry.expects(:hours=).with(@hours)
522
+ Freshtrack.create_entry(@entry_data)
523
+ end
524
+
525
+ it 'should set the notes' do
526
+ @time_entry.expects(:notes=).with(@notes)
527
+ Freshtrack.create_entry(@entry_data)
528
+ end
529
+ end
530
+
531
+ it 'should create the time entry' do
532
+ @time_entry.expects(:create)
533
+ Freshtrack.create_entry(@entry_data)
534
+ end
535
+
536
+ describe 'successfully' do
537
+ before :each do
538
+ @time_entry.stubs(:create).returns(5)
539
+ end
540
+
541
+ it 'should be silent' do
542
+ STDERR.expects(:puts).never
543
+ Freshtrack.create_entry(@entry_data)
544
+ end
545
+
546
+ it 'should return true' do
547
+ Freshtrack.create_entry(@entry_data).should be(true)
548
+ end
549
+ end
550
+
551
+ describe 'unsuccessfully' do
552
+ before :each do
553
+ @time_entry.stubs(:create).returns(nil)
554
+ end
555
+
556
+ it 'should output an indication' do
557
+ STDERR.expects(:puts).with(regexp_matches(/#{@date.to_s}/))
558
+ Freshtrack.create_entry(@entry_data)
559
+ end
560
+
561
+ it 'should return nil' do
562
+ Freshtrack.create_entry(@entry_data).should be_nil
563
+ end
564
+ end
565
+ end
566
+ end
@@ -0,0 +1,21 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe Integer do
4
+ it 'should be convertible from seconds to hours' do
5
+ 90.should respond_to(:secs_to_hours)
6
+ end
7
+
8
+ it 'should return this number of seconds as an amount of hours' do
9
+ 90.secs_to_hours.should == 0.025
10
+ end
11
+ end
12
+
13
+ describe Float do
14
+ it 'should be convertible from seconds to hours' do
15
+ 90.0.should respond_to(:secs_to_hours)
16
+ end
17
+
18
+ it 'should return this number of seconds as an amount of hours' do
19
+ 90.0.secs_to_hours.should == 0.025
20
+ end
21
+ end