timetrap 1.15.1 → 1.15.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +6 -3
- data/CONTRIBUTORS +1 -0
- data/README.md +5 -5
- data/lib/timetrap.rb +1 -0
- data/lib/timetrap/cli.rb +5 -1
- data/lib/timetrap/helpers.rb +6 -6
- data/lib/timetrap/models.rb +1 -20
- data/lib/timetrap/schema.rb +47 -0
- data/lib/timetrap/version.rb +1 -1
- data/spec/timetrap_spec.rb +256 -250
- data/timetrap.gemspec +8 -8
- metadata +43 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f48cd84b986337e9398f94f74021e05b2c9c9c04b5c89a24bad5c143d43dfc34
|
4
|
+
data.tar.gz: 44fc2b5138062fefabb94d4c482b019334a5a529ae3451a6815a5f97de611c2e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dbc8022b3c79514daf37aba54db6c73b389960d287acb2ac5fda085765bf3527f3640c368dbe4e5d3da3b750cf65fd8bdd8cec087264974605fda092f87960a7
|
7
|
+
data.tar.gz: 6cc7de1ae316c5172faa5bf6efdee26e27e45c60cac0440b8a63b3f81fb88617c4cfab89e2f8ced73676e248568a49bb6ee4cb422f836cc238ed5fbb20a0b93a
|
data/.travis.yml
CHANGED
data/CONTRIBUTORS
CHANGED
data/README.md
CHANGED
@@ -113,7 +113,7 @@ Command line flags also have short versions.
|
|
113
113
|
$ # equivalent to the command above
|
114
114
|
$ t i -a "5 minutes ago"
|
115
115
|
|
116
|
-
You can consult the Chronic gem (
|
116
|
+
You can consult the Chronic gem (https://github.com/mojombo/chronic) for a full
|
117
117
|
list of parsable time formats, but all of these should work.
|
118
118
|
|
119
119
|
$ t out --at "in 30 minutes"
|
@@ -308,7 +308,7 @@ Commands
|
|
308
308
|
--------
|
309
309
|
|
310
310
|
**archive**
|
311
|
-
|
311
|
+
Archive the selected entries (by moving them to a sheet called ``_[SHEET]``)
|
312
312
|
These entries can be seen by running ``t display _[SHEET]``.
|
313
313
|
|
314
314
|
usage: ``t archive [--start DATE] [--end DATE] [--grep REGEX] [SHEET]``
|
@@ -320,8 +320,8 @@ Commands
|
|
320
320
|
usage: ``t backend``
|
321
321
|
|
322
322
|
**configure**
|
323
|
-
|
324
|
-
one doesn't exist. If one does exist
|
323
|
+
Create a config file at ``~/.timetrap.yml`` or ``ENV['TIMETRAP_CONFIG_FILE']`` if
|
324
|
+
one doesn't exist. If one does exist, update it with new
|
325
325
|
configuration options preserving any user overrides. Prints path to config
|
326
326
|
file. This file may contain ERB.
|
327
327
|
|
@@ -344,7 +344,7 @@ Commands
|
|
344
344
|
usage: ``t display [--ids] [--round] [--start DATE] [--end DATE] [--format FMT] [--grep REGEX] [SHEET | all | full]``
|
345
345
|
|
346
346
|
**edit**
|
347
|
-
|
347
|
+
Insert a note associated with the an entry in the timesheet, or edit the
|
348
348
|
start or end times. Defaults to the current entry, or previously running
|
349
349
|
entry. An ``--id`` flag can be passed with the entry's id (see display.)
|
350
350
|
|
data/lib/timetrap.rb
CHANGED
data/lib/timetrap/cli.rb
CHANGED
@@ -388,7 +388,11 @@ COMMAND is one of:
|
|
388
388
|
end
|
389
389
|
|
390
390
|
Timer.current_sheet = sheet
|
391
|
-
|
391
|
+
if Timer.last_sheet == sheet
|
392
|
+
warn "Already on sheet #{sheet.inspect}"
|
393
|
+
else
|
394
|
+
warn "Switching to sheet #{sheet.inspect}"
|
395
|
+
end
|
392
396
|
end
|
393
397
|
|
394
398
|
def list
|
data/lib/timetrap/helpers.rb
CHANGED
@@ -40,16 +40,16 @@ module Timetrap
|
|
40
40
|
|
41
41
|
def selected_entries
|
42
42
|
ee = if (sheet = sheet_name_from_string(unused_args)) == 'all'
|
43
|
-
Timetrap::Entry.
|
43
|
+
Timetrap::Entry.where(Sequel.lit('sheet not like ? escape "!"', '!_%'))
|
44
44
|
elsif (sheet = sheet_name_from_string(unused_args)) == 'full'
|
45
|
-
|
45
|
+
Timetrap::Entry.where()
|
46
46
|
elsif sheet =~ /.+/
|
47
|
-
Timetrap::Entry.
|
47
|
+
Timetrap::Entry.where(sheet: sheet)
|
48
48
|
else
|
49
|
-
Timetrap::Entry.
|
49
|
+
Timetrap::Entry.where(sheet: Timer.current_sheet)
|
50
50
|
end
|
51
|
-
ee = ee.filter('start >= ?', Date.parse(Timer.process_time(args['-s']).to_s)) if args['-s']
|
52
|
-
ee = ee.filter('start <= ?', Date.parse(Timer.process_time(args['-e']).to_s) + 1) if args['-e']
|
51
|
+
ee = ee.filter(Sequel.lit('start >= ?', Date.parse(Timer.process_time(args['-s']).to_s))) if args['-s']
|
52
|
+
ee = ee.filter(Sequel.lit('start <= ?', Date.parse(Timer.process_time(args['-e']).to_s) + 1)) if args['-e']
|
53
53
|
ee = ee.order(:start)
|
54
54
|
if args['-g']
|
55
55
|
re = Regexp::new(args['-g'])
|
data/lib/timetrap/models.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
module Timetrap
|
2
2
|
class Entry < Sequel::Model
|
3
|
-
plugin :schema
|
4
|
-
|
5
3
|
class << self
|
6
4
|
# a class level instance variable that controls whether or not all entries
|
7
5
|
# should respond to #start and #end with times rounded to 15 minute
|
@@ -68,27 +66,10 @@ module Timetrap
|
|
68
66
|
end
|
69
67
|
|
70
68
|
private
|
71
|
-
|
72
|
-
set_schema do
|
73
|
-
primary_key :id
|
74
|
-
column :note, String
|
75
|
-
column :start, DateTime
|
76
|
-
column :end, DateTime
|
77
|
-
column :sheet, String
|
78
|
-
end
|
79
|
-
create_table unless table_exists?
|
69
|
+
|
80
70
|
end
|
81
71
|
|
82
72
|
class Meta < Sequel::Model(:meta)
|
83
|
-
plugin :schema
|
84
|
-
|
85
|
-
set_schema do
|
86
|
-
primary_key :id
|
87
|
-
column :key, String
|
88
|
-
column :value, String
|
89
|
-
end
|
90
|
-
create_table unless table_exists?
|
91
|
-
|
92
73
|
def value
|
93
74
|
self[:value].to_s
|
94
75
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# Defines the table schemas. Acts as migration.
|
2
|
+
#
|
3
|
+
# Npte the executing below the classes. These create the tables
|
4
|
+
module Timetrap
|
5
|
+
class Schema
|
6
|
+
def self.create_table!
|
7
|
+
DB.drop_table(self::TABLE)
|
8
|
+
create_table
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.create_table
|
12
|
+
self.new.create_table
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.try_create_table
|
16
|
+
create_table unless DB.table_exists?(self::TABLE)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class EntrySchema < Schema
|
21
|
+
TABLE = :entries
|
22
|
+
def create_table
|
23
|
+
DB.create_table(TABLE) do
|
24
|
+
primary_key :id
|
25
|
+
column :note, String
|
26
|
+
column :start, DateTime
|
27
|
+
column :end, DateTime
|
28
|
+
column :sheet, String
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class MetaSchema < Schema
|
34
|
+
TABLE = :meta
|
35
|
+
def create_table
|
36
|
+
DB.create_table(TABLE) do
|
37
|
+
primary_key :id
|
38
|
+
column :key, String
|
39
|
+
column :value, String
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
## Executes the schema, acting as a small migration
|
45
|
+
EntrySchema.try_create_table
|
46
|
+
MetaSchema.try_create_table
|
47
|
+
end
|
data/lib/timetrap/version.rb
CHANGED
data/spec/timetrap_spec.rb
CHANGED
@@ -26,7 +26,7 @@ end
|
|
26
26
|
module Timetrap::StubConfig
|
27
27
|
def with_stubbed_config options = {}
|
28
28
|
defaults = Timetrap::Config.defaults.dup
|
29
|
-
Timetrap::Config.
|
29
|
+
allow(Timetrap::Config).to receive(:[]) do |k|
|
30
30
|
defaults.merge(options)[k]
|
31
31
|
end
|
32
32
|
yield if block_given?
|
@@ -46,10 +46,9 @@ describe Timetrap do
|
|
46
46
|
:note => 'note'}.merge(atts))
|
47
47
|
end
|
48
48
|
|
49
|
-
|
50
49
|
before :each do
|
51
|
-
Timetrap::
|
52
|
-
Timetrap::
|
50
|
+
Timetrap::EntrySchema.create_table!
|
51
|
+
Timetrap::MetaSchema.create_table!
|
53
52
|
$stdout = StringIO.new
|
54
53
|
$stdin = StringIO.new
|
55
54
|
$stderr = StringIO.new
|
@@ -66,7 +65,7 @@ describe Timetrap do
|
|
66
65
|
it "should invoke --help" do
|
67
66
|
with_stubbed_config('default_command' => nil) do
|
68
67
|
invoke ''
|
69
|
-
$stdout.string.
|
68
|
+
expect($stdout.string).to include "Usage"
|
70
69
|
end
|
71
70
|
end
|
72
71
|
end
|
@@ -75,7 +74,7 @@ describe Timetrap do
|
|
75
74
|
it "should invoke the default command" do
|
76
75
|
with_stubbed_config('default_command' => 'n') do
|
77
76
|
invoke ''
|
78
|
-
$stderr.string.
|
77
|
+
expect($stderr.string).to include('*default: not running')
|
79
78
|
end
|
80
79
|
end
|
81
80
|
|
@@ -84,7 +83,7 @@ describe Timetrap do
|
|
84
83
|
invoke 'in foo bar'
|
85
84
|
invoke 'out'
|
86
85
|
invoke ''
|
87
|
-
$stdout.string.
|
86
|
+
expect($stdout.string).to include(',"foo bar"')
|
88
87
|
end
|
89
88
|
end
|
90
89
|
end
|
@@ -92,7 +91,7 @@ describe Timetrap do
|
|
92
91
|
describe 'with an invalid command' do
|
93
92
|
it "should tell me I'm wrong" do
|
94
93
|
invoke 'poo'
|
95
|
-
$stderr.string.
|
94
|
+
expect($stderr.string).to include 'Invalid command: "poo"'
|
96
95
|
end
|
97
96
|
end
|
98
97
|
|
@@ -112,9 +111,9 @@ describe Timetrap do
|
|
112
111
|
invoke 'archive --grep [g][r][e][p]'
|
113
112
|
Timetrap::Entry.each do |e|
|
114
113
|
if e.note == 'grep'
|
115
|
-
e.sheet.
|
114
|
+
expect(e.sheet).to eq '_default'
|
116
115
|
else
|
117
|
-
e.sheet.
|
116
|
+
expect(e.sheet).to eq 'default'
|
118
117
|
end
|
119
118
|
end
|
120
119
|
end
|
@@ -123,7 +122,7 @@ describe Timetrap do
|
|
123
122
|
$stdin.string = "yes\n"
|
124
123
|
invoke 'archive'
|
125
124
|
Timetrap::Entry.each do |e|
|
126
|
-
e.sheet.
|
125
|
+
expect(e.sheet).to eq '_default'
|
127
126
|
end
|
128
127
|
end
|
129
128
|
|
@@ -131,7 +130,7 @@ describe Timetrap do
|
|
131
130
|
invoke "in"
|
132
131
|
$stdin.string = "yes\n"
|
133
132
|
invoke 'archive'
|
134
|
-
Timetrap::Entry.order(:id).last.sheet.
|
133
|
+
expect(Timetrap::Entry.order(:id).last.sheet).to eq 'default'
|
135
134
|
end
|
136
135
|
end
|
137
136
|
|
@@ -141,16 +140,16 @@ describe Timetrap do
|
|
141
140
|
FileUtils.mkdir_p(ENV['HOME'])
|
142
141
|
config_file = ENV['HOME'] + '/.timetrap.yml'
|
143
142
|
FileUtils.rm(config_file) if File.exist? config_file
|
144
|
-
File.exist?(config_file).
|
143
|
+
expect(File.exist?(config_file)).to be_falsey
|
145
144
|
invoke "configure"
|
146
|
-
File.exist?(config_file).
|
145
|
+
expect(File.exist?(config_file)).to be_truthy
|
147
146
|
end
|
148
147
|
end
|
149
148
|
|
150
149
|
it "should describe config file" do
|
151
150
|
FakeFS do
|
152
151
|
invoke "configure"
|
153
|
-
$stdout.string.
|
152
|
+
expect($stdout.string).to eq "Config file is at \"#{ENV['HOME']}/.timetrap.yml\"\n"
|
154
153
|
end
|
155
154
|
end
|
156
155
|
end
|
@@ -161,23 +160,23 @@ describe Timetrap do
|
|
161
160
|
end
|
162
161
|
|
163
162
|
it "should edit the description of the active period" do
|
164
|
-
Timetrap::Timer.active_entry.note.
|
163
|
+
expect(Timetrap::Timer.active_entry.note).to eq 'running entry'
|
165
164
|
invoke 'edit new description'
|
166
|
-
Timetrap::Timer.active_entry.note.
|
165
|
+
expect(Timetrap::Timer.active_entry.note).to eq 'new description'
|
167
166
|
end
|
168
167
|
|
169
168
|
it "should allow you to move an entry to another sheet" do
|
170
169
|
invoke 'edit --move blahblah'
|
171
|
-
Timetrap::Timer.active_entry[:sheet].
|
170
|
+
expect(Timetrap::Timer.active_entry[:sheet]).to eq 'blahblah'
|
172
171
|
invoke 'edit -m blahblahblah'
|
173
|
-
Timetrap::Timer.active_entry[:sheet].
|
172
|
+
expect(Timetrap::Timer.active_entry[:sheet]).to eq 'blahblahblah'
|
174
173
|
end
|
175
174
|
|
176
175
|
it "should change the current sheet if the current entry's sheet is changed" do
|
177
|
-
Timetrap::Timer.current_sheet.
|
176
|
+
expect(Timetrap::Timer.current_sheet).not_to eq 'blahblahblah'
|
178
177
|
invoke 'edit -m blahblahblah'
|
179
|
-
Timetrap::Timer.active_entry[:sheet].
|
180
|
-
Timetrap::Timer.current_sheet.
|
178
|
+
expect(Timetrap::Timer.active_entry[:sheet]).to eq 'blahblahblah'
|
179
|
+
expect(Timetrap::Timer.current_sheet).to eq 'blahblahblah'
|
181
180
|
end
|
182
181
|
|
183
182
|
it "should change the current sheet if a non current entry's sheet is changed" do
|
@@ -185,30 +184,30 @@ describe Timetrap do
|
|
185
184
|
id = Timetrap::Timer.active_entry[:id]
|
186
185
|
invoke 'out'
|
187
186
|
invoke "edit -m blahblahblah -i #{id}"
|
188
|
-
Timetrap::Timer.current_sheet.
|
189
|
-
Timetrap::Entry[id][:sheet].
|
187
|
+
expect(Timetrap::Timer.current_sheet).to eq sheet
|
188
|
+
expect(Timetrap::Entry[id][:sheet]).to eq 'blahblahblah'
|
190
189
|
end
|
191
190
|
|
192
191
|
it "should allow appending to the description of the active period" do
|
193
192
|
with_stubbed_config('append_notes_delimiter' => '//')
|
194
|
-
Timetrap::Timer.active_entry.note.
|
193
|
+
expect(Timetrap::Timer.active_entry.note).to eq 'running entry'
|
195
194
|
invoke 'edit --append new'
|
196
|
-
Timetrap::Timer.active_entry.note.
|
195
|
+
expect(Timetrap::Timer.active_entry.note).to eq 'running entry//new'
|
197
196
|
invoke 'edit -z more'
|
198
|
-
Timetrap::Timer.active_entry.note.
|
197
|
+
expect(Timetrap::Timer.active_entry.note).to eq 'running entry//new//more'
|
199
198
|
end
|
200
199
|
|
201
200
|
it "should edit the start time of the active period" do
|
202
201
|
invoke 'edit --start "yesterday 10am"'
|
203
|
-
Timetrap::Timer.active_entry.start.
|
204
|
-
Timetrap::Timer.active_entry.note.
|
202
|
+
expect(Timetrap::Timer.active_entry.start).to eq Chronic.parse("yesterday 10am")
|
203
|
+
expect(Timetrap::Timer.active_entry.note).to eq 'running entry'
|
205
204
|
end
|
206
205
|
|
207
206
|
it "should edit the end time of the active period" do
|
208
207
|
entry = Timetrap::Timer.active_entry
|
209
208
|
invoke 'edit --end "yesterday 10am"'
|
210
|
-
entry.refresh.end.
|
211
|
-
entry.refresh.note.
|
209
|
+
expect(entry.refresh.end).to eq Chronic.parse("yesterday 10am")
|
210
|
+
expect(entry.refresh.note).to eq 'running entry'
|
212
211
|
end
|
213
212
|
|
214
213
|
it "should edit a non running entry based on id" do
|
@@ -225,14 +224,14 @@ describe Timetrap do
|
|
225
224
|
Timetrap::Timer.start "another entry", nil
|
226
225
|
|
227
226
|
invoke "edit --id #{not_running.id} a new description"
|
228
|
-
not_running.refresh.note.
|
227
|
+
expect(not_running.refresh.note).to eq 'a new description'
|
229
228
|
end
|
230
229
|
|
231
230
|
it "should edit the entry last checked out of if none is running" do
|
232
231
|
not_running = Timetrap::Timer.active_entry
|
233
232
|
Timetrap::Timer.stop(Timetrap::Timer.current_sheet)
|
234
233
|
invoke "edit -z 'a new description'"
|
235
|
-
not_running.refresh.note.
|
234
|
+
expect(not_running.refresh.note).to include 'a new description'
|
236
235
|
end
|
237
236
|
|
238
237
|
it "should edit the entry last checked out of if none is running even if the sheet is changed" do
|
@@ -240,9 +239,9 @@ describe Timetrap do
|
|
240
239
|
Timetrap::Timer.stop(Timetrap::Timer.current_sheet)
|
241
240
|
invoke "edit -z 'a new description'"
|
242
241
|
invoke "sheet another second sheet"
|
243
|
-
not_running.refresh.note.
|
244
|
-
not_running.refresh.sheet.
|
245
|
-
Timetrap::Timer.current_sheet.
|
242
|
+
expect(not_running.refresh.note).to include 'a new description'
|
243
|
+
expect(not_running.refresh.sheet).to eq 'default'
|
244
|
+
expect(Timetrap::Timer.current_sheet).to eq 'another second sheet'
|
246
245
|
end
|
247
246
|
|
248
247
|
context "with external editor" do
|
@@ -253,18 +252,18 @@ describe Timetrap do
|
|
253
252
|
end
|
254
253
|
|
255
254
|
it "should open an editor for editing the note" do |example|
|
256
|
-
Timetrap::CLI.
|
255
|
+
allow(Timetrap::CLI).to receive(:system) do |editor_command|
|
257
256
|
path = editor_command.match(/#{note_editor_command} (?<path>.*)/)
|
258
257
|
File.write(path[:path], "edited note")
|
259
258
|
end
|
260
|
-
Timetrap::Timer.active_entry.note.
|
259
|
+
expect(Timetrap::Timer.active_entry.note).to eq 'running entry'
|
261
260
|
invoke "edit"
|
262
|
-
Timetrap::Timer.active_entry.note.
|
261
|
+
expect(Timetrap::Timer.active_entry.note).to eq 'edited note'
|
263
262
|
end
|
264
263
|
|
265
264
|
it "should pass existing note to editor" do |example|
|
266
265
|
capture = nil
|
267
|
-
Timetrap::CLI.
|
266
|
+
allow(Timetrap::CLI).to receive(:system) do |editor_command|
|
268
267
|
path = editor_command.match(/#{note_editor_command} (?<path>.*)/)
|
269
268
|
|
270
269
|
capture = File.read(path[:path])
|
@@ -286,14 +285,14 @@ describe Timetrap do
|
|
286
285
|
|
287
286
|
Timetrap::Timer.stop(Timetrap::Timer.current_sheet)
|
288
287
|
|
289
|
-
Timetrap::CLI.
|
288
|
+
allow(Timetrap::CLI).to receive(:system) do |editor_command|
|
290
289
|
path = editor_command.match(/#{note_editor_command} (?<path>.*)/)
|
291
290
|
File.write(path[:path], "id passed note")
|
292
291
|
end
|
293
292
|
|
294
293
|
invoke "edit --id #{not_running.id}"
|
295
294
|
|
296
|
-
not_running.refresh.note.
|
295
|
+
expect(not_running.refresh.note).to eq "id passed note"
|
297
296
|
end
|
298
297
|
|
299
298
|
it "should not call the editor if there are arguments other than --id" do
|
@@ -308,23 +307,23 @@ describe Timetrap do
|
|
308
307
|
|
309
308
|
context "appending" do
|
310
309
|
it "should open an editor for editing the note with -z" do |example|
|
311
|
-
Timetrap::CLI.
|
310
|
+
allow(Timetrap::CLI).to receive(:system) do |editor_command|
|
312
311
|
path = editor_command.match(/#{note_editor_command} (?<path>.*)/)
|
313
312
|
File.write(path[:path], "appended in editor")
|
314
313
|
end
|
315
|
-
Timetrap::Timer.active_entry.note.
|
314
|
+
expect(Timetrap::Timer.active_entry.note).to eq 'running entry'
|
316
315
|
invoke "edit -z"
|
317
|
-
Timetrap::Timer.active_entry.note.
|
316
|
+
expect(Timetrap::Timer.active_entry.note).to eq 'running entry//appended in editor'
|
318
317
|
end
|
319
318
|
|
320
319
|
it "should open a editor for editing the note with --append" do |example|
|
321
|
-
Timetrap::CLI.
|
320
|
+
allow(Timetrap::CLI).to receive(:system) do |editor_command|
|
322
321
|
path = editor_command.match(/#{note_editor_command} (?<path>.*)/)
|
323
322
|
File.write(path[:path], "appended in editor")
|
324
323
|
end
|
325
|
-
Timetrap::Timer.active_entry.note.
|
324
|
+
expect(Timetrap::Timer.active_entry.note).to eq 'running entry'
|
326
325
|
invoke "edit --append"
|
327
|
-
Timetrap::Timer.active_entry.note.
|
326
|
+
expect(Timetrap::Timer.active_entry.note).to eq 'running entry//appended in editor'
|
328
327
|
end
|
329
328
|
end
|
330
329
|
end
|
@@ -336,7 +335,7 @@ describe Timetrap do
|
|
336
335
|
it 'should use sheet defined in dotfile' do
|
337
336
|
Dir.chdir('spec/dotfile') do
|
338
337
|
with_stubbed_config('auto_sheet' => 'dotfiles')
|
339
|
-
Timetrap::Timer.current_sheet.
|
338
|
+
expect(Timetrap::Timer.current_sheet).to eq 'dotfile-sheet'
|
340
339
|
end
|
341
340
|
end
|
342
341
|
end
|
@@ -349,7 +348,7 @@ describe Timetrap do
|
|
349
348
|
'auto_sheet_paths' => {
|
350
349
|
'a sheet' => ['/not/cwd/', Dir.getwd]
|
351
350
|
}, 'auto_sheet' => 'yaml_cwd')
|
352
|
-
Timetrap::Timer.current_sheet.
|
351
|
+
expect(Timetrap::Timer.current_sheet).to eq 'a sheet'
|
353
352
|
end
|
354
353
|
end
|
355
354
|
|
@@ -359,7 +358,7 @@ describe Timetrap do
|
|
359
358
|
'auto_sheet_paths' => {'a sheet' => '/'},
|
360
359
|
'auto_sheet' => 'yaml_cwd'
|
361
360
|
)
|
362
|
-
Timetrap::Timer.current_sheet.
|
361
|
+
expect(Timetrap::Timer.current_sheet).to eq 'a sheet'
|
363
362
|
end
|
364
363
|
end
|
365
364
|
|
@@ -369,7 +368,7 @@ describe Timetrap do
|
|
369
368
|
'auto_sheet_paths' => {
|
370
369
|
'a sheet' => '/not/the/current/working/directory/'
|
371
370
|
},'auto_sheet' => 'yaml_cwd')
|
372
|
-
Timetrap::Timer.current_sheet.
|
371
|
+
expect(Timetrap::Timer.current_sheet).to eq 'default'
|
373
372
|
end
|
374
373
|
end
|
375
374
|
|
@@ -379,12 +378,12 @@ describe Timetrap do
|
|
379
378
|
'auto_sheet_paths' => {
|
380
379
|
'general sheet' => '/', 'more specific sheet' => Dir.getwd
|
381
380
|
}, 'auto_sheet' => 'yaml_cwd')
|
382
|
-
Timetrap::Timer.current_sheet.
|
381
|
+
expect(Timetrap::Timer.current_sheet).to eq 'more specific sheet'
|
383
382
|
with_stubbed_config(
|
384
383
|
'auto_sheet_paths' => {
|
385
384
|
'more specific sheet' => Dir.getwd, 'general sheet' => '/'
|
386
385
|
}, 'auto_sheet' => 'yaml_cwd')
|
387
|
-
Timetrap::Timer.current_sheet.
|
386
|
+
expect(Timetrap::Timer.current_sheet).to eq 'more specific sheet'
|
388
387
|
end
|
389
388
|
end
|
390
389
|
end
|
@@ -394,13 +393,13 @@ describe Timetrap do
|
|
394
393
|
it 'should use sheet defined in dotfile' do
|
395
394
|
Dir.chdir('spec/dotfile') do
|
396
395
|
with_stubbed_config('auto_sheet' => 'nested_dotfiles')
|
397
|
-
Timetrap::Timer.current_sheet.
|
396
|
+
expect(Timetrap::Timer.current_sheet).to eq 'dotfile-sheet'
|
398
397
|
end
|
399
398
|
end
|
400
399
|
it 'should use top-most sheet found in dir heirarchy' do
|
401
400
|
Dir.chdir('spec/dotfile/nested') do
|
402
401
|
with_stubbed_config('auto_sheet' => 'nested_dotfiles')
|
403
|
-
Timetrap::Timer.current_sheet.
|
402
|
+
expect(Timetrap::Timer.current_sheet).to eq 'nested-sheet'
|
404
403
|
end
|
405
404
|
end
|
406
405
|
end
|
@@ -409,7 +408,7 @@ describe Timetrap do
|
|
409
408
|
it 'should use sheet defined in ancestor\'s dotfile' do
|
410
409
|
Dir.chdir('spec/dotfile/nested/no-sheet') do
|
411
410
|
with_stubbed_config('auto_sheet' => 'nested_dotfiles')
|
412
|
-
Timetrap::Timer.current_sheet.
|
411
|
+
expect(Timetrap::Timer.current_sheet).to eq 'nested-sheet'
|
413
412
|
end
|
414
413
|
end
|
415
414
|
end
|
@@ -418,7 +417,7 @@ describe Timetrap do
|
|
418
417
|
|
419
418
|
describe "backend" do
|
420
419
|
it "should open an sqlite console to the db" do
|
421
|
-
Timetrap::CLI.
|
420
|
+
expect(Timetrap::CLI).to receive(:exec).with("sqlite3 #{Timetrap::DB_NAME}")
|
422
421
|
invoke 'backend'
|
423
422
|
end
|
424
423
|
end
|
@@ -429,7 +428,7 @@ describe Timetrap do
|
|
429
428
|
end
|
430
429
|
it "should be deprecated" do
|
431
430
|
invoke 'format'
|
432
|
-
$stderr.string.
|
431
|
+
expect($stderr.string).to eq <<-WARN
|
433
432
|
The "format" command is deprecated in favor of "display". Sorry for the inconvenience.
|
434
433
|
WARN
|
435
434
|
end
|
@@ -461,7 +460,7 @@ The "format" command is deprecated in favor of "display". Sorry for the inconven
|
|
461
460
|
)
|
462
461
|
|
463
462
|
now = local_time('2008-10-05 20:00:00')
|
464
|
-
Time.
|
463
|
+
allow(Time).to receive(:now).and_return now
|
465
464
|
@desired_output = <<-OUTPUT
|
466
465
|
Timesheet: SpecSheet
|
467
466
|
Day Start End Duration Notes
|
@@ -555,19 +554,19 @@ Timesheet: SheetWithLineBreakNote
|
|
555
554
|
it "should display the current timesheet" do
|
556
555
|
Timetrap::Timer.current_sheet = 'SpecSheet'
|
557
556
|
invoke 'display'
|
558
|
-
$stdout.string.
|
557
|
+
expect($stdout.string).to eq @desired_output
|
559
558
|
end
|
560
559
|
|
561
560
|
it "should display a non current timesheet" do
|
562
561
|
Timetrap::Timer.current_sheet = 'another'
|
563
562
|
invoke 'display SpecSheet'
|
564
|
-
$stdout.string.
|
563
|
+
expect($stdout.string).to eq @desired_output
|
565
564
|
end
|
566
565
|
|
567
566
|
it "should display a non current timesheet based on a partial name match" do
|
568
567
|
Timetrap::Timer.current_sheet = 'another'
|
569
568
|
invoke 'display S'
|
570
|
-
$stdout.string.
|
569
|
+
expect($stdout.string).to eq @desired_output
|
571
570
|
end
|
572
571
|
|
573
572
|
it "should prefer an exact match of a named sheet to a partial match" do
|
@@ -576,50 +575,50 @@ Timesheet: SheetWithLineBreakNote
|
|
576
575
|
:note => 'entry 5', :start => '2008-10-05 18:00:00'
|
577
576
|
)
|
578
577
|
invoke 'display Spec'
|
579
|
-
$stdout.string.
|
578
|
+
expect($stdout.string).to include("entry 5")
|
580
579
|
end
|
581
580
|
|
582
581
|
it "should only display entries that are matched by the provided regex" do
|
583
582
|
Timetrap::Timer.current_sheet = 'SpecSheet'
|
584
583
|
invoke 'display --grep [13]'
|
585
|
-
$stdout.string.
|
584
|
+
expect($stdout.string).to eq @desired_output_grepped
|
586
585
|
end
|
587
586
|
|
588
587
|
it "should display a timesheet with ids" do
|
589
588
|
invoke 'display S --ids'
|
590
|
-
$stdout.string.
|
589
|
+
expect($stdout.string).to eq @desired_output_with_ids
|
591
590
|
end
|
592
591
|
|
593
592
|
it "should properly format a timesheet with long ids" do
|
594
593
|
Timetrap::DB["UPDATE entries SET id = 40000 WHERE id = 4"].all
|
595
594
|
invoke 'display S --ids'
|
596
|
-
$stdout.string.
|
595
|
+
expect($stdout.string).to eq @desired_output_with_long_ids
|
597
596
|
end
|
598
597
|
|
599
598
|
it "should properly format a timesheet with no ids even if long ids are in the db" do
|
600
599
|
Timetrap::DB["UPDATE entries SET id = 40000 WHERE id = 4"].all
|
601
600
|
invoke 'display S'
|
602
|
-
$stdout.string.
|
601
|
+
expect($stdout.string).to eq @desired_output
|
603
602
|
end
|
604
603
|
|
605
604
|
|
606
605
|
it "should display long notes nicely" do
|
607
606
|
Timetrap::Timer.current_sheet = 'LongNoteSheet'
|
608
607
|
invoke 'display'
|
609
|
-
$stdout.string.
|
608
|
+
expect($stdout.string).to eq @desired_output_for_long_note_sheet
|
610
609
|
end
|
611
610
|
|
612
611
|
it "should display long notes with linebreaks nicely" do
|
613
612
|
Timetrap::Timer.current_sheet = 'SheetWithLineBreakNote'
|
614
613
|
invoke 'display'
|
615
|
-
$stdout.string.
|
614
|
+
expect($stdout.string).to eq @desired_output_for_note_with_linebreak
|
616
615
|
end
|
617
616
|
|
618
617
|
it "should display long notes with ids nicely" do
|
619
618
|
Timetrap::DB["UPDATE entries SET id = 60000 WHERE id = 6"].all
|
620
619
|
Timetrap::Timer.current_sheet = 'LongNoteSheet'
|
621
620
|
invoke 'display --ids'
|
622
|
-
$stdout.string.
|
621
|
+
expect($stdout.string).to eq @desired_output_for_long_note_sheet_with_ids
|
623
622
|
end
|
624
623
|
|
625
624
|
it "should not display archived for all timesheets" do
|
@@ -627,7 +626,7 @@ Timesheet: SheetWithLineBreakNote
|
|
627
626
|
invoke 'archive SpecSheet'
|
628
627
|
$stdout.string = ''
|
629
628
|
invoke 'display all'
|
630
|
-
$stdout.string.
|
629
|
+
expect($stdout.string).not_to match /_SpecSheet/
|
631
630
|
end
|
632
631
|
|
633
632
|
it "it should find a user provided formatter class and require it" do
|
@@ -647,7 +646,7 @@ Timesheet: SheetWithLineBreakNote
|
|
647
646
|
RUBY
|
648
647
|
end
|
649
648
|
invoke 'd -fbaz'
|
650
|
-
$stdout.string.
|
649
|
+
expect($stdout.string).to eq "yeah I did it\n"
|
651
650
|
FileUtils.rm_r dir
|
652
651
|
end
|
653
652
|
|
@@ -657,7 +656,7 @@ Timesheet: SheetWithLineBreakNote
|
|
657
656
|
)
|
658
657
|
invoke 'd SpecSheet'
|
659
658
|
# check it doesn't error and produces valid looking output
|
660
|
-
$stdout.string.
|
659
|
+
expect($stdout.string).to include('Timesheet: SpecSheet')
|
661
660
|
end
|
662
661
|
end
|
663
662
|
|
@@ -672,7 +671,7 @@ Timesheet: SheetWithLineBreakNote
|
|
672
671
|
'formatter_search_paths' => nil
|
673
672
|
|
674
673
|
invoke 'd'
|
675
|
-
$stdout.string.
|
674
|
+
expect($stdout.string).to eq Timetrap::Entry.all.map(&:id).join(" ") + "\n"
|
676
675
|
end
|
677
676
|
end
|
678
677
|
|
@@ -685,7 +684,7 @@ Timesheet: SheetWithLineBreakNote
|
|
685
684
|
it "should not export running items" do
|
686
685
|
invoke 'in'
|
687
686
|
invoke 'display --format ids'
|
688
|
-
$stdout.string.
|
687
|
+
expect($stdout.string).to eq Timetrap::Entry.all.map(&:id).join(" ") + "\n"
|
689
688
|
end
|
690
689
|
|
691
690
|
end
|
@@ -699,7 +698,7 @@ Timesheet: SheetWithLineBreakNote
|
|
699
698
|
it "should not export running items" do
|
700
699
|
invoke 'in'
|
701
700
|
invoke 'display --format csv'
|
702
|
-
$stdout.string.
|
701
|
+
expect($stdout.string).to eq <<-EOF
|
703
702
|
start,end,note,sheet
|
704
703
|
"2008-10-03 12:00:00","2008-10-03 14:00:00","note","default"
|
705
704
|
"2008-10-05 12:00:00","2008-10-05 14:00:00","note","default"
|
@@ -708,7 +707,7 @@ start,end,note,sheet
|
|
708
707
|
|
709
708
|
it "should filter events by the passed dates" do
|
710
709
|
invoke 'display --format csv --start 2008-10-03 --end 2008-10-03'
|
711
|
-
$stdout.string.
|
710
|
+
expect($stdout.string).to eq <<-EOF
|
712
711
|
start,end,note,sheet
|
713
712
|
"2008-10-03 12:00:00","2008-10-03 14:00:00","note","default"
|
714
713
|
EOF
|
@@ -716,7 +715,7 @@ start,end,note,sheet
|
|
716
715
|
|
717
716
|
it "should not filter events by date when none are passed" do
|
718
717
|
invoke 'display --format csv'
|
719
|
-
$stdout.string.
|
718
|
+
expect($stdout.string).to eq <<-EOF
|
720
719
|
start,end,note,sheet
|
721
720
|
"2008-10-03 12:00:00","2008-10-03 14:00:00","note","default"
|
722
721
|
"2008-10-05 12:00:00","2008-10-05 14:00:00","note","default"
|
@@ -733,7 +732,7 @@ start,end,note,sheet
|
|
733
732
|
it "should export to json not including running items" do
|
734
733
|
invoke 'in'
|
735
734
|
invoke 'display -f json'
|
736
|
-
JSON.parse($stdout.string).
|
735
|
+
expect(JSON.parse($stdout.string)).to eq JSON.parse(<<-EOF)
|
737
736
|
[{\"sheet\":\"default\",\"end\":\"#{local_time('2008-10-03 14:00:00')}\",\"start\":\"#{local_time('2008-10-03 12:00:00')}\",\"note\":\"note\",\"id\":1},{\"sheet\":\"default\",\"end\":\"#{local_time('2008-10-05 14:00:00')}\",\"start\":\"#{local_time('2008-10-05 12:00:00')}\",\"note\":\"note\",\"id\":2}]
|
738
737
|
EOF
|
739
738
|
end
|
@@ -779,7 +778,7 @@ END:VEVENT
|
|
779
778
|
END:VCALENDAR
|
780
779
|
EOF
|
781
780
|
desired.each_line do |line|
|
782
|
-
$stdout.string.
|
781
|
+
expect($stdout.string).to match /#{line.chomp}/
|
783
782
|
end
|
784
783
|
end
|
785
784
|
end
|
@@ -787,49 +786,50 @@ END:VCALENDAR
|
|
787
786
|
|
788
787
|
describe "in" do
|
789
788
|
it "should start the time for the current timesheet" do
|
790
|
-
|
791
|
-
|
792
|
-
|
789
|
+
expect(
|
790
|
+
lambda do
|
791
|
+
invoke 'in'
|
792
|
+
end).to change(Timetrap::Entry, :count).by(1)
|
793
793
|
end
|
794
794
|
|
795
795
|
it "should set the note when starting a new entry" do
|
796
796
|
invoke 'in working on something'
|
797
|
-
Timetrap::Entry.order_by(:id).last.note.
|
797
|
+
expect(Timetrap::Entry.order_by(:id).last.note).to eq 'working on something'
|
798
798
|
end
|
799
799
|
|
800
800
|
it "should set the start when starting a new entry" do
|
801
801
|
@time = Time.now
|
802
|
-
Time.
|
802
|
+
allow(Time).to receive(:now).and_return @time
|
803
803
|
invoke 'in working on something'
|
804
|
-
Timetrap::Entry.order_by(:id).last.start.to_i.
|
804
|
+
expect(Timetrap::Entry.order_by(:id).last.start.to_i).to eq @time.to_i
|
805
805
|
end
|
806
806
|
|
807
807
|
it "should not start the time if the timetrap is running" do
|
808
|
-
Timetrap::Timer.
|
809
|
-
lambda do
|
808
|
+
allow(Timetrap::Timer).to receive(:running?).and_return true
|
809
|
+
expect(lambda do
|
810
810
|
invoke 'in'
|
811
|
-
|
811
|
+
end).not_to change(Timetrap::Entry, :count)
|
812
812
|
end
|
813
813
|
|
814
814
|
it "should allow the sheet to be started at a certain time" do
|
815
815
|
invoke 'in work --at "10am 2008-10-03"'
|
816
|
-
Timetrap::Entry.order_by(:id).last.start.
|
816
|
+
expect(Timetrap::Entry.order_by(:id).last.start).to eq Time.parse('2008-10-03 10:00')
|
817
817
|
end
|
818
818
|
|
819
819
|
it "should fail with a warning for misformatted cli options it can't parse" do
|
820
820
|
now = Time.now
|
821
|
-
Time.
|
821
|
+
allow(Time).to receive(:now).and_return now
|
822
822
|
invoke 'in work --at="18 minutes ago"'
|
823
|
-
Timetrap::Entry.order_by(:id).last.
|
824
|
-
$stderr.string.
|
823
|
+
expect(Timetrap::Entry.order_by(:id).last).to be_nil
|
824
|
+
expect($stderr.string).to match /\w+/
|
825
825
|
end
|
826
826
|
|
827
827
|
it "should fail with a time argurment of total garbage" do
|
828
828
|
now = Time.now
|
829
|
-
Time.
|
829
|
+
allow(Time).to receive(:now).and_return now
|
830
830
|
invoke 'in work --at "total garbage"'
|
831
|
-
Timetrap::Entry.order_by(:id).last.
|
832
|
-
$stderr.string.
|
831
|
+
expect(Timetrap::Entry.order_by(:id).last).to be_nil
|
832
|
+
expect($stderr.string).to match /\w+/
|
833
833
|
end
|
834
834
|
|
835
835
|
describe "with require_note config option set" do
|
@@ -841,21 +841,21 @@ END:VCALENDAR
|
|
841
841
|
it "should prompt for a note if one isn't passed" do
|
842
842
|
$stdin.string = "an interactive note\n"
|
843
843
|
invoke "in"
|
844
|
-
$stderr.string.
|
845
|
-
Timetrap::Timer.active_entry.note.
|
844
|
+
expect($stderr.string).to include('enter a note')
|
845
|
+
expect(Timetrap::Timer.active_entry.note).to eq "an interactive note"
|
846
846
|
end
|
847
847
|
|
848
848
|
it "should not prompt for a note if one is passed" do
|
849
849
|
$stdin.string = "an interactive note\n"
|
850
850
|
invoke "in a normal note"
|
851
|
-
Timetrap::Timer.active_entry.note.
|
851
|
+
expect(Timetrap::Timer.active_entry.note).to eq "a normal note"
|
852
852
|
end
|
853
853
|
|
854
854
|
it "should not stop the running entry or prompt" do
|
855
855
|
invoke "in a normal note"
|
856
856
|
$stdin.string = "an interactive note\n"
|
857
857
|
invoke "in"
|
858
|
-
Timetrap::Timer.active_entry.note.
|
858
|
+
expect(Timetrap::Timer.active_entry.note).to eq "a normal note"
|
859
859
|
end
|
860
860
|
end
|
861
861
|
|
@@ -866,22 +866,22 @@ END:VCALENDAR
|
|
866
866
|
end
|
867
867
|
|
868
868
|
it "should open an editor for writing the note" do |example|
|
869
|
-
Timetrap::CLI.
|
869
|
+
allow(Timetrap::CLI).to receive(:system) do |editor_command|
|
870
870
|
path = editor_command.match(/#{note_editor_command} (?<path>.*)/)
|
871
871
|
File.write(path[:path], "written in editor")
|
872
872
|
end
|
873
873
|
invoke "in"
|
874
|
-
$stderr.string.
|
875
|
-
Timetrap::Timer.active_entry.note.
|
874
|
+
expect($stderr.string).not_to include('enter a note')
|
875
|
+
expect(Timetrap::Timer.active_entry.note).to eq "written in editor"
|
876
876
|
end
|
877
877
|
|
878
878
|
it "should preserve linebreaks from editor" do |example|
|
879
|
-
Timetrap::CLI.
|
879
|
+
allow(Timetrap::CLI).to receive(:system) do |editor_command|
|
880
880
|
path = editor_command.match(/#{note_editor_command} (?<path>.*)/)
|
881
881
|
File.write(path[:path], "line1\nline2")
|
882
882
|
end
|
883
883
|
invoke "in"
|
884
|
-
Timetrap::Timer.active_entry.note.
|
884
|
+
expect(Timetrap::Timer.active_entry.note).to eq "line1\nline2"
|
885
885
|
end
|
886
886
|
end
|
887
887
|
end
|
@@ -892,9 +892,9 @@ END:VCALENDAR
|
|
892
892
|
end
|
893
893
|
|
894
894
|
it "should check in normally if nothing else is running" do
|
895
|
-
Timetrap::Timer.
|
895
|
+
expect(Timetrap::Timer).not_to be_running #precondition
|
896
896
|
invoke 'in'
|
897
|
-
Timetrap::Timer.
|
897
|
+
expect(Timetrap::Timer).to be_running
|
898
898
|
end
|
899
899
|
|
900
900
|
describe "with a running entry on current sheet" do
|
@@ -906,12 +906,12 @@ END:VCALENDAR
|
|
906
906
|
it "should check out and back in" do
|
907
907
|
entry = Timetrap::Timer.active_entry('sheet1')
|
908
908
|
invoke 'in second task'
|
909
|
-
Timetrap::Timer.active_entry('sheet1').note.
|
909
|
+
expect(Timetrap::Timer.active_entry('sheet1').note).to eq 'second task'
|
910
910
|
end
|
911
911
|
|
912
912
|
it "should tell me what it's doing" do
|
913
913
|
invoke 'in second task'
|
914
|
-
$stderr.string.
|
914
|
+
expect($stderr.string).to include "Checked out"
|
915
915
|
end
|
916
916
|
end
|
917
917
|
|
@@ -923,25 +923,25 @@ END:VCALENDAR
|
|
923
923
|
end
|
924
924
|
|
925
925
|
it "should check out of the running entry" do
|
926
|
-
Timetrap::Timer.active_entry('sheet1').
|
926
|
+
expect(Timetrap::Timer.active_entry('sheet1')).to be_a(Timetrap::Entry)
|
927
927
|
invoke 'in second task'
|
928
|
-
Timetrap::Timer.active_entry('sheet1').
|
928
|
+
expect(Timetrap::Timer.active_entry('sheet1')).to be nil
|
929
929
|
end
|
930
930
|
|
931
931
|
it "should check out of the running entry at another time" do
|
932
932
|
now = Time.at(Time.now - 5 * 60) # 5 minutes ago
|
933
933
|
entry = Timetrap::Timer.active_entry('sheet1')
|
934
|
-
entry.
|
934
|
+
expect(entry).to be_a(Timetrap::Entry)
|
935
935
|
invoke "in -a '#{now}' second task"
|
936
|
-
entry.reload.end.to_s.
|
936
|
+
expect(entry.reload.end.to_s).to eq now.to_s
|
937
937
|
end
|
938
938
|
|
939
939
|
it "should check out of the running entry without having to start a new entry" do
|
940
940
|
entry = Timetrap::Timer.active_entry('sheet1')
|
941
|
-
entry.
|
942
|
-
entry.end.
|
941
|
+
expect(entry).to be_a(Timetrap::Entry)
|
942
|
+
expect(entry.end).to be_nil
|
943
943
|
invoke "out"
|
944
|
-
entry.reload.end.
|
944
|
+
expect(entry.reload.end).not_to be_nil
|
945
945
|
end
|
946
946
|
end
|
947
947
|
end
|
@@ -956,8 +956,8 @@ END:VCALENDAR
|
|
956
956
|
)
|
957
957
|
create_entry
|
958
958
|
invoke 'today'
|
959
|
-
$stdout.string.
|
960
|
-
$stdout.string.
|
959
|
+
expect($stdout.string).to include Time.now.strftime('%a %b %d, %Y')
|
960
|
+
expect($stdout.string).not_to include yesterday.strftime('%a %b %d, %Y')
|
961
961
|
end
|
962
962
|
end
|
963
963
|
|
@@ -970,8 +970,8 @@ END:VCALENDAR
|
|
970
970
|
)
|
971
971
|
create_entry
|
972
972
|
invoke 'yesterday'
|
973
|
-
$stdout.string.
|
974
|
-
$stdout.string.
|
973
|
+
expect($stdout.string).to include yesterday.strftime('%a %b %d, %Y')
|
974
|
+
expect($stdout.string).not_to include Time.now.strftime('%a %b %d, %Y')
|
975
975
|
end
|
976
976
|
end
|
977
977
|
|
@@ -983,8 +983,8 @@ END:VCALENDAR
|
|
983
983
|
)
|
984
984
|
create_entry
|
985
985
|
invoke 'week'
|
986
|
-
$stdout.string.
|
987
|
-
$stdout.string.
|
986
|
+
expect($stdout.string).to include Time.now.strftime('%a %b %d, %Y')
|
987
|
+
expect($stdout.string).not_to include 'Feb 01, 2012'
|
988
988
|
end
|
989
989
|
|
990
990
|
describe "with week_start config option set" do
|
@@ -995,14 +995,14 @@ END:VCALENDAR
|
|
995
995
|
|
996
996
|
#https://github.com/samg/timetrap/issues/161
|
997
997
|
it "should work at the end of the month" do
|
998
|
-
Date.
|
998
|
+
expect(Date).to receive(:today).and_return(Date.new(2017 , 7, 30))
|
999
999
|
|
1000
1000
|
create_entry(
|
1001
1001
|
:start => Time.local(2017, 7, 29, 1, 2, 3),
|
1002
1002
|
:end => Time.local(2017, 7, 29, 2, 2, 3)
|
1003
1003
|
)
|
1004
1004
|
invoke "week"
|
1005
|
-
$stdout.string.
|
1005
|
+
expect($stdout.string).to include 'Jul 29, 2017'
|
1006
1006
|
|
1007
1007
|
end
|
1008
1008
|
|
@@ -1020,12 +1020,12 @@ END:VCALENDAR
|
|
1020
1020
|
:end => Time.local(2012, 2, 9, 2, 2, 3)
|
1021
1021
|
)
|
1022
1022
|
|
1023
|
-
Date.
|
1023
|
+
expect(Date).to receive(:today).and_return(Date.new(2012, 2, 9))
|
1024
1024
|
invoke 'week'
|
1025
1025
|
|
1026
|
-
$stdout.string.
|
1027
|
-
$stdout.string.
|
1028
|
-
$stdout.string.
|
1026
|
+
expect($stdout.string).to include 'Feb 08, 2012'
|
1027
|
+
expect($stdout.string).to include 'Feb 09, 2012'
|
1028
|
+
expect($stdout.string).not_to include 'Feb 05, 2012'
|
1029
1029
|
end
|
1030
1030
|
|
1031
1031
|
it "should only show entries from today if today is start of week" do
|
@@ -1042,12 +1042,12 @@ END:VCALENDAR
|
|
1042
1042
|
:end => Time.local(2012, 2, 7, 2, 2, 3)
|
1043
1043
|
)
|
1044
1044
|
|
1045
|
-
Date.
|
1045
|
+
expect(Date).to receive(:today).and_return(Date.new(2012, 2, 7))
|
1046
1046
|
invoke 'week'
|
1047
1047
|
|
1048
|
-
$stdout.string.
|
1049
|
-
$stdout.string.
|
1050
|
-
$stdout.string.
|
1048
|
+
expect($stdout.string).to include 'Feb 07, 2012'
|
1049
|
+
expect($stdout.string).not_to include 'Jan 31, 2012'
|
1050
|
+
expect($stdout.string).not_to include 'Feb 05, 2012'
|
1051
1051
|
end
|
1052
1052
|
|
1053
1053
|
it "should not show entries 7 days past start of week" do
|
@@ -1064,12 +1064,12 @@ END:VCALENDAR
|
|
1064
1064
|
:end => Time.local(2012, 2, 16, 2, 2, 3)
|
1065
1065
|
)
|
1066
1066
|
|
1067
|
-
Date.
|
1067
|
+
expect(Date).to receive(:today).and_return(Date.new(2012, 2, 7))
|
1068
1068
|
invoke 'week'
|
1069
1069
|
|
1070
|
-
$stdout.string.
|
1071
|
-
$stdout.string.
|
1072
|
-
$stdout.string.
|
1070
|
+
expect($stdout.string).to include 'Feb 09, 2012'
|
1071
|
+
expect($stdout.string).not_to include 'Feb 14, 2012'
|
1072
|
+
expect($stdout.string).not_to include 'Feb 16, 2012'
|
1073
1073
|
end
|
1074
1074
|
end
|
1075
1075
|
end
|
@@ -1089,13 +1089,13 @@ END:VCALENDAR
|
|
1089
1089
|
:end => Time.local(2012, 1, 5, 2, 2, 3)
|
1090
1090
|
)
|
1091
1091
|
|
1092
|
-
Date.
|
1092
|
+
expect(Date).to receive(:today).and_return(Date.new(2012, 2, 5))
|
1093
1093
|
invoke "month"
|
1094
1094
|
|
1095
1095
|
|
1096
|
-
$stdout.string.
|
1097
|
-
$stdout.string.
|
1098
|
-
$stdout.string.
|
1096
|
+
expect($stdout.string).to include 'Feb 05, 2012'
|
1097
|
+
expect($stdout.string).to include 'Feb 06, 2012'
|
1098
|
+
expect($stdout.string).not_to include 'Jan'
|
1099
1099
|
end
|
1100
1100
|
|
1101
1101
|
it "should work in December" do
|
@@ -1104,10 +1104,10 @@ END:VCALENDAR
|
|
1104
1104
|
:end => Time.local(2012, 12, 5, 2, 2, 3)
|
1105
1105
|
)
|
1106
1106
|
|
1107
|
-
Date.
|
1107
|
+
expect(Date).to receive(:today).and_return(Date.new(2012, 12, 5))
|
1108
1108
|
invoke "month"
|
1109
1109
|
|
1110
|
-
$stdout.string.
|
1110
|
+
expect($stdout.string).to include 'Wed Dec 05, 2012 01:02:03 - 02:02:03'
|
1111
1111
|
end
|
1112
1112
|
end
|
1113
1113
|
|
@@ -1123,41 +1123,41 @@ END:VCALENDAR
|
|
1123
1123
|
it "should delete a timesheet" do
|
1124
1124
|
create_entry
|
1125
1125
|
entry = create_entry
|
1126
|
-
lambda do
|
1126
|
+
expect(lambda do
|
1127
1127
|
$stdin.string = "yes\n"
|
1128
1128
|
invoke "kill #{entry.sheet}"
|
1129
|
-
|
1129
|
+
end).to change(Timetrap::Entry, :count).by(-2)
|
1130
1130
|
end
|
1131
1131
|
|
1132
1132
|
it "should delete an entry" do
|
1133
1133
|
create_entry
|
1134
1134
|
entry = create_entry
|
1135
|
-
lambda do
|
1135
|
+
expect(lambda do
|
1136
1136
|
$stdin.string = "yes\n"
|
1137
1137
|
invoke "kill --id #{entry.id}"
|
1138
|
-
|
1138
|
+
end).to change(Timetrap::Entry, :count).by(-1)
|
1139
1139
|
end
|
1140
1140
|
|
1141
1141
|
it "should not prompt the user if the --yes flag is passed" do
|
1142
1142
|
create_entry
|
1143
1143
|
entry = create_entry
|
1144
|
-
lambda do
|
1144
|
+
expect(lambda do
|
1145
1145
|
invoke "kill --id #{entry.id} --yes"
|
1146
|
-
|
1146
|
+
end).to change(Timetrap::Entry, :count).by(-1)
|
1147
1147
|
end
|
1148
1148
|
|
1149
1149
|
describe "with a numeric sheet name" do
|
1150
1150
|
before do
|
1151
1151
|
now = local_time("2008-10-05 18:00:00")
|
1152
|
-
Time.
|
1152
|
+
allow(Time).to receive(:now).and_return now
|
1153
1153
|
create_entry( :sheet => 1234, :start => local_time_cli('2008-10-03 12:00:00'),
|
1154
1154
|
:end => local_time_cli('2008-10-03 14:00:00'))
|
1155
1155
|
end
|
1156
1156
|
|
1157
1157
|
it "should kill the sheet" do
|
1158
|
-
lambda do
|
1158
|
+
expect(lambda do
|
1159
1159
|
invoke 'kill -y 1234'
|
1160
|
-
|
1160
|
+
end).to change(Timetrap::Entry, :count).by(-1)
|
1161
1161
|
end
|
1162
1162
|
end
|
1163
1163
|
end
|
@@ -1166,21 +1166,21 @@ END:VCALENDAR
|
|
1166
1166
|
describe "with no sheets defined" do
|
1167
1167
|
it "should list the default sheet" do
|
1168
1168
|
invoke 'list'
|
1169
|
-
$stdout.string.chomp.
|
1169
|
+
expect($stdout.string.chomp).to eq " Timesheet Running Today Total Time\n*default 0:00:00 0:00:00 0:00:00"
|
1170
1170
|
end
|
1171
1171
|
end
|
1172
1172
|
|
1173
1173
|
describe "with a numeric sheet name" do
|
1174
1174
|
before do
|
1175
1175
|
now = local_time("2008-10-05 18:00:00")
|
1176
|
-
Time.
|
1176
|
+
allow(Time).to receive(:now).and_return now
|
1177
1177
|
create_entry( :sheet => '1234', :start => local_time_cli('2008-10-03 12:00:00'),
|
1178
1178
|
:end => local_time_cli('2008-10-03 14:00:00'))
|
1179
1179
|
end
|
1180
1180
|
|
1181
1181
|
it "should list the sheet" do
|
1182
1182
|
invoke 'list'
|
1183
|
-
$stdout.string.
|
1183
|
+
expect($stdout.string).to eq " Timesheet Running Today Total Time\n 1234 0:00:00 0:00:00 2:00:00\n*default 0:00:00 0:00:00 0:00:00\n"
|
1184
1184
|
end
|
1185
1185
|
end
|
1186
1186
|
|
@@ -1191,14 +1191,14 @@ END:VCALENDAR
|
|
1191
1191
|
|
1192
1192
|
it "should list the sheet" do
|
1193
1193
|
invoke 'list'
|
1194
|
-
$stdout.string.
|
1194
|
+
expect($stdout.string).to eq " Timesheet Running Today Total Time\n*1234 0:00:00 0:00:00 0:00:00\n"
|
1195
1195
|
end
|
1196
1196
|
end
|
1197
1197
|
|
1198
1198
|
describe "with sheets defined" do
|
1199
1199
|
before :each do
|
1200
1200
|
now = local_time("2008-10-05 18:00:00")
|
1201
|
-
Time.
|
1201
|
+
allow(Time).to receive(:now).and_return now
|
1202
1202
|
create_entry( :sheet => 'A Longly Named Sheet 2', :start => local_time_cli('2008-10-03 12:00:00'),
|
1203
1203
|
:end => local_time_cli('2008-10-03 14:00:00'))
|
1204
1204
|
create_entry( :sheet => 'A Longly Named Sheet 2', :start => local_time_cli('2008-10-03 12:00:00'),
|
@@ -1213,7 +1213,7 @@ END:VCALENDAR
|
|
1213
1213
|
end
|
1214
1214
|
it "should list available timesheets" do
|
1215
1215
|
invoke 'list'
|
1216
|
-
$stdout.string.
|
1216
|
+
expect($stdout.string).to eq <<-OUTPUT
|
1217
1217
|
Timesheet Running Today Total Time
|
1218
1218
|
*A Longly Named Sheet 2 4:00:00 6:00:00 10:00:00
|
1219
1219
|
Sheet 1 0:00:00 0:00:00 2:00:00
|
@@ -1224,7 +1224,7 @@ END:VCALENDAR
|
|
1224
1224
|
invoke 'sheet Sheet 1'
|
1225
1225
|
$stdout.string = ''
|
1226
1226
|
invoke 'list'
|
1227
|
-
$stdout.string.
|
1227
|
+
expect($stdout.string).to eq <<-OUTPUT
|
1228
1228
|
Timesheet Running Today Total Time
|
1229
1229
|
-A Longly Named Sheet 2 4:00:00 6:00:00 10:00:00
|
1230
1230
|
*Sheet 1 0:00:00 0:00:00 2:00:00
|
@@ -1236,7 +1236,7 @@ END:VCALENDAR
|
|
1236
1236
|
invoke 'sheet Sheet 1'
|
1237
1237
|
$stdout.string = ''
|
1238
1238
|
invoke 'list'
|
1239
|
-
$stdout.string.
|
1239
|
+
expect($stdout.string).to eq <<-OUTPUT
|
1240
1240
|
Timesheet Running Today Total Time
|
1241
1241
|
A Longly Named Sheet 2 4:00:00 6:00:00 10:00:00
|
1242
1242
|
*Sheet 1 0:00:00 0:00:00 2:00:00
|
@@ -1247,7 +1247,7 @@ END:VCALENDAR
|
|
1247
1247
|
invoke 'sheet empty sheet'
|
1248
1248
|
$stdout.string = ''
|
1249
1249
|
invoke 'list'
|
1250
|
-
$stdout.string.
|
1250
|
+
expect($stdout.string).to eq <<-OUTPUT
|
1251
1251
|
Timesheet Running Today Total Time
|
1252
1252
|
-A Longly Named Sheet 2 4:00:00 6:00:00 10:00:00
|
1253
1253
|
*empty sheet 0:00:00 0:00:00 0:00:00
|
@@ -1265,7 +1265,7 @@ END:VCALENDAR
|
|
1265
1265
|
describe "when the current timesheet isn't running" do
|
1266
1266
|
it "should show that it isn't running" do
|
1267
1267
|
invoke 'now'
|
1268
|
-
$stderr.string.
|
1268
|
+
expect($stderr.string).to eq <<-OUTPUT
|
1269
1269
|
*current sheet: not running
|
1270
1270
|
OUTPUT
|
1271
1271
|
end
|
@@ -1277,12 +1277,12 @@ END:VCALENDAR
|
|
1277
1277
|
@entry = Timetrap::Timer.active_entry
|
1278
1278
|
@entry.start = Time.at(0)
|
1279
1279
|
@entry.save
|
1280
|
-
Time.
|
1280
|
+
allow(Time).to receive(:now).and_return Time.at(60)
|
1281
1281
|
end
|
1282
1282
|
|
1283
1283
|
it "should show how long the current item is running for" do
|
1284
1284
|
invoke 'now'
|
1285
|
-
$stdout.string.
|
1285
|
+
expect($stdout.string).to eq <<-OUTPUT
|
1286
1286
|
*current sheet: 0:01:00 (a timesheet that is running)
|
1287
1287
|
OUTPUT
|
1288
1288
|
end
|
@@ -1294,12 +1294,12 @@ END:VCALENDAR
|
|
1294
1294
|
@entry = Timetrap::Timer.active_entry
|
1295
1295
|
@entry.start = Time.at(0)
|
1296
1296
|
@entry.save
|
1297
|
-
Time.
|
1297
|
+
allow(Time).to receive(:now).and_return Time.at(60)
|
1298
1298
|
end
|
1299
1299
|
|
1300
1300
|
it "should show both entries" do
|
1301
1301
|
invoke 'now'
|
1302
|
-
$stdout.string.
|
1302
|
+
expect($stdout.string).to eq <<-OUTPUT
|
1303
1303
|
current sheet: 0:01:00 (a timesheet that is running)
|
1304
1304
|
*another-sheet: 0:01:00 (also running)
|
1305
1305
|
OUTPUT
|
@@ -1313,41 +1313,41 @@ END:VCALENDAR
|
|
1313
1313
|
invoke 'in'
|
1314
1314
|
@active = Timetrap::Timer.active_entry
|
1315
1315
|
@now = Time.now
|
1316
|
-
Time.
|
1316
|
+
allow(Time).to receive(:now).and_return @now
|
1317
1317
|
end
|
1318
1318
|
it "should set the stop for the running entry" do
|
1319
|
-
@active.refresh.end.
|
1319
|
+
expect(@active.refresh.end).to eq nil
|
1320
1320
|
invoke 'out'
|
1321
|
-
@active.refresh.end.to_i.
|
1321
|
+
expect(@active.refresh.end.to_i).to eq @now.to_i
|
1322
1322
|
end
|
1323
1323
|
|
1324
1324
|
it "should not do anything if nothing is running" do
|
1325
|
-
lambda do
|
1325
|
+
expect(lambda do
|
1326
1326
|
invoke 'out'
|
1327
1327
|
invoke 'out'
|
1328
|
-
|
1328
|
+
end).not_to raise_error
|
1329
1329
|
end
|
1330
1330
|
|
1331
1331
|
it "should allow the sheet to be stopped at a certain time" do
|
1332
1332
|
invoke 'out --at "10am 2008-10-03"'
|
1333
|
-
@active.refresh.end.
|
1333
|
+
expect(@active.refresh.end).to eq Time.parse('2008-10-03 10:00')
|
1334
1334
|
end
|
1335
1335
|
|
1336
1336
|
it "should allow you to check out of a non active sheet" do
|
1337
1337
|
invoke 'sheet SomeOtherSheet'
|
1338
1338
|
invoke 'in'
|
1339
1339
|
@new_active = Timetrap::Timer.active_entry
|
1340
|
-
@active.
|
1340
|
+
expect(@active).not_to eq @new_active
|
1341
1341
|
invoke %'out #{@active.sheet} --at "10am 2008-10-03"'
|
1342
|
-
@active.refresh.end.
|
1343
|
-
@new_active.refresh.end.
|
1342
|
+
expect(@active.refresh.end).to eq Time.parse('2008-10-03 10:00')
|
1343
|
+
expect(@new_active.refresh.end).to be_nil
|
1344
1344
|
end
|
1345
1345
|
end
|
1346
1346
|
|
1347
1347
|
describe "resume" do
|
1348
1348
|
before :each do
|
1349
1349
|
@time = Time.now
|
1350
|
-
Time.
|
1350
|
+
allow(Time).to receive(:now).and_return @time
|
1351
1351
|
|
1352
1352
|
invoke 'in A previous task that isnt last'
|
1353
1353
|
@previous = Timetrap::Timer.active_entry
|
@@ -1357,15 +1357,15 @@ END:VCALENDAR
|
|
1357
1357
|
@last_active = Timetrap::Timer.active_entry
|
1358
1358
|
invoke 'out'
|
1359
1359
|
|
1360
|
-
Timetrap::Timer.active_entry.
|
1361
|
-
@last_active.
|
1360
|
+
expect(Timetrap::Timer.active_entry).to be_nil
|
1361
|
+
expect(@last_active).not_to be_nil
|
1362
1362
|
end
|
1363
1363
|
|
1364
1364
|
it "should allow to resume the last active entry" do
|
1365
1365
|
invoke 'resume'
|
1366
1366
|
|
1367
|
-
Timetrap::Timer.active_entry.note.
|
1368
|
-
Timetrap::Timer.active_entry.start.to_s.
|
1367
|
+
expect(Timetrap::Timer.active_entry.note).to eq(@last_active.note)
|
1368
|
+
expect(Timetrap::Timer.active_entry.start.to_s).to eq @time.to_s
|
1369
1369
|
end
|
1370
1370
|
|
1371
1371
|
it "should allow to resume the last entry from the current sheet" do
|
@@ -1375,28 +1375,28 @@ END:VCALENDAR
|
|
1375
1375
|
invoke 'sheet -'
|
1376
1376
|
invoke 'resume'
|
1377
1377
|
|
1378
|
-
Timetrap::Timer.active_entry.note.
|
1379
|
-
Timetrap::Timer.active_entry.start.to_s.
|
1378
|
+
expect(Timetrap::Timer.active_entry.note).to eq(@last_active.note)
|
1379
|
+
expect(Timetrap::Timer.active_entry.start.to_s).to eq @time.to_s
|
1380
1380
|
end
|
1381
1381
|
|
1382
1382
|
it "should allow to resume a specific entry" do
|
1383
1383
|
invoke "resume --id #{@previous.id}"
|
1384
1384
|
|
1385
|
-
Timetrap::Timer.active_entry.note.
|
1386
|
-
Timetrap::Timer.active_entry.start.to_s.
|
1385
|
+
expect(Timetrap::Timer.active_entry.note).to eq(@previous.note)
|
1386
|
+
expect(Timetrap::Timer.active_entry.start.to_s).to eq @time.to_s
|
1387
1387
|
end
|
1388
1388
|
|
1389
1389
|
it "should allow to resume a specific entry with a given time" do
|
1390
1390
|
invoke "resume --id #{@previous.id} --at \"10am 2008-10-03\""
|
1391
1391
|
|
1392
|
-
Timetrap::Timer.active_entry.note.
|
1393
|
-
Timetrap::Timer.active_entry.start.
|
1392
|
+
expect(Timetrap::Timer.active_entry.note).to eq(@previous.note)
|
1393
|
+
expect(Timetrap::Timer.active_entry.start).to eql(Time.parse('2008-10-03 10:00'))
|
1394
1394
|
end
|
1395
1395
|
|
1396
1396
|
it "should allow to resume the activity with a given time" do
|
1397
1397
|
invoke 'resume --at "10am 2008-10-03"'
|
1398
1398
|
|
1399
|
-
Timetrap::Timer.active_entry.start.
|
1399
|
+
expect(Timetrap::Timer.active_entry.start).to eql(Time.parse('2008-10-03 10:00'))
|
1400
1400
|
end
|
1401
1401
|
|
1402
1402
|
describe "no existing entries" do
|
@@ -1405,8 +1405,8 @@ END:VCALENDAR
|
|
1405
1405
|
e.destroy
|
1406
1406
|
end
|
1407
1407
|
|
1408
|
-
Timetrap::Timer.entries(Timetrap::Timer.current_sheet).
|
1409
|
-
Timetrap::Timer.active_entry.
|
1408
|
+
expect(Timetrap::Timer.entries(Timetrap::Timer.current_sheet)).to be_empty
|
1409
|
+
expect(Timetrap::Timer.active_entry).to be_nil
|
1410
1410
|
end
|
1411
1411
|
|
1412
1412
|
end
|
@@ -1415,15 +1415,15 @@ END:VCALENDAR
|
|
1415
1415
|
before(:each) do
|
1416
1416
|
$stdin.string = "yes\n"
|
1417
1417
|
invoke "archive"
|
1418
|
-
Timetrap::Timer.entries(Timetrap::Timer.current_sheet).
|
1419
|
-
Timetrap::Timer.active_entry.
|
1418
|
+
expect(Timetrap::Timer.entries(Timetrap::Timer.current_sheet)).to be_empty
|
1419
|
+
expect(Timetrap::Timer.active_entry).to be_nil
|
1420
1420
|
end
|
1421
1421
|
|
1422
1422
|
it "retrieves the note of the most recent archived entry" do
|
1423
1423
|
invoke "resume"
|
1424
|
-
Timetrap::Timer.active_entry.
|
1425
|
-
Timetrap::Timer.active_entry.note.
|
1426
|
-
Timetrap::Timer.active_entry.start.to_s.
|
1424
|
+
expect(Timetrap::Timer.active_entry).not_to be_nil
|
1425
|
+
expect(Timetrap::Timer.active_entry.note).to eq @last_active.note
|
1426
|
+
expect(Timetrap::Timer.active_entry.start.to_s).to eq @time.to_s
|
1427
1427
|
end
|
1428
1428
|
end
|
1429
1429
|
|
@@ -1433,9 +1433,9 @@ END:VCALENDAR
|
|
1433
1433
|
end
|
1434
1434
|
|
1435
1435
|
it "should check in normally if nothing else is running" do
|
1436
|
-
Timetrap::Timer.
|
1436
|
+
expect(Timetrap::Timer).not_to be_running #precondition
|
1437
1437
|
invoke 'resume'
|
1438
|
-
Timetrap::Timer.
|
1438
|
+
expect(Timetrap::Timer).to be_running
|
1439
1439
|
end
|
1440
1440
|
|
1441
1441
|
describe "with a running entry on current sheet" do
|
@@ -1447,7 +1447,7 @@ END:VCALENDAR
|
|
1447
1447
|
it "should check out and back in" do
|
1448
1448
|
entry = Timetrap::Timer.active_entry('sheet1')
|
1449
1449
|
invoke 'resume second task'
|
1450
|
-
Timetrap::Timer.active_entry('sheet1').id.
|
1450
|
+
expect(Timetrap::Timer.active_entry('sheet1').id).not_to eq entry.id
|
1451
1451
|
end
|
1452
1452
|
end
|
1453
1453
|
|
@@ -1463,17 +1463,17 @@ END:VCALENDAR
|
|
1463
1463
|
end
|
1464
1464
|
|
1465
1465
|
it "should check out of the running entry" do
|
1466
|
-
Timetrap::Timer.active_entry('sheet1').
|
1466
|
+
expect(Timetrap::Timer.active_entry('sheet1')).to be_a(Timetrap::Entry)
|
1467
1467
|
invoke 'resume'
|
1468
|
-
Timetrap::Timer.active_entry('sheet1').
|
1468
|
+
expect(Timetrap::Timer.active_entry('sheet1')).to be nil
|
1469
1469
|
end
|
1470
1470
|
|
1471
1471
|
it "should check out of the running entry at another time" do
|
1472
1472
|
now = Time.at(Time.now - 5 * 60) # 5 minutes ago
|
1473
1473
|
entry = Timetrap::Timer.active_entry('sheet1')
|
1474
|
-
entry.
|
1474
|
+
expect(entry).to be_a(Timetrap::Entry)
|
1475
1475
|
invoke "resume -a '#{now}'"
|
1476
|
-
entry.reload.end.to_s.
|
1476
|
+
expect(entry.reload.end.to_s).to eq now.to_s
|
1477
1477
|
end
|
1478
1478
|
end
|
1479
1479
|
end
|
@@ -1482,36 +1482,42 @@ END:VCALENDAR
|
|
1482
1482
|
describe "sheet" do
|
1483
1483
|
it "should switch to a new timesheet" do
|
1484
1484
|
invoke 'sheet sheet 1'
|
1485
|
-
Timetrap::Timer.current_sheet.
|
1485
|
+
expect(Timetrap::Timer.current_sheet).to eq 'sheet 1'
|
1486
1486
|
invoke 'sheet sheet 2'
|
1487
|
-
Timetrap::Timer.current_sheet.
|
1487
|
+
expect(Timetrap::Timer.current_sheet).to eq 'sheet 2'
|
1488
1488
|
end
|
1489
1489
|
|
1490
1490
|
it "should not switch to an blank timesheet" do
|
1491
1491
|
invoke 'sheet sheet 1'
|
1492
1492
|
invoke 'sheet'
|
1493
|
-
Timetrap::Timer.current_sheet.
|
1493
|
+
expect(Timetrap::Timer.current_sheet).to eq 'sheet 1'
|
1494
1494
|
end
|
1495
1495
|
|
1496
1496
|
it "should list timesheets when there are no arguments" do
|
1497
1497
|
invoke 'sheet sheet 1'
|
1498
1498
|
invoke 'sheet'
|
1499
|
-
$stdout.string.
|
1499
|
+
expect($stdout.string).to eq " Timesheet Running Today Total Time\n*sheet 1 0:00:00 0:00:00 0:00:00\n"
|
1500
|
+
end
|
1501
|
+
|
1502
|
+
it "should note if the user is already on that sheet" do
|
1503
|
+
invoke 'sheet sheet 1'
|
1504
|
+
invoke 'sheet sheet 1'
|
1505
|
+
expect($stderr.string).to eq "Switching to sheet \"sheet 1\"\nAlready on sheet \"sheet 1\"\n"
|
1500
1506
|
end
|
1501
1507
|
|
1502
1508
|
describe "using - to switch to the last sheet" do
|
1503
1509
|
it "should warn if there isn't a sheet set" do
|
1504
|
-
lambda do
|
1510
|
+
expect(lambda do
|
1505
1511
|
invoke 'sheet -'
|
1506
|
-
|
1507
|
-
|
1512
|
+
end).not_to change(Timetrap::Timer, :current_sheet)
|
1513
|
+
expect($stderr.string).to include 'LAST_SHEET is not set'
|
1508
1514
|
end
|
1509
1515
|
|
1510
1516
|
it "should switch to the last active sheet" do
|
1511
1517
|
invoke 'sheet second'
|
1512
|
-
lambda do
|
1518
|
+
expect(lambda do
|
1513
1519
|
invoke 'sheet -'
|
1514
|
-
|
1520
|
+
end).to change(Timetrap::Timer, :current_sheet).
|
1515
1521
|
from('second').to('default')
|
1516
1522
|
end
|
1517
1523
|
|
@@ -1520,9 +1526,9 @@ END:VCALENDAR
|
|
1520
1526
|
invoke 'sheet second'
|
1521
1527
|
5.times do
|
1522
1528
|
invoke 's -'
|
1523
|
-
Timetrap::Timer.current_sheet.
|
1529
|
+
expect(Timetrap::Timer.current_sheet).to eq 'first'
|
1524
1530
|
invoke 's -'
|
1525
|
-
Timetrap::Timer.current_sheet.
|
1531
|
+
expect(Timetrap::Timer.current_sheet).to eq 'second'
|
1526
1532
|
end
|
1527
1533
|
end
|
1528
1534
|
end
|
@@ -1535,7 +1541,7 @@ END:VCALENDAR
|
|
1535
1541
|
rescue SystemExit #Getopt::Declare calls exit after --version is invoked
|
1536
1542
|
end
|
1537
1543
|
|
1538
|
-
$stdout.string.
|
1544
|
+
expect($stdout.string).to include(::Timetrap::VERSION)
|
1539
1545
|
end
|
1540
1546
|
end
|
1541
1547
|
end
|
@@ -1544,7 +1550,7 @@ END:VCALENDAR
|
|
1544
1550
|
describe "entries" do
|
1545
1551
|
it "should give the entires for a sheet" do
|
1546
1552
|
e = create_entry :sheet => 'sheet'
|
1547
|
-
Timetrap::Timer.entries('sheet').all.
|
1553
|
+
expect(Timetrap::Timer.entries('sheet').all).to include(e)
|
1548
1554
|
end
|
1549
1555
|
|
1550
1556
|
end
|
@@ -1553,26 +1559,26 @@ END:VCALENDAR
|
|
1553
1559
|
it "should start an new entry" do
|
1554
1560
|
@time = Time.now
|
1555
1561
|
Timetrap::Timer.current_sheet = 'sheet1'
|
1556
|
-
lambda do
|
1562
|
+
expect(lambda do
|
1557
1563
|
Timetrap::Timer.start 'some work', @time
|
1558
|
-
|
1559
|
-
Timetrap::Entry.order(:id).last.sheet.
|
1560
|
-
Timetrap::Entry.order(:id).last.note.
|
1561
|
-
Timetrap::Entry.order(:id).last.start.to_i.
|
1562
|
-
Timetrap::Entry.order(:id).last.end.
|
1564
|
+
end).to change(Timetrap::Entry, :count).by(1)
|
1565
|
+
expect(Timetrap::Entry.order(:id).last.sheet).to eq 'sheet1'
|
1566
|
+
expect(Timetrap::Entry.order(:id).last.note).to eq 'some work'
|
1567
|
+
expect(Timetrap::Entry.order(:id).last.start.to_i).to eq @time.to_i
|
1568
|
+
expect(Timetrap::Entry.order(:id).last.end).to be_nil
|
1563
1569
|
end
|
1564
1570
|
|
1565
1571
|
it "should be running if it is started" do
|
1566
|
-
Timetrap::Timer.
|
1572
|
+
expect(Timetrap::Timer).not_to be_running
|
1567
1573
|
Timetrap::Timer.start 'some work', @time
|
1568
|
-
Timetrap::Timer.
|
1574
|
+
expect(Timetrap::Timer).to be_running
|
1569
1575
|
end
|
1570
1576
|
|
1571
1577
|
it "should raise an error if it is already running" do
|
1572
|
-
lambda do
|
1578
|
+
expect(lambda do
|
1573
1579
|
Timetrap::Timer.start 'some work', @time
|
1574
1580
|
Timetrap::Timer.start 'some work', @time
|
1575
|
-
|
1581
|
+
end).to raise_error(Timetrap::Timer::AlreadyRunning)
|
1576
1582
|
end
|
1577
1583
|
end
|
1578
1584
|
|
@@ -1581,16 +1587,16 @@ END:VCALENDAR
|
|
1581
1587
|
@time = Time.now
|
1582
1588
|
Timetrap::Timer.start 'some work', @time
|
1583
1589
|
entry = Timetrap::Timer.active_entry
|
1584
|
-
entry.end.
|
1590
|
+
expect(entry.end).to be_nil
|
1585
1591
|
Timetrap::Timer.stop Timetrap::Timer.current_sheet, @time
|
1586
|
-
entry.refresh.end.to_i.
|
1592
|
+
expect(entry.refresh.end.to_i).to eq @time.to_i
|
1587
1593
|
end
|
1588
1594
|
|
1589
1595
|
it "should not be running if it is stopped" do
|
1590
|
-
Timetrap::Timer.
|
1596
|
+
expect(Timetrap::Timer).not_to be_running
|
1591
1597
|
Timetrap::Timer.start 'some work', @time
|
1592
1598
|
Timetrap::Timer.stop Timetrap::Timer.current_sheet
|
1593
|
-
Timetrap::Timer.
|
1599
|
+
expect(Timetrap::Timer).not_to be_running
|
1594
1600
|
end
|
1595
1601
|
|
1596
1602
|
it "should not stop it twice" do
|
@@ -1599,14 +1605,14 @@ END:VCALENDAR
|
|
1599
1605
|
Timetrap::Timer.stop Timetrap::Timer.current_sheet
|
1600
1606
|
time = e.refresh.end
|
1601
1607
|
Timetrap::Timer.stop Timetrap::Timer.current_sheet
|
1602
|
-
time.to_i.
|
1608
|
+
expect(time.to_i).to eq e.refresh.end.to_i
|
1603
1609
|
end
|
1604
1610
|
|
1605
1611
|
it "should track the last entry that was checked out of" do
|
1606
1612
|
Timetrap::Timer.start 'some work'
|
1607
1613
|
e = Timetrap::Timer.active_entry
|
1608
1614
|
Timetrap::Timer.stop Timetrap::Timer.current_sheet
|
1609
|
-
Timetrap::Timer.last_checkout.id.
|
1615
|
+
expect(Timetrap::Timer.last_checkout.id).to eq e.id
|
1610
1616
|
end
|
1611
1617
|
|
1612
1618
|
end
|
@@ -1617,11 +1623,11 @@ END:VCALENDAR
|
|
1617
1623
|
@helper.extend Timetrap::Helpers
|
1618
1624
|
end
|
1619
1625
|
it "should correctly format positive durations" do
|
1620
|
-
@helper.format_duration(1234).
|
1626
|
+
expect(@helper.format_duration(1234)).to eq " 0:20:34"
|
1621
1627
|
end
|
1622
1628
|
|
1623
1629
|
it "should correctly format negative durations" do
|
1624
|
-
@helper.format_duration(-1234).
|
1630
|
+
expect(@helper.format_duration(-1234)).to eq "- 0:20:34"
|
1625
1631
|
end
|
1626
1632
|
end
|
1627
1633
|
|
@@ -1643,7 +1649,7 @@ END:VCALENDAR
|
|
1643
1649
|
Timetrap::Entry.create( :sheet => 'SpecSheet',
|
1644
1650
|
:note => 'entry 2', :start => '2008-10-03 16:00:00', :end => '2008-10-03 18:00:00'
|
1645
1651
|
)
|
1646
|
-
Timetrap::Entry.sheets.
|
1652
|
+
expect(Timetrap::Entry.sheets).to eq %w(another SpecSheet).sort
|
1647
1653
|
end
|
1648
1654
|
end
|
1649
1655
|
|
@@ -1651,22 +1657,22 @@ END:VCALENDAR
|
|
1651
1657
|
describe 'attributes' do
|
1652
1658
|
it "should have a note" do
|
1653
1659
|
@entry.note = "world takeover"
|
1654
|
-
@entry.note.
|
1660
|
+
expect(@entry.note).to eq "world takeover"
|
1655
1661
|
end
|
1656
1662
|
|
1657
1663
|
it "should have a start" do
|
1658
1664
|
@entry.start = @time
|
1659
|
-
@entry.start.to_i.
|
1665
|
+
expect(@entry.start.to_i).to eq @time.to_i
|
1660
1666
|
end
|
1661
1667
|
|
1662
1668
|
it "should have a end" do
|
1663
1669
|
@entry.end = @time
|
1664
|
-
@entry.end.to_i.
|
1670
|
+
expect(@entry.end.to_i).to eq @time.to_i
|
1665
1671
|
end
|
1666
1672
|
|
1667
1673
|
it "should have a sheet" do
|
1668
1674
|
@entry.sheet= 'name'
|
1669
|
-
@entry.sheet.
|
1675
|
+
expect(@entry.sheet).to eq 'name'
|
1670
1676
|
end
|
1671
1677
|
|
1672
1678
|
def with_rounding_on
|
@@ -1684,7 +1690,7 @@ END:VCALENDAR
|
|
1684
1690
|
with_stubbed_config('round_in_seconds' => 900) do
|
1685
1691
|
@time = Chronic.parse("12:55")
|
1686
1692
|
@entry.start = @time
|
1687
|
-
@entry.start.
|
1693
|
+
expect(@entry.start).to eq Chronic.parse("1")
|
1688
1694
|
end
|
1689
1695
|
end
|
1690
1696
|
end
|
@@ -1694,7 +1700,7 @@ END:VCALENDAR
|
|
1694
1700
|
with_stubbed_config('round_in_seconds' => 900) do
|
1695
1701
|
@time = Chronic.parse("12:50")
|
1696
1702
|
@entry.start = @time
|
1697
|
-
@entry.start.
|
1703
|
+
expect(@entry.start).to eq Chronic.parse("12:45")
|
1698
1704
|
end
|
1699
1705
|
end
|
1700
1706
|
end
|
@@ -1703,27 +1709,27 @@ END:VCALENDAR
|
|
1703
1709
|
with_stubbed_config('round_in_seconds' => 900) do
|
1704
1710
|
@time = Chronic.parse("12:50")
|
1705
1711
|
@entry.start = @time
|
1706
|
-
@entry.rounded_start.
|
1712
|
+
expect(@entry.rounded_start).to eq Chronic.parse("12:45")
|
1707
1713
|
end
|
1708
1714
|
end
|
1709
1715
|
|
1710
1716
|
it "should not round nil times" do
|
1711
1717
|
@entry.start = nil
|
1712
|
-
@entry.rounded_start.
|
1718
|
+
expect(@entry.rounded_start).to be_nil
|
1713
1719
|
end
|
1714
1720
|
end
|
1715
1721
|
|
1716
1722
|
describe "parsing natural language times" do
|
1717
1723
|
it "should set start time using english" do
|
1718
1724
|
@entry.start = "yesterday 10am"
|
1719
|
-
@entry.start.
|
1720
|
-
@entry.start.
|
1725
|
+
expect(@entry.start).not_to be_nil
|
1726
|
+
expect(@entry.start).to eq Chronic.parse("yesterday 10am")
|
1721
1727
|
end
|
1722
1728
|
|
1723
1729
|
it "should set end time using english" do
|
1724
1730
|
@entry.end = "tomorrow 1pm"
|
1725
|
-
@entry.end.
|
1726
|
-
@entry.end.
|
1731
|
+
expect(@entry.end).not_to be_nil
|
1732
|
+
expect(@entry.end).to eq Chronic.parse("tomorrow 1pm")
|
1727
1733
|
end
|
1728
1734
|
end
|
1729
1735
|
|
@@ -1734,21 +1740,21 @@ END:VCALENDAR
|
|
1734
1740
|
|
1735
1741
|
# should be about 55 minutes duration. Allow for second rollover
|
1736
1742
|
# within this test.
|
1737
|
-
(3299..3301).
|
1743
|
+
expect((3299..3301)).to include(@entry.duration)
|
1738
1744
|
end
|
1739
1745
|
|
1740
1746
|
it "should not assume negative durations around 12 hour length" do
|
1741
1747
|
@entry.start= Time.at(Time.now - (15 * 3600)) # 15.hour.ago
|
1742
1748
|
@entry.end = Time.at(Time.now - 300).strftime("%H:%M:%S") # ambiguous 5.minutes.ago
|
1743
1749
|
|
1744
|
-
(53699..53701).
|
1750
|
+
expect((53699..53701)).to include(@entry.duration)
|
1745
1751
|
end
|
1746
1752
|
|
1747
1753
|
it "should assume a start time near the current time" do
|
1748
1754
|
time = Time.at(Time.now - 300)
|
1749
1755
|
@entry.start= time.strftime("%H:%M:%S") # ambiguous 5.minutes.ago
|
1750
1756
|
|
1751
|
-
@entry.start.to_i.
|
1757
|
+
expect(@entry.start.to_i).to eq time.to_i
|
1752
1758
|
end
|
1753
1759
|
end
|
1754
1760
|
end
|
@@ -1759,8 +1765,8 @@ END:VCALENDAR
|
|
1759
1765
|
it 'should include a t bin and an equivalent timetrap bin' do
|
1760
1766
|
timetrap = File.open(File.expand_path(File.join(File.dirname(__FILE__), '..', 'bin', 'timetrap')))
|
1761
1767
|
t = File.open(File.expand_path(File.join(File.dirname(__FILE__), '..', 'bin', 't')))
|
1762
|
-
t.read.
|
1763
|
-
t.stat.mode.
|
1768
|
+
expect(t.read).to eq timetrap.read
|
1769
|
+
expect(t.stat.mode).to eq timetrap.stat.mode
|
1764
1770
|
end
|
1765
1771
|
end
|
1766
1772
|
|