zenhob-hcl 0.2.2 → 0.2.3
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/.document +1 -0
- data/.gitignore +3 -0
- data/CHANGELOG +41 -0
- data/README.markdown +1 -1
- data/Rakefile +7 -0
- data/VERSION +1 -1
- data/hcl.gemspec +17 -6
- data/lib/hcl/app.rb +91 -161
- data/lib/hcl/commands.rb +90 -0
- data/lib/hcl/day_entry.rb +5 -6
- data/lib/hcl/utility.rb +8 -1
- data/test/app_test.rb +8 -0
- data/test/day_entry_test.rb +49 -0
- data/test/test_helper.rb +6 -0
- data/test/utility_test.rb +17 -0
- metadata +14 -6
- data/.gitmodules +0 -3
- data/hcl_conf.yml.example +0 -3
data/.document
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--files CHANGELOG
|
data/CHANGELOG
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
= Recent Changes in HCl
|
2
|
+
|
3
|
+
== v0.2.3 Sun Aug 23 21:39:34 2009 -0700
|
4
|
+
|
5
|
+
* Allow decimal time offset without a dot, closes #29.
|
6
|
+
* Reverted and re-fixed: Adding note fails when task is started without notes, #26.
|
7
|
+
* Reinstate the --version option
|
8
|
+
|
9
|
+
== v0.2.2 Sun Aug 9 11:16:34 2009 -0700
|
10
|
+
|
11
|
+
* Support installation via rip, closes #27.
|
12
|
+
* Fixed: Adding note fails when task is started without notes, closes #26.
|
13
|
+
* Avoid stack trace on missing XML root node, closes #25.
|
14
|
+
|
15
|
+
== v0.2.1 Thu Jul 30 14:02:23 2009 -0700
|
16
|
+
|
17
|
+
* Fixed: Creating timers without starting them.
|
18
|
+
|
19
|
+
== v0.2.0 Thu Jul 30 11:40:33 2009 -0700
|
20
|
+
|
21
|
+
* Allow an initial time to be specified when starting a timer, closes #9.
|
22
|
+
* Always display hours as HH:MM, closes #22.
|
23
|
+
* Do not write empty task cache, closes #23.
|
24
|
+
|
25
|
+
== v0.1.3 Tue Jul 28 09:19:53 2009 -0700
|
26
|
+
|
27
|
+
* Add a note about ruby-dev for debian/ubuntu users, closes #20.
|
28
|
+
* Friendlier error message on unrecognized task, closes #18, #21.
|
29
|
+
|
30
|
+
== v0.1.2 Mon Jul 27 11:46:50 2009 -0700
|
31
|
+
|
32
|
+
* Automatically include rubygems in bin/hcl.
|
33
|
+
|
34
|
+
== v0.1.1 Fri Jul 24 19:32:32 2009 -0700
|
35
|
+
|
36
|
+
* Mention gem in README, read version from file.
|
37
|
+
|
38
|
+
== v0.1.0 Fri Jul 24 19:09:23 2009 -0700
|
39
|
+
|
40
|
+
* Initial public release
|
41
|
+
|
data/README.markdown
CHANGED
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.3
|
data/hcl.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{hcl}
|
5
|
-
s.version = "0.2.
|
5
|
+
s.version = "0.2.3"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Zack Hobson"]
|
9
|
-
s.date = %q{2009-08-
|
9
|
+
s.date = %q{2009-08-23}
|
10
10
|
s.default_executable = %q{hcl}
|
11
11
|
s.description = %q{HCl is a command-line client for manipulating Harvest time sheets.}
|
12
12
|
s.email = %q{zack@opensourcery.com}
|
@@ -16,8 +16,9 @@ Gem::Specification.new do |s|
|
|
16
16
|
"README.markdown"
|
17
17
|
]
|
18
18
|
s.files = [
|
19
|
-
".
|
20
|
-
".
|
19
|
+
".document",
|
20
|
+
".gitignore",
|
21
|
+
"CHANGELOG",
|
21
22
|
"LICENSE",
|
22
23
|
"README.markdown",
|
23
24
|
"Rakefile",
|
@@ -25,13 +26,17 @@ Gem::Specification.new do |s|
|
|
25
26
|
"bin/hcl",
|
26
27
|
"deps.rip",
|
27
28
|
"hcl.gemspec",
|
28
|
-
"hcl_conf.yml.example",
|
29
29
|
"lib/hcl/app.rb",
|
30
|
+
"lib/hcl/commands.rb",
|
30
31
|
"lib/hcl/day_entry.rb",
|
31
32
|
"lib/hcl/project.rb",
|
32
33
|
"lib/hcl/task.rb",
|
33
34
|
"lib/hcl/timesheet_resource.rb",
|
34
|
-
"lib/hcl/utility.rb"
|
35
|
+
"lib/hcl/utility.rb",
|
36
|
+
"test/app_test.rb",
|
37
|
+
"test/day_entry_test.rb",
|
38
|
+
"test/test_helper.rb",
|
39
|
+
"test/utility_test.rb"
|
35
40
|
]
|
36
41
|
s.has_rdoc = true
|
37
42
|
s.homepage = %q{http://github.com/zenhob/hcl}
|
@@ -39,6 +44,12 @@ Gem::Specification.new do |s|
|
|
39
44
|
s.require_paths = ["lib"]
|
40
45
|
s.rubygems_version = %q{1.3.1}
|
41
46
|
s.summary = %q{Harvest timesheets from the command-line}
|
47
|
+
s.test_files = [
|
48
|
+
"test/app_test.rb",
|
49
|
+
"test/day_entry_test.rb",
|
50
|
+
"test/test_helper.rb",
|
51
|
+
"test/utility_test.rb"
|
52
|
+
]
|
42
53
|
|
43
54
|
if s.respond_to? :specification_version then
|
44
55
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
data/lib/hcl/app.rb
CHANGED
@@ -11,6 +11,7 @@ require 'highline/import'
|
|
11
11
|
|
12
12
|
## app dependencies
|
13
13
|
require 'hcl/utility'
|
14
|
+
require 'hcl/commands'
|
14
15
|
require 'hcl/timesheet_resource'
|
15
16
|
require 'hcl/project'
|
16
17
|
require 'hcl/task'
|
@@ -29,51 +30,65 @@ class Net::HTTP
|
|
29
30
|
end
|
30
31
|
|
31
32
|
module HCl
|
32
|
-
|
33
|
-
include HCl::Utility
|
34
|
-
|
35
|
-
SETTINGS_FILE = "#{ENV['HOME']}/.hcl_settings"
|
36
|
-
CONFIG_FILE = "#{ENV['HOME']}/.hcl_config"
|
33
|
+
VERSION = "0.2.3"
|
37
34
|
|
38
|
-
class
|
35
|
+
class App
|
36
|
+
include HCl::Utility
|
37
|
+
include HCl::Commands
|
38
|
+
|
39
|
+
SETTINGS_FILE = "#{ENV['HOME']}/.hcl_settings"
|
40
|
+
CONFIG_FILE = "#{ENV['HOME']}/.hcl_config"
|
41
|
+
|
42
|
+
class UnknownCommand < StandardError; end
|
43
|
+
|
44
|
+
def initialize
|
45
|
+
read_config
|
46
|
+
read_settings
|
47
|
+
end
|
39
48
|
|
40
|
-
|
41
|
-
|
42
|
-
|
49
|
+
# Run the given command and arguments.
|
50
|
+
def self.command *args
|
51
|
+
hcl = new.process_args(*args).run
|
52
|
+
end
|
43
53
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
+
# Return true if the string is a known command, false otherwise.
|
55
|
+
#
|
56
|
+
# @param [#to_s] command name of command
|
57
|
+
# @return [true, false]
|
58
|
+
def command? command
|
59
|
+
Commands.instance_methods.include? command.to_s
|
60
|
+
end
|
61
|
+
|
62
|
+
# Start the application.
|
63
|
+
def run
|
64
|
+
begin
|
65
|
+
if @command
|
66
|
+
if command? @command
|
67
|
+
result = send @command, *@args
|
68
|
+
if not result.nil?
|
69
|
+
if result.respond_to? :to_a
|
70
|
+
puts result.to_a.join(', ')
|
71
|
+
elsif result.respond_to? :to_s
|
72
|
+
puts result
|
73
|
+
end
|
54
74
|
end
|
75
|
+
else
|
76
|
+
raise UnknownCommand, "unrecognized command `#{@command}'"
|
55
77
|
end
|
56
78
|
else
|
57
|
-
|
79
|
+
show
|
58
80
|
end
|
59
|
-
|
60
|
-
|
81
|
+
rescue TimesheetResource::Failure => e
|
82
|
+
puts "Internal failure. #{e}"
|
83
|
+
exit 1
|
61
84
|
end
|
62
|
-
rescue TimesheetResource::Failure => e
|
63
|
-
puts "Internal failure. #{e}"
|
64
|
-
exit 1
|
65
85
|
end
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
def process_args *args
|
74
|
-
Trollop::options(args) do
|
75
|
-
stop_on %w[ show tasks set unset note add rm start stop ]
|
76
|
-
banner <<-EOM
|
86
|
+
|
87
|
+
def process_args *args
|
88
|
+
Trollop::options(args) do
|
89
|
+
stop_on Commands.instance_methods
|
90
|
+
version "HCl version #{VERSION}"
|
91
|
+
banner <<-EOM
|
77
92
|
HCl is a command-line client for manipulating Harvest time sheets.
|
78
93
|
|
79
94
|
Commands:
|
@@ -81,6 +96,7 @@ Commands:
|
|
81
96
|
hcl tasks
|
82
97
|
hcl aliases
|
83
98
|
hcl set <key> <value ...>
|
99
|
+
hcl unset <key>
|
84
100
|
hcl start <task> [msg]
|
85
101
|
hcl stop [msg]
|
86
102
|
hcl note <msg>
|
@@ -95,140 +111,54 @@ Examples:
|
|
95
111
|
|
96
112
|
Options:
|
97
113
|
EOM
|
98
|
-
end
|
99
|
-
@command = args.shift
|
100
|
-
@args = args
|
101
|
-
self
|
102
|
-
end
|
103
|
-
|
104
|
-
def tasks
|
105
|
-
tasks = Task.all
|
106
|
-
if tasks.empty?
|
107
|
-
puts "No cached tasks. Run `hcl show' to populate the cache and try again."
|
108
|
-
else
|
109
|
-
tasks.each { |task| puts "#{task.project.id} #{task.id}\t#{task}" }
|
110
|
-
end
|
111
|
-
nil
|
112
|
-
end
|
113
|
-
|
114
|
-
def read_config
|
115
|
-
if File.exists? CONFIG_FILE
|
116
|
-
config = YAML::load File.read(CONFIG_FILE)
|
117
|
-
TimesheetResource.configure config
|
118
|
-
elsif File.exists? old_conf = File.dirname(__FILE__) + "/../hcl_conf.yml"
|
119
|
-
config = YAML::load File.read(old_conf)
|
120
|
-
TimesheetResource.configure config
|
121
|
-
write_config config
|
122
|
-
else
|
123
|
-
config = {}
|
124
|
-
puts "Please specify your Harvest credentials.\n"
|
125
|
-
config['login'] = ask("Email Address: ")
|
126
|
-
config['password'] = ask("Password: ") { |q| q.echo = false }
|
127
|
-
config['subdomain'] = ask("Subdomain: ")
|
128
|
-
TimesheetResource.configure config
|
129
|
-
write_config config
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
def write_config config
|
134
|
-
puts "Writing configuration to #{CONFIG_FILE}."
|
135
|
-
File.open(CONFIG_FILE, 'w') do |f|
|
136
|
-
f.write config.to_yaml
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
def read_settings
|
141
|
-
if File.exists? SETTINGS_FILE
|
142
|
-
@settings = YAML.load(File.read(SETTINGS_FILE))
|
143
|
-
else
|
144
|
-
@settings = {}
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
def write_settings
|
149
|
-
File.open(SETTINGS_FILE, 'w') do |f|
|
150
|
-
f.write @settings.to_yaml
|
151
|
-
end
|
152
|
-
nil
|
153
|
-
end
|
154
|
-
|
155
|
-
def set key = nil, *args
|
156
|
-
if key.nil?
|
157
|
-
@settings.each do |k, v|
|
158
|
-
puts "#{k}: #{v}"
|
159
114
|
end
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
@settings[key] = value
|
164
|
-
write_settings
|
115
|
+
@command = args.shift
|
116
|
+
@args = args
|
117
|
+
self
|
165
118
|
end
|
166
|
-
nil
|
167
|
-
end
|
168
|
-
|
169
|
-
def unset key
|
170
|
-
@settings.delete key
|
171
|
-
write_settings
|
172
|
-
end
|
173
119
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
ident = args.shift
|
185
|
-
task_ids = if @settings.key? "task.#{ident}"
|
186
|
-
@settings["task.#{ident}"].split(/\s+/)
|
120
|
+
protected
|
121
|
+
|
122
|
+
def read_config
|
123
|
+
if File.exists? CONFIG_FILE
|
124
|
+
config = YAML::load File.read(CONFIG_FILE)
|
125
|
+
TimesheetResource.configure config
|
126
|
+
elsif File.exists? old_conf = File.dirname(__FILE__) + "/../hcl_conf.yml"
|
127
|
+
config = YAML::load File.read(old_conf)
|
128
|
+
TimesheetResource.configure config
|
129
|
+
write_config config
|
187
130
|
else
|
188
|
-
|
131
|
+
config = {}
|
132
|
+
puts "Please specify your Harvest credentials.\n"
|
133
|
+
config['login'] = ask("Email Address: ")
|
134
|
+
config['password'] = ask("Password: ") { |q| q.echo = false }
|
135
|
+
config['subdomain'] = ask("Subdomain: ")
|
136
|
+
TimesheetResource.configure config
|
137
|
+
write_config config
|
189
138
|
end
|
190
|
-
task = Task.find *task_ids
|
191
|
-
if task.nil?
|
192
|
-
puts "Unknown project/task alias, try one of the following: #{aliases.join(', ')}."
|
193
|
-
exit 1
|
194
139
|
end
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
if entry
|
202
|
-
entry.toggle
|
203
|
-
puts "Stopped #{entry}."
|
204
|
-
else
|
205
|
-
puts "No running timers found."
|
140
|
+
|
141
|
+
def write_config config
|
142
|
+
puts "Writing configuration to #{CONFIG_FILE}."
|
143
|
+
File.open(CONFIG_FILE, 'w') do |f|
|
144
|
+
f.write config.to_yaml
|
145
|
+
end
|
206
146
|
end
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
puts "Added note '#{message}' to #{entry}."
|
215
|
-
else
|
216
|
-
puts "No running timers found."
|
147
|
+
|
148
|
+
def read_settings
|
149
|
+
if File.exists? SETTINGS_FILE
|
150
|
+
@settings = YAML.load(File.read(SETTINGS_FILE))
|
151
|
+
else
|
152
|
+
@settings = {}
|
153
|
+
end
|
217
154
|
end
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
running = day.running? ? '(running) ' : ''
|
225
|
-
puts "\t#{day.formatted_hours}\t#{running}#{day.project} #{day.notes}"[0..78]
|
226
|
-
total_hours = total_hours + day.hours.to_f
|
155
|
+
|
156
|
+
def write_settings
|
157
|
+
File.open(SETTINGS_FILE, 'w') do |f|
|
158
|
+
f.write @settings.to_yaml
|
159
|
+
end
|
160
|
+
nil
|
227
161
|
end
|
228
|
-
puts "\t" + '-' * 13
|
229
|
-
puts "\t#{as_hours total_hours}\ttotal"
|
230
|
-
end
|
231
|
-
|
232
162
|
end
|
233
163
|
end
|
234
164
|
|
data/lib/hcl/commands.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
module HCl
|
2
|
+
module Commands
|
3
|
+
def tasks
|
4
|
+
tasks = Task.all
|
5
|
+
if tasks.empty?
|
6
|
+
puts "No cached tasks. Run `hcl show' to populate the cache and try again."
|
7
|
+
else
|
8
|
+
tasks.each { |task| puts "#{task.project.id} #{task.id}\t#{task}" }
|
9
|
+
end
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def set key = nil, *args
|
14
|
+
if key.nil?
|
15
|
+
@settings.each do |k, v|
|
16
|
+
puts "#{k}: #{v}"
|
17
|
+
end
|
18
|
+
else
|
19
|
+
value = args.join(' ')
|
20
|
+
@settings ||= {}
|
21
|
+
@settings[key] = value
|
22
|
+
write_settings
|
23
|
+
end
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def unset key
|
28
|
+
@settings.delete key
|
29
|
+
write_settings
|
30
|
+
end
|
31
|
+
|
32
|
+
def aliases
|
33
|
+
@settings.keys.select { |s| s =~ /^task\./ }.map { |s| s.slice(5..-1) }
|
34
|
+
end
|
35
|
+
|
36
|
+
def start *args
|
37
|
+
starting_time = args.detect {|x| x =~ /^\+\d*(\.|:)?\d+$/ }
|
38
|
+
if starting_time
|
39
|
+
args.delete(starting_time)
|
40
|
+
starting_time = time2float starting_time
|
41
|
+
end
|
42
|
+
ident = args.shift
|
43
|
+
task_ids = if @settings.key? "task.#{ident}"
|
44
|
+
@settings["task.#{ident}"].split(/\s+/)
|
45
|
+
else
|
46
|
+
[ident, args.shift]
|
47
|
+
end
|
48
|
+
task = Task.find *task_ids
|
49
|
+
if task.nil?
|
50
|
+
puts "Unknown project/task alias, try one of the following: #{aliases.join(', ')}."
|
51
|
+
exit 1
|
52
|
+
end
|
53
|
+
timer = task.start(:starting_time => starting_time, :note => args.join(' '))
|
54
|
+
puts "Started timer for #{timer}."
|
55
|
+
end
|
56
|
+
|
57
|
+
def stop
|
58
|
+
entry = DayEntry.with_timer
|
59
|
+
if entry
|
60
|
+
entry.toggle
|
61
|
+
puts "Stopped #{entry}."
|
62
|
+
else
|
63
|
+
puts "No running timers found."
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def note *args
|
68
|
+
message = args.join ' '
|
69
|
+
entry = DayEntry.with_timer
|
70
|
+
if entry
|
71
|
+
entry.append_note message
|
72
|
+
puts "Added note '#{message}' to #{entry}."
|
73
|
+
else
|
74
|
+
puts "No running timers found."
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def show *args
|
79
|
+
date = args.empty? ? nil : Chronic.parse(args.join(' '))
|
80
|
+
total_hours = 0.0
|
81
|
+
DayEntry.all(date).each do |day|
|
82
|
+
running = day.running? ? '(running) ' : ''
|
83
|
+
puts "\t#{day.formatted_hours}\t#{running}#{day.project} #{day.notes}"[0..78]
|
84
|
+
total_hours = total_hours + day.hours.to_f
|
85
|
+
end
|
86
|
+
puts "\t" + '-' * 13
|
87
|
+
puts "\t#{as_hours total_hours}\ttotal"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/lib/hcl/day_entry.rb
CHANGED
@@ -23,18 +23,17 @@ module HCl
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
+
def notes
|
27
|
+
super || @data[:notes] = ''
|
28
|
+
end
|
29
|
+
|
26
30
|
# Append a string to the notes for this task.
|
27
31
|
def append_note new_notes
|
28
32
|
# If I don't include hours it gets reset.
|
29
33
|
# This doens't appear to be the case for task and project.
|
30
|
-
if notes.nil?
|
31
|
-
notes = new_notes
|
32
|
-
else
|
33
|
-
notes << " #{new_notes}"
|
34
|
-
end
|
35
34
|
DayEntry.post("daily/update/#{id}", <<-EOD)
|
36
35
|
<request>
|
37
|
-
<notes>#{notes}</notes>
|
36
|
+
<notes>#{notes << " #{new_notes}"}</notes>
|
38
37
|
<hours>#{hours}</hours>
|
39
38
|
</request>
|
40
39
|
EOD
|
data/lib/hcl/utility.rb
CHANGED
@@ -1,16 +1,23 @@
|
|
1
1
|
module HCl
|
2
2
|
module Utility
|
3
3
|
# Convert from decimal to a string of the form HH:MM.
|
4
|
+
#
|
5
|
+
# @param [#to_f] hours number of hours in decimal
|
6
|
+
# @return [String] of the form "HH:MM"
|
4
7
|
def as_hours hours
|
5
8
|
minutes = hours.to_f * 60.0
|
6
9
|
sprintf "%d:%02d", (minutes / 60).to_i, (minutes % 60).to_i
|
7
10
|
end
|
8
11
|
|
12
|
+
# Convert from a time span in hour or decimal format to a float.
|
13
|
+
#
|
14
|
+
# @param [String] time_string either "M:MM" or decimal
|
15
|
+
# @return [#to_f] converted to a floating-point number
|
9
16
|
def time2float time_string
|
10
17
|
if time_string =~ /:/
|
11
18
|
hours, minutes = time_string.split(':')
|
12
19
|
hours.to_f + (minutes.to_f / 60.0)
|
13
|
-
|
20
|
+
else
|
14
21
|
time_string.to_f
|
15
22
|
end
|
16
23
|
end
|
data/test/app_test.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class DayEntryTest < Test::Unit::TestCase
|
4
|
+
should "read DayEntry xml" do
|
5
|
+
entries = HCl::DayEntry.from_xml(<<-EOD)
|
6
|
+
<daily>
|
7
|
+
<for_day type="date">Wed, 18 Oct 2006</for_day>
|
8
|
+
<day_entries>
|
9
|
+
<day_entry>
|
10
|
+
<id type="integer">195168</id>
|
11
|
+
<client>Iridesco</client>
|
12
|
+
<project>Harvest</project>
|
13
|
+
<task>Backend Programming</task>
|
14
|
+
<hours type="float">2.06</hours>
|
15
|
+
<notes>Test api support</notes>
|
16
|
+
<timer_started_at type="datetime">
|
17
|
+
Wed, 18 Oct 2006 09:53:06 -0000
|
18
|
+
</timer_started_at>
|
19
|
+
<created_at type="datetime">Wed, 18 Oct 2006 09:53:06 -0000</created_at>
|
20
|
+
</day_entry>
|
21
|
+
</day_entries>
|
22
|
+
</daily>
|
23
|
+
EOD
|
24
|
+
assert_equal 1, entries.size
|
25
|
+
{
|
26
|
+
:project => 'Harvest',
|
27
|
+
:client => 'Iridesco',
|
28
|
+
:task => 'Backend Programming',
|
29
|
+
:notes => 'Test api support',
|
30
|
+
:hours => '2.06',
|
31
|
+
}.each do |method, value|
|
32
|
+
assert_equal value, entries.first.send(method)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
should "append to an existing note" do
|
37
|
+
entry = HCl::DayEntry.new(:id => '1', :notes => 'yourmom.', :hours => '1.0')
|
38
|
+
HCl::DayEntry.stubs(:post)
|
39
|
+
entry.append_note('hi world')
|
40
|
+
assert_equal 'yourmom. hi world', entry.notes
|
41
|
+
end
|
42
|
+
|
43
|
+
should "append to an undefined note" do
|
44
|
+
entry = HCl::DayEntry.new(:id => '1', :notes => nil, :hours => '1.0')
|
45
|
+
HCl::DayEntry.stubs(:post)
|
46
|
+
entry.append_note('hi world')
|
47
|
+
assert_equal ' hi world', entry.notes
|
48
|
+
end
|
49
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class UtilityTest < Test::Unit::TestCase
|
4
|
+
include HCl::Utility
|
5
|
+
|
6
|
+
should "convert decimal input when converting time2float" do
|
7
|
+
assert_equal 2.5, time2float("2.5")
|
8
|
+
end
|
9
|
+
|
10
|
+
should "convert HH:MM input when converting time2float" do
|
11
|
+
assert_equal 2.5, time2float("2:30")
|
12
|
+
end
|
13
|
+
|
14
|
+
should "assume decimal input when converting time2float" do
|
15
|
+
assert_equal 2.0, time2float("2")
|
16
|
+
end
|
17
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zenhob-hcl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zack Hobson
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-08-
|
12
|
+
date: 2009-08-23 00:00:00 -07:00
|
13
13
|
default_executable: hcl
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -62,8 +62,9 @@ extra_rdoc_files:
|
|
62
62
|
- LICENSE
|
63
63
|
- README.markdown
|
64
64
|
files:
|
65
|
+
- .document
|
65
66
|
- .gitignore
|
66
|
-
-
|
67
|
+
- CHANGELOG
|
67
68
|
- LICENSE
|
68
69
|
- README.markdown
|
69
70
|
- Rakefile
|
@@ -71,13 +72,17 @@ files:
|
|
71
72
|
- bin/hcl
|
72
73
|
- deps.rip
|
73
74
|
- hcl.gemspec
|
74
|
-
- hcl_conf.yml.example
|
75
75
|
- lib/hcl/app.rb
|
76
|
+
- lib/hcl/commands.rb
|
76
77
|
- lib/hcl/day_entry.rb
|
77
78
|
- lib/hcl/project.rb
|
78
79
|
- lib/hcl/task.rb
|
79
80
|
- lib/hcl/timesheet_resource.rb
|
80
81
|
- lib/hcl/utility.rb
|
82
|
+
- test/app_test.rb
|
83
|
+
- test/day_entry_test.rb
|
84
|
+
- test/test_helper.rb
|
85
|
+
- test/utility_test.rb
|
81
86
|
has_rdoc: true
|
82
87
|
homepage: http://github.com/zenhob/hcl
|
83
88
|
licenses:
|
@@ -105,5 +110,8 @@ rubygems_version: 1.3.5
|
|
105
110
|
signing_key:
|
106
111
|
specification_version: 2
|
107
112
|
summary: Harvest timesheets from the command-line
|
108
|
-
test_files:
|
109
|
-
|
113
|
+
test_files:
|
114
|
+
- test/app_test.rb
|
115
|
+
- test/day_entry_test.rb
|
116
|
+
- test/test_helper.rb
|
117
|
+
- test/utility_test.rb
|
data/.gitmodules
DELETED
data/hcl_conf.yml.example
DELETED