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.
@@ -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