Pratt 1.6.8-x86-linux

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.
Files changed (72) hide show
  1. data/.exrc +61 -0
  2. data/.gitignore +6 -0
  3. data/History.txt +6 -0
  4. data/Manifest.txt +46 -0
  5. data/Pratt.gemspec +173 -0
  6. data/Pratt.mm +1867 -0
  7. data/README.txt +67 -0
  8. data/Rakefile +96 -0
  9. data/TODO +56 -0
  10. data/VERSION +1 -0
  11. data/bin/pratt +13 -0
  12. data/config.rb +19 -0
  13. data/db/sqlite_databases_go_here +0 -0
  14. data/db/zips.csv.zip +0 -0
  15. data/lib/models.rb +8 -0
  16. data/lib/pratt.rb +308 -0
  17. data/lib/pratt/core_ext.rb +6 -0
  18. data/lib/pratt/core_ext/array.rb +20 -0
  19. data/lib/pratt/core_ext/float.rb +29 -0
  20. data/lib/pratt/core_ext/nil.rb +5 -0
  21. data/lib/pratt/core_ext/numeric.rb +9 -0
  22. data/lib/pratt/core_ext/string.rb +31 -0
  23. data/lib/pratt/core_ext/time.rb +20 -0
  24. data/lib/pratt/dialogs.rb +81 -0
  25. data/lib/pratt/formatting.rb +19 -0
  26. data/lib/pratt/project_actions.rb +25 -0
  27. data/lib/pratt/reports.rb +140 -0
  28. data/models/app.rb +39 -0
  29. data/models/customer.rb +50 -0
  30. data/models/invoice.rb +28 -0
  31. data/models/invoice_whence.rb +18 -0
  32. data/models/payment.rb +22 -0
  33. data/models/pratt.rb +15 -0
  34. data/models/project.rb +89 -0
  35. data/models/whence.rb +77 -0
  36. data/models/zip.rb +27 -0
  37. data/pratt.mm +1875 -0
  38. data/spec/app_spec.rb +48 -0
  39. data/spec/array_spec.rb +24 -0
  40. data/spec/customer_spec.rb +31 -0
  41. data/spec/fixtures/empty_graph.expectation +8 -0
  42. data/spec/fixtures/graph.expectation +13 -0
  43. data/spec/fixtures/proportions.expectation +4 -0
  44. data/spec/float_spec.rb +24 -0
  45. data/spec/formatting_spec.rb +7 -0
  46. data/spec/money_spec.rb +9 -0
  47. data/spec/nil_class_spec.rb +8 -0
  48. data/spec/numeric_spec.rb +30 -0
  49. data/spec/payment_spec.rb +19 -0
  50. data/spec/pratt_spec.rb +106 -0
  51. data/spec/project_spec.rb +182 -0
  52. data/spec/rcov.opts +0 -0
  53. data/spec/report_action_spec.rb +83 -0
  54. data/spec/report_spec.rb +205 -0
  55. data/spec/seed_data.rb +33 -0
  56. data/spec/spec.opts +1 -0
  57. data/spec/spec_helper.rb +24 -0
  58. data/spec/string_ext_spec.rb +33 -0
  59. data/spec/whence_spec.rb +54 -0
  60. data/tasks/pratt.rb +87 -0
  61. data/templates/model.eruby +12 -0
  62. data/templates/spec.eruby +8 -0
  63. data/views/current.eruby +5 -0
  64. data/views/general-invoice.eruby +538 -0
  65. data/views/graph.eruby +16 -0
  66. data/views/invoice.eruby +148 -0
  67. data/views/main.rb +90 -0
  68. data/views/pid.eruby +3 -0
  69. data/views/pop.rb +78 -0
  70. data/views/proportions.eruby +4 -0
  71. data/views/raw.eruby +11 -0
  72. metadata +275 -0
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe App do
4
+ context "instances" do
5
+ it "should only have one" do
6
+ App.last.should_not be_nil
7
+ end
8
+
9
+ it "should have log" do
10
+ @app = App.last
11
+ @app.expects(:log).with('pop').returns(@app)
12
+ @app.log 'pop'
13
+ end
14
+
15
+ it "should say it has something logged" do
16
+ @app = App.new
17
+ @app.gui?('main').should be_false
18
+ @app.gui?('pop').should be_false
19
+
20
+ @app.gui = 'main'
21
+ @app.gui?('main').should be_true
22
+
23
+ @app.gui = 'pop'
24
+ @app.gui?('main').should be_false
25
+
26
+ @app.gui = 'pop'
27
+ @app.gui?('pop').should be_true
28
+
29
+ @app.gui = 'pop'
30
+ @app.gui?('bob').should be_false
31
+ end
32
+
33
+ it "should remove the gui when expected" do
34
+ @app = App.create :gui => 'pop'
35
+
36
+ @app.gui?('pop').should be_true
37
+ @app.unlock
38
+ @app.gui?('pop').should be_false
39
+
40
+ @app.gui = 'main'
41
+ @app.save
42
+ @app.gui?('pop').should be_false
43
+ @app.gui?('main').should be_true
44
+
45
+ @app.destroy
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ require 'pratt'
3
+
4
+ describe Array do
5
+ it "to_sentence concatenates each element correctly with no elements" do
6
+ [].to_sentence.should eql('')
7
+ end
8
+
9
+ it "to_sentence concatenates each element correctly with one element" do
10
+ %w(a).to_sentence.should eql('a')
11
+ end
12
+
13
+ it "to_sentence concatenates each element correctly with two elements" do
14
+ %w(a b).to_sentence.should eql('a and b')
15
+ end
16
+
17
+ it "to_sentence concatenates each element correctly with >= three elements" do
18
+ %w(a b c d).to_sentence.should eql('a, b, c, and d')
19
+ end
20
+
21
+ it "to_sentence concatenates each element correctly with >= three elements and a different conjunction" do
22
+ %w(a b c d).to_sentence('&').should eql('a, b, c, & d')
23
+ end
24
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+ require 'pratt'
3
+
4
+ describe Customer do
5
+ it_should_behave_like "being a billable item"
6
+
7
+ describe "instance" do
8
+ before :each do
9
+ @customer = Customer.create :name => "frogstarr78", :address => '312 NW 7th', :zip => '97862'
10
+ end
11
+
12
+ after :each do
13
+ Customer.find_by_name('frogstarr78').destroy
14
+ end
15
+
16
+ it "responds to :projects" do
17
+ Customer.new.should respond_to(:projects)
18
+ end
19
+
20
+ it "responds to :payment" do
21
+ Customer.new.should respond_to(:payment)
22
+ end
23
+
24
+ it "calculates amount correctly" do
25
+ payment = mock('payment')
26
+ payment.expects(:rate).once.returns(31500)
27
+ @customer.expects(:payment).once.returns(payment)
28
+ @customer.amount.should == 315.0
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,8 @@
1
+ Project detail
2
+ by week from
3
+ Mon 00:00:00 Sep 28 2009 to Sun 23:59:59 Oct 04 2009
4
+ dys hrs min total
5
+ -------------------------------------------------------------------
6
+
7
+
8
+ -------------------------------------------------------------------
@@ -0,0 +1,13 @@
1
+ Project detail
2
+ by week from
3
+ Mon 00:00:00 Sep 28 2009 to Sun 23:59:59 Oct 04 2009
4
+ dys hrs min total
5
+ -------------------------------------------------------------------
6
+
7
+ Lunch/Break | 00 day 01 hour 21 min 1.35
8
+ Task1 | 00 day 01 hour 03 min 1.07
9
+ Task2 | 00 day 00 hour 58 min 0.97
10
+ Another Task | 00 day 00 hour 05 min 0.08
11
+ Task3 | 01 day 17 hour 31 min 41.53
12
+
13
+ -------------------------------------------------------------------
@@ -0,0 +1,4 @@
1
+ Total 43.65 hrs
2
+ Refactor 0.00%
3
+ Lunch/Break 3.09%
4
+ Other 100.00%
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ require 'pratt'
3
+
4
+ describe Float do
5
+ it { 2.0.should respond_to(:format_integer) }
6
+ it { 2.0.should respond_to(:percentage) }
7
+
8
+ it "should format correctly" do
9
+ 2.0.format_integer.should eql("02")
10
+ end
11
+
12
+ it "shows percentage correctly with no total" do
13
+ 2.3.percentage.should eql("230.00%")
14
+ end
15
+
16
+ it "shows percentage correctly with total" do
17
+ 2.5.percentage(5).should eql("50.00%")
18
+ end
19
+
20
+ it "handles with_label as expected" do
21
+ Project.expects(:longest_project_name).returns 21
22
+ 3.5.with_label("label").should eql(" label 3.5")
23
+ end
24
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+ require 'pratt'
3
+
4
+ describe 'formatting' do
5
+ it "" do
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+ require 'pratt'
3
+
4
+ describe Money do
5
+ it "generates expected pretty_print output" do
6
+ @money = Money.new 2.5
7
+ @money.pretty_print.should eql("$2.50")
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+ require 'pratt'
3
+
4
+ describe NilClass do
5
+ it "generates expected pretty_print output" do
6
+ nil.pretty_print.should eql("")
7
+ end
8
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+ require 'pratt'
3
+
4
+ describe Numeric do
5
+ it { 1.should respond_to(:format_integer) }
6
+ it { 1.should respond_to(:with_label) }
7
+
8
+ it "should format correctly" do
9
+ Pratt.color = false
10
+ 1.format_integer.should eql("01")
11
+ end
12
+
13
+ it '"format" with with_label' do
14
+ Pratt.color = false
15
+ Project.expects(:longest_project_name).returns(11)
16
+ 1.with_label(:blue).should eql(" blue 1")
17
+ end
18
+
19
+ it "recursively applies formatting without color" do
20
+ Pratt.color = false
21
+ Project.expects(:longest_project_name).returns(11)
22
+ 1.format_integer.blue.with_label("#").should eql(" # 01")
23
+ end
24
+
25
+ it "recursively applies formatting with color" do
26
+ Pratt.color = true
27
+ Project.expects(:longest_project_name).returns(11)
28
+ 1.format_integer.blue.with_label("#").should eql(" # \e[34m01\e[0m")
29
+ end
30
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+ require 'pratt'
3
+
4
+ describe Payment do
5
+ describe "instances" do
6
+ before :each do
7
+ @payment = Payment.new
8
+ end
9
+
10
+ it "responds to :pretty_print" do
11
+ @payment.should respond_to(:pretty_print)
12
+ end
13
+
14
+ it "pretty_print is the expected format " do
15
+ @payment.rate = '100'
16
+ @payment.pretty_print.should == '$1.00'
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,106 @@
1
+ require 'spec_helper'
2
+ require 'pratt'
3
+
4
+ describe Pratt do
5
+ before :each do
6
+ @pratt = Pratt.new
7
+ end
8
+
9
+ it "should act like an array" do
10
+ @pratt.should respond_to(:<<)
11
+ lambda {
12
+ @pratt << :this
13
+ }.should change(@pratt.todo, :size).by(1)
14
+ @pratt.todo.should == [:this]
15
+ end
16
+
17
+ it "correctly report i_should?" do
18
+ @pratt.send(:i_should?, :this).should be_false
19
+ @pratt << :this
20
+ @pratt.send(:i_should?, :this).should be_true
21
+ end
22
+
23
+ it "should start a new project when calling begin" do
24
+ @pratt.project = mock('Refactor')
25
+ @pratt.when_to = Time.now
26
+ @pratt.project.expects(:start!).with(@pratt.when_to)
27
+
28
+ @pratt.begin
29
+ end
30
+
31
+ it "should allow project to be set by object" do
32
+ primary = Project.new :name => 'project', :weight => 1
33
+ Project.expects(:find_or_create_by_name).never
34
+ @pratt.project = primary
35
+ @pratt.project.should == primary
36
+ end
37
+
38
+ it "should allow project to be set by a string" do
39
+ Project.expects(:find_or_create_by_name).with( { :name => 'Refactor' } )
40
+ @pratt.project = 'Refactor'
41
+ end
42
+
43
+ describe "color" do
44
+
45
+ it "should color when expected" do
46
+ Pratt.color = true
47
+ 'this'.red.should == 'this'.red
48
+ end
49
+
50
+ it "should not color when not expected" do
51
+ Pratt.color = false
52
+ 'this'.red.should == 'this'
53
+ end
54
+ end
55
+
56
+ describe "\b#root" do
57
+ before :each do
58
+ @expected_root = File.dirname( File.expand_path( '..', __FILE__ ) ).to_s
59
+ Dir.stubs(:pwd).returns(@expected_root)
60
+ end
61
+
62
+ it "is correct without arguments" do
63
+ Pratt.root.should == [Pathname.new(@expected_root)]
64
+ end
65
+
66
+ it "is correct with a block but no argument" do
67
+ received = []
68
+ Pratt.root {|model| received << model }
69
+ received.should == [Pathname.new(@expected_root)]
70
+ end
71
+
72
+ it "is correct with an argument but no block" do
73
+ Pratt.root('models').should == [Pathname.new(File.join(@expected_root, "models"))]
74
+ end
75
+
76
+ it "is correct with an argument and block" do
77
+ received = []
78
+ expected = %w(app.rb customer.rb project.rb payment.rb pratt.rb whence.rb invoice.rb invoice_whence.rb zip.rb)
79
+ Pratt.root('models', '*.rb') {|model| received << model }
80
+ received.to_set.should == expected.collect {|model| Pathname.new File.join(@expected_root, "models", model) }.to_set
81
+ end
82
+ end
83
+
84
+ describe "parse" do
85
+ # do
86
+ ## Pratt.expects(:connect).with('staging')
87
+ ## lambda {
88
+ # Pratt.parse %w(--env staging)
89
+ ## }.should change(ENV['PRATT_ENV']).from('test').to('staging')
90
+ # ENV['PRATT_ENV'].should == 'staging'
91
+ # end
92
+
93
+ it "inits an irb console when given console argument" do
94
+ Pratt.any_instance.stubs(:i_should?).returns false
95
+ # ^ to bypass actually calling the code
96
+ Pratt.any_instance.expects(:<<).with(:console)
97
+ Pratt.parse %w(console)
98
+ end
99
+ end
100
+
101
+ it "should start IRB when console method is called" do
102
+ ARGV.expects(:clear)
103
+ IRB.expects(:start)
104
+ @pratt.console
105
+ end
106
+ end
@@ -0,0 +1,182 @@
1
+ require 'spec_helper'
2
+
3
+ # enable laziness
4
+ class Mocha::Mock
5
+ def name
6
+ @name.instance_variable_get("@name")
7
+ end
8
+ end
9
+
10
+ describe Project do
11
+ it_should_behave_like "being a billable item"
12
+
13
+ it{ Project.should respond_to(:primary) }
14
+ it{ Project.should respond_to(:off) }
15
+ it{ Project.should respond_to(:rest) }
16
+ it{ Project.should respond_to(:longest_project_name) }
17
+
18
+ context "scopes" do
19
+ it "named primary" do
20
+ Project.expects(:first).with(:conditions => { :weight => 1 }).returns(mock('Refactor'))
21
+ Project.primary.name.should == 'Refactor'
22
+ end
23
+
24
+ it "named off" do
25
+ Project.expects(:first).with(:conditions => { :name => 'Lunch/Break' }).returns(mock('Lunch/Break'))
26
+ Project.off.name.should == 'Lunch/Break'
27
+ end
28
+
29
+ it "named rest" do
30
+ prim = mock('Refactor')
31
+ off = mock('Lunch/Break')
32
+ other = mock('Other')
33
+
34
+ Project.expects(:primary).returns prim
35
+ Project.expects(:off).returns off
36
+ Project.expects(:all).returns([prim, off, other])
37
+ Project.rest.should == [other]
38
+ end
39
+
40
+ it "named named" do
41
+ Project.expects(:first).with(:conditions => { :name => 'Refactor' }).returns(mock('Refactor'))
42
+ Project.named('Refactor').name.should == 'Refactor'
43
+
44
+ Project.expects(:named).with(nil).returns nil
45
+ Project.named(nil).should be_nil
46
+ end
47
+ end
48
+
49
+ context "instances" do
50
+ include SeedData
51
+
52
+ before :each do
53
+ load_seed_data
54
+ @project = Project.primary
55
+ @log_count = @project.whences.size
56
+ end
57
+
58
+ after :each do
59
+ @project.whences.destroy_all
60
+ end
61
+
62
+ it "should correctly log entries using start! and stop!" do
63
+ lambda {
64
+ @project.start!
65
+ }.should change(@project.whences, :count).by(1)
66
+ @project.whences.last.end_at.should be_nil
67
+
68
+ sleep 1
69
+ lambda {
70
+ @project.stop!
71
+ }.should_not change(@project.whences, :count)
72
+ @project.should be_valid
73
+ @project.whences.reload
74
+ @project.whences.last.end_at.should > @project.whences.last.start_at
75
+ end
76
+
77
+ it "should log correct time if given (not the default)" do
78
+ lambda {
79
+ @project.start!
80
+ }.should change(@project.whences, :count).by(1)
81
+ @project.whences.last.end_at.should be_nil
82
+ end
83
+
84
+ it "should do nothing if attempting to start a project when there is one that has not been finished" do
85
+ @project.start!
86
+ @project.reload
87
+
88
+ $stdout.expects(:puts).with "Unable to start a new Project when there is an existing project #{@project.name} that hasn't been finished"
89
+ lambda {
90
+ @project.start!
91
+ }.should_not change(@project.whences, :count)
92
+ end
93
+
94
+ it "should do nothing if attempting to stop a project that hasn't been started" do
95
+ lambda {
96
+ @project.stop!
97
+ }.should_not change(@project.whences, :count)
98
+ end
99
+
100
+ it "should stop! then start! when calling restart!" do
101
+ @project.start!
102
+ first_started_id = @project.whences.last.id
103
+
104
+ lambda {
105
+ @project.restart!
106
+ }.should change(@project.whences, :count).by(1)
107
+ @project.whences.last.end_at.should be_nil
108
+ @project.whences.last.id.should_not == first_started_id
109
+ end
110
+
111
+ it "has a customer association" do
112
+ @project.should respond_to(:customer)
113
+ end
114
+
115
+ context "amount calculation" do
116
+ before :each do
117
+ Payment.create :rate => '315.0', :billable => @project
118
+
119
+ @now = Time.parse("2009-10-04 17:53:58")
120
+ Time.stubs(:now).returns(@now.beginning_of_week)
121
+
122
+ whence = Time.now-1.day
123
+ @project.start! whence
124
+ @project.stop! whence+3.hours
125
+
126
+ whence = Time.now
127
+ @project.start! whence
128
+ @project.stop! whence+3.hours
129
+
130
+ @project.reload
131
+ end
132
+
133
+ it "is correct with no arguments" do
134
+ @project.amount(@project.time_spent).should == 6*3.15
135
+ end
136
+
137
+ it "is correct with a scale" do
138
+ @project.amount(@project.time_spent(:month)).should == 6*3.15
139
+ end
140
+
141
+ it "is correct with a scale and time" do
142
+ @project.amount(@project.time_spent(:week, @now)).should == 3*3.15
143
+ end
144
+ end
145
+ end
146
+
147
+ context "time_spent" do
148
+ before :each do
149
+ @project = Project.new
150
+ end
151
+
152
+ it "correctly calculates with no data" do
153
+ @project.expects(:time_spent).returns 0
154
+ @project.time_spent.should == 0.0
155
+ end
156
+
157
+ it "correctly calculates with time argument" do
158
+ now = Time.now.beginning_of_day
159
+ Whence.expects(:find).returns [mock('whence1', :start_at => now, :end_at => now+=1.hour), mock('whence2', :start_at => now+=2.hours, :end_at => now+=2.hour+30.minutes)]
160
+ @project.time_spent.should == 3.5
161
+ end
162
+
163
+ it "correctly calculates with string time argument" do
164
+ whence = mock('whence', :start_at => Chronic.parse('last monday 12:00 pm'), :end_at => Chronic.parse('last monday 12:00:05 pm'))
165
+ Whence.expects(:find).returns [whence]
166
+ @project.time_spent.should == 5.0/3600
167
+ end
168
+
169
+ it "correctly calculates with a scale" do
170
+ whence = mock('whence', :start_at => Time.parse('2009-10-04 23:53:32'), :end_at => Time.parse('2009-10-05 00:10:32'))
171
+ Whence.expects(:find).returns [whence]
172
+ @project.time_spent('month').should == 17.0/60
173
+ end
174
+
175
+ it "correctly calculates with a scale and specific time" do
176
+ whence = mock('whence', :start_at => Time.parse('2009-10-05 23:54:32'), :end_at => Time.parse('2009-10-06 00:12:32'))
177
+ Whence.expects(:find).returns [whence]
178
+ @project.time_spent('day', Chronic.parse('yesterday')).should == 18.0/60
179
+ end
180
+ end
181
+
182
+ end