Pratt 1.6.5 → 1.6.8
Sign up to get free protection for your applications and to get access to all the features.
- data/Pratt.gemspec +16 -4
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/config.rb +0 -1
- data/lib/pratt.rb +1 -1
- data/lib/pratt/core_ext/array.rb +5 -1
- data/lib/pratt/core_ext/float.rb +1 -0
- data/lib/pratt/dialogs.rb +2 -1
- data/lib/pratt/formatting.rb +1 -1
- data/lib/pratt/reports.rb +16 -9
- data/models/customer.rb +5 -1
- data/models/pratt.rb +5 -0
- data/models/project.rb +8 -7
- data/models/whence.rb +1 -3
- data/spec/array_spec.rb +24 -0
- data/spec/fixtures/empty_graph.expectation +8 -0
- data/spec/fixtures/graph.expectation +8 -8
- data/spec/fixtures/proportions.expectation +4 -4
- data/spec/formatting_spec.rb +7 -0
- data/spec/money_spec.rb +9 -0
- data/spec/nil_class_spec.rb +8 -0
- data/spec/pratt_spec.rb +12 -61
- data/spec/project_spec.rb +6 -3
- data/spec/report_action_spec.rb +83 -0
- data/spec/report_spec.rb +205 -0
- data/spec/spec_helper.rb +34 -28
- data/views/general-invoice.eruby +3 -3
- data/views/invoice.eruby +1 -1
- metadata +16 -4
- data/Session.vim +0 -1010
data/spec/project_spec.rb
CHANGED
@@ -47,7 +47,10 @@ describe Project do
|
|
47
47
|
end
|
48
48
|
|
49
49
|
context "instances" do
|
50
|
+
include SeedData
|
51
|
+
|
50
52
|
before :each do
|
53
|
+
load_seed_data
|
51
54
|
@project = Project.primary
|
52
55
|
@log_count = @project.whences.size
|
53
56
|
end
|
@@ -118,15 +121,15 @@ describe Project do
|
|
118
121
|
end
|
119
122
|
|
120
123
|
it "is correct with no arguments" do
|
121
|
-
@project.amount.should == 6*3.15
|
124
|
+
@project.amount(@project.time_spent).should == 6*3.15
|
122
125
|
end
|
123
126
|
|
124
127
|
it "is correct with a scale" do
|
125
|
-
@project.amount(:month).should == 6*3.15
|
128
|
+
@project.amount(@project.time_spent(:month)).should == 6*3.15
|
126
129
|
end
|
127
130
|
|
128
131
|
it "is correct with a scale and time" do
|
129
|
-
@project.amount(:week, @now).should == 3*3.15
|
132
|
+
@project.amount(@project.time_spent(:week, @now)).should == 3*3.15
|
130
133
|
end
|
131
134
|
end
|
132
135
|
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pratt'
|
3
|
+
|
4
|
+
describe "Pratt report actions" do
|
5
|
+
include SeedData
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
@pratt = Pratt.new
|
9
|
+
@when_to = DateTime.now
|
10
|
+
load_seed_data
|
11
|
+
end
|
12
|
+
|
13
|
+
after :each do
|
14
|
+
Whence.delete_all
|
15
|
+
end
|
16
|
+
|
17
|
+
it "calls project#start! in begin method" do
|
18
|
+
@pratt.project = Project.primary
|
19
|
+
@pratt.when_to = @when_to
|
20
|
+
@pratt.project.expects(:start!).with @when_to
|
21
|
+
@pratt.begin
|
22
|
+
end
|
23
|
+
|
24
|
+
it "calls project#restart! in restart method with defined project" do
|
25
|
+
@next_when_to = @when_to + 7.minutes
|
26
|
+
primary = Project.primary
|
27
|
+
primary.start! @when_to
|
28
|
+
@pratt.project = primary
|
29
|
+
@pratt.when_to = @next_when_to
|
30
|
+
whence = primary.whences.last
|
31
|
+
Whence.expects(:last_unended).never
|
32
|
+
primary.expects(:restart!).with @next_when_to
|
33
|
+
@pratt.restart
|
34
|
+
end
|
35
|
+
|
36
|
+
it "calls last unended project in restart method without defined project" do
|
37
|
+
@next_when_to = @when_to + 7.minutes
|
38
|
+
primary = Project.primary
|
39
|
+
primary.start! @when_to
|
40
|
+
@pratt.when_to = @next_when_to
|
41
|
+
whence = primary.whences.last
|
42
|
+
Whence.expects(:last_unended).returns whence
|
43
|
+
whence.project.expects(:restart!).with @next_when_to
|
44
|
+
@pratt.restart
|
45
|
+
whence.project.should eql(primary)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "stops! defined project in end method" do
|
49
|
+
@pratt.project = Project.primary
|
50
|
+
@pratt.when_to = @when_to
|
51
|
+
@pratt.project.expects(:stop!).with @when_to
|
52
|
+
@pratt.end
|
53
|
+
end
|
54
|
+
|
55
|
+
it "stops! the last unended project in end method without defined project" do
|
56
|
+
primary = Project.primary
|
57
|
+
primary.start! @when_to
|
58
|
+
whence = primary.whences.last
|
59
|
+
Whence.expects(:last_unended).returns whence
|
60
|
+
whence.expects(:stop!).with @when_to
|
61
|
+
@pratt.when_to = @when_to
|
62
|
+
@pratt.end
|
63
|
+
end
|
64
|
+
|
65
|
+
it "changes last project in change method" do
|
66
|
+
primary = Project.primary
|
67
|
+
primary.start! @when_to
|
68
|
+
primary.stop! @when_to+10.minutes
|
69
|
+
other = Project.rest.first
|
70
|
+
whence = primary.whences.last
|
71
|
+
Whence.expects(:last).returns whence
|
72
|
+
whence.expects(:change!).with other.name
|
73
|
+
@pratt.project = other
|
74
|
+
@pratt.change
|
75
|
+
end
|
76
|
+
|
77
|
+
it "destroys defined project in destroy method" do
|
78
|
+
@pratt.project = Project.create :name => "to be destroyed"
|
79
|
+
lambda {
|
80
|
+
@pratt.destroy
|
81
|
+
}.should change(Project, :count).by -1
|
82
|
+
end
|
83
|
+
end
|
data/spec/report_spec.rb
ADDED
@@ -0,0 +1,205 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pratt'
|
3
|
+
|
4
|
+
describe "Pratt report method" do
|
5
|
+
|
6
|
+
describe "#pid" do
|
7
|
+
@pratt = Pratt.new
|
8
|
+
@pratt.expects(:template=).with("pid")
|
9
|
+
@pratt.expects(:process_template!)
|
10
|
+
@pratt.pid
|
11
|
+
end
|
12
|
+
|
13
|
+
# FIXME: Get this working
|
14
|
+
describe "#cpid" #do
|
15
|
+
# @pratt = Pratt.new
|
16
|
+
# ::Kernel.expects(:`)
|
17
|
+
# @pratt.cpid
|
18
|
+
# end
|
19
|
+
|
20
|
+
describe "#graph" do
|
21
|
+
before :each do
|
22
|
+
@pratt = Pratt.new
|
23
|
+
end
|
24
|
+
|
25
|
+
it "with no project uses Project.all to generate output" do
|
26
|
+
@pratt.expects(:template=).with("graph")
|
27
|
+
@pratt.expects(:project?).returns false
|
28
|
+
Project.expects(:all).returns([])
|
29
|
+
@pratt.expects(:process_template!)
|
30
|
+
@pratt.graph
|
31
|
+
end
|
32
|
+
|
33
|
+
it "with project uses defined project to generate output" do
|
34
|
+
@pratt.project = Project.new
|
35
|
+
@pratt.expects(:template=).with("graph")
|
36
|
+
@pratt.expects(:project?).returns true
|
37
|
+
@pratt.expects(:process_template!)
|
38
|
+
@pratt.graph
|
39
|
+
@pratt.instance_variable_get("@projects").should eql([@pratt.project])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "output" do
|
44
|
+
include SeedData
|
45
|
+
|
46
|
+
before :each do
|
47
|
+
@pratt = Pratt.new
|
48
|
+
end
|
49
|
+
before :each do
|
50
|
+
@when_to = Chronic.parse('September 29 2009').beginning_of_week
|
51
|
+
@pratt.scale = 'week'
|
52
|
+
@pratt.when_to = @when_to
|
53
|
+
@customer = Customer.create :name => 'Bob Hope', :address => '123 Where St', :zip => '22222'
|
54
|
+
@tasks = []
|
55
|
+
end
|
56
|
+
|
57
|
+
after :each do
|
58
|
+
Whence.delete_all
|
59
|
+
@customer.destroy
|
60
|
+
@tasks.each(&:destroy)
|
61
|
+
end
|
62
|
+
|
63
|
+
def get_expected_display fixture_name
|
64
|
+
Pratt.root('spec', 'fixtures', "#{fixture_name}.expectation").first.read
|
65
|
+
end
|
66
|
+
|
67
|
+
it "graphs output as expected with no data" do
|
68
|
+
Pratt.color = false
|
69
|
+
Project.stubs(:longest_project_name).returns 12
|
70
|
+
Project.stubs(:all).returns([])
|
71
|
+
$stdout.expects(:puts)
|
72
|
+
@pratt.graph
|
73
|
+
@pratt.send(:output).should eql( get_expected_display("empty_graph") )
|
74
|
+
end
|
75
|
+
|
76
|
+
it "graphs output as expected with data" do
|
77
|
+
populate_with_data
|
78
|
+
Pratt.color = false
|
79
|
+
Project.stubs(:longest_project_name).returns 12
|
80
|
+
$stdout.expects(:puts)
|
81
|
+
|
82
|
+
@pratt.graph
|
83
|
+
@pratt.send(:output).should eql( get_expected_display("graph") )
|
84
|
+
end
|
85
|
+
|
86
|
+
it "generates proportions graphs output as expected with data" do
|
87
|
+
populate_with_data
|
88
|
+
Pratt.color = false
|
89
|
+
Project.stubs(:longest_project_name).returns 12
|
90
|
+
$stdout.expects(:puts)
|
91
|
+
|
92
|
+
@pratt.proportions
|
93
|
+
@pratt.send(:output).should eql( get_expected_display("proportions") )
|
94
|
+
end
|
95
|
+
|
96
|
+
def task name, time_spent
|
97
|
+
task = Project.find_or_create_by_name :name => name, :customer => @customer
|
98
|
+
task.start! @when_to
|
99
|
+
task.stop! @when_to+time_spent
|
100
|
+
@tasks << task
|
101
|
+
end
|
102
|
+
|
103
|
+
def populate_with_data
|
104
|
+
load_seed_data
|
105
|
+
@tasks << Project.primary
|
106
|
+
task 'Lunch/Break', 1.hour+21.minutes+0.seconds
|
107
|
+
task 'Task1', 1.hour+4.minutes+0.seconds
|
108
|
+
task 'Task2', 58.minutes+0.seconds
|
109
|
+
task 'Another Task', 5.minutes+0.seconds
|
110
|
+
task 'Task3', 1.day+17.hours+32.minutes+0.seconds
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "#proportions" do
|
115
|
+
include SeedData
|
116
|
+
|
117
|
+
before :each do
|
118
|
+
@pratt = Pratt.new
|
119
|
+
end
|
120
|
+
before :each do
|
121
|
+
@when_to = Chronic.parse('last week').beginning_of_week
|
122
|
+
@pratt.scale = 'week'
|
123
|
+
@pratt.when_to = @when_to
|
124
|
+
@customer = Customer.create :name => 'Bob Hope', :address => '123 Where St', :zip => '22222'
|
125
|
+
@tasks = []
|
126
|
+
end
|
127
|
+
|
128
|
+
after :each do
|
129
|
+
Whence.delete_all
|
130
|
+
@customer.destroy
|
131
|
+
@tasks.each(&:destroy)
|
132
|
+
end
|
133
|
+
|
134
|
+
def task name, time_spent
|
135
|
+
task = Project.find_or_create_by_name :name => name, :customer => @customer, :weight => -1
|
136
|
+
task.start! @when_to
|
137
|
+
task.stop! @when_to+time_spent
|
138
|
+
@tasks << task
|
139
|
+
end
|
140
|
+
|
141
|
+
def populate_with_data
|
142
|
+
load_seed_data
|
143
|
+
primary = Project.primary
|
144
|
+
primary.start! @when_to
|
145
|
+
primary.stop! @when_to+20.hours
|
146
|
+
@tasks << primary
|
147
|
+
task 'Lunch/Break', 1.hour+21.minutes
|
148
|
+
task 'Task1', 1.hour+4.minutes
|
149
|
+
task 'Task2', 58.minutes
|
150
|
+
task 'Another Task', 5.minutes
|
151
|
+
task 'Task3', 1.day+17.hours+32.minutes
|
152
|
+
end
|
153
|
+
|
154
|
+
it "uses Project.all with data to generate output" do
|
155
|
+
populate_with_data
|
156
|
+
@pratt.expects(:template=).with("proportions")
|
157
|
+
@pratt.expects(:project?).returns false
|
158
|
+
@pratt.expects(:process_template!)
|
159
|
+
@pratt.proportions
|
160
|
+
@pratt.instance_variable_get("@primary").should eql(20.0)
|
161
|
+
@pratt.instance_variable_get("@off_total").should eql(1.35)
|
162
|
+
@pratt.instance_variable_get("@rest_total").should eql(43.65)
|
163
|
+
@pratt.instance_variable_get("@projects").should eql(Project.all)
|
164
|
+
@pratt.instance_variable_get("@scaled_total").should eql(63.65)
|
165
|
+
end
|
166
|
+
|
167
|
+
it "uses defined project with data to generate output" do
|
168
|
+
populate_with_data
|
169
|
+
@pratt.expects(:template=).with("proportions")
|
170
|
+
@pratt.expects(:project?).returns true
|
171
|
+
@pratt.project = Project.named('Task1')
|
172
|
+
@pratt.expects(:process_template!)
|
173
|
+
@pratt.proportions
|
174
|
+
@pratt.instance_variable_get("@primary").should eql(64/60.0)
|
175
|
+
@pratt.instance_variable_get("@off_total").should eql(0.0)
|
176
|
+
@pratt.instance_variable_get("@rest_total").should eql(0.0)
|
177
|
+
@pratt.instance_variable_get("@projects").should eql([@pratt.project])
|
178
|
+
@pratt.instance_variable_get("@scaled_total").should eql(64/60.0)
|
179
|
+
end
|
180
|
+
|
181
|
+
it "uses Project.all with no data to generate output" do
|
182
|
+
@pratt.expects(:template=).with("proportions")
|
183
|
+
@pratt.expects(:project?).returns false
|
184
|
+
Project.expects(:all).returns []
|
185
|
+
@pratt.expects(:process_template!).never
|
186
|
+
$stdout.expects(:puts).with "No data to report"
|
187
|
+
@pratt.proportions
|
188
|
+
end
|
189
|
+
|
190
|
+
it "uses defined project with no with data to generate output" do
|
191
|
+
@pratt.expects(:template=).with("proportions")
|
192
|
+
@pratt.expects(:project?).returns true
|
193
|
+
@pratt.project = Project.new
|
194
|
+
@pratt.project.expects(:time_spent).twice.returns 0.0
|
195
|
+
@pratt.expects(:process_template!).never
|
196
|
+
$stdout.expects(:puts).with "No data to report"
|
197
|
+
@pratt.proportions
|
198
|
+
@pratt.instance_variable_get("@primary").should eql(0.0)
|
199
|
+
@pratt.instance_variable_get("@off_total").should eql(0.0)
|
200
|
+
@pratt.instance_variable_get("@rest_total").should eql(0.0)
|
201
|
+
@pratt.instance_variable_get("@projects").should eql([@pratt.project])
|
202
|
+
@pratt.instance_variable_get("@scaled_total").should eql(0.0)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -6,39 +6,45 @@ require 'mocha'
|
|
6
6
|
require 'lib/pratt'
|
7
7
|
require 'ruby-debug'
|
8
8
|
|
9
|
+
module SeedData
|
10
|
+
def load_seed_data
|
11
|
+
Customer.delete_all
|
12
|
+
customer = Customer.create(
|
13
|
+
:name => 'Scott Noel-Hemming',
|
14
|
+
:company_name => 'Frogstarr78 Software',
|
15
|
+
:address => '312 NW 7th',
|
16
|
+
:phone => '509.730.5401',
|
17
|
+
:zip => '97862'
|
18
|
+
)
|
19
|
+
|
20
|
+
Project.delete_all
|
21
|
+
Project.create(
|
22
|
+
[
|
23
|
+
{
|
24
|
+
:name => 'Refactor',
|
25
|
+
:weight => 1,
|
26
|
+
:customer => customer
|
27
|
+
},
|
28
|
+
{
|
29
|
+
:name => 'Lunch/Break',
|
30
|
+
:weight => 0,
|
31
|
+
:customer => customer
|
32
|
+
},
|
33
|
+
{
|
34
|
+
:name => 'Other',
|
35
|
+
:weight => -1,
|
36
|
+
:customer => customer
|
37
|
+
}
|
38
|
+
]
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
9
43
|
Spec::Runner.configure do |config|
|
10
44
|
# config.mock_with :rspec
|
11
45
|
config.mock_with :mocha
|
12
46
|
|
13
47
|
Pratt.connect! 'test'
|
14
|
-
|
15
|
-
Customer.create(
|
16
|
-
:name => 'Scott Noel-Hemming',
|
17
|
-
:company_name => 'Frogstarr78 Software',
|
18
|
-
:address => '312 NW 7th',
|
19
|
-
:phone => '509.730.5401',
|
20
|
-
:zip => '97862'
|
21
|
-
) unless Customer.count > 0
|
22
|
-
|
23
|
-
Project.create(
|
24
|
-
[
|
25
|
-
{
|
26
|
-
:name => 'Refactor',
|
27
|
-
:weight => 1,
|
28
|
-
:customer_id => 0
|
29
|
-
},
|
30
|
-
{
|
31
|
-
:name => 'Lunch/Break',
|
32
|
-
:weight => 0,
|
33
|
-
:customer_id => 0
|
34
|
-
},
|
35
|
-
{
|
36
|
-
:name => 'Other',
|
37
|
-
:weight => -1,
|
38
|
-
:customer_id => 0
|
39
|
-
}
|
40
|
-
]
|
41
|
-
) unless Project.count > 0
|
42
48
|
end
|
43
49
|
|
44
50
|
shared_examples_for "Time spent on a project" do
|
data/views/general-invoice.eruby
CHANGED
@@ -450,7 +450,7 @@
|
|
450
450
|
<p><%= project.payment.pretty_print %></p>
|
451
451
|
</td>
|
452
452
|
<td style="text-align:right; " class="ce31">
|
453
|
-
<p><%= project.amount(scale, when_to).pretty_print %></p>
|
453
|
+
<p><%= project.amount( project.time_spent( scale, when_to ) ).pretty_print %></p>
|
454
454
|
</td>
|
455
455
|
</tr>
|
456
456
|
<% end %>
|
@@ -468,7 +468,7 @@
|
|
468
468
|
<!--p>SUBTOTAL</p-->
|
469
469
|
</td>
|
470
470
|
<td style="text-align:right; " class="ce36">
|
471
|
-
<!--p><%= project.amount(scale, when_to).pretty_print %></p-->
|
471
|
+
<!--p><%= project.amount( project.time_spent( scale, when_to ) ).pretty_print %></p-->
|
472
472
|
</td>
|
473
473
|
</tr>
|
474
474
|
<tr class="ro2">
|
@@ -480,7 +480,7 @@
|
|
480
480
|
<p>TOTAL</p>
|
481
481
|
</td>
|
482
482
|
<td style="text-align:right; " class="ce21 ce34">
|
483
|
-
<p><%= project.amount(scale, when_to).pretty_print %></p>
|
483
|
+
<p><%= project.amount( project.time_spent( scale, when_to ) ).pretty_print %></p>
|
484
484
|
</td>
|
485
485
|
</tr>
|
486
486
|
<tr class="ro2">
|
data/views/invoice.eruby
CHANGED
@@ -107,7 +107,7 @@
|
|
107
107
|
<P ALIGN=RIGHT><%= project.payment.pretty_print %></P>
|
108
108
|
</TD>
|
109
109
|
<TD WIDTH=97>
|
110
|
-
<P ALIGN=RIGHT><FONT SIZE=2><%= project.amount(scale, when_to).pretty_print %></FONT></P>
|
110
|
+
<P ALIGN=RIGHT><FONT SIZE=2><%= project.amount( project.time_spent( scale, when_to ) ).pretty_print %></FONT></P>
|
111
111
|
</TD>
|
112
112
|
</TR>
|
113
113
|
<% end %>
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 1
|
7
7
|
- 6
|
8
|
-
-
|
9
|
-
version: 1.6.
|
8
|
+
- 8
|
9
|
+
version: 1.6.8
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Scott Noel-Hemming
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-05-
|
17
|
+
date: 2010-05-31 00:00:00 -07:00
|
18
18
|
default_executable: pratt.rb
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -116,7 +116,6 @@ files:
|
|
116
116
|
- README.html
|
117
117
|
- README.txt
|
118
118
|
- Rakefile
|
119
|
-
- Session.vim
|
120
119
|
- TODO
|
121
120
|
- VERSION
|
122
121
|
- bin/pratt.rb
|
@@ -391,15 +390,22 @@ files:
|
|
391
390
|
- reports/travel.log
|
392
391
|
- reports/travel.log.2009
|
393
392
|
- spec/app_spec.rb
|
393
|
+
- spec/array_spec.rb
|
394
394
|
- spec/customer_spec.rb
|
395
|
+
- spec/fixtures/empty_graph.expectation
|
395
396
|
- spec/fixtures/graph.expectation
|
396
397
|
- spec/fixtures/proportions.expectation
|
397
398
|
- spec/float_spec.rb
|
399
|
+
- spec/formatting_spec.rb
|
400
|
+
- spec/money_spec.rb
|
401
|
+
- spec/nil_class_spec.rb
|
398
402
|
- spec/numeric_spec.rb
|
399
403
|
- spec/payment_spec.rb
|
400
404
|
- spec/pratt_spec.rb
|
401
405
|
- spec/project_spec.rb
|
402
406
|
- spec/rcov.opts
|
407
|
+
- spec/report_action_spec.rb
|
408
|
+
- spec/report_spec.rb
|
403
409
|
- spec/spec.opts
|
404
410
|
- spec/spec_helper.rb
|
405
411
|
- spec/string_ext_spec.rb
|
@@ -447,13 +453,19 @@ signing_key:
|
|
447
453
|
specification_version: 3
|
448
454
|
summary: Pro/Re-Active Time Tracker. Track time based on what you expect to be working on, with frequent prompts to ensure accuracy.
|
449
455
|
test_files:
|
456
|
+
- spec/nil_class_spec.rb
|
450
457
|
- spec/whence_spec.rb
|
458
|
+
- spec/array_spec.rb
|
451
459
|
- spec/spec_helper.rb
|
452
460
|
- spec/float_spec.rb
|
453
461
|
- spec/pratt_spec.rb
|
454
462
|
- spec/project_spec.rb
|
455
463
|
- spec/numeric_spec.rb
|
456
464
|
- spec/app_spec.rb
|
465
|
+
- spec/formatting_spec.rb
|
457
466
|
- spec/string_ext_spec.rb
|
458
467
|
- spec/customer_spec.rb
|
468
|
+
- spec/report_spec.rb
|
469
|
+
- spec/money_spec.rb
|
470
|
+
- spec/report_action_spec.rb
|
459
471
|
- spec/payment_spec.rb
|