timetrap 1.15.1 → 1.15.2
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.
- 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
|
|