methodical 0.0.1
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 +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +17 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/lib/methodical.rb +1 -0
- data/lib/methodical/action_item.rb +139 -0
- data/lib/methodical/checklist.rb +29 -0
- data/lib/methodical/disposition.rb +132 -0
- data/lib/methodical/dsl.rb +111 -0
- data/lib/methodical/executable.rb +61 -0
- data/lib/methodical/modifier.rb +43 -0
- data/lib/methodical/simple_action_item.rb +30 -0
- data/lib/methodical/walkthrough.rb +143 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +9 -0
- data/test/methodical/checklist_test.rb +79 -0
- data/test/methodical/disposition_test.rb +120 -0
- data/test/methodical/dsl_test.rb +217 -0
- data/test/methodical/modifier_test.rb +79 -0
- data/test/methodical/simple_action_item_test.rb +825 -0
- data/test/methodical/walkthrough_test.rb +387 -0
- data/test/test_helper.rb +2 -0
- metadata +147 -0
@@ -0,0 +1,217 @@
|
|
1
|
+
require File.expand_path("../test_helper", File.dirname(__FILE__))
|
2
|
+
require 'methodical/dsl'
|
3
|
+
require 'methodical/action_item'
|
4
|
+
|
5
|
+
class DslTest < Test::Unit::TestCase
|
6
|
+
include Methodical::DSL
|
7
|
+
|
8
|
+
context "#action" do
|
9
|
+
specify "constructs an ActionItem" do
|
10
|
+
step = action("TITLE") do
|
11
|
+
"RESULT"
|
12
|
+
end
|
13
|
+
|
14
|
+
assert_kind_of Methodical::ActionItem, step
|
15
|
+
assert_equal "TITLE", step.title
|
16
|
+
assert_equal "RESULT", step.execute!.result
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "#sufficient" do
|
21
|
+
specify "makes successful actions sufficient" do
|
22
|
+
step = action("TITLE") do "RESULT" end
|
23
|
+
sufficient_step = sufficient << step
|
24
|
+
|
25
|
+
assert_equal :sufficient, sufficient_step.execute!.status
|
26
|
+
end
|
27
|
+
|
28
|
+
specify "has no effect on unsuccessful actions" do
|
29
|
+
step = action("TITLE") do raise "FAIL" end
|
30
|
+
sufficient_step = sufficient << step
|
31
|
+
|
32
|
+
assert_equal :failed, sufficient_step.execute!.status
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "#requisite" do
|
37
|
+
specify "makes failed actions abort" do
|
38
|
+
step = action("TITLE") do raise "FAIL" end
|
39
|
+
requisite_step = requisite << step
|
40
|
+
|
41
|
+
disposition = requisite_step.execute!
|
42
|
+
assert_equal :abort, disposition.status
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "#ignore" do
|
47
|
+
specify "makes steps ignorable" do
|
48
|
+
step = action("TITLE") do raise "FAIL" end
|
49
|
+
ignored_step = ignore << step
|
50
|
+
ignored_step.execute!
|
51
|
+
assert ignored_step.ignored?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "#skip_if" do
|
56
|
+
specify "skips step if condition is true" do
|
57
|
+
step = skip_if(""){true} << action("TITLE") do
|
58
|
+
flunk("Should not get here")
|
59
|
+
end
|
60
|
+
assert_equal :skipped, step.execute!().status
|
61
|
+
end
|
62
|
+
|
63
|
+
specify "performs step if condition is false" do
|
64
|
+
sensor = :unset
|
65
|
+
step = skip_if(""){false} << action("TITLE") do
|
66
|
+
"RESULT"
|
67
|
+
end
|
68
|
+
assert_equal "RESULT", step.execute!.result
|
69
|
+
end
|
70
|
+
|
71
|
+
specify "passes baton into condition" do
|
72
|
+
baton = stub("Baton")
|
73
|
+
sensor = :unset
|
74
|
+
step = skip_if(""){|b, s| sensor = b} << action("TITLE") do
|
75
|
+
"RESULT"
|
76
|
+
end
|
77
|
+
step.execute!(baton)
|
78
|
+
assert_same baton, sensor
|
79
|
+
end
|
80
|
+
|
81
|
+
specify "passes step into condition" do
|
82
|
+
baton = stub("Baton")
|
83
|
+
sensor = :unset
|
84
|
+
step = skip_if(""){|b, s| sensor = s} << inner = action("TITLE") do
|
85
|
+
"RESULT"
|
86
|
+
end
|
87
|
+
step.execute!(baton)
|
88
|
+
assert_same inner, sensor
|
89
|
+
end
|
90
|
+
|
91
|
+
specify "returns reason if skipped" do
|
92
|
+
step = skip_if("EXPL"){true} << action("TITLE") do
|
93
|
+
flunk("Should not get here")
|
94
|
+
end
|
95
|
+
assert_equal "EXPL", step.execute!().explanation
|
96
|
+
end
|
97
|
+
|
98
|
+
specify "updates status of step" do
|
99
|
+
step = skip_if("EXPL"){true} << action("TITLE") do
|
100
|
+
flunk("Should not get here")
|
101
|
+
end
|
102
|
+
step.execute!
|
103
|
+
assert_equal "EXPL", step.explanation
|
104
|
+
assert_equal :skipped, step.status
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "#handle_error" do
|
109
|
+
specify "rescues errors" do
|
110
|
+
step = handle_error(RuntimeError){|b,s,e| s.succeed! } <<
|
111
|
+
action("TITLE") do
|
112
|
+
raise "UH-OH"
|
113
|
+
end
|
114
|
+
assert_nothing_raised do
|
115
|
+
step.execute!(nil, true)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
specify "substitutes its own disposition" do
|
120
|
+
step = handle_error(RuntimeError){|b,s,e| s.succeed! } <<
|
121
|
+
action("TITLE") do
|
122
|
+
raise "UH-OH"
|
123
|
+
end
|
124
|
+
assert_equal :succeeded, step.execute!(nil, true).status
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
context "#filter" do
|
130
|
+
specify "modifies step disposition" do
|
131
|
+
step = filter {|d|
|
132
|
+
d.merge(:status => :failed, :explanation => "MODIFIED")
|
133
|
+
} << action("TITLE") {
|
134
|
+
|b,s| s.succeed!("ORIGINAL")
|
135
|
+
}
|
136
|
+
result = step.execute!
|
137
|
+
assert_equal :failed, result.status
|
138
|
+
assert_equal "MODIFIED", result.explanation
|
139
|
+
assert_equal :failed, step.status
|
140
|
+
assert_equal "MODIFIED", step.explanation
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context "#recover_failure" do
|
145
|
+
specify "executes block on failure" do
|
146
|
+
sensor = :unset
|
147
|
+
step = action("test") do |b,s| s.fail!("FAIL") end
|
148
|
+
wrapped_step = recover_failure do |baton, step, disposition|
|
149
|
+
sensor = :set
|
150
|
+
end << step
|
151
|
+
wrapped_step.execute!
|
152
|
+
assert_equal :set, sensor
|
153
|
+
end
|
154
|
+
|
155
|
+
specify "does not execute block on success" do
|
156
|
+
sensor = :unset
|
157
|
+
step = action("test") do |b,s| s.succeed!("OK") end
|
158
|
+
wrapped_step = recover_failure do |baton, step, disposition|
|
159
|
+
sensor = :set
|
160
|
+
end << step
|
161
|
+
wrapped_step.execute!
|
162
|
+
assert_equal :unset, sensor
|
163
|
+
end
|
164
|
+
|
165
|
+
specify "does not execute block on error" do
|
166
|
+
sensor = :unset
|
167
|
+
step = action("test") do raise StandardError, "BAD" end
|
168
|
+
wrapped_step = recover_failure do |baton, step, disposition|
|
169
|
+
sensor = :set
|
170
|
+
end << step
|
171
|
+
wrapped_step.execute!
|
172
|
+
assert_equal :unset, sensor
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
context "#retry_on_failure" do
|
177
|
+
specify "retries on failure" do
|
178
|
+
call_count = 0
|
179
|
+
step = action("test") do
|
180
|
+
call_count += 1
|
181
|
+
if call_count == 1
|
182
|
+
raise RuntimeError, "FAIL!"
|
183
|
+
end
|
184
|
+
end
|
185
|
+
wrapped_step = (retry_on_failure(2) << step)
|
186
|
+
wrapped_step.execute!
|
187
|
+
assert_equal 2, call_count
|
188
|
+
end
|
189
|
+
|
190
|
+
specify "will not retry more than the specified number of times" do
|
191
|
+
call_count = 0
|
192
|
+
step = action("test") do
|
193
|
+
call_count += 1
|
194
|
+
raise RuntimeError, "FAIL!"
|
195
|
+
end
|
196
|
+
wrapped_step = (retry_on_failure(2) << step)
|
197
|
+
wrapped_step.execute!
|
198
|
+
assert_equal 3, call_count
|
199
|
+
end
|
200
|
+
|
201
|
+
specify "will not retry if timeout expires" do
|
202
|
+
time = Time.mktime(1970, 1, 1)
|
203
|
+
clock = stub("Clock", :now => time)
|
204
|
+
call_count = 0
|
205
|
+
step = action("test") do
|
206
|
+
call_count += 1
|
207
|
+
time += 1
|
208
|
+
clock.stubs(:now => time)
|
209
|
+
raise RuntimeError, "FAIL!"
|
210
|
+
end
|
211
|
+
wrapped_step = (retry_on_failure(2, 1, :clock => clock) << step)
|
212
|
+
wrapped_step.execute!
|
213
|
+
assert_equal 1, call_count
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require File.expand_path("../test_helper", File.dirname(__FILE__))
|
2
|
+
require 'methodical/modifier'
|
3
|
+
require 'methodical/action_item'
|
4
|
+
|
5
|
+
class ModifierTest < Test::Unit::TestCase
|
6
|
+
context "#execute!" do
|
7
|
+
specify "executes the modifier block" do
|
8
|
+
step = stub_everything("ActionItem")
|
9
|
+
sensor = :unset
|
10
|
+
it = Methodical::Modifier.new("NAME", step) do
|
11
|
+
sensor = :set
|
12
|
+
end
|
13
|
+
it.execute!
|
14
|
+
assert_equal :set, sensor
|
15
|
+
end
|
16
|
+
|
17
|
+
specify "passes the action item to the block" do
|
18
|
+
step = stub_everything("ActionItem")
|
19
|
+
sensor = :unset
|
20
|
+
it = Methodical::Modifier.new("NAME", step) do |action_item, baton|
|
21
|
+
sensor = action_item
|
22
|
+
end
|
23
|
+
it.execute!
|
24
|
+
assert_same step, sensor
|
25
|
+
end
|
26
|
+
|
27
|
+
specify "passes a baton to the block" do
|
28
|
+
baton = stub("Baton")
|
29
|
+
step = stub_everything("ActionItem")
|
30
|
+
sensor = :unset
|
31
|
+
it = Methodical::Modifier.new("NAME", step) do |action_item, baton|
|
32
|
+
sensor = baton
|
33
|
+
end
|
34
|
+
it.execute!(baton)
|
35
|
+
assert_not_nil sensor
|
36
|
+
assert_same baton, sensor
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "#<<" do
|
41
|
+
specify "composes modifier and modified" do
|
42
|
+
step = stub_everything("ActionItem")
|
43
|
+
it = Methodical::Modifier.new("NAME")
|
44
|
+
it << step
|
45
|
+
assert_same step, it.action_item
|
46
|
+
end
|
47
|
+
|
48
|
+
specify "returns the modifier" do
|
49
|
+
step = stub_everything("ActionItem")
|
50
|
+
it = Methodical::Modifier.new("NAME")
|
51
|
+
assert_same it, (it << step)
|
52
|
+
end
|
53
|
+
|
54
|
+
specify "delegates to action_item, if set" do
|
55
|
+
mod2 = stub("Inner Modifier")
|
56
|
+
step = stub_everything("ActionItem")
|
57
|
+
it = Methodical::Modifier.new("NAME", mod2)
|
58
|
+
mod2.expects(:<<).with(step)
|
59
|
+
it << step
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "#clone" do
|
64
|
+
specify "deeply copies action item" do
|
65
|
+
step = stub_everything("ActionItem")
|
66
|
+
copy = stub_everything("Copy")
|
67
|
+
it = Methodical::Modifier.new("NAME", step)
|
68
|
+
step.expects(:clone).returns(copy).at_least_once
|
69
|
+
assert_same copy, it.clone.action_item
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
specify "delegates unknown methods to action item" do
|
74
|
+
step = stub_everything("ActionItem")
|
75
|
+
it = Methodical::Modifier.new("NAME", step)
|
76
|
+
step.expects(:foo).with("bar")
|
77
|
+
it.foo("bar")
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,825 @@
|
|
1
|
+
require File.expand_path("../test_helper", File.dirname(__FILE__))
|
2
|
+
require 'methodical/simple_action_item'
|
3
|
+
|
4
|
+
class SimpleActionItemTest < Test::Unit::TestCase
|
5
|
+
include Methodical
|
6
|
+
|
7
|
+
specify "can be updated all at once" do
|
8
|
+
it = SimpleActionItem.new("Test") {}
|
9
|
+
it.update!(:skipped, "EXPLANATION", [1,2,3])
|
10
|
+
assert_equal :skipped, it.status
|
11
|
+
assert_equal "EXPLANATION", it.explanation
|
12
|
+
assert_equal [1,2,3], it.result
|
13
|
+
end
|
14
|
+
|
15
|
+
context "#update" do
|
16
|
+
specify "returns a disposition" do
|
17
|
+
it = SimpleActionItem.new("Test") {}
|
18
|
+
assert_equal(
|
19
|
+
Disposition.new([:skipped, "EXPLANATION", [1,2,3]]),
|
20
|
+
it.update!(:skipped, "EXPLANATION", [1,2,3]))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
specify "defaults to NOT ignored" do
|
25
|
+
it = SimpleActionItem.new("Test") {}
|
26
|
+
assert !it.ignored?
|
27
|
+
end
|
28
|
+
|
29
|
+
specify "defaults to being relevant" do
|
30
|
+
it = SimpleActionItem.new("Test") {}
|
31
|
+
assert it.relevant?
|
32
|
+
end
|
33
|
+
|
34
|
+
specify "defaults to empty details" do
|
35
|
+
it = SimpleActionItem.new("Test") {}
|
36
|
+
assert_equal "", it.details
|
37
|
+
end
|
38
|
+
|
39
|
+
context "created from a block" do
|
40
|
+
specify "executes the block when called" do
|
41
|
+
sensor = :unset
|
42
|
+
it = SimpleActionItem.new("Test") do
|
43
|
+
sensor = :set
|
44
|
+
end
|
45
|
+
it.execute!
|
46
|
+
assert_equal :set, sensor
|
47
|
+
end
|
48
|
+
|
49
|
+
specify "has the given title" do
|
50
|
+
it = SimpleActionItem.new("Foo") {}
|
51
|
+
assert_equal "Foo", it.title
|
52
|
+
end
|
53
|
+
|
54
|
+
specify "knows it is undone before being called" do
|
55
|
+
it = SimpleActionItem.new("Foo") {}
|
56
|
+
assert !it.done?
|
57
|
+
end
|
58
|
+
|
59
|
+
specify "knows it is done after being called" do
|
60
|
+
it = SimpleActionItem.new("Foo") {}
|
61
|
+
it.execute!
|
62
|
+
assert it.done?
|
63
|
+
end
|
64
|
+
|
65
|
+
specify "has a status of :succeeded after being called" do
|
66
|
+
it = SimpleActionItem.new("Foo") {}
|
67
|
+
it.execute!
|
68
|
+
assert_equal :succeeded, it.status
|
69
|
+
end
|
70
|
+
|
71
|
+
specify "has a status of :not_started before being called" do
|
72
|
+
it = SimpleActionItem.new("Foo") {}
|
73
|
+
assert_equal :not_started, it.status
|
74
|
+
end
|
75
|
+
|
76
|
+
specify "knows it has neither succeeded or failed before being called" do
|
77
|
+
it = SimpleActionItem.new("Foo") {}
|
78
|
+
assert !it.succeeded?
|
79
|
+
assert !it.failed?
|
80
|
+
assert !it.bad?
|
81
|
+
end
|
82
|
+
|
83
|
+
specify "can format a status message" do
|
84
|
+
it = SimpleActionItem.new("Foo") {}
|
85
|
+
assert_equal "Foo: Not started.", it.synopsis
|
86
|
+
end
|
87
|
+
|
88
|
+
specify "passes self to block" do
|
89
|
+
sensor = :unset
|
90
|
+
it = SimpleActionItem.new("Foo") do |baton, step|
|
91
|
+
sensor = step
|
92
|
+
end
|
93
|
+
it.execute!(nil)
|
94
|
+
assert_same it, sensor
|
95
|
+
end
|
96
|
+
|
97
|
+
specify "called with a baton object, passes baton to block" do
|
98
|
+
sensor = :unset
|
99
|
+
it = SimpleActionItem.new("Foo") do |baton, step|
|
100
|
+
sensor = baton
|
101
|
+
end
|
102
|
+
test_baton = stub("Baton")
|
103
|
+
it.execute!(test_baton)
|
104
|
+
assert_same test_baton, sensor
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "created from a callable" do
|
109
|
+
specify "executes the callable when called" do
|
110
|
+
sensor = :unset
|
111
|
+
callable = lambda do |baton, step|
|
112
|
+
sensor = :set
|
113
|
+
end
|
114
|
+
it = SimpleActionItem.new("Test", callable)
|
115
|
+
it.execute!
|
116
|
+
assert_equal :set, sensor
|
117
|
+
end
|
118
|
+
|
119
|
+
specify "called with a baton object, passes baton to callable" do
|
120
|
+
sensor = :unset
|
121
|
+
callable = lambda do |baton, step|
|
122
|
+
sensor = baton
|
123
|
+
end
|
124
|
+
it = SimpleActionItem.new("Foo", callable)
|
125
|
+
test_baton = stub("Baton")
|
126
|
+
it.execute!(test_baton)
|
127
|
+
assert_same test_baton, sensor
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context "with a block that throws a disposition" do
|
132
|
+
specify "should save and return the disposition" do
|
133
|
+
it = SimpleActionItem.new("Failure") do
|
134
|
+
throw(:methodical_disposition,
|
135
|
+
Methodical::Disposition(:in_progress, "Procrastinating", 42))
|
136
|
+
end
|
137
|
+
assert_equal(Methodical::Disposition(:in_progress, "Procrastinating", 42),
|
138
|
+
it.execute!)
|
139
|
+
assert_equal(Methodical::Disposition(:in_progress, "Procrastinating", 42),
|
140
|
+
it.disposition)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context "with a block that raises a runtime error" do
|
145
|
+
specify "has a status of :failed after being called" do
|
146
|
+
it = SimpleActionItem.new("Failure") do raise "Fail" end
|
147
|
+
it.execute!
|
148
|
+
assert_equal :failed, it.status
|
149
|
+
end
|
150
|
+
|
151
|
+
specify "stores the exception" do
|
152
|
+
it = SimpleActionItem.new("Failure") do raise "Fail" end
|
153
|
+
it.execute!
|
154
|
+
assert_kind_of RuntimeError, it.error
|
155
|
+
assert_equal "Fail", it.error.message
|
156
|
+
end
|
157
|
+
|
158
|
+
specify "returns a disposition from call" do
|
159
|
+
it = SimpleActionItem.new("Failure") do raise "Fail" end
|
160
|
+
assert_kind_of Methodical::Disposition, it.execute!
|
161
|
+
assert_equal "Fail", it.execute!.explanation
|
162
|
+
end
|
163
|
+
|
164
|
+
specify "details should be derived from the error backtrace" do
|
165
|
+
error = RuntimeError.new("Fail")
|
166
|
+
error.set_backtrace(['FRAME1', 'FRAME2'])
|
167
|
+
it = SimpleActionItem.new("Failure") do raise error end
|
168
|
+
assert_equal "FRAME1\nFRAME2", it.execute!.details
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
context "with a block that raises a StandardError" do
|
174
|
+
specify "has a status of :bad after being called" do
|
175
|
+
it = SimpleActionItem.new("Failure") do
|
176
|
+
raise StandardError, "Fail"
|
177
|
+
end
|
178
|
+
it.execute!
|
179
|
+
assert_equal :bad, it.status
|
180
|
+
end
|
181
|
+
|
182
|
+
specify "stores the exception" do
|
183
|
+
it = SimpleActionItem.new("Failure") do
|
184
|
+
raise StandardError, "Fail"
|
185
|
+
end
|
186
|
+
it.execute!
|
187
|
+
assert_kind_of StandardError, it.error
|
188
|
+
assert_equal "Fail", it.error.message
|
189
|
+
end
|
190
|
+
|
191
|
+
specify "details should be derived from the error backtrace" do
|
192
|
+
error = StandardError.new("Fail")
|
193
|
+
error.set_backtrace(['FRAME1', 'FRAME2'])
|
194
|
+
it = SimpleActionItem.new("Failure") do raise error end
|
195
|
+
assert_equal "FRAME1\nFRAME2", it.execute!.details
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
context "with a block that raises a Exception" do
|
200
|
+
specify "has a status of :bad after being called" do
|
201
|
+
it = SimpleActionItem.new("Failure") do
|
202
|
+
raise Exception, "Alert!"
|
203
|
+
end
|
204
|
+
begin
|
205
|
+
it.execute!
|
206
|
+
rescue Exception
|
207
|
+
end
|
208
|
+
assert_equal :bad, it.status
|
209
|
+
end
|
210
|
+
|
211
|
+
specify "stores the exception" do
|
212
|
+
it = SimpleActionItem.new("Failure") do
|
213
|
+
raise Exception, "Fail"
|
214
|
+
end
|
215
|
+
begin
|
216
|
+
it.execute!
|
217
|
+
rescue Exception
|
218
|
+
end
|
219
|
+
assert_kind_of Exception, it.error
|
220
|
+
assert_equal "Fail", it.error.message
|
221
|
+
assert_equal "Fail", it.explanation
|
222
|
+
end
|
223
|
+
|
224
|
+
specify "passes the exception on" do
|
225
|
+
it = SimpleActionItem.new("Failure") do
|
226
|
+
raise Exception, "Fail"
|
227
|
+
end
|
228
|
+
assert_raises(Exception) do
|
229
|
+
it.execute!
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
specify "details should be derived from the error backtrace" do
|
234
|
+
error = Exception.new("Fail")
|
235
|
+
error.set_backtrace(['FRAME1', 'FRAME2'])
|
236
|
+
it = SimpleActionItem.new("Failure") do raise error end
|
237
|
+
begin
|
238
|
+
it.execute!
|
239
|
+
rescue Exception
|
240
|
+
end
|
241
|
+
assert_equal "FRAME1\nFRAME2", it.details
|
242
|
+
end
|
243
|
+
|
244
|
+
end
|
245
|
+
|
246
|
+
context "with a block that returns no details" do
|
247
|
+
specify "has no explanation" do
|
248
|
+
it = SimpleActionItem.new("Foo") {}
|
249
|
+
it.execute!
|
250
|
+
assert it.explanation.blank?
|
251
|
+
end
|
252
|
+
|
253
|
+
specify "returns a disposition on call" do
|
254
|
+
it = SimpleActionItem.new("Foo") {}
|
255
|
+
assert_kind_of Methodical::Disposition, it.execute!
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
context "with a block that returns success details" do
|
260
|
+
specify "uses second element for explanation" do
|
261
|
+
it = SimpleActionItem.new("Foo") do
|
262
|
+
[:succeeded, "EXPLANATION", nil]
|
263
|
+
end
|
264
|
+
it.execute!
|
265
|
+
assert_equal "EXPLANATION", it.explanation
|
266
|
+
end
|
267
|
+
|
268
|
+
specify "uses third element for result" do
|
269
|
+
it = SimpleActionItem.new("Foo") do
|
270
|
+
[:succeeded, "EXPLANATION", {:frobozz => "magic"}]
|
271
|
+
end
|
272
|
+
it.execute!
|
273
|
+
assert_equal({:frobozz => "magic"}, it.result)
|
274
|
+
end
|
275
|
+
|
276
|
+
specify "returns a disposition on call" do
|
277
|
+
it = SimpleActionItem.new("Foo") do
|
278
|
+
[:succeeded, "EXPLANATION", {:frobozz => "magic"}]
|
279
|
+
end
|
280
|
+
assert_kind_of Methodical::Disposition, it.execute!
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
context "with a status of :skipped" do
|
285
|
+
specify "can format a status message" do
|
286
|
+
it = SimpleActionItem.new("Foo") {}
|
287
|
+
it.status = :skipped
|
288
|
+
assert_equal "Foo: Skipped.", it.synopsis
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
context "with a status of :abort" do
|
293
|
+
specify "can format a status message" do
|
294
|
+
it = SimpleActionItem.new("Foo") {}
|
295
|
+
it.status = :abort
|
296
|
+
assert_equal "Foo: Failed.", it.synopsis
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
context "with the ignored bit set" do
|
301
|
+
specify "knows it is ignored" do
|
302
|
+
it = SimpleActionItem.new("Foo") {}
|
303
|
+
it.ignored = true
|
304
|
+
assert it.ignored?
|
305
|
+
end
|
306
|
+
|
307
|
+
specify "does not count towards overall outcome" do
|
308
|
+
it = SimpleActionItem.new("Foo") {}
|
309
|
+
it.ignored = true
|
310
|
+
assert !it.relevant?
|
311
|
+
end
|
312
|
+
|
313
|
+
end
|
314
|
+
|
315
|
+
context "failed, with the ignored bit set" do
|
316
|
+
specify "can format a status message" do
|
317
|
+
it = SimpleActionItem.new("Foo") {}
|
318
|
+
it.status = :failed
|
319
|
+
it.explanation = "Stuff happened"
|
320
|
+
it.ignored = true
|
321
|
+
assert_equal "Foo: Failed (Stuff happened) (Ignored).", it.synopsis
|
322
|
+
end
|
323
|
+
|
324
|
+
specify "should say continuing is OK" do
|
325
|
+
it = SimpleActionItem.new("Foo") {}
|
326
|
+
it.status = :failed
|
327
|
+
it.explanation = "Stuff happened"
|
328
|
+
it.ignored = true
|
329
|
+
assert it.continue?
|
330
|
+
end
|
331
|
+
|
332
|
+
specify "is not decisive" do
|
333
|
+
it = SimpleActionItem.new("Foo") {}
|
334
|
+
it.status = :failed
|
335
|
+
it.ignored = true
|
336
|
+
assert !it.decisive?
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
context "aborted, with the ignored bit set" do
|
341
|
+
specify "can format a status message" do
|
342
|
+
it = SimpleActionItem.new("Foo") {}
|
343
|
+
it.status = :abort
|
344
|
+
it.explanation = "Stuff happened"
|
345
|
+
it.ignored = true
|
346
|
+
assert_equal "Foo: Failed (Stuff happened) (Ignored).", it.synopsis
|
347
|
+
end
|
348
|
+
|
349
|
+
specify "should NOT say continuing is OK" do
|
350
|
+
it = SimpleActionItem.new("Foo") {}
|
351
|
+
it.status = :abort
|
352
|
+
it.explanation = "Stuff happened"
|
353
|
+
it.ignored = true
|
354
|
+
assert !it.continue?
|
355
|
+
end
|
356
|
+
|
357
|
+
specify "is not decisive" do
|
358
|
+
it = SimpleActionItem.new("Foo") {}
|
359
|
+
it.status = :aborted
|
360
|
+
it.ignored = true
|
361
|
+
assert !it.decisive?
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
context "succeeded, with the ignored bit set" do
|
366
|
+
specify "can format a status message" do
|
367
|
+
it = SimpleActionItem.new("Foo") {}
|
368
|
+
it.status = :succeeded
|
369
|
+
it.explanation = "Stuff happened"
|
370
|
+
it.ignored = true
|
371
|
+
assert_equal "Foo: OK (Stuff happened).", it.synopsis
|
372
|
+
end
|
373
|
+
|
374
|
+
specify "should say continuing is OK" do
|
375
|
+
it = SimpleActionItem.new("Foo") {}
|
376
|
+
it.status = :succeeded
|
377
|
+
it.explanation = "Stuff happened"
|
378
|
+
it.ignored = true
|
379
|
+
assert it.continue?
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
context "with a status of :sufficient" do
|
384
|
+
specify "can format a status message" do
|
385
|
+
it = SimpleActionItem.new("Foo") {}
|
386
|
+
it.status = :sufficient
|
387
|
+
assert_equal "Foo: OK.", it.synopsis
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
context "with a status of :finish" do
|
392
|
+
specify "can format a status message" do
|
393
|
+
it = SimpleActionItem.new("Foo") {}
|
394
|
+
it.status = :finish
|
395
|
+
assert_equal "Foo: OK.", it.synopsis
|
396
|
+
end
|
397
|
+
|
398
|
+
specify "should NOT approve continuation" do
|
399
|
+
it = SimpleActionItem.new("Foo") {}
|
400
|
+
it.status = :finish
|
401
|
+
assert !it.continue?
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
context "with a block that returns a single value" do
|
406
|
+
specify "has no explanation" do
|
407
|
+
it = SimpleActionItem.new("Foo") do
|
408
|
+
"RESULT"
|
409
|
+
end
|
410
|
+
it.execute!
|
411
|
+
assert it.explanation.blank?
|
412
|
+
end
|
413
|
+
|
414
|
+
specify "uses value for result" do
|
415
|
+
it = SimpleActionItem.new("Foo") do
|
416
|
+
"RESULT"
|
417
|
+
end
|
418
|
+
it.execute!
|
419
|
+
assert_equal("RESULT", it.result)
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
context "which has failed" do
|
424
|
+
specify "knows it has failed" do
|
425
|
+
it = SimpleActionItem.new("Failure") do raise "Fail" end
|
426
|
+
it.execute!
|
427
|
+
assert it.failed?
|
428
|
+
end
|
429
|
+
|
430
|
+
specify "knows it has not succeeded" do
|
431
|
+
it = SimpleActionItem.new("Failure") do raise "Fail" end
|
432
|
+
it.execute!
|
433
|
+
assert !it.succeeded?
|
434
|
+
end
|
435
|
+
|
436
|
+
specify "is decisive" do
|
437
|
+
it = SimpleActionItem.new("Failure") do raise "Fail" end
|
438
|
+
it.execute!
|
439
|
+
assert it.decisive?
|
440
|
+
end
|
441
|
+
|
442
|
+
specify "knows it is not bad" do
|
443
|
+
it = SimpleActionItem.new("Fail") do raise "Fail" end
|
444
|
+
it.execute!
|
445
|
+
assert !it.bad?
|
446
|
+
end
|
447
|
+
|
448
|
+
specify "gets explanation from error" do
|
449
|
+
it = SimpleActionItem.new("Fail") do raise "Fail" end
|
450
|
+
it.execute!
|
451
|
+
assert_equal "Fail", it.explanation
|
452
|
+
end
|
453
|
+
|
454
|
+
specify "can format a status message" do
|
455
|
+
it = SimpleActionItem.new("Foo") do raise "MESSAGE" end
|
456
|
+
it.execute!
|
457
|
+
assert_equal "Foo: Failed (MESSAGE).", it.synopsis
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
461
|
+
context "which has raised a standard error" do
|
462
|
+
specify "knows it has failed" do
|
463
|
+
it = SimpleActionItem.new("Failure") do
|
464
|
+
raise StandardError, "Fail"
|
465
|
+
end
|
466
|
+
it.execute!
|
467
|
+
assert it.failed?
|
468
|
+
end
|
469
|
+
|
470
|
+
specify "knows it has not succeeded" do
|
471
|
+
it = SimpleActionItem.new("Failure") do
|
472
|
+
raise StandardError, "Fail"
|
473
|
+
end
|
474
|
+
it.execute!
|
475
|
+
assert !it.succeeded?
|
476
|
+
end
|
477
|
+
|
478
|
+
specify "knows it is bad" do
|
479
|
+
it = SimpleActionItem.new("Fail") do
|
480
|
+
raise StandardError, "Fail"
|
481
|
+
end
|
482
|
+
it.execute!
|
483
|
+
assert it.bad?
|
484
|
+
end
|
485
|
+
|
486
|
+
specify "gets explanation from error" do
|
487
|
+
it = SimpleActionItem.new("Fail") do raise StandardError, "Fail" end
|
488
|
+
it.execute!
|
489
|
+
assert_equal "Fail", it.explanation
|
490
|
+
end
|
491
|
+
|
492
|
+
specify "can format a status message" do
|
493
|
+
it = SimpleActionItem.new("Foo") do
|
494
|
+
raise StandardError, "SOME_ERROR"
|
495
|
+
end
|
496
|
+
it.execute!
|
497
|
+
assert_equal "Foo: Error (SOME_ERROR).", it.synopsis
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
501
|
+
context "which has succeeded" do
|
502
|
+
specify "knows it has not failed" do
|
503
|
+
it = SimpleActionItem.new("Success") do end
|
504
|
+
it.execute!
|
505
|
+
assert !it.failed?
|
506
|
+
end
|
507
|
+
|
508
|
+
specify "knows it has succeeded" do
|
509
|
+
it = SimpleActionItem.new("Success") do end
|
510
|
+
it.execute!
|
511
|
+
assert it.succeeded?
|
512
|
+
end
|
513
|
+
|
514
|
+
specify "knows it is not bad" do
|
515
|
+
it = SimpleActionItem.new("Success") do end
|
516
|
+
it.execute!
|
517
|
+
assert !it.bad?
|
518
|
+
end
|
519
|
+
|
520
|
+
specify "can format a status message" do
|
521
|
+
it = SimpleActionItem.new("Foo") {}
|
522
|
+
it.execute!
|
523
|
+
assert_equal "Foo: OK.", it.synopsis
|
524
|
+
end
|
525
|
+
|
526
|
+
end
|
527
|
+
|
528
|
+
context "#succeed!" do
|
529
|
+
specify "throws :methodical_disposition" do
|
530
|
+
it = SimpleActionItem.new("TEST") {}
|
531
|
+
assert_throws(:methodical_disposition) do
|
532
|
+
it.succeed!
|
533
|
+
end
|
534
|
+
end
|
535
|
+
|
536
|
+
specify "throws a disposition object" do
|
537
|
+
it = SimpleActionItem.new("TEST") {}
|
538
|
+
assert_kind_of(Methodical::Disposition,
|
539
|
+
catch(:methodical_disposition) { it.succeed! })
|
540
|
+
end
|
541
|
+
|
542
|
+
specify "throws a successful disposition" do
|
543
|
+
it = SimpleActionItem.new("TEST") {}
|
544
|
+
assert_equal(:succeeded,
|
545
|
+
catch(:methodical_disposition) { it.succeed! }.status)
|
546
|
+
end
|
547
|
+
|
548
|
+
specify "throws the given explanation" do
|
549
|
+
it = SimpleActionItem.new("TEST") {}
|
550
|
+
assert_equal("EXPL",
|
551
|
+
catch(:methodical_disposition) { it.succeed!("EXPL") }.explanation)
|
552
|
+
end
|
553
|
+
|
554
|
+
specify "throws the given result" do
|
555
|
+
it = SimpleActionItem.new("TEST") {}
|
556
|
+
assert_equal(42,
|
557
|
+
catch(:methodical_disposition) { it.succeed!("EXPL", 42) }.result)
|
558
|
+
end
|
559
|
+
|
560
|
+
specify "throws the given details" do
|
561
|
+
it = SimpleActionItem.new("TEST") {}
|
562
|
+
assert_equal("DETAILS",
|
563
|
+
catch(:methodical_disposition) {
|
564
|
+
it.succeed!("EXPL", 42, "DETAILS")
|
565
|
+
}.details)
|
566
|
+
end
|
567
|
+
end
|
568
|
+
|
569
|
+
context "#failed!" do
|
570
|
+
specify "throws :methodical_disposition" do
|
571
|
+
it = SimpleActionItem.new("TEST") {}
|
572
|
+
assert_throws(:methodical_disposition) do
|
573
|
+
it.fail!
|
574
|
+
end
|
575
|
+
end
|
576
|
+
|
577
|
+
specify "throws a disposition object" do
|
578
|
+
it = SimpleActionItem.new("TEST") {}
|
579
|
+
assert_kind_of(Methodical::Disposition,
|
580
|
+
catch(:methodical_disposition) { it.fail! })
|
581
|
+
end
|
582
|
+
|
583
|
+
specify "throws a failed disposition" do
|
584
|
+
it = SimpleActionItem.new("TEST") {}
|
585
|
+
assert_equal(:failed,
|
586
|
+
catch(:methodical_disposition) { it.fail! }.status)
|
587
|
+
end
|
588
|
+
|
589
|
+
specify "throws the given explanation" do
|
590
|
+
it = SimpleActionItem.new("TEST") {}
|
591
|
+
assert_equal("EXPL",
|
592
|
+
catch(:methodical_disposition) { it.fail!("EXPL") }.explanation)
|
593
|
+
end
|
594
|
+
|
595
|
+
specify "throws the given result" do
|
596
|
+
it = SimpleActionItem.new("TEST") {}
|
597
|
+
assert_equal(42,
|
598
|
+
catch(:methodical_disposition) { it.fail!("EXPL", 42) }.result)
|
599
|
+
end
|
600
|
+
|
601
|
+
specify "throws the given error" do
|
602
|
+
it = SimpleActionItem.new("TEST") {}
|
603
|
+
assert_equal("FOO",
|
604
|
+
catch(:methodical_disposition) {
|
605
|
+
it.fail!("EXPL", 42, RuntimeError.new("FOO"))
|
606
|
+
}.error.message)
|
607
|
+
end
|
608
|
+
|
609
|
+
specify "throws the given details" do
|
610
|
+
it = SimpleActionItem.new("TEST") {}
|
611
|
+
assert_equal("DETAILS",
|
612
|
+
catch(:methodical_disposition) {
|
613
|
+
it.fail!("EXPL", 42, nil, "DETAILS")
|
614
|
+
}.details)
|
615
|
+
end
|
616
|
+
end
|
617
|
+
|
618
|
+
context "#skip!" do
|
619
|
+
specify "throws :methodical_disposition" do
|
620
|
+
it = SimpleActionItem.new("TEST") {}
|
621
|
+
assert_throws(:methodical_disposition) do
|
622
|
+
it.skip!
|
623
|
+
end
|
624
|
+
end
|
625
|
+
|
626
|
+
specify "throws a disposition object" do
|
627
|
+
it = SimpleActionItem.new("TEST") {}
|
628
|
+
assert_kind_of(Methodical::Disposition,
|
629
|
+
catch(:methodical_disposition) { it.skip! })
|
630
|
+
end
|
631
|
+
|
632
|
+
specify "throws a skipped disposition" do
|
633
|
+
it = SimpleActionItem.new("TEST") {}
|
634
|
+
assert_equal(:skipped,
|
635
|
+
catch(:methodical_disposition) { it.skip! }.status)
|
636
|
+
end
|
637
|
+
|
638
|
+
specify "throws the given explanation" do
|
639
|
+
it = SimpleActionItem.new("TEST") {}
|
640
|
+
assert_equal("EXPL",
|
641
|
+
catch(:methodical_disposition) { it.skip!("EXPL") }.explanation)
|
642
|
+
end
|
643
|
+
|
644
|
+
specify "throws the given details" do
|
645
|
+
it = SimpleActionItem.new("TEST") {}
|
646
|
+
assert_equal("DETAILS",
|
647
|
+
catch(:methodical_disposition) {
|
648
|
+
it.skip!("EXPL", "DETAILS")
|
649
|
+
}.details)
|
650
|
+
end
|
651
|
+
end
|
652
|
+
|
653
|
+
context "#checkpoint!" do
|
654
|
+
specify "throws :methodical_disposition" do
|
655
|
+
it = SimpleActionItem.new("TEST") {}
|
656
|
+
assert_throws(:methodical_disposition) do
|
657
|
+
it.checkpoint!
|
658
|
+
end
|
659
|
+
end
|
660
|
+
|
661
|
+
specify "throws a disposition object" do
|
662
|
+
it = SimpleActionItem.new("TEST") {}
|
663
|
+
assert_kind_of(Methodical::Disposition,
|
664
|
+
catch(:methodical_disposition) { it.checkpoint! })
|
665
|
+
end
|
666
|
+
|
667
|
+
specify "throws an in_progress disposition" do
|
668
|
+
it = SimpleActionItem.new("TEST") {}
|
669
|
+
assert_equal(:in_progress,
|
670
|
+
catch(:methodical_disposition) { it.checkpoint! }.status)
|
671
|
+
end
|
672
|
+
|
673
|
+
specify "throws the given explanation" do
|
674
|
+
it = SimpleActionItem.new("TEST") {}
|
675
|
+
assert_equal("EXPL",
|
676
|
+
catch(:methodical_disposition) { it.checkpoint!("EXPL") }.explanation)
|
677
|
+
end
|
678
|
+
|
679
|
+
specify "throws the given memento" do
|
680
|
+
it = SimpleActionItem.new("TEST") {}
|
681
|
+
assert_equal(42,
|
682
|
+
catch(:methodical_disposition) { it.checkpoint!("EXPL", 42) }.memento)
|
683
|
+
end
|
684
|
+
|
685
|
+
specify "throws the given details" do
|
686
|
+
it = SimpleActionItem.new("TEST") {}
|
687
|
+
assert_equal("DETAILS",
|
688
|
+
catch(:methodical_disposition) {
|
689
|
+
it.checkpoint!("EXPL", 42, "DETAILS")
|
690
|
+
}.details)
|
691
|
+
end
|
692
|
+
end
|
693
|
+
|
694
|
+
|
695
|
+
context "#sufficient!" do
|
696
|
+
specify "throws :methodical_disposition" do
|
697
|
+
it = SimpleActionItem.new("TEST") {}
|
698
|
+
assert_throws(:methodical_disposition) do
|
699
|
+
it.sufficient!
|
700
|
+
end
|
701
|
+
end
|
702
|
+
|
703
|
+
specify "throws a disposition object" do
|
704
|
+
it = SimpleActionItem.new("TEST") {}
|
705
|
+
assert_kind_of(Methodical::Disposition,
|
706
|
+
catch(:methodical_disposition) { it.sufficient! })
|
707
|
+
end
|
708
|
+
|
709
|
+
specify "throws a sufficient disposition" do
|
710
|
+
it = SimpleActionItem.new("TEST") {}
|
711
|
+
assert_equal(:sufficient,
|
712
|
+
catch(:methodical_disposition) { it.sufficient! }.status)
|
713
|
+
end
|
714
|
+
|
715
|
+
specify "throws the given explanation" do
|
716
|
+
it = SimpleActionItem.new("TEST") {}
|
717
|
+
assert_equal("EXPL",
|
718
|
+
catch(:methodical_disposition) { it.sufficient!("EXPL") }.explanation)
|
719
|
+
end
|
720
|
+
|
721
|
+
specify "throws the given result" do
|
722
|
+
it = SimpleActionItem.new("TEST") {}
|
723
|
+
assert_equal(42,
|
724
|
+
catch(:methodical_disposition) { it.sufficient!("EXPL", 42) }.result)
|
725
|
+
end
|
726
|
+
|
727
|
+
specify "throws the given details" do
|
728
|
+
it = SimpleActionItem.new("TEST") {}
|
729
|
+
assert_equal("DETAILS",
|
730
|
+
catch(:methodical_disposition) {
|
731
|
+
it.sufficient!("EXPL", 42, "DETAILS")
|
732
|
+
}.details)
|
733
|
+
end
|
734
|
+
end
|
735
|
+
|
736
|
+
context "#finish!" do
|
737
|
+
specify "throws :methodical_disposition" do
|
738
|
+
it = SimpleActionItem.new("TEST") {}
|
739
|
+
assert_throws(:methodical_disposition) do
|
740
|
+
it.finish!
|
741
|
+
end
|
742
|
+
end
|
743
|
+
|
744
|
+
specify "throws a disposition object" do
|
745
|
+
it = SimpleActionItem.new("TEST") {}
|
746
|
+
assert_kind_of(Methodical::Disposition,
|
747
|
+
catch(:methodical_disposition) { it.finish! })
|
748
|
+
end
|
749
|
+
|
750
|
+
specify "throws a finish disposition" do
|
751
|
+
it = SimpleActionItem.new("TEST") {}
|
752
|
+
assert_equal(:finish,
|
753
|
+
catch(:methodical_disposition) { it.finish! }.status)
|
754
|
+
end
|
755
|
+
|
756
|
+
specify "throws the given explanation" do
|
757
|
+
it = SimpleActionItem.new("TEST") {}
|
758
|
+
assert_equal("EXPL",
|
759
|
+
catch(:methodical_disposition) { it.finish!("EXPL") }.explanation)
|
760
|
+
end
|
761
|
+
|
762
|
+
specify "throws the given result" do
|
763
|
+
it = SimpleActionItem.new("TEST") {}
|
764
|
+
assert_equal(42,
|
765
|
+
catch(:methodical_disposition) { it.finish!("EXPL", 42) }.result)
|
766
|
+
end
|
767
|
+
|
768
|
+
specify "throws the given details" do
|
769
|
+
it = SimpleActionItem.new("TEST") {}
|
770
|
+
assert_equal("DETAILS",
|
771
|
+
catch(:methodical_disposition) {
|
772
|
+
it.finish!("EXPL", 42, "DETAILS")
|
773
|
+
}.details)
|
774
|
+
end
|
775
|
+
end
|
776
|
+
|
777
|
+
context "#abort!" do
|
778
|
+
specify "throws :methodical_disposition" do
|
779
|
+
it = SimpleActionItem.new("TEST") {}
|
780
|
+
assert_throws(:methodical_disposition) do
|
781
|
+
it.abort!
|
782
|
+
end
|
783
|
+
end
|
784
|
+
|
785
|
+
specify "throws a disposition object" do
|
786
|
+
it = SimpleActionItem.new("TEST") {}
|
787
|
+
assert_kind_of(Methodical::Disposition,
|
788
|
+
catch(:methodical_disposition) { it.abort! })
|
789
|
+
end
|
790
|
+
|
791
|
+
specify "throws an abort disposition" do
|
792
|
+
it = SimpleActionItem.new("TEST") {}
|
793
|
+
assert_equal(:abort,
|
794
|
+
catch(:methodical_disposition) { it.abort! }.status)
|
795
|
+
end
|
796
|
+
|
797
|
+
specify "throws the given explanation" do
|
798
|
+
it = SimpleActionItem.new("TEST") {}
|
799
|
+
assert_equal("EXPL",
|
800
|
+
catch(:methodical_disposition) { it.abort!("EXPL") }.explanation)
|
801
|
+
end
|
802
|
+
|
803
|
+
specify "throws the given result" do
|
804
|
+
it = SimpleActionItem.new("TEST") {}
|
805
|
+
assert_equal(42,
|
806
|
+
catch(:methodical_disposition) { it.abort!("EXPL", 42) }.result)
|
807
|
+
end
|
808
|
+
|
809
|
+
specify "throws the given error" do
|
810
|
+
it = SimpleActionItem.new("TEST") {}
|
811
|
+
assert_equal("FOO",
|
812
|
+
catch(:methodical_disposition) {
|
813
|
+
it.abort!("EXPL", 42, RuntimeError.new("FOO"))
|
814
|
+
}.error.message)
|
815
|
+
end
|
816
|
+
|
817
|
+
specify "throws the given details" do
|
818
|
+
it = SimpleActionItem.new("TEST") {}
|
819
|
+
assert_equal("DETAILS",
|
820
|
+
catch(:methodical_disposition) {
|
821
|
+
it.abort!("EXPL", 42, nil, "DETAILS")
|
822
|
+
}.details)
|
823
|
+
end
|
824
|
+
end
|
825
|
+
end
|