freshtrack 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,8 @@
1
+ == 0.5.0 2011-03-28
2
+
3
+ * 1 minor enhancement:
4
+ * Allowing Freshbooks API credentials to appear at a per-project level
5
+
1
6
  == 0.4.2 2009-08-02
2
7
 
3
8
  * 1 tiny enhancement:
data/Rakefile CHANGED
@@ -1,4 +1,51 @@
1
- require 'config/requirements'
2
- require 'config/hoe' # setup Hoe + all gem configuration
3
-
4
- Dir['tasks/**/*.rake'].each { |rake| load rake }
1
+ require 'rubygems'
2
+ #require 'bundler'
3
+ #begin
4
+ # Bundler.setup(:default, :development)
5
+ #rescue Bundler::BundlerError => e
6
+ # $stderr.puts e.message
7
+ # $stderr.puts "Run `bundle install` to install missing gems"
8
+ # exit e.status_code
9
+ #end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "freshtrack"
16
+ gem.homepage = "http://github.com/flogic/freshtrack"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{Track your time on FreshBooks}
19
+ gem.email = "ymendel@pobox.com"
20
+ gem.authors = ["Yossef Mendelssohn"]
21
+ gem.add_runtime_dependency 'freshbooks', '= 2.1'
22
+ gem.add_development_dependency 'bacon', '>= 1.1.0'
23
+ gem.add_development_dependency 'facon', '>= 0.4.1'
24
+ end
25
+ Jeweler::RubygemsDotOrgTasks.new
26
+
27
+ require 'rake/testtask'
28
+ Rake::TestTask.new(:test) do |test|
29
+ test.libs << 'lib' << 'test'
30
+ test.pattern = 'test/**/test_*.rb'
31
+ test.verbose = true
32
+ end
33
+
34
+ #require 'rcov/rcovtask'
35
+ #Rcov::RcovTask.new do |test|
36
+ # test.libs << 'test'
37
+ # test.pattern = 'test/**/test_*.rb'
38
+ # test.verbose = true
39
+ #end
40
+
41
+ task :default => :test
42
+
43
+ require 'rake/rdoctask'
44
+ Rake::RDocTask.new do |rdoc|
45
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
46
+
47
+ rdoc.rdoc_dir = 'rdoc'
48
+ rdoc.title = "freshtrack #{version}"
49
+ rdoc.rdoc_files.include('README*')
50
+ rdoc.rdoc_files.include('lib/**/*.rb')
51
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.5.0
data/bin/freshtrack CHANGED
@@ -42,8 +42,10 @@ BANNER
42
42
  end
43
43
  end
44
44
 
45
+ project = ARGV.shift
46
+
45
47
  if aging
46
- Freshtrack.init
48
+ Freshtrack.init(project)
47
49
  aging = Freshtrack.invoice_aging
48
50
  printf "%-8s %-40s %-5s %-6s %8s %8s\n", 'Invoice', 'Client', 'Age', 'Status', 'Amount', 'Owed'
49
51
  printf "%s\n", '-' * 86
@@ -53,12 +55,10 @@ if aging
53
55
  exit
54
56
  end
55
57
 
56
- project = ARGV.shift
57
-
58
58
  unless project
59
59
  puts "Usage: #{File.basename($0)} [project] [options]"
60
60
  exit
61
61
  end
62
62
 
63
- Freshtrack.init
63
+ Freshtrack.init(project)
64
64
  Freshtrack.track(project, OPTIONS)
data/config/hoe.rb CHANGED
@@ -11,8 +11,8 @@ EXTRA_DEPENDENCIES = [
11
11
  ['freshbooks', '= 2.1']
12
12
  ] # An array of rubygem dependencies [name, version]
13
13
  EXTRA_DEV_DEPENDENCIES = [
14
- ['rspec', '>= 1.1.4'],
15
- ['mocha', '>= 0.9.1']
14
+ ['bacon', '>= 1.1.0'],
15
+ ['facon', '>= 0.4.1']
16
16
  ] # An array of rubygem dependencies [name, version]
17
17
 
18
18
  @config_file = "~/.rubyforge/user-config.yml"
@@ -1,8 +1,8 @@
1
1
  module Freshtrack #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 4
5
- TINY = 2
4
+ MINOR = 5
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/lib/freshtrack.rb CHANGED
@@ -5,10 +5,11 @@ require 'yaml'
5
5
 
6
6
  module Freshtrack
7
7
  class << self
8
- attr_reader :config, :project, :task
8
+ attr_reader :config, :project_name, :project, :task
9
9
 
10
- def init
10
+ def init(project = nil)
11
11
  load_config
12
+ @project_name = project
12
13
  FreshBooks.setup("#{company}.freshbooks.com", token)
13
14
  end
14
15
 
@@ -17,13 +18,21 @@ module Freshtrack
17
18
  end
18
19
 
19
20
  def company
20
- config['company']
21
+ project_info_value('company')
21
22
  end
22
23
 
23
24
  def token
24
- config['token']
25
+ project_info_value('token')
25
26
  end
26
27
 
28
+ def project_info_value(key)
29
+ return config[key.to_s] unless project_name
30
+ info = project_task_mapping[project_name]
31
+ return config[key.to_s] unless info[:company] and info[:token]
32
+ info[key.to_sym]
33
+ end
34
+ private :project_info_value
35
+
27
36
  def project_task_mapping
28
37
  config['project_task_mapping']
29
38
  end
data/spec/.bacon ADDED
File without changes
@@ -2,24 +2,24 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
2
2
 
3
3
  describe Array do
4
4
  it 'should be groupable' do
5
- Array.new.should respond_to(:group_by)
5
+ Array.new.should.respond_to(:group_by)
6
6
  end
7
7
 
8
8
  describe 'when grouping' do
9
- before :each do
9
+ before do
10
10
  @array = (1..10).to_a
11
11
  end
12
12
 
13
13
  it 'should require a block' do
14
- lambda { @array.group_by }.should raise_error(ArgumentError)
14
+ lambda { @array.group_by }.should.raise(ArgumentError)
15
15
  end
16
16
 
17
17
  it 'should accept a block' do
18
- lambda { @array.group_by {} }.should_not raise_error(ArgumentError)
18
+ lambda { @array.group_by {} }.should.not.raise(ArgumentError)
19
19
  end
20
20
 
21
21
  it 'should return a hash' do
22
- @array.group_by {}.should be_kind_of(Hash)
22
+ @array.group_by {}.should.be.kind_of(Hash)
23
23
  end
24
24
 
25
25
  it 'should group the elements by the return value of the block' do
@@ -2,7 +2,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
2
2
 
3
3
  describe Integer do
4
4
  it 'should be convertible from seconds to hours' do
5
- 90.should respond_to(:secs_to_hours)
5
+ 90.should.respond_to(:secs_to_hours)
6
6
  end
7
7
 
8
8
  it 'should return this number of seconds as an amount of hours' do
@@ -12,7 +12,7 @@ end
12
12
 
13
13
  describe Float do
14
14
  it 'should be convertible from seconds to hours' do
15
- 90.0.should respond_to(:secs_to_hours)
15
+ 90.0.should.respond_to(:secs_to_hours)
16
16
  end
17
17
 
18
18
  it 'should return this number of seconds as an amount of hours' do
@@ -2,17 +2,17 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
2
2
 
3
3
  describe Time do
4
4
  it 'should be convertible to date' do
5
- Time.now.should respond_to(:to_date)
5
+ Time.now.should.respond_to(:to_date)
6
6
  end
7
7
 
8
8
  describe 'when converting to date' do
9
- before :each do
9
+ before do
10
10
  @time = Time.now
11
11
  @date = @time.to_date
12
12
  end
13
13
 
14
14
  it 'should return a date' do
15
- @date.should be_kind_of(Date)
15
+ @date.should.be.kind_of(Date)
16
16
  end
17
17
 
18
18
  it 'should return an date with matching year' do
@@ -5,17 +5,17 @@ ThingDeal = FreshBooks::BaseObject.new(:attr)
5
5
 
6
6
  describe FreshBooks::BaseObject do
7
7
  it 'should have a mapping function for Date' do
8
- FreshBooks::BaseObject::MAPPING_FNS[Date].should respond_to(:call)
8
+ FreshBooks::BaseObject::MAPPING_FNS[Date].should.respond_to(:call)
9
9
  end
10
10
 
11
11
  describe 'Date mapping function' do
12
- before :each do
12
+ before do
13
13
  @func = FreshBooks::BaseObject::MAPPING_FNS[Date]
14
- @date = stub('date arg', :text => '2008-01-29')
14
+ @date = mock('date arg', :text => '2008-01-29')
15
15
  end
16
16
 
17
17
  it 'should return a date' do
18
- @func.call(@date).should be_kind_of(Date)
18
+ @func.call(@date).should.be.kind_of(Date)
19
19
  end
20
20
 
21
21
  it 'should return a date matching the text of its argument' do
@@ -24,18 +24,18 @@ describe FreshBooks::BaseObject do
24
24
  end
25
25
 
26
26
  describe 'converting an instance to XML' do
27
- before :each do
27
+ before do
28
28
  @thing = Thing.new
29
29
  end
30
30
 
31
31
  it 'should use the elem name' do
32
- @thing.expects(:elem_name)
32
+ @thing.should.receive(:elem_name)
33
33
  @thing.to_xml
34
34
  end
35
35
  end
36
36
 
37
37
  describe 'getting the elem name' do
38
- before :each do
38
+ before do
39
39
  @thing = Thing.new
40
40
  @thing_deal = ThingDeal.new
41
41
  end
@@ -1,34 +1,34 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
2
2
 
3
3
  describe FreshBooks::Invoice do
4
- before :each do
4
+ before do
5
5
  @invoice = FreshBooks::Invoice.new
6
6
  end
7
7
 
8
8
  describe 'attributes' do
9
9
  it 'should have an invoice_id' do
10
- @invoice.should respond_to(:invoice_id)
10
+ @invoice.should.respond_to(:invoice_id)
11
11
  end
12
12
 
13
13
  it 'should have a client_id' do
14
- @invoice.should respond_to(:client_id)
14
+ @invoice.should.respond_to(:client_id)
15
15
  end
16
16
 
17
17
  it 'should have a date' do
18
- @invoice.should respond_to(:date)
18
+ @invoice.should.respond_to(:date)
19
19
  end
20
20
 
21
21
  it 'should have a status' do
22
- @invoice.should respond_to(:status)
22
+ @invoice.should.respond_to(:status)
23
23
  end
24
24
 
25
25
  it 'should have an amount' do
26
- @invoice.should respond_to(:amount)
26
+ @invoice.should.respond_to(:amount)
27
27
  end
28
28
  end
29
29
 
30
30
  describe 'type mappings' do
31
- before :each do
31
+ before do
32
32
  @mapping = FreshBooks::Invoice::TYPE_MAPPINGS
33
33
  end
34
34
 
@@ -46,53 +46,53 @@ describe FreshBooks::Invoice do
46
46
  end
47
47
 
48
48
  it 'should indicate open status' do
49
- @invoice.should respond_to(:open?)
49
+ @invoice.should.respond_to(:open?)
50
50
  end
51
51
 
52
52
  describe 'indicating open status' do
53
53
  it "should be false if the status is 'draft'" do
54
54
  @invoice.status = 'draft'
55
- @invoice.should_not be_open
55
+ @invoice.should.not.be.open
56
56
  end
57
57
 
58
58
  it "should be true if the status is 'sent'" do
59
59
  @invoice.status = 'sent'
60
- @invoice.should be_open
60
+ @invoice.should.be.open
61
61
  end
62
62
 
63
63
  it "should be true if the status is 'viewed'" do
64
64
  @invoice.status = 'viewed'
65
- @invoice.should be_open
65
+ @invoice.should.be.open
66
66
  end
67
67
 
68
68
  it "should be false if the status is 'paid'" do
69
69
  @invoice.status = 'paid'
70
- @invoice.should_not be_open
70
+ @invoice.should.not.be.open
71
71
  end
72
72
 
73
73
  it "should be true if the status is 'partial'" do
74
74
  @invoice.status = 'partial'
75
- @invoice.should be_open
75
+ @invoice.should.be.open
76
76
  end
77
77
  end
78
78
 
79
79
  it 'should have a client' do
80
- @invoice.should respond_to(:client)
80
+ @invoice.should.respond_to(:client)
81
81
  end
82
82
 
83
83
  describe 'client' do
84
84
  it 'should find client based on client_id' do
85
- client_id = stub('client ID')
86
- @invoice.stubs(:client_id).returns(client_id)
87
- FreshBooks::Client.expects(:get).with(client_id)
85
+ client_id = mock('client ID')
86
+ @invoice.stub!(:client_id).and_return(client_id)
87
+ FreshBooks::Client.should.receive(:get).with(client_id)
88
88
  @invoice.client
89
89
  end
90
90
 
91
91
  it 'should return found client' do
92
- client = stub('client')
93
- client_id = stub('client ID')
94
- @invoice.stubs(:client_id).returns(client_id)
95
- FreshBooks::Client.expects(:get).with(client_id).returns(client)
92
+ client = mock('client')
93
+ client_id = mock('client ID')
94
+ @invoice.stub!(:client_id).and_return(client_id)
95
+ FreshBooks::Client.should.receive(:get).with(client_id).and_return(client)
96
96
  @invoice.client.should == client
97
97
  end
98
98
  end
@@ -114,12 +114,12 @@ describe FreshBooks::Invoice do
114
114
  end
115
115
 
116
116
  it 'should show up in the members list' do
117
- FreshBooks::Invoice.members.should include('number')
117
+ FreshBooks::Invoice.members.should.include('number')
118
118
  end
119
119
  end
120
120
 
121
121
  it 'should still have important core behavior' do
122
- FreshBooks::Invoice.should respond_to(:list)
122
+ FreshBooks::Invoice.should.respond_to(:list)
123
123
  end
124
124
 
125
125
  it 'should still be a type of BaseObject' do
@@ -128,10 +128,10 @@ describe FreshBooks::Invoice do
128
128
 
129
129
  it 'should still have other fields in the members list' do
130
130
  members = FreshBooks::Invoice.members
131
- members.should include('invoice_id')
132
- members.should include('client_id')
133
- members.should include('status')
134
- members.should include('date')
131
+ members.should.include('invoice_id')
132
+ members.should.include('client_id')
133
+ members.should.include('status')
134
+ members.should.include('date')
135
135
  end
136
136
 
137
137
  it 'should still allow other fields to be set and get using []' do
@@ -143,23 +143,23 @@ describe FreshBooks::Invoice do
143
143
  end
144
144
 
145
145
  it 'should have payments' do
146
- @invoice.should respond_to(:payments)
146
+ @invoice.should.respond_to(:payments)
147
147
  end
148
148
 
149
149
  describe 'payments' do
150
- before :each do
151
- @payments = Array.new(3) { stub('payment') }
152
- FreshBooks::Payment.stubs(:list).returns(@payments)
150
+ before do
151
+ @payments = Array.new(3) { mock('payment') }
152
+ FreshBooks::Payment.stub!(:list).and_return(@payments)
153
153
  end
154
154
 
155
155
  it 'should get a list from Payment' do
156
- FreshBooks::Payment.expects(:list)
156
+ FreshBooks::Payment.should.receive(:list)
157
157
  @invoice.payments
158
158
  end
159
159
 
160
160
  it 'should pass the invoice_id when getting the list' do
161
161
  @invoice.invoice_id = '0000073'
162
- FreshBooks::Payment.expects(:list).with('invoice_id' => @invoice.invoice_id)
162
+ FreshBooks::Payment.should.receive(:list).with('invoice_id' => @invoice.invoice_id)
163
163
  @invoice.payments
164
164
  end
165
165
 
@@ -168,36 +168,36 @@ describe FreshBooks::Invoice do
168
168
  end
169
169
 
170
170
  it 'should return an empty array if Payment returns nil' do
171
- FreshBooks::Payment.stubs(:list).returns(nil)
171
+ FreshBooks::Payment.stub!(:list).and_return(nil)
172
172
  @invoice.payments.should == []
173
173
  end
174
174
  end
175
175
 
176
176
  it 'should have a paid amount' do
177
- @invoice.should respond_to(:paid_amount)
177
+ @invoice.should.respond_to(:paid_amount)
178
178
  end
179
179
 
180
180
  describe 'paid amount' do
181
181
  it 'should be the sum of payment amounts' do
182
- payments = [stub('payment', :amount => 3), stub('payment', :amount => 15), stub('payment', :amount => 5)]
183
- @invoice.stubs(:payments).returns(payments)
182
+ payments = [mock('payment', :amount => 3), mock('payment', :amount => 15), mock('payment', :amount => 5)]
183
+ @invoice.stub!(:payments).and_return(payments)
184
184
  @invoice.paid_amount.should == 23
185
185
  end
186
186
 
187
187
  it 'should be 0 if there are no payments' do
188
- @invoice.stubs(:payments).returns([])
188
+ @invoice.stub!(:payments).and_return([])
189
189
  @invoice.paid_amount.should == 0
190
190
  end
191
191
  end
192
192
 
193
193
  it 'should have an owed amount' do
194
- @invoice.should respond_to(:owed_amount)
194
+ @invoice.should.respond_to(:owed_amount)
195
195
  end
196
196
 
197
197
  describe 'owed amount' do
198
198
  it 'should be invoice amount less paid amount' do
199
199
  @invoice.amount = 60
200
- @invoice.stubs(:paid_amount).returns(50)
200
+ @invoice.stub!(:paid_amount).and_return(50)
201
201
  @invoice.owed_amount.should == 10
202
202
  end
203
203
  end
@@ -1,22 +1,22 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
2
2
 
3
3
  describe FreshBooks::Payment do
4
- before :each do
4
+ before do
5
5
  @payment = FreshBooks::Payment.new
6
6
  end
7
7
 
8
8
  describe 'attributes' do
9
9
  it 'should have an invoice_id' do
10
- @payment.should respond_to(:invoice_id)
10
+ @payment.should.respond_to(:invoice_id)
11
11
  end
12
12
 
13
13
  it 'should have an amount' do
14
- @payment.should respond_to(:amount)
14
+ @payment.should.respond_to(:amount)
15
15
  end
16
16
  end
17
17
 
18
18
  describe 'type mappings' do
19
- before :each do
19
+ before do
20
20
  @mapping = FreshBooks::Payment::TYPE_MAPPINGS
21
21
  end
22
22