timetrap 1.1.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/LICENSE.txt +23 -0
- data/README.md +183 -0
- data/Rakefile +60 -0
- data/VERSION.yml +4 -0
- data/bin/dev_t +4 -0
- data/bin/t +11 -0
- data/lib/timetrap/cli.rb +227 -0
- data/lib/timetrap/formatters/csv.rb +19 -0
- data/lib/timetrap/formatters/ical.rb +29 -0
- data/lib/timetrap/formatters/text.rb +55 -0
- data/lib/timetrap/helpers.rb +59 -0
- data/lib/timetrap/models.rb +80 -0
- data/lib/timetrap.rb +80 -0
- data/spec/timetrap_spec.rb +622 -0
- metadata +129 -0
@@ -0,0 +1,622 @@
|
|
1
|
+
TEST_MODE = true
|
2
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'timetrap')
|
3
|
+
require 'spec'
|
4
|
+
|
5
|
+
describe Timetrap do
|
6
|
+
def create_entry atts = {}
|
7
|
+
Timetrap::Entry.create({
|
8
|
+
:sheet => 'default',
|
9
|
+
:start => Time.now,
|
10
|
+
:end => Time.now,
|
11
|
+
:note => 'note'}.merge(atts))
|
12
|
+
end
|
13
|
+
|
14
|
+
before :each do
|
15
|
+
Timetrap::Entry.create_table!
|
16
|
+
Timetrap::Meta.create_table!
|
17
|
+
$stdout = StringIO.new
|
18
|
+
$stdin = StringIO.new
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'CLI' do
|
22
|
+
describe "COMMANDS" do
|
23
|
+
def invoke command
|
24
|
+
Timetrap::CLI.parse command
|
25
|
+
Timetrap::CLI.invoke
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'archive' do
|
29
|
+
before do
|
30
|
+
3.times do |i|
|
31
|
+
create_entry
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should put the entries in a hidden sheet" do
|
36
|
+
$stdin.string = "yes\n"
|
37
|
+
invoke 'archive'
|
38
|
+
Timetrap::Entry.each do |e|
|
39
|
+
e.sheet.should == '_default'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should leave the running entry alone" do
|
44
|
+
invoke "in"
|
45
|
+
$stdin.string = "yes\n"
|
46
|
+
invoke 'archive'
|
47
|
+
Timetrap::Entry.order(:id).last.sheet.should == 'default'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe 'edit' do
|
52
|
+
before do
|
53
|
+
Timetrap.start "running entry", nil
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should edit the description of the active period" do
|
57
|
+
Timetrap.active_entry.note.should == 'running entry'
|
58
|
+
invoke 'edit new description'
|
59
|
+
Timetrap.active_entry.note.should == 'new description'
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should edit the start time of the active period" do
|
63
|
+
invoke 'edit --start "yesterday 10am"'
|
64
|
+
Timetrap.active_entry.start.should == Chronic.parse("yesterday 10am")
|
65
|
+
Timetrap.active_entry.note.should == 'running entry'
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should edit the end time of the active period" do
|
69
|
+
entry = Timetrap.active_entry
|
70
|
+
invoke 'edit --end "yesterday 10am"'
|
71
|
+
entry.refresh.end.should == Chronic.parse("yesterday 10am")
|
72
|
+
entry.refresh.note.should == 'running entry'
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should edit a non running entry based on id" do
|
76
|
+
not_running = Timetrap.active_entry
|
77
|
+
Timetrap.stop
|
78
|
+
Timetrap.start "another entry", nil
|
79
|
+
invoke "edit --id #{not_running.id} a new description"
|
80
|
+
not_running.refresh.note.should == 'a new description'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "backend" do
|
85
|
+
it "should open an sqlite console to the db" do
|
86
|
+
Timetrap::CLI.should_receive(:exec).with("sqlite3 #{DB_NAME}")
|
87
|
+
invoke 'backend'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "display" do
|
92
|
+
before do
|
93
|
+
Timetrap::Entry.create( :sheet => 'another',
|
94
|
+
:note => 'entry 4', :start => '2008-10-05 18:00:00'
|
95
|
+
)
|
96
|
+
Timetrap::Entry.create( :sheet => 'SpecSheet',
|
97
|
+
:note => 'entry 2', :start => '2008-10-03 16:00:00', :end => '2008-10-03 18:00:00'
|
98
|
+
)
|
99
|
+
Timetrap::Entry.create( :sheet => 'SpecSheet',
|
100
|
+
:note => 'entry 1', :start => '2008-10-03 12:00:00', :end => '2008-10-03 14:00:00'
|
101
|
+
)
|
102
|
+
Timetrap::Entry.create( :sheet => 'SpecSheet',
|
103
|
+
:note => 'entry 3', :start => '2008-10-05 16:00:00', :end => '2008-10-05 18:00:00'
|
104
|
+
)
|
105
|
+
Timetrap::Entry.create( :sheet => 'SpecSheet',
|
106
|
+
:note => 'entry 4', :start => '2008-10-05 18:00:00'
|
107
|
+
)
|
108
|
+
|
109
|
+
Time.stub!(:now).and_return Time.at(1223254800 + (60*60*2))
|
110
|
+
@desired_output = <<-OUTPUT
|
111
|
+
Timesheet: SpecSheet
|
112
|
+
Day Start End Duration Notes
|
113
|
+
Fri Oct 03, 2008 12:00:00 - 14:00:00 2:00:00 entry 1
|
114
|
+
16:00:00 - 18:00:00 2:00:00 entry 2
|
115
|
+
4:00:00
|
116
|
+
Sun Oct 05, 2008 16:00:00 - 18:00:00 2:00:00 entry 3
|
117
|
+
18:00:00 - 2:00:00 entry 4
|
118
|
+
4:00:00
|
119
|
+
---------------------------------------------------------
|
120
|
+
Total 8:00:00
|
121
|
+
OUTPUT
|
122
|
+
|
123
|
+
@desired_output_with_ids = <<-OUTPUT
|
124
|
+
Timesheet: SpecSheet
|
125
|
+
Id Day Start End Duration Notes
|
126
|
+
3 Fri Oct 03, 2008 12:00:00 - 14:00:00 2:00:00 entry 1
|
127
|
+
2 16:00:00 - 18:00:00 2:00:00 entry 2
|
128
|
+
4:00:00
|
129
|
+
4 Sun Oct 05, 2008 16:00:00 - 18:00:00 2:00:00 entry 3
|
130
|
+
5 18:00:00 - 2:00:00 entry 4
|
131
|
+
4:00:00
|
132
|
+
---------------------------------------------------------
|
133
|
+
Total 8:00:00
|
134
|
+
OUTPUT
|
135
|
+
|
136
|
+
@desired_output_for_all = <<-OUTPUT
|
137
|
+
Timesheet: SpecSheet
|
138
|
+
Day Start End Duration Notes
|
139
|
+
Fri Oct 03, 2008 12:00:00 - 14:00:00 2:00:00 entry 1
|
140
|
+
16:00:00 - 18:00:00 2:00:00 entry 2
|
141
|
+
4:00:00
|
142
|
+
Sun Oct 05, 2008 16:00:00 - 18:00:00 2:00:00 entry 3
|
143
|
+
18:00:00 - 2:00:00 entry 4
|
144
|
+
4:00:00
|
145
|
+
---------------------------------------------------------
|
146
|
+
Total 8:00:00
|
147
|
+
|
148
|
+
Timesheet: another
|
149
|
+
Day Start End Duration Notes
|
150
|
+
Sun Oct 05, 2008 18:00:00 - 2:00:00 entry 4
|
151
|
+
2:00:00
|
152
|
+
---------------------------------------------------------
|
153
|
+
Total 2:00:00
|
154
|
+
-------------------------------------------------------------
|
155
|
+
Grand Total 10:00:00
|
156
|
+
OUTPUT
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should display the current timesheet" do
|
160
|
+
Timetrap.current_sheet = 'SpecSheet'
|
161
|
+
invoke 'display'
|
162
|
+
$stdout.string.should == @desired_output
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should display a non current timesheet" do
|
166
|
+
Timetrap.current_sheet = 'another'
|
167
|
+
invoke 'display SpecSheet'
|
168
|
+
$stdout.string.should == @desired_output
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should display a non current timesheet based on a partial name match" do
|
172
|
+
Timetrap.current_sheet = 'another'
|
173
|
+
invoke 'display S'
|
174
|
+
$stdout.string.should == @desired_output
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should display a timesheet with ids" do
|
178
|
+
invoke 'display S --ids'
|
179
|
+
$stdout.string.should == @desired_output_with_ids
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should display all timesheets" do
|
183
|
+
Timetrap.current_sheet = 'another'
|
184
|
+
invoke 'display all'
|
185
|
+
$stdout.string.should == @desired_output_for_all
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should not display archived for all timesheets" do
|
189
|
+
$stdin.string = "yes\n"
|
190
|
+
invoke 'archive SpecSheet'
|
191
|
+
$stdout.string = ''
|
192
|
+
invoke 'display all'
|
193
|
+
$stdout.string.should_not =~ /_SpecSheet/
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
describe "format" do
|
198
|
+
before do
|
199
|
+
create_entry(:start => '2008-10-03 12:00:00', :end => '2008-10-03 14:00:00')
|
200
|
+
create_entry(:start => '2008-10-05 12:00:00', :end => '2008-10-05 14:00:00')
|
201
|
+
end
|
202
|
+
describe 'csv' do
|
203
|
+
|
204
|
+
it "should not export running items" do
|
205
|
+
invoke 'in'
|
206
|
+
invoke 'format --format csv'
|
207
|
+
$stdout.string.should == <<-EOF
|
208
|
+
start,end,note
|
209
|
+
"2008-10-03 12:00:00","2008-10-03 14:00:00","note"
|
210
|
+
"2008-10-05 12:00:00","2008-10-05 14:00:00","note"
|
211
|
+
EOF
|
212
|
+
end
|
213
|
+
|
214
|
+
it "should filter events by the passed dates" do
|
215
|
+
invoke 'format --format csv --start 2008-10-03 --end 2008-10-03'
|
216
|
+
$stdout.string.should == <<-EOF
|
217
|
+
start,end,note
|
218
|
+
"2008-10-03 12:00:00","2008-10-03 14:00:00","note"
|
219
|
+
EOF
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should not filter events by date when none are passed" do
|
223
|
+
invoke 'format --format csv'
|
224
|
+
$stdout.string.should == <<-EOF
|
225
|
+
start,end,note
|
226
|
+
"2008-10-03 12:00:00","2008-10-03 14:00:00","note"
|
227
|
+
"2008-10-05 12:00:00","2008-10-05 14:00:00","note"
|
228
|
+
EOF
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
describe 'ical' do
|
233
|
+
|
234
|
+
it "should not export running items" do
|
235
|
+
invoke 'in'
|
236
|
+
invoke 'format --format ical'
|
237
|
+
$stdout.string.scan(/BEGIN:VEVENT/).should have(2).item
|
238
|
+
end
|
239
|
+
|
240
|
+
it "should filter events by the passed dates" do
|
241
|
+
invoke 'format --format ical --start 2008-10-03 --end 2008-10-03'
|
242
|
+
$stdout.string.scan(/BEGIN:VEVENT/).should have(1).item
|
243
|
+
end
|
244
|
+
|
245
|
+
it "should not filter events by date when none are passed" do
|
246
|
+
invoke 'format --format ical'
|
247
|
+
$stdout.string.scan(/BEGIN:VEVENT/).should have(2).item
|
248
|
+
end
|
249
|
+
|
250
|
+
it "should export a sheet to an ical format" do
|
251
|
+
invoke 'format --format ical --start 2008-10-03 --end 2008-10-03'
|
252
|
+
desired = <<-EOF
|
253
|
+
BEGIN:VCALENDAR
|
254
|
+
VERSION:2.0
|
255
|
+
CALSCALE:GREGORIAN
|
256
|
+
METHOD:PUBLISH
|
257
|
+
PRODID:iCalendar-Ruby
|
258
|
+
BEGIN:VEVENT
|
259
|
+
SEQUENCE:0
|
260
|
+
DTEND:20081003T140000
|
261
|
+
SUMMARY:note
|
262
|
+
DTSTART:20081003T120000
|
263
|
+
END:VEVENT
|
264
|
+
END:VCALENDAR
|
265
|
+
EOF
|
266
|
+
desired.each_line do |line|
|
267
|
+
$stdout.string.should =~ /#{line.chomp}/
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
describe "in" do
|
274
|
+
it "should start the time for the current timesheet" do
|
275
|
+
lambda do
|
276
|
+
invoke 'in'
|
277
|
+
end.should change(Timetrap::Entry, :count).by(1)
|
278
|
+
end
|
279
|
+
|
280
|
+
it "should set the note when starting a new entry" do
|
281
|
+
invoke 'in working on something'
|
282
|
+
Timetrap::Entry.order_by(:id).last.note.should == 'working on something'
|
283
|
+
end
|
284
|
+
|
285
|
+
it "should set the start when starting a new entry" do
|
286
|
+
@time = Time.now
|
287
|
+
Time.stub!(:now).and_return @time
|
288
|
+
invoke 'in working on something'
|
289
|
+
Timetrap::Entry.order_by(:id).last.start.to_i.should == @time.to_i
|
290
|
+
end
|
291
|
+
|
292
|
+
it "should not start the time if the timetrap is running" do
|
293
|
+
Timetrap.stub!(:running?).and_return true
|
294
|
+
lambda do
|
295
|
+
invoke 'in'
|
296
|
+
end.should_not change(Timetrap::Entry, :count)
|
297
|
+
end
|
298
|
+
|
299
|
+
it "should allow the sheet to be started at a certain time" do
|
300
|
+
invoke 'in work --at "10am 2008-10-03"'
|
301
|
+
Timetrap::Entry.order_by(:id).last.start.should == Time.parse('2008-10-03 10:00')
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
describe "kill" do
|
306
|
+
it "should give me a chance not to fuck up" do
|
307
|
+
entry = create_entry
|
308
|
+
lambda do
|
309
|
+
$stdin.string = ""
|
310
|
+
invoke "kill #{entry.sheet}"
|
311
|
+
end.should_not change(Timetrap::Entry, :count).by(-1)
|
312
|
+
end
|
313
|
+
|
314
|
+
it "should delete a timesheet" do
|
315
|
+
create_entry
|
316
|
+
entry = create_entry
|
317
|
+
lambda do
|
318
|
+
$stdin.string = "yes\n"
|
319
|
+
invoke "kill #{entry.sheet}"
|
320
|
+
end.should change(Timetrap::Entry, :count).by(-2)
|
321
|
+
end
|
322
|
+
|
323
|
+
it "should delete an entry" do
|
324
|
+
create_entry
|
325
|
+
entry = create_entry
|
326
|
+
lambda do
|
327
|
+
$stdin.string = "yes\n"
|
328
|
+
invoke "kill --id #{entry.id}"
|
329
|
+
end.should change(Timetrap::Entry, :count).by(-1)
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
describe "list" do
|
334
|
+
describe "with no sheets defined" do
|
335
|
+
it "should say that there are no sheets" do
|
336
|
+
invoke 'list'
|
337
|
+
$stdout.string.chomp.should == 'No sheets found'
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
describe "with sheets defined" do
|
342
|
+
before do
|
343
|
+
Time.stub!(:now).and_return Time.parse("Oct 5 18:00:00 -0700 2008")
|
344
|
+
create_entry( :sheet => 'A Longly Named Sheet 2', :start => '2008-10-03 12:00:00',
|
345
|
+
:end => '2008-10-03 14:00:00')
|
346
|
+
create_entry( :sheet => 'A Longly Named Sheet 2', :start => '2008-10-03 12:00:00',
|
347
|
+
:end => '2008-10-03 14:00:00')
|
348
|
+
create_entry( :sheet => 'A Longly Named Sheet 2', :start => '2008-10-05 12:00:00',
|
349
|
+
:end => '2008-10-05 14:00:00')
|
350
|
+
create_entry( :sheet => 'A Longly Named Sheet 2', :start => '2008-10-05 14:00:00',
|
351
|
+
:end => nil)
|
352
|
+
create_entry( :sheet => 'Sheet 1', :start => '2008-10-03 16:00:00',
|
353
|
+
:end => '2008-10-03 18:00:00')
|
354
|
+
Timetrap.current_sheet = 'A Longly Named Sheet 2'
|
355
|
+
end
|
356
|
+
it "should list available timesheets" do
|
357
|
+
invoke 'list'
|
358
|
+
$stdout.string.should == <<-OUTPUT
|
359
|
+
Timesheet Running Today Total Time
|
360
|
+
*A Longly Named Sheet 2 4:00:00 6:00:00 10:00:00
|
361
|
+
Sheet 1 0:00:00 0:00:00 2:00:00
|
362
|
+
OUTPUT
|
363
|
+
end
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
describe "now" do
|
368
|
+
before do
|
369
|
+
Timetrap.current_sheet = 'current sheet'
|
370
|
+
end
|
371
|
+
|
372
|
+
describe "when the current timesheet isn't running" do
|
373
|
+
it "should show that it isn't running" do
|
374
|
+
invoke 'now'
|
375
|
+
$stdout.string.should == <<-OUTPUT
|
376
|
+
current sheet: not running
|
377
|
+
OUTPUT
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
describe "when the current timesheet is running" do
|
382
|
+
before do
|
383
|
+
invoke 'in a timesheet that is running'
|
384
|
+
@entry = Timetrap.active_entry
|
385
|
+
@entry.stub!(:start).and_return(Time.at(0))
|
386
|
+
Time.stub!(:now).and_return Time.at(60)
|
387
|
+
Timetrap.stub!(:active_entry).and_return @entry
|
388
|
+
end
|
389
|
+
|
390
|
+
it "should show how long the current item is running for" do
|
391
|
+
invoke 'now'
|
392
|
+
$stdout.string.should == <<-OUTPUT
|
393
|
+
current sheet: 0:01:00 (a timesheet that is running)
|
394
|
+
OUTPUT
|
395
|
+
end
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
describe "out" do
|
400
|
+
before :each do
|
401
|
+
invoke 'in'
|
402
|
+
@active = Timetrap.active_entry
|
403
|
+
@now = Time.now
|
404
|
+
Time.stub!(:now).and_return @now
|
405
|
+
end
|
406
|
+
it "should set the stop for the running entry" do
|
407
|
+
@active.refresh.end.should == nil
|
408
|
+
invoke 'out'
|
409
|
+
@active.refresh.end.to_i.should == @now.to_i
|
410
|
+
end
|
411
|
+
|
412
|
+
it "should not do anything if nothing is running" do
|
413
|
+
lambda do
|
414
|
+
invoke 'out'
|
415
|
+
invoke 'out'
|
416
|
+
end.should_not raise_error
|
417
|
+
end
|
418
|
+
|
419
|
+
it "should allow the sheet to be stopped at a certain time" do
|
420
|
+
invoke 'out --at "10am 2008-10-03"'
|
421
|
+
Timetrap::Entry.order_by(:id).last.end.should == Time.parse('2008-10-03 10:00')
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
describe "running" do
|
426
|
+
it "should show all running timesheets" do
|
427
|
+
create_entry :sheet => 'one', :end => nil
|
428
|
+
create_entry :sheet => 'two', :end => nil
|
429
|
+
create_entry :sheet => 'three'
|
430
|
+
invoke 'running'
|
431
|
+
$stdout.string.should == "Running Timesheets:\n one: note\n two: note\n"
|
432
|
+
end
|
433
|
+
it "should show no runnig timesheets" do
|
434
|
+
invoke 'running'
|
435
|
+
$stdout.string.should == "Running Timesheets:\n"
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
describe "switch" do
|
440
|
+
it "should switch to a new timesheet" do
|
441
|
+
invoke 'switch sheet 1'
|
442
|
+
Timetrap.current_sheet.should == 'sheet 1'
|
443
|
+
invoke 'switch sheet 2'
|
444
|
+
Timetrap.current_sheet.should == 'sheet 2'
|
445
|
+
end
|
446
|
+
|
447
|
+
it "should not switch to an blank timesheet" do
|
448
|
+
invoke 'switch sheet 1'
|
449
|
+
invoke 'switch'
|
450
|
+
Timetrap.current_sheet.should == 'sheet 1'
|
451
|
+
end
|
452
|
+
end
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
describe "entries" do
|
457
|
+
it "should give the entires for a sheet" do
|
458
|
+
e = create_entry :sheet => 'sheet'
|
459
|
+
Timetrap.entries('sheet').all.should include(e)
|
460
|
+
end
|
461
|
+
|
462
|
+
end
|
463
|
+
|
464
|
+
describe "start" do
|
465
|
+
it "should start an new entry" do
|
466
|
+
@time = Time.now
|
467
|
+
Timetrap.current_sheet = 'sheet1'
|
468
|
+
lambda do
|
469
|
+
Timetrap.start 'some work', @time
|
470
|
+
end.should change(Timetrap::Entry, :count).by(1)
|
471
|
+
Timetrap::Entry.order(:id).last.sheet.should == 'sheet1'
|
472
|
+
Timetrap::Entry.order(:id).last.note.should == 'some work'
|
473
|
+
Timetrap::Entry.order(:id).last.start.to_i.should == @time.to_i
|
474
|
+
Timetrap::Entry.order(:id).last.end.should be_nil
|
475
|
+
end
|
476
|
+
|
477
|
+
it "should be running if it is started" do
|
478
|
+
Timetrap.should_not be_running
|
479
|
+
Timetrap.start 'some work', @time
|
480
|
+
Timetrap.should be_running
|
481
|
+
end
|
482
|
+
|
483
|
+
it "should raise and error if it is already running" do
|
484
|
+
lambda do
|
485
|
+
Timetrap.start 'some work', @time
|
486
|
+
Timetrap.start 'some work', @time
|
487
|
+
end.should change(Timetrap::Entry, :count).by(1)
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
describe "stop" do
|
492
|
+
it "should stop a new entry" do
|
493
|
+
@time = Time.now
|
494
|
+
Timetrap.start 'some work', @time
|
495
|
+
entry = Timetrap.active_entry
|
496
|
+
entry.end.should be_nil
|
497
|
+
Timetrap.stop @time
|
498
|
+
entry.refresh.end.to_i.should == @time.to_i
|
499
|
+
end
|
500
|
+
|
501
|
+
it "should not be running if it is stopped" do
|
502
|
+
Timetrap.should_not be_running
|
503
|
+
Timetrap.start 'some work', @time
|
504
|
+
Timetrap.stop
|
505
|
+
Timetrap.should_not be_running
|
506
|
+
end
|
507
|
+
|
508
|
+
it "should not stop it twice" do
|
509
|
+
Timetrap.start 'some work'
|
510
|
+
e = Timetrap.active_entry
|
511
|
+
Timetrap.stop
|
512
|
+
time = e.refresh.end
|
513
|
+
Timetrap.stop
|
514
|
+
time.to_i.should == e.refresh.end.to_i
|
515
|
+
end
|
516
|
+
|
517
|
+
end
|
518
|
+
|
519
|
+
describe 'switch' do
|
520
|
+
it "should switch to a new sheet" do
|
521
|
+
Timetrap.switch 'sheet1'
|
522
|
+
Timetrap.current_sheet.should == 'sheet1'
|
523
|
+
Timetrap.switch 'sheet2'
|
524
|
+
Timetrap.current_sheet.should == 'sheet2'
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
528
|
+
end
|
529
|
+
|
530
|
+
describe Timetrap::Entry do
|
531
|
+
describe "with an instance" do
|
532
|
+
before do
|
533
|
+
@time = Time.now
|
534
|
+
@entry = Timetrap::Entry.new
|
535
|
+
end
|
536
|
+
|
537
|
+
describe 'attributes' do
|
538
|
+
it "should have a note" do
|
539
|
+
@entry.note = "world takeover"
|
540
|
+
@entry.note.should == "world takeover"
|
541
|
+
end
|
542
|
+
|
543
|
+
it "should have a start" do
|
544
|
+
@entry.start = @time
|
545
|
+
@entry.start.should == @time
|
546
|
+
end
|
547
|
+
|
548
|
+
it "should have a end" do
|
549
|
+
@entry.end = @time
|
550
|
+
@entry.end.should == @time
|
551
|
+
end
|
552
|
+
|
553
|
+
it "should have a sheet" do
|
554
|
+
@entry.sheet= 'name'
|
555
|
+
@entry.sheet.should == 'name'
|
556
|
+
end
|
557
|
+
|
558
|
+
def with_global_round_set_to val
|
559
|
+
old_val = Timetrap::Entry.round
|
560
|
+
begin
|
561
|
+
Timetrap::Entry.round = val
|
562
|
+
block_return_value = yield
|
563
|
+
ensure
|
564
|
+
Timetrap::Entry.round = old_val
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
568
|
+
it "should use round start if the global round attribute is set" do
|
569
|
+
with_global_round_set_to true do
|
570
|
+
@time = Chronic.parse("12:55am")
|
571
|
+
@entry.start = @time
|
572
|
+
@entry.start.should == Chronic.parse("1am")
|
573
|
+
end
|
574
|
+
end
|
575
|
+
|
576
|
+
it "should use round start if the global round attribute is set" do
|
577
|
+
with_global_round_set_to true do
|
578
|
+
@time = Chronic.parse("12:50am")
|
579
|
+
@entry.start = @time
|
580
|
+
@entry.start.should == Chronic.parse("12:45am")
|
581
|
+
end
|
582
|
+
end
|
583
|
+
|
584
|
+
it "should have a rounded start" do
|
585
|
+
@time = Chronic.parse("12:50am")
|
586
|
+
@entry.start = @time
|
587
|
+
@entry.rounded_start.should == Chronic.parse("12:45am")
|
588
|
+
end
|
589
|
+
|
590
|
+
it "should not round nil times" do
|
591
|
+
@entry.start = nil
|
592
|
+
@entry.rounded_start.should be_nil
|
593
|
+
end
|
594
|
+
end
|
595
|
+
|
596
|
+
describe "parsing natural language times" do
|
597
|
+
it "should set start time using english" do
|
598
|
+
@entry.start = "yesterday 10am"
|
599
|
+
@entry.start.should_not be_nil
|
600
|
+
@entry.start.should == Chronic.parse("yesterday 10am")
|
601
|
+
end
|
602
|
+
|
603
|
+
it "should set end time using english" do
|
604
|
+
@entry.end = "tomorrow 1pm"
|
605
|
+
@entry.end.should_not be_nil
|
606
|
+
@entry.end.should == Chronic.parse("tomorrow 1pm")
|
607
|
+
end
|
608
|
+
end
|
609
|
+
end
|
610
|
+
|
611
|
+
describe '::sheets' do
|
612
|
+
it "should output a list of all the available sheets" do
|
613
|
+
Timetrap::Entry.create( :sheet => 'another',
|
614
|
+
:note => 'entry 4', :start => '2008-10-05 18:00:00'
|
615
|
+
)
|
616
|
+
Timetrap::Entry.create( :sheet => 'SpecSheet',
|
617
|
+
:note => 'entry 2', :start => '2008-10-03 16:00:00', :end => '2008-10-03 18:00:00'
|
618
|
+
)
|
619
|
+
Timetrap::Entry.sheets.should == %w(another SpecSheet).sort
|
620
|
+
end
|
621
|
+
end
|
622
|
+
end
|