summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/hcl/commands.rb4
-rw-r--r--lib/hcl/day_entry.rb18
-rw-r--r--lib/hcl/net.rb3
-rw-r--r--lib/hcl/project.rb1
-rw-r--r--lib/hcl/timesheet_resource.rb49
-rw-r--r--test/app_test.rb3
-rw-r--r--test/command_test.rb9
-rw-r--r--test/day_entry_test.rb12
-rw-r--r--test/ext/capture_output.rb8
9 files changed, 83 insertions, 24 deletions
diff --git a/lib/hcl/commands.rb b/lib/hcl/commands.rb
index 3e96077..834ba2c 100644
--- a/lib/hcl/commands.rb
+++ b/lib/hcl/commands.rb
@@ -19,7 +19,7 @@ module HCl
def tasks project_code=nil
tasks = Task.all
if tasks.empty? # cache tasks
- DayEntry.all
+ DayEntry.today
tasks = Task.all
end
tasks.select! {|t| t.project.code == project_code } if project_code
@@ -133,7 +133,7 @@ module HCl
date = args.empty? ? nil : Chronic.parse(args.join(' '))
total_hours = 0.0
result = ''
- DayEntry.all(date).each do |day|
+ DayEntry.daily(date).each do |day|
running = day.running? ? '(running) ' : ''
columns = HighLine::SystemExtensions.terminal_size[0] rescue 80
result << "\t#{day.formatted_hours}\t#{running}#{day.project}: #{day.notes.lines.to_a.last}\n"[0..columns-1]
diff --git a/lib/hcl/day_entry.rb b/lib/hcl/day_entry.rb
index bea1b82..8485139 100644
--- a/lib/hcl/day_entry.rb
+++ b/lib/hcl/day_entry.rb
@@ -2,14 +2,10 @@ module HCl
class DayEntry < TimesheetResource
include Utility
- # Get the time sheet entries for a given day. If no date is provided
- # defaults to today.
- def self.all date = nil
- url = date.nil? ? 'daily' : "daily/#{date.strftime '%j/%Y'}"
- doc = Net.get url
- Task.cache_tasks_hash doc
- doc[:day_entries].map {|e| new e}
- end
+ collection_name :day_entries
+ resources :today, 'daily', load_cb:->(data) { Task.cache_tasks_hash data }
+ resources(:daily) {|date| date ? "daily/#{date.strftime '%j/%Y'}" : 'daily' }
+ resource(:project_info, class_name:'Project') { "projects/#{project_id}" }
def to_s
"#{client} - #{project} - #{task} (#{formatted_hours})"
@@ -41,16 +37,16 @@ module HCl
end
def self.with_timer date=nil
- all(date).detect {|t| t.running? }
+ daily(date).detect {|t| t.running? }
end
def self.last_by_task project_id, task_id
- all.sort {|a,b| b.updated_at<=>a.updated_at}.
+ today.sort {|a,b| b.updated_at<=>a.updated_at}.
detect {|t| t.project_id == project_id && t.task_id == task_id }
end
def self.last
- all.sort {|a,b| a.updated_at<=>b.updated_at}[-1]
+ today.sort {|a,b| a.updated_at<=>b.updated_at}[-1]
end
def running?
diff --git a/lib/hcl/net.rb b/lib/hcl/net.rb
index 70a14c7..01fb737 100644
--- a/lib/hcl/net.rb
+++ b/lib/hcl/net.rb
@@ -1,4 +1,5 @@
require 'hcl/harvest_middleware'
+require 'faraday'
module HCl
module Net
@@ -20,7 +21,7 @@ module HCl
def http
@http ||= Faraday.new(
- "http#{ssl && 's'}://#{subdomain}.harvestapp.com"
+ "http#{ssl ? 's' : '' }://#{subdomain}.harvestapp.com"
) do |f|
f.use :harvest, login, password
f.adapter Faraday.default_adapter
diff --git a/lib/hcl/project.rb b/lib/hcl/project.rb
index df9ea0c..170fcd9 100644
--- a/lib/hcl/project.rb
+++ b/lib/hcl/project.rb
@@ -1,3 +1,4 @@
class HCl::Project < HCl::TimesheetResource
+ collection_name :projects
end
diff --git a/lib/hcl/timesheet_resource.rb b/lib/hcl/timesheet_resource.rb
index 28e5378..54c74f1 100644
--- a/lib/hcl/timesheet_resource.rb
+++ b/lib/hcl/timesheet_resource.rb
@@ -15,5 +15,54 @@ module HCl
def respond_to? method
(@data && @data.key?(method.to_sym)) || super
end
+
+ class << self
+ def _prepare_resource name, *args, &url_cb
+ ((@resources ||= {})[name] = {}).tap do |res|
+ opt_or_cb = args.pop
+ res[:url_cb] = url_cb
+ res[:opts] = {}
+ case opt_or_cb
+ when String
+ res[:url_cb] = ->() { opt_or_cb }
+ res[:opts] = args.pop || {}
+ when Hash
+ res[:opts] = opt_or_cb
+ url = args.pop
+ res[:url_cb] = ->() { url } if url
+ end
+ end
+ end
+
+ def resources name, *args, &url_cb
+ res = _prepare_resource name, *args, &url_cb
+ cls = res[:opts][:class_name] ? HCl.const_get(res[:opts][:class_name]) : self
+ method = cls == self ? :define_singleton_method : :define_method
+ send(method, name) do |*args|
+ url = instance_exec *args, &res[:url_cb]
+ cb = res[:opts][:load_cb]
+ Net.get(url).tap{|e| cb.call(e) if cb }[cls.collection_name].map{|e|new(e)}
+ end
+ end
+
+ def resource name, *args, &url_cb
+ res = _prepare_resource name, *args, &url_cb
+ cls = res[:opts][:class_name] ? HCl.const_get(res[:opts][:class_name]) : self
+ method = cls == self ? :define_singleton_method : :define_method
+ send(method, name) do |*args|
+ url = instance_exec *args, &res[:url_cb]
+ cb = res[:opts][:load_cb]
+ cls.new Net.get(url).tap{|e| cb.call(e) if cb }[cls.underscore_name]
+ end
+ end
+
+ def underscore_name
+ @underscore_name ||= name.split('::').last.split(/(?=[A-Z])/).map(&:downcase).join('_').to_sym
+ end
+
+ def collection_name name=nil
+ name ? (@collection_name = name) : @collection_name
+ end
+ end
end
end
diff --git a/test/app_test.rb b/test/app_test.rb
index 1fc1073..e6dbc3d 100644
--- a/test/app_test.rb
+++ b/test/app_test.rb
@@ -2,6 +2,7 @@ require 'test_helper'
class AppTest < HCl::TestCase
def setup
+ super
# touch config to avoid triggering manual config
FileUtils.mkdir_p HCl::App::HCL_DIR
FileUtils.touch File.join(HCl::App::HCL_DIR, "config.yml")
@@ -13,7 +14,7 @@ class AppTest < HCl::TestCase
end
def test_command_show
- HCl::DayEntry.expects(:all).returns [HCl::DayEntry.new(
+ HCl::DayEntry.expects(:daily).returns [HCl::DayEntry.new(
hours:'2.06', notes:'hi world', project:'App'
)]
HCl::App.command 'show'
diff --git a/test/command_test.rb b/test/command_test.rb
index dd6f440..56c7d93 100644
--- a/test/command_test.rb
+++ b/test/command_test.rb
@@ -4,6 +4,7 @@ class CommandTest < HCl::TestCase
include HCl::Utility
def setup
+ super
@settings = {}
end
@@ -34,7 +35,7 @@ class CommandTest < HCl::TestCase
end
def test_show
- HCl::DayEntry.expects(:all).returns([HCl::DayEntry.new({
+ HCl::DayEntry.expects(:daily).returns([HCl::DayEntry.new({
hours:'2.06',
notes: 'hi world',
project: 'App'
@@ -74,9 +75,9 @@ class CommandTest < HCl::TestCase
def test_stop
entry = stub
- HCl::DayEntry.expects(:with_timer).returns(entry)
- entry.expects(:append_note).with('all done')
- entry.expects(:toggle)
+ register_uri(:get, '/daily', {day_entries:[{id:123,notes:'',hours:1,client:nil,project:nil,timer_started_at:DateTime.now}]})
+ register_uri(:post, '/daily/update/123', {day_entry:{notes:'all done'}})
+ register_uri(:get, '/daily/timer/123')
stop 'all done'
end
diff --git a/test/day_entry_test.rb b/test/day_entry_test.rb
index 6566a86..5b53463 100644
--- a/test/day_entry_test.rb
+++ b/test/day_entry_test.rb
@@ -1,19 +1,25 @@
require 'test_helper'
class DayEntryTest < HCl::TestCase
+ def test_project_info
+ register_uri(:get, '/daily', {projects:[], day_entries:[{project_id:123}]})
+ register_uri(:get, '/projects/123', {project:{name:'fun times'}})
+ assert_equal 'fun times', HCl::DayEntry.today.first.project_info.name
+ end
+
def test_all_today_empty
register_uri(:get, '/daily', {projects:[],day_entries:[]})
- assert HCl::DayEntry.all.empty?
+ assert HCl::DayEntry.today.empty?
end
def test_all_today
register_uri(:get, '/daily', {projects:[], day_entries:[{id:1,note:'hi'}]})
- assert_equal 'hi', HCl::DayEntry.all.first.note
+ assert_equal 'hi', HCl::DayEntry.today.first.note
end
def test_all_with_date
register_uri(:get, '/daily/013/2013', {projects:[], day_entries:[{id:1,note:'hi'}]})
- assert_equal 'hi', HCl::DayEntry.all(Date.civil(2013,1,13)).first.note
+ assert_equal 'hi', HCl::DayEntry.daily(Date.civil(2013,1,13)).first.note
end
def test_toggle
diff --git a/test/ext/capture_output.rb b/test/ext/capture_output.rb
index a469e21..bbf5424 100644
--- a/test/ext/capture_output.rb
+++ b/test/ext/capture_output.rb
@@ -1,11 +1,15 @@
module CaptureOutput
def before_setup
super
- $stderr = @stderr = StringIO.new
- $stdout = @stdout = StringIO.new
+ @stderr = StringIO.new
+ @stdout = StringIO.new
+ return if ENV['VERBOSE']
+ $stderr = @stderr
+ $stdout = @stdout
end
def after_teardown
super
+ return if ENV['VERBOSE']
$stderr = STDERR
$stdout = STDOUT
end