tempo-cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +56 -0
- data/README.md +326 -0
- data/Rakefile +65 -0
- data/bin/tempo +477 -0
- data/features/arrange.feature +43 -0
- data/features/checkout.feature +63 -0
- data/features/end.feature +65 -0
- data/features/project.feature +246 -0
- data/features/report.feature +62 -0
- data/features/start.feature +87 -0
- data/features/step_definitions/tempo_steps.rb +138 -0
- data/features/support/env.rb +26 -0
- data/features/tempo.feature +13 -0
- data/features/update.feature +69 -0
- data/lib/file_record/directory.rb +11 -0
- data/lib/file_record/directory_structure/tempo/README.txt +4 -0
- data/lib/file_record/directory_structure/tempo/tempo_projects.yaml +6 -0
- data/lib/file_record/record.rb +120 -0
- data/lib/tempo/controllers/arrange_controller.rb +52 -0
- data/lib/tempo/controllers/base.rb +117 -0
- data/lib/tempo/controllers/checkout_controller.rb +42 -0
- data/lib/tempo/controllers/end_controller.rb +42 -0
- data/lib/tempo/controllers/projects_controller.rb +107 -0
- data/lib/tempo/controllers/records_controller.rb +21 -0
- data/lib/tempo/controllers/report_controller.rb +55 -0
- data/lib/tempo/controllers/start_controller.rb +42 -0
- data/lib/tempo/controllers/update_controller.rb +78 -0
- data/lib/tempo/models/base.rb +176 -0
- data/lib/tempo/models/composite.rb +71 -0
- data/lib/tempo/models/log.rb +194 -0
- data/lib/tempo/models/project.rb +73 -0
- data/lib/tempo/models/time_record.rb +235 -0
- data/lib/tempo/version.rb +3 -0
- data/lib/tempo/views/arrange_view.rb +27 -0
- data/lib/tempo/views/base.rb +82 -0
- data/lib/tempo/views/formatters/base.rb +30 -0
- data/lib/tempo/views/formatters/screen.rb +86 -0
- data/lib/tempo/views/projects_view.rb +82 -0
- data/lib/tempo/views/report_view.rb +26 -0
- data/lib/tempo/views/reporter.rb +70 -0
- data/lib/tempo/views/time_record_view.rb +30 -0
- data/lib/tempo/views/view_records/base.rb +117 -0
- data/lib/tempo/views/view_records/composite.rb +40 -0
- data/lib/tempo/views/view_records/log.rb +28 -0
- data/lib/tempo/views/view_records/project.rb +32 -0
- data/lib/tempo/views/view_records/time_record.rb +48 -0
- data/lib/tempo.rb +26 -0
- data/lib/time_utilities.rb +30 -0
- data/tempo-cli.gemspec +26 -0
- data/test/lib/file_record/directory_test.rb +30 -0
- data/test/lib/file_record/record_test.rb +106 -0
- data/test/lib/tempo/controllers/base_controller_test.rb +60 -0
- data/test/lib/tempo/controllers/project_controller_test.rb +24 -0
- data/test/lib/tempo/models/base_test.rb +173 -0
- data/test/lib/tempo/models/composite_test.rb +76 -0
- data/test/lib/tempo/models/log_test.rb +171 -0
- data/test/lib/tempo/models/project_test.rb +105 -0
- data/test/lib/tempo/models/time_record_test.rb +212 -0
- data/test/lib/tempo/views/base_test.rb +31 -0
- data/test/lib/tempo/views/formatters/base_test.rb +13 -0
- data/test/lib/tempo/views/formatters/screen_test.rb +94 -0
- data/test/lib/tempo/views/reporter_test.rb +40 -0
- data/test/lib/tempo/views/view_records/base_test.rb +77 -0
- data/test/lib/tempo/views/view_records/composite_test.rb +57 -0
- data/test/lib/tempo/views/view_records/log_test.rb +28 -0
- data/test/lib/tempo/views/view_records/project_test.rb +0 -0
- data/test/lib/tempo/views/view_records/time_record_test.rb +0 -0
- data/test/support/factories.rb +177 -0
- data/test/support/helpers.rb +69 -0
- data/test/test_helper.rb +31 -0
- metadata +230 -0
data/bin/tempo
ADDED
@@ -0,0 +1,477 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# In development, you need to use `bundle exec bin/tempo` to run this app
|
4
|
+
require 'gli'
|
5
|
+
require 'tempo'
|
6
|
+
require 'pry'
|
7
|
+
include GLI::App
|
8
|
+
# to preserve all the args in ARGV:
|
9
|
+
# preserve_argv
|
10
|
+
|
11
|
+
program_desc 'Command line time tracking by project'
|
12
|
+
|
13
|
+
version Tempo::VERSION
|
14
|
+
|
15
|
+
# == GLOBAL OPTIONS ==
|
16
|
+
|
17
|
+
desc 'verbose output'
|
18
|
+
long_desc 'include verbose reporting in the command output'
|
19
|
+
switch [:v, :verbose]
|
20
|
+
|
21
|
+
desc 'output id'
|
22
|
+
long_desc 'include id reporting in the command output'
|
23
|
+
switch [:i, :id]
|
24
|
+
|
25
|
+
# desc 'Describe some flag here'
|
26
|
+
# default_value 'the default'
|
27
|
+
# arg_name 'The name of the argument'
|
28
|
+
# flag [:f,:flagname]
|
29
|
+
|
30
|
+
# COMMAND: PROJECT
|
31
|
+
|
32
|
+
desc 'Manage the Projects that timed tasks are assigned to'
|
33
|
+
long_desc "Manage the Projects that timed tasks are assigned to.
|
34
|
+
|
35
|
+
Manage the Projects that timed tasks are assigned to.
|
36
|
+
By default, lists the current project, or with --list tag, lists all projects.
|
37
|
+
The active project will be marked by an asterisk.
|
38
|
+
|
39
|
+
If supplied with arguments and no command options,
|
40
|
+
a new project will be added.
|
41
|
+
|
42
|
+
Arguments supplied to --list, --delete, and --[un]tag
|
43
|
+
will use fuzzy matching unless you:
|
44
|
+
|
45
|
+
- Use the --exact flag to match the arguments exactly
|
46
|
+
|
47
|
+
- Use the --id tag to match by id
|
48
|
+
|
49
|
+
examples:
|
50
|
+
|
51
|
+
# list current project
|
52
|
+
|
53
|
+
$ tempo project
|
54
|
+
|
55
|
+
# list all projects
|
56
|
+
|
57
|
+
$ tempo project --list
|
58
|
+
|
59
|
+
# adding a new project titled 'star gazing'
|
60
|
+
|
61
|
+
$ tempo project star gazing
|
62
|
+
|
63
|
+
# adding a new project with a tag
|
64
|
+
|
65
|
+
$ tempo project --add star gazing --tag cellar
|
66
|
+
|
67
|
+
# untagging and tagging an existing project
|
68
|
+
|
69
|
+
$ tempo project star gazing --untag cellar --tag stellar"
|
70
|
+
|
71
|
+
arg_name '"name of the project"'
|
72
|
+
command [:project, :p] do |c|
|
73
|
+
|
74
|
+
c.desc 'Add a Project'
|
75
|
+
c.long_desc "Add a Project (default command behavior). When used with --tag adds a new project with the given tag"
|
76
|
+
c.switch [:a, :add], negatable: false
|
77
|
+
|
78
|
+
c.desc 'List Projects'
|
79
|
+
c.long_desc "Lists all projects that match the supplied argument"
|
80
|
+
c.switch [:l, :list], negatable: false
|
81
|
+
|
82
|
+
c.desc 'Exact Match'
|
83
|
+
c.long_desc "Match project with an exact title"
|
84
|
+
c.switch [:e, :exact]
|
85
|
+
|
86
|
+
c.desc 'List by or perform command by project id'
|
87
|
+
c.long_desc 'show IDs in output or perform command by matching to id'
|
88
|
+
c.switch [:i, :id], negatable: false
|
89
|
+
|
90
|
+
c.desc 'Delete a Project'
|
91
|
+
c.default_value nil
|
92
|
+
c.arg_name 'title'
|
93
|
+
c.flag [:d, :delete]
|
94
|
+
|
95
|
+
c.desc 'Tag a Project'
|
96
|
+
c.long_desc "Tag a project with one-word tags. Pass multiple tags in quotes to add multiple tags"
|
97
|
+
c.default_value nil
|
98
|
+
c.arg_name 'tagword'
|
99
|
+
c.flag [:t, :tag]
|
100
|
+
|
101
|
+
c.desc 'Untag a Project'
|
102
|
+
c.default_value nil
|
103
|
+
c.arg_name 'tagword'
|
104
|
+
c.flag [:u, :untag]
|
105
|
+
|
106
|
+
c.action do |global_options, options, args|
|
107
|
+
|
108
|
+
controller = Tempo::Controllers::Projects
|
109
|
+
|
110
|
+
# tag a project
|
111
|
+
#
|
112
|
+
if options[:tag]
|
113
|
+
controller.tag options, args
|
114
|
+
|
115
|
+
# untag a project
|
116
|
+
#
|
117
|
+
elsif options[:untag]
|
118
|
+
controller.tag options, args
|
119
|
+
|
120
|
+
# delete a project
|
121
|
+
#
|
122
|
+
elsif options[:delete]
|
123
|
+
controller.delete options, args
|
124
|
+
|
125
|
+
# add a project
|
126
|
+
#
|
127
|
+
elsif !options[:list] && !args.empty?
|
128
|
+
controller.add options, args
|
129
|
+
|
130
|
+
elsif !options[:list] && args.empty?
|
131
|
+
controller.show_active
|
132
|
+
|
133
|
+
# list projects, fiter by args
|
134
|
+
#
|
135
|
+
else
|
136
|
+
controller.index options, args
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# COMMAND: CHECKOUT
|
142
|
+
|
143
|
+
desc 'Checkout a project to track time against'
|
144
|
+
long_desc "Checkout the Projects that timed tasks are assigned to.
|
145
|
+
|
146
|
+
Arguments supplied will use fuzzy matching unless you:
|
147
|
+
|
148
|
+
- Use the --exact flag to match the arguments exactly
|
149
|
+
|
150
|
+
- Use the --id tag to match by id
|
151
|
+
|
152
|
+
examples:
|
153
|
+
|
154
|
+
# checking out an existing project titled 'star gazing'
|
155
|
+
|
156
|
+
$ tempo checkout star gazing
|
157
|
+
|
158
|
+
# adding and checking out a new project titled 'star gazing'
|
159
|
+
|
160
|
+
$ tempo checkout -a star gazing"
|
161
|
+
|
162
|
+
arg_name '"name of the project"'
|
163
|
+
command [:checkout, :c] do |c|
|
164
|
+
|
165
|
+
c.desc 'Add and Checkout a new project'
|
166
|
+
c.arg_name 'title'
|
167
|
+
c.flag [:a, :add]
|
168
|
+
|
169
|
+
c.desc 'use an exact match for project title'
|
170
|
+
c.switch [:e, :exact]
|
171
|
+
|
172
|
+
c.desc 'checkout by project id'
|
173
|
+
c.switch [:i, :id], negatable: false
|
174
|
+
|
175
|
+
c.action do |global_options,options,args|
|
176
|
+
|
177
|
+
controller = Tempo::Controllers::Checkout
|
178
|
+
|
179
|
+
# add and checkout a project
|
180
|
+
#
|
181
|
+
if options[:add]
|
182
|
+
controller.add_project options, args
|
183
|
+
|
184
|
+
# checkout existing project
|
185
|
+
else
|
186
|
+
if args.empty?
|
187
|
+
controller.assistance
|
188
|
+
else
|
189
|
+
controller.existing_project options, args
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
|
196
|
+
# COMMAND: ARRANGE
|
197
|
+
|
198
|
+
desc 'Arrange project hierarchy'
|
199
|
+
long_desc "Arrange projects into a parent/child hierarchy
|
200
|
+
|
201
|
+
New projects are added as root projects by default.
|
202
|
+
|
203
|
+
Use the --child flag with the project command to add a new project as the child of the current project
|
204
|
+
|
205
|
+
Use arrange to arrange existing projects as child or root projects.
|
206
|
+
|
207
|
+
Arguments supplied will use fuzzy matching unless you:
|
208
|
+
|
209
|
+
- Use the --exact flag to match the arguments exactly
|
210
|
+
|
211
|
+
- Use the --id tag to match by id
|
212
|
+
|
213
|
+
examples:
|
214
|
+
|
215
|
+
# Arrange an existing project as a root project
|
216
|
+
|
217
|
+
$ tempo arrange : aquascaping
|
218
|
+
|
219
|
+
# Arrange an existing project as a child project
|
220
|
+
|
221
|
+
$ tempo arrange aquascaping : coral pruning"
|
222
|
+
|
223
|
+
arg_name '[parent project] : child project'
|
224
|
+
command [:arrange, :a] do |c|
|
225
|
+
|
226
|
+
c.desc 'use an exact match for project title'
|
227
|
+
c.switch [:e, :exact]
|
228
|
+
|
229
|
+
c.desc 'checkout by project id'
|
230
|
+
c.switch [:i, :id]
|
231
|
+
|
232
|
+
c.action do |global_options, options, args|
|
233
|
+
controller = Tempo::Controllers::Arrange
|
234
|
+
controller.parse options, args
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
# COMMAND: EDIT
|
239
|
+
|
240
|
+
# COMMAND: START
|
241
|
+
|
242
|
+
desc 'Start a time entry'
|
243
|
+
long_desc "Starts a new time entry, and closes out any running time entries.
|
244
|
+
|
245
|
+
You can also add a description of the time entry.
|
246
|
+
|
247
|
+
To start a time entry at a time other than the current, pass it in as an argument
|
248
|
+
to the --at flag. This will accept a number of human readable formats, multiple
|
249
|
+
word time formats should be enclosed in quotes.
|
250
|
+
|
251
|
+
examples:
|
252
|
+
|
253
|
+
# start a new time record at the current time with no description
|
254
|
+
|
255
|
+
$ tempo start
|
256
|
+
|
257
|
+
# start and end a previous time record with a description
|
258
|
+
|
259
|
+
$ tempo start learning how to do the Hustle --at 'yesterday at 8:00 in the evening' --end 'yesterday at 11:59pm'
|
260
|
+
"
|
261
|
+
|
262
|
+
arg_name 'description'
|
263
|
+
command [:start, :s] do |c|
|
264
|
+
|
265
|
+
c.desc 'end the entry at a given time'
|
266
|
+
c.arg_name 'time'
|
267
|
+
c.flag [:e, :end]
|
268
|
+
|
269
|
+
c.desc 'start the entry at a given time'
|
270
|
+
c.arg_name 'time'
|
271
|
+
c.flag [:a, :at]
|
272
|
+
|
273
|
+
c.action do |global_options, options, args|
|
274
|
+
controller = Tempo::Controllers::Start
|
275
|
+
|
276
|
+
controller.start_timer options, args
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
# COMMAND: END
|
281
|
+
|
282
|
+
desc 'End a time entry'
|
283
|
+
long_desc "Closes out any running time entries.
|
284
|
+
|
285
|
+
You can optionally add a description of the time entry, which will overwrite the current description.
|
286
|
+
|
287
|
+
To end a time entry at a time other than the current, pass it in as an argument
|
288
|
+
to the --at flag. This will accept a number of human readable formats, multiple
|
289
|
+
word time formats should be enclosed in quotes.
|
290
|
+
|
291
|
+
examples:
|
292
|
+
|
293
|
+
# creating an entry at 4:55pm, then ending it 5 minutes later and changing the description
|
294
|
+
|
295
|
+
$ tempo start --at 16:55 practicing the human torch trick
|
296
|
+
|
297
|
+
$ tempo end --at 'today at 5:00pm' learning how to stop, drop, and roll
|
298
|
+
"
|
299
|
+
|
300
|
+
|
301
|
+
arg_name 'time out, defaults to now'
|
302
|
+
command [:end, :e] do |c|
|
303
|
+
|
304
|
+
c.desc 'time'
|
305
|
+
c.arg_name 'end the current time entry at the given time'
|
306
|
+
c.flag [:a, :at]
|
307
|
+
|
308
|
+
c.action do |global_options, options, args|
|
309
|
+
controller = Tempo::Controllers::End
|
310
|
+
|
311
|
+
controller.end_timer options, args
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
# COMMAND: REPORT
|
316
|
+
|
317
|
+
desc 'Report time entries'
|
318
|
+
long_desc "Reports time entries for a day or a period of days.
|
319
|
+
|
320
|
+
By default, lists the last recorded day's entries.
|
321
|
+
|
322
|
+
To list a different day, supply a day as the args
|
323
|
+
|
324
|
+
To list a series of records, include a --from and --to value
|
325
|
+
|
326
|
+
examples:
|
327
|
+
|
328
|
+
# report current day's entries
|
329
|
+
|
330
|
+
$ tempo report
|
331
|
+
|
332
|
+
# report a different day
|
333
|
+
|
334
|
+
$ tempo report 11/24/14
|
335
|
+
|
336
|
+
# report the past week
|
337
|
+
|
338
|
+
$ tempo report -f 'a week ago'
|
339
|
+
|
340
|
+
# report a period of days
|
341
|
+
|
342
|
+
$ tempo report -f 'last monday' -t 'last friday'"
|
343
|
+
|
344
|
+
arg_name '[day]'
|
345
|
+
command [:report, :r] do |c|
|
346
|
+
|
347
|
+
c.desc 'begin time records on this date'
|
348
|
+
c.arg_name 'time'
|
349
|
+
c.default_value 'last record'
|
350
|
+
c.flag [:f, :from]
|
351
|
+
|
352
|
+
c.desc 'end time records on this date'
|
353
|
+
c.arg_name 'time'
|
354
|
+
c.default_value 'today'
|
355
|
+
c.flag [:t, :to]
|
356
|
+
|
357
|
+
c.action do |global_options, options, args|
|
358
|
+
controller = Tempo::Controllers::Report
|
359
|
+
|
360
|
+
controller.report options, args
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
# COMMAND: UPDATE
|
365
|
+
|
366
|
+
desc 'update a time entry'
|
367
|
+
long_desc "update the project, start time, or end time for a time
|
368
|
+
entry.
|
369
|
+
|
370
|
+
Defaults to the current time entry, or most recently completed time entry
|
371
|
+
if none are running. Optionally, you can supply an id for a time entry on the current
|
372
|
+
day, or a day and id to update previous time entries.
|
373
|
+
|
374
|
+
The description, if passed in, will be used to replace the existing description. You can
|
375
|
+
also change the start or end time, or delete the entire time entry.
|
376
|
+
|
377
|
+
examples:
|
378
|
+
|
379
|
+
# update description for the last time entry
|
380
|
+
|
381
|
+
$ tempo update practicing banjo
|
382
|
+
|
383
|
+
# update the description for yesterday's entry with id of 2
|
384
|
+
|
385
|
+
$ tempo update --id 2 --on 'yesterday' practicing banjo
|
386
|
+
|
387
|
+
# update the start time for the last time entry
|
388
|
+
|
389
|
+
$ tempo update --start 7:00
|
390
|
+
|
391
|
+
# update the end time and description
|
392
|
+
|
393
|
+
$ tempo update --end '8:00pm' practicing banjo
|
394
|
+
|
395
|
+
# delete the last time entry
|
396
|
+
|
397
|
+
$ tempo update --delete
|
398
|
+
|
399
|
+
# update the description, start, and end time for a previous day's entry
|
400
|
+
|
401
|
+
$ tempo update --on 1/17/14 --start \"1/17/14 8am\" --end \"1/17/14 10am\" practicing banjo
|
402
|
+
"
|
403
|
+
|
404
|
+
arg_name '[description]'
|
405
|
+
command [:update, :u] do |c|
|
406
|
+
|
407
|
+
c.desc 'Select by Id'
|
408
|
+
c.arg_name 'number'
|
409
|
+
c.flag [:i, :id]
|
410
|
+
|
411
|
+
c.desc 'Select On Date'
|
412
|
+
c.arg_name 'date'
|
413
|
+
c.flag [:o, :on]
|
414
|
+
|
415
|
+
c.desc 'Update to the active project'
|
416
|
+
c.switch [:p, :project], negatable: false
|
417
|
+
|
418
|
+
c.desc 'Update the Start Time'
|
419
|
+
c.arg_name 'time'
|
420
|
+
c.flag [:s, :start]
|
421
|
+
|
422
|
+
c.desc 'Update the End Time'
|
423
|
+
c.arg_name 'time'
|
424
|
+
c.flag [:e, :end]
|
425
|
+
|
426
|
+
c.desc 'Delete a Time Entry'
|
427
|
+
c.switch [:d, :delete], negatable: false
|
428
|
+
|
429
|
+
c.action do |global_options, options, args|
|
430
|
+
controller = Tempo::Controllers::Update
|
431
|
+
|
432
|
+
controller.parse options, args
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
pre do |global,command,options,args|
|
437
|
+
# Return true to proceed; false to abort and not call the
|
438
|
+
# chosen command
|
439
|
+
# Use skips_pre before a command to skip this block
|
440
|
+
# on that command only
|
441
|
+
|
442
|
+
# add reporting of all arguments
|
443
|
+
if global[:v]
|
444
|
+
Tempo::Views::options_report command.name, global, options, args
|
445
|
+
end
|
446
|
+
|
447
|
+
Tempo::Views::initialize_view_options command.name, global, options
|
448
|
+
|
449
|
+
# Load the stored records
|
450
|
+
Tempo::Controllers::Records.initialize_from_records options, args
|
451
|
+
|
452
|
+
# TODO: send formats in through global options, and then:
|
453
|
+
# Tempo::Views::Reporter.add_formats
|
454
|
+
|
455
|
+
true
|
456
|
+
end
|
457
|
+
|
458
|
+
post do |global,command,options,args|
|
459
|
+
# Post logic here
|
460
|
+
# Use skips_post before a command to skip this
|
461
|
+
# block on that command only
|
462
|
+
|
463
|
+
Tempo::Views::Reporter.report
|
464
|
+
|
465
|
+
end
|
466
|
+
|
467
|
+
on_error do |exception|
|
468
|
+
# Error logic here
|
469
|
+
# return false to skip default error handling
|
470
|
+
|
471
|
+
# remove before distribution:
|
472
|
+
#puts exception.backtrace
|
473
|
+
|
474
|
+
true
|
475
|
+
end
|
476
|
+
|
477
|
+
exit run(ARGV)
|
@@ -0,0 +1,43 @@
|
|
1
|
+
Feature: Arrange Command manages the hierarchy of a list of projects
|
2
|
+
Projects can be ordered as root projects or children of other projects
|
3
|
+
The arrange command manages the relationship between parentg and child projects
|
4
|
+
|
5
|
+
Scenario: Arranging a project as a root projects
|
6
|
+
Given an existing project file
|
7
|
+
When I successfully run `tempo arrange : basement mushrooms`
|
8
|
+
Then the stdout should contain "root project:\nbasement mushrooms"
|
9
|
+
And the project file should contain ":parent: :root" at line 20
|
10
|
+
|
11
|
+
Scenario: Arranging a project as a child of another project
|
12
|
+
Given an existing project file
|
13
|
+
When I successfully run `tempo arrange horticulture : nano aquarium`
|
14
|
+
Then the stdout should contain "parent project:\nhorticulture"
|
15
|
+
And the stdout should contain "child project:\nnano aquarium"
|
16
|
+
And the project file should contain ":parent: 1" at line 39
|
17
|
+
And the project file should contain "- 5" at line 7
|
18
|
+
|
19
|
+
Scenario: Attempting to arrange projects without using a colon in the args
|
20
|
+
Given an existing project file
|
21
|
+
When I run `tempo arrange horticulture aquaculture`
|
22
|
+
Then the stderr should contain "arrange requires a colon (:) in the arguments"
|
23
|
+
|
24
|
+
Scenario: Attempting to arrange a root project as a root project
|
25
|
+
Given an existing project file
|
26
|
+
When I run `tempo arrange : horticulture`
|
27
|
+
Then the stdout should contain "already a root project:\nhorticulture"
|
28
|
+
|
29
|
+
Scenario: Arranging projects by id
|
30
|
+
Given an existing project file
|
31
|
+
When I successfully run `tempo arrange -i 4 : 1`
|
32
|
+
Then the stdout should contain "parent project:\naquaculture"
|
33
|
+
And the stdout should contain "child project:\nhorticulture"
|
34
|
+
And the project file should contain ":parent: 4" at line 3
|
35
|
+
And the project file should contain "- 1" at line 31
|
36
|
+
|
37
|
+
Scenario: Arranging projects by exact match
|
38
|
+
Given an existing project file
|
39
|
+
When I successfully run `tempo arrange -e reading aquaculture digest : aquaculture`
|
40
|
+
Then the stdout should contain "parent project:\nreading aquaculture digest"
|
41
|
+
And the stdout should contain "child project:\naquaculture"
|
42
|
+
And the project file should contain ":parent: 6" at line 29
|
43
|
+
And the project file should contain "- 4" at line 47
|
@@ -0,0 +1,63 @@
|
|
1
|
+
Feature: Checkout Command manages the active project
|
2
|
+
A New project can be added and checked out
|
3
|
+
An Exiting project can be checked out
|
4
|
+
|
5
|
+
Scenario: Checkout an existing project with checkout
|
6
|
+
Given an existing project file
|
7
|
+
When I successfully run `tempo checkout "backyard bonsai"`
|
8
|
+
Then the stdout should contain "switched to project:\nbackyard bonsai"
|
9
|
+
And the project file should contain ":current: true" at line 18
|
10
|
+
|
11
|
+
Scenario: Checkout an exising project with c
|
12
|
+
Given an existing project file
|
13
|
+
When I successfully run `tempo c "backyard bonsai"`
|
14
|
+
Then the stdout should contain "switched to project:\nbackyard bonsai"
|
15
|
+
And the project file should contain ":current: true" at line 18
|
16
|
+
|
17
|
+
Scenario: Checkout an existing project by partial match
|
18
|
+
Given an existing project file
|
19
|
+
When I successfully run `tempo checkout "bonsai"`
|
20
|
+
Then the stdout should contain "switched to project:\nbackyard bonsai"
|
21
|
+
And the project file should contain ":current: true" at line 18
|
22
|
+
|
23
|
+
Scenario: Checkout a project by id
|
24
|
+
Given an existing project file
|
25
|
+
When I successfully run `tempo checkout -i 3`
|
26
|
+
Then the stdout should contain "switched to project:\nbasement mushrooms"
|
27
|
+
|
28
|
+
Scenario: Checkout a project by exact match
|
29
|
+
Given an existing project file
|
30
|
+
And I successfully run `tempo checkout -e aquaculture`
|
31
|
+
Then the stdout should contain "switched to project:\naquaculture"
|
32
|
+
And the stdout should not contain "switched to project:\nreading aquaculture digest"
|
33
|
+
|
34
|
+
Scenario: Attempting to Checkout an existing project by partial match with multiple possibilities
|
35
|
+
Given an existing project file
|
36
|
+
And I run `tempo checkout aquaculture`
|
37
|
+
Then the stdout should contain "The following projects matched your search:"
|
38
|
+
And the stdout should contain "aquaculture"
|
39
|
+
And the stdout should contain "reading aquaculture digest"
|
40
|
+
And the stderr should contain "error: cannot checkout multiple projects"
|
41
|
+
|
42
|
+
Scenario: Attempting to Checkout the current project
|
43
|
+
Given an existing project file
|
44
|
+
When I successfully run `tempo checkout "horticulture"`
|
45
|
+
Then the stdout should contain "already on project:\nhorticulture"
|
46
|
+
|
47
|
+
Scenario: Attempting to checkout a non-existant project
|
48
|
+
Given an existing project file
|
49
|
+
When I run `tempo checkout "new project"`
|
50
|
+
And the stdout should not contain "switched"
|
51
|
+
Then the stderr should contain "no projects match the request: new project"
|
52
|
+
|
53
|
+
Scenario: Adding and checking out a new project
|
54
|
+
Given an existing project file
|
55
|
+
When I successfully run `tempo checkout --add "bathtup scuba diving"`
|
56
|
+
Then the stdout should contain "switched to project:\nbathtup scuba diving"
|
57
|
+
And the project file should contain ":title: bathtup scuba diving"
|
58
|
+
And the project file should contain ":current: true"
|
59
|
+
|
60
|
+
Scenario: Attempting to add an exising project
|
61
|
+
Given an existing project file
|
62
|
+
When I run `tempo checkout --add "basement mushrooms"`
|
63
|
+
Then the stderr should contain "error: project 'basement mushrooms' already exists"
|
@@ -0,0 +1,65 @@
|
|
1
|
+
Feature: End Command ends the current time record
|
2
|
+
The end command ends the currenly running time record. It can be passed a value
|
3
|
+
that will end the record at a given time
|
4
|
+
|
5
|
+
Scenario: Attempting to add time before any projects exist
|
6
|
+
Given a clean installation
|
7
|
+
When I run `tempo end`
|
8
|
+
Then the stderr should contain "no projects exist"
|
9
|
+
And the project file should contain "#" at line 1
|
10
|
+
|
11
|
+
Scenario: Attempting to end a time record when none are running
|
12
|
+
Given an existing project file
|
13
|
+
When I run `tempo end`
|
14
|
+
Then the stderr should contain "no running time records exist"
|
15
|
+
|
16
|
+
Scenario: Ending the current time record
|
17
|
+
Given an existing project file
|
18
|
+
When I run `tempo start`
|
19
|
+
And I run `tempo end`
|
20
|
+
Then the stdout should contain "time record ended"
|
21
|
+
And the output should match /\d{2}:\d{2} - \d{2}:\d{2}[^\*]/
|
22
|
+
|
23
|
+
Scenario: Ending the current time record and changing the description
|
24
|
+
Given an existing project file
|
25
|
+
When I run `tempo start old description`
|
26
|
+
And I run `tempo end new description`
|
27
|
+
Then the stdout should contain "time record ended"
|
28
|
+
And the output should contain "new description"
|
29
|
+
And the output should match /\d{2}:\d{2} - \d{2}:\d{2}[^\*]/
|
30
|
+
|
31
|
+
Scenario: Attempting to add an invalid end time
|
32
|
+
Given an existing project file
|
33
|
+
When I run `tempo start`
|
34
|
+
When I run `tempo end --at "invalid time"`
|
35
|
+
Then the stderr should contain "no valid timeframe matches the request: invalid time"
|
36
|
+
|
37
|
+
Scenario: Ending a time record for a specific time
|
38
|
+
Given an existing project file
|
39
|
+
When I run `tempo start --at "1-5-2014 7:00"`
|
40
|
+
And I run `tempo end --at "1-5-2014 15:00"`
|
41
|
+
Then the stdout should contain "time record ended"
|
42
|
+
And the output should match /7:00 - 15:00/
|
43
|
+
@pending
|
44
|
+
Scenario: Attempting to end after the beginning time
|
45
|
+
Given an existing project file
|
46
|
+
When I run `tempo start --at "1-5-2014 17:00"`
|
47
|
+
And I run `tempo end --at "1-5-2014 6:00"`
|
48
|
+
Then the stderr should contain "you cannot end a time record before the starting time"
|
49
|
+
|
50
|
+
@pending
|
51
|
+
Scenario: Ending a time record with tags
|
52
|
+
Given an existing project file
|
53
|
+
@pending
|
54
|
+
Scenario: Ending a time record on a previous day
|
55
|
+
Given an existing project file
|
56
|
+
When I run `tempo start --at "1-1-2014 7:00"`
|
57
|
+
And I run `tempo end --at "1-3-2014 10:00"`
|
58
|
+
Then the stdout should contain "time record ended"
|
59
|
+
And the time record 20140101 should contain ":end_time: 2014-01-01 23:59" at line 5
|
60
|
+
And the time record 20140102 should contain ":end_time: 2014-01-01 23:59" at line 5
|
61
|
+
And the time record 20140103 should contain ":end_time: 2014-01-01 10:00" at line 5
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
|